Skip to main content

crewship hooks

Manage the lifecycle-hook registry — shell commands, HTTP webhooks, or subagents that fire on platform events (pre_agent_start, post_agent_stop, on_approval_requested, …). See the Hooks guide for the full 14-event catalog and the three handler kinds. There is no pre_tool_call — the platform has no interception point before a tool runs. Every one of the 14 catalog events, including post_tool_call, now dispatches from a real call site — see Currently-dispatched events below.
Every write requires OWNER or ADMIN. Creating or editing a shell hook requires OWNER — a shell handler runs its command on the crewshipd host, outside container isolation.

Subcommands

hooks list, create, and update honour the global --format flag (json/yaml/ndjson) — see Output Formats.

crewship hooks list

Sample output:
TARGET is derived from handler_config: the URL for http, the command for shell, the agent for subagent, truncated to 40 characters.

crewship hooks create

Requires --event and --handler, plus a target for that handler kind. New hooks are enabled unless you pass --disabled.
Sample output:

crewship hooks update <id>

Takes the same flags as create, all optional. Only the flags you pass are sent — an omitted flag keeps its current server-side value. If a blocking pre_* hook is changed to a post_* or on_* event, explicitly pass --blocking=false; the server refuses an observation event that retains the old blocking flag. Passing no flags at all is an error rather than an empty patch. Converting a hook to --handler shell, or editing one that is already shell, requires OWNER.

crewship hooks delete <id>

Without --yes the command refuses and points at crewship hooks disable, which stops the hook firing while keeping its definition.

crewship hooks enable <id>

Sample output:
Requires OWNER or ADMIN (403 otherwise). Emits system.hook_toggled into the Crew Journal with the actor’s user ID.

crewship hooks disable <id>

Same auth and audit semantics as enable.

Errors

Currently-dispatched events

All 14 events in the --event catalog now dispatch from a real call site — see the Hooks guide coverage table for the call site behind each one. internal/hooks/dispatch_site_test.go enforces this as an invariant: a source-scan test fails CI if an event is ever added to AllEvents without a matching hooks.Dispatch call reachable from outside the hooks package.pre_tool_call used to be exactly the opposite trap — an event that registered cleanly and never fired, with no “wire it up” path on the roadmap — and was removed from the valid event list rather than left there: it is the one event name that is now a 400, not a silently-dead 201.