# Hooks

Hooks are cross-cutting interceptors that run before, after, or on error of any command — including commands from other packages. They are defined at the package level alongside `profiles` in the `.aux4` file.

## Defining Hooks

Hooks live in the `hooks` array at the root of the `.aux4` file:

```json
{
  "profiles": [
    {
      "name": "main",
      "commands": [
        {
          "name": "deploy",
          "execute": [
            "log:deploying to ${env}"
          ],
          "help": {
            "text": "deploy to environment",
            "variables": [
              {
                "name": "env",
                "text": "target environment"
              }
            ]
          }
        }
      ]
    }
  ],
  "hooks": [
    {
      "command": "main/deploy",
      "before": [
        "log:preparing deployment to ${env}..."
      ],
      "after": [
        "log:deployment complete: ${__response}"
      ],
      "error": [
        "log:deployment failed: ${__error}"
      ]
    }
  ]
}
```

```bash
> aux4 deploy --env production
```

```text
preparing deployment to production...
deploying to production
deployment complete: deploying to production
```

## Hook Phases

| Phase | When it runs | On failure |
|-------|-------------|------------|
| `before` | Before the command executes | Aborts command, runs error hooks |
| `after` | After the command succeeds | Logs warning, original exit code preserved |
| `error` | After the command fails | Logs warning, original error propagates |

Hook steps use the same executors as `execute` arrays — `log:`, `set:`, `aux4:`, shell commands, etc.

## Command Patterns

Hooks match commands by pattern. Use `*` as a wildcard for any single segment:

| Pattern | Matches |
|---------|---------|
| `main/deploy` | Exact profile and command |
| `*/deploy` | Command `deploy` in any profile |
| `deploy/*` | Any command in the `deploy` profile |
| `*/*` | All commands |

## Variables in Hooks

Hook steps have access to all variables passed to the intercepted command. These built-in variables are also available:

| Variable | Phases | Description |
|----------|--------|-------------|
| `${__command}` | all | Full command path |
| `${__scope}` | all | Package scope |
| `${__package}` | all | Package name |
| `${__response}` | `after`, `error` | stdout from the command |
| `${__error}` | `error` | Error message |
| `${__exitCode}` | `after`, `error` | Exit code |

## Variable Injection

A `set:` in a `before` hook injects variables into the command's scope. The variable is then available in the command and in `after`/`error` hooks:

```json
{
  "hooks": [
    {
      "command": "main/deploy",
      "before": [
        "set:timestamp=!date +%s"
      ],
      "after": [
        "log:deployed at ${timestamp}"
      ]
    }
  ]
}
```

## Hook Ordering

Hooks have an optional `order` field (default `0`). Lower values run first. Hooks with the same order run by package installation order:

```json
{
  "hooks": [
    {
      "command": "main/deploy",
      "order": 10,
      "before": ["log:second"]
    },
    {
      "command": "main/deploy",
      "order": 5,
      "before": ["log:first"]
    }
  ]
}
```

## Conditional Hooks (params)

Hooks can match based on variable values using the `params` field. All specified params must match (AND). Use `|` for alternatives (OR):

```json
{
  "hooks": [
    {
      "command": "main/deploy",
      "params": {
        "env": "production"
      },
      "before": [
        "confirm:Are you sure you want to deploy to production?"
      ]
    },
    {
      "command": "main/deploy",
      "params": {
        "env": "dev|staging"
      },
      "before": [
        "log:deploying to non-prod ${env}"
      ]
    }
  ]
}
```

When `--env production` is passed, only the first hook fires. When `--env dev` or `--env staging`, only the second. Hooks without `params` always match.

## Skipping Hooks

Use the `--noHooks` flag or `AUX4_NO_HOOKS=true` environment variable:

```bash
> aux4 deploy --env production --noHooks
> AUX4_NO_HOOKS=true aux4 deploy --env production
```

A command can also block hooks by setting `noHooks` in its definition:

```json
{
  "name": "internal-task",
  "execute": ["echo secret"],
  "noHooks": true
}
```

## Blocked Executors

The `profile:` and `stdin:` executors cannot be used in hooks and will produce an error. Hooks also do not trigger other hooks — there is no recursion.

## Hook Discovery

```bash
> aux4 aux4 hooks                                     # list all hooks
> aux4 aux4 hooks --command "main/deploy"              # filter by command
> aux4 aux4 hooks --package mycompany/deploy-hooks     # filter by package
> aux4 deploy --showHooks                              # show hooks for a command
```

---

## See Also

- [Executors](/executors)
- [Variables](/variables)
- [Commands](/commands)
- [Packaging](/packaging)
