---
canonical: "https://agi-labo.com/tools/cockpit/docs/cockpit-cli/reference/hooks"
title: "cockpit hooks"
description: "cockpit hooksの構文、オプション、結果、制約をcockpit CLIの正本から自動生成したリファレンスです。"
section: "リファレンス"
order: 112
pageType: reference
lastVerifiedVersion: 4.64.0
lastVerifiedAt: "2026-08-30"
draft: false
surfaces:
  - cli
operatingSystems:
  - windows
  - macos
  - linux
plans:
  - guest
  - member
navigation: false
---

このReference本文は、アプリが配布するcockpit CLIヘルプと同じ英語の正本から自動生成されています。日本語の概念説明と安全な使い方は[cockpit CLI](/tools/cockpit/docs/cockpit-cli)を参照してください。

Cockpit Hooks run a shell action when a Cockpit lifecycle event fires. A hook is one persisted event-to-action declaration: it selects events, optionally filters their payloads, and runs either an inline script or a script file. Cockpit Hooks are separate from the agent status-report hooks installed by Cockpit.

This command family is local-only. `--host` is rejected because hooks register arbitrary code on the Cockpit instance that executes them.

```bash
cockpit hooks add --event task.completed --name notify-complete --run 'cockpit display --text "${COCKPIT_TASK_NAME} completed"'
cockpit hooks list [--json]
cockpit hooks get <hookId>
cockpit hooks update <hookId> --timeout 120
cockpit hooks remove <hookId>
cockpit hooks enable <hookId>
cockpit hooks disable <hookId>
cockpit hooks runs [--hook <hookId>] [--limit <n>]
cockpit hooks test <hookId> [--task <taskId>]
cockpit hooks events
cockpit hooks help
```

## Events

Hooks can select comma-separated event names or repeat `--event`. Family wildcards expand when the hook is saved. Supported wildcards are `task.*`, `ask.*`, `autorun.*`, `fleet.run.*`, and `app.*`; `hotkey` is an exact event name.

| Event | Fires when |
|---|---|
| `task.created` | A task is created through the UI, CLI, Autorun, Fleet, or Master Agent |
| `task.resumed` | A task returns to `running` from `waiting_confirmation`, `error`, or `completed` |
| `task.waiting` | A task enters `waiting_confirmation` |
| `task.completed` | A task enters `completed` |
| `task.error` | A task enters `error` |
| `task.removed` | A task is removed |
| `ask.created` | A task creates an Ask |
| `ask.resolved` | An Ask is answered |
| `ask.dismissed` | An Ask is closed without an answer |
| `hotkey` | The hook's accelerator is pressed in its configured scope |
| `autorun.triggered` | An Autorun schedule dispatches, whether it targets a new or existing task |
| `fleet.run.started` | A Fleet Run starts |
| `fleet.run.completed` | A Fleet Run reaches `completed`, `failed`, or `canceled` |
| `app.ready` | Cockpit starts and the hooks engine is ready |
| `app.quit` | Cockpit begins quitting |

Task status hooks fire only for real transitions. Rewriting the same status does not run a hook, and task creation fires `task.created`, not `task.resumed`. Hooks are independent of task-status notification settings. `app.quit` actions are best-effort: Cockpit waits at most five seconds for all hook work and terminates remaining hook processes before quitting.

Run `cockpit hooks events` to inspect every registered event, its family, accepted payload roots and fields, the common envelope fields, and wildcard selectors.

## Payload and environment

The action receives compact JSON version 1 on stdin. The common shape is:

```json
{
  "event": "task.waiting",
  "version": 1,
  "firedAt": "2026-08-20T12:34:56.789Z",
  "depth": 0,
  "hook": { "id": "hk_a1b2c3d4", "name": "notify-waiting" },
  "task": {
    "id": "task_123",
    "name": "Review API",
    "status": "waiting_confirmation",
    "previousStatus": "running",
    "waitingReason": "question",
    "agentType": "codex",
    "model": "gpt-5.4",
    "effort": "high",
    "directory": "/path/to/project",
    "isAutorun": false,
    "isFleet": false,
    "isChild": false
  }
}
```

The full `task` object is the same item returned by `cockpit task list`, plus `previousStatus`, `isAutorun`, `isFleet`, and `isChild`. Ask events include both that task and the complete `cockpit ask list` item as `ask`; `ask.resolved` adds `outcome`, `answeredBy`, and `answers`, while `ask.dismissed` adds `outcome: "dismissed"`. Other families add only their own object:

- `hotkey`: `hookId`, `accelerator`, `scope`, `selectionText`, and optional `selectionUnavailable`
- `autorun`: `id`, `name`, `executionTarget`, and `targetTaskId`
- `fleetRun`: `name`, `runId`, `status`, and `directory`
- `app.*`: no event-specific object

Key fields are also exposed as environment variables:

| Variables | Content |
|---|---|
| `COCKPIT_HOOK_ID`, `COCKPIT_HOOK_NAME`, `COCKPIT_HOOK_EVENT`, `COCKPIT_HOOK_DEPTH` | Hook identity, event, and the depth forwarded to nested `cockpit` calls |
| `COCKPIT_TASK_ID`, `COCKPIT_TASK_NAME`, `COCKPIT_TASK_STATUS`, `COCKPIT_TASK_PREV_STATUS` | Task identity and transition |
| `COCKPIT_TASK_WAITING_REASON`, `COCKPIT_TASK_AGENT`, `COCKPIT_TASK_MODEL`, `COCKPIT_TASK_EFFORT`, `COCKPIT_TASK_DIRECTORY` | Task runtime fields |
| `COCKPIT_TASK_IS_AUTORUN`, `COCKPIT_TASK_IS_FLEET`, `COCKPIT_TASK_IS_CHILD` | String booleans, `true` or `false` |
| `COCKPIT_ASK_ID`, `COCKPIT_ASK_SUMMARY` | Ask identity and summary; structured questions, media, and answers remain in stdin JSON |
| `COCKPIT_HOTKEY_ACCELERATOR`, `COCKPIT_SELECTION` | Hotkey accelerator and captured selection |
| `COCKPIT_AUTORUN_ID`, `COCKPIT_AUTORUN_NAME`, `COCKPIT_AUTORUN_TARGET` | Autorun identity and execution target |
| `COCKPIT_FLEET_NAME`, `COCKPIT_FLEET_RUN_ID`, `COCKPIT_FLEET_RUN_STATUS` | Fleet Run identity and status |

For a received event at depth `n`, the action gets `COCKPIT_HOOK_DEPTH=n+1`. The CLI forwards that value when the action creates another task so downstream events retain the loop-prevention depth.

## Filters

`--filter <path>=<value>` matches a payload field. Values support `*` and `?` globs and can be comma-separated. Multiple filters are ANDed; values inside one filter are ORed. Booleans match `true` or `false`, and a missing or null field matches only `null`.

```bash
cockpit hooks add --event task.* \
  --filter 'task.name=Release *' \
  --filter 'task.model=gpt-5.*' \
  --run-file ./release-hook.sh
```

The path must be present in every selected event's payload specification. Task filters are valid only when every selected event is in `task.*` or `ask.*`. Named flags are aliases for the same stored path filters:

| Alias | Stored match |
|---|---|
| `--task <taskId>` | `task.id=<taskId>` |
| `--task-name <glob>` | `task.name=<glob>` |
| `--agent <value>[,value...]` | `task.agentType` |
| `--model <glob>[,glob...]` | `task.model` |
| `--effort <value>[,value...]` | `task.effort` |
| `--autorun` / `--no-autorun` | `task.isAutorun=true|false` |
| `--fleet` / `--no-fleet` | `task.isFleet=true|false` |
| `--child` / `--no-child` | `task.isChild=true|false` |
| `--created-by <value>[,value...]` | `task.createdBy` |
| `--waiting-reason <value>[,value...]` | `task.waitingReason` |
| `--directory <prefix>` | `task.directory=<prefix>*` |

## Actions and execution controls

Use exactly one action source when adding a hook:

- `--run '<script>'` stores an inline, optionally multiline shell script.
- `--run-file <path>` stores a script path and is preferable for long or maintained actions.

The action runs through Cockpit's login-shell resolution with the event's task directory as its working directory, the Fleet Run directory for `fleet.run.*`, and the home directory otherwise. `--timeout <seconds>` accepts 1–3600 and defaults to 60. A timeout terminates the process tree and records `timedOut: true`. `--debounce <seconds>` accepts 0–3600; repeated events for the same hook inside the window collapse to the latest event. `--disabled` creates or updates the hook as disabled.

Cockpit runs at most four hook actions globally. Each hook has its own FIFO queue and never runs concurrently with itself. Events at depth 3 or greater are ignored. A global circuit breaker pauses dispatch after 60 executions within 60 seconds, clears queued and debounced work, records `circuitBreaker: true`, and resumes on the next real task-status transition.

## Hotkeys

A hotkey hook selects only the exact `hotkey` event and requires `--accelerator`. Accelerators use Electron syntax and must include Control, Alt, Command, or Meta. They cannot conflict with Cockpit's Quick Task shortcut. `--scope app|global` defaults to `app`; app scope fires while a Cockpit window is focused, while global scope registers an operating-system shortcut. `--with-selection` adds selected text to `COCKPIT_SELECTION` and `hotkey.selectionText`.

```bash
cockpit hooks add --event hotkey \
  --accelerator 'CommandOrControl+Shift+T' \
  --scope global \
  --with-selection \
  --run 'cockpit task run --instruction "Summarize: ${COCKPIT_SELECTION}" --directory "$HOME"'
```

`hooks list` and `hooks get` add `registered: true|false` to hotkey hooks. A false value means the accelerator is not active, including operating-system registration failures or a later Quick Task conflict.

On macOS, global selection capture saves the clipboard, sends Copy through AppleScript, reads the selection, and restores the clipboard. Grant AGI Cockpit access in **System Settings > Privacy & Security > Accessibility**. Without that permission, the hook still runs with an empty `COCKPIT_SELECTION`; its history record has `selectionUnavailable: true`. The first global selection hook added on macOS returns this guidance in `data.notice`.

## Commands and JSON results

Successful control commands return `{"ok":true,"data":...}`. Hook definitions include `id`, `name`, `events`, generic `filters`, `action`, `enabled`, `debounceMs`, timestamps, and hotkey fields when applicable. The global `--json` flag is accepted by `hooks list` and the other control commands as a no-op because their output is already JSON.

| Command | Options | `data` shape |
|---|---|---|
| `cockpit hooks add` | `--event` and exactly one of `--run` / `--run-file`; filters; `--name`; `--timeout`; `--debounce`; `--disabled`; hotkey options | `{hook}` and optional macOS `notice` |
| `cockpit hooks list` | Optional global `--json` | `{hooks: Hook[]}` |
| `cockpit hooks get <hookId>` | Hook id | `{hook}` |
| `cockpit hooks update <hookId>` | Any add option; omitted fields retain their values | `{hook}` |
| `cockpit hooks remove <hookId>` | Hook id | `{removed: hookId}` |
| `cockpit hooks enable <hookId>` | Hook id | `{hook}` with `enabled: true` |
| `cockpit hooks disable <hookId>` | Hook id | `{hook}` with `enabled: false` |
| `cockpit hooks runs` | `--hook <hookId>`, `--limit <n>` | `{runs: HookRun[]}`; default 20, maximum 200 |
| `cockpit hooks test <hookId>` | Optional `--task <taskId>` | `{hookId, event, result}` |
| `cockpit hooks events` | None | `{events, envelope, wildcards}` |
| `cockpit hooks help` | None | Prints the built-in usage text |

Supplying generic or named filters to `update` replaces the hook's user filters; omitting all filter options preserves them. Hotkey routing filters are managed automatically.

`test` executes the action immediately with the first expanded event selected by the hook. It bypasses normal matching, debounce, queueing, depth checks, circuit breaker accounting, and run-history persistence. For `task.*` and `ask.*`, `--task` selects a real task; without it Cockpit uses the first cached task, and the command fails if none exists. The returned `result` contains `exitCode`, `timedOut`, `stdoutTail`, `stderrTail`, and `durationMs`.

## History and persistence

Definitions are stored separately from execution history under the Cockpit data directory's `hooks/` folder: `hooks.json` contains only definitions, and `runs.jsonl` contains one execution record per line. Definitions use atomic replacement. Run records contain `seq`, `hookId`, `event`, `taskId`, `startedAt`, `durationMs`, `exitCode`, `timedOut`, and the last 4 KB each of stdout and stderr, plus circuit-breaker or selection-unavailable flags when relevant.

`cockpit hooks runs` returns the newest matching records in chronological order. History rotates after 2,000 lines or 2 MB by retaining the latest 1,000 lines. Removing a hook does not remove its existing run records.

## Ask to Slack round trip

Use an `ask.created` hook to forward the complete Ask payload to Slack, then let the Slack interaction handler resolve the original Ask through the CLI:

```bash
cockpit hooks add --event ask.created --name ask-to-slack --run-file ~/.config/cockpit/ask-to-slack.sh
```

The script reads stdin, posts `ask.summary`, `ask.questions`, choices, descriptions, and media metadata to Slack, and associates the Slack message with `ask.id`. When the user clicks a Slack choice, the integration calls:

```bash
cockpit ask answer <askId> --choice "staging"
```

That resolves the same persistent Ask, emits `ask.resolved` with its answers, and resumes the originating task. If Slack should only mirror the decision, one `ask.created` hook is enough; add a separate `ask.resolved` hook when the external message also needs its final answered state.
