Skip to content
Hoody.com

Lifecycle hooks let you run arbitrary commands on agent events. The endpoints below let you list, upsert, delete, toggle, test-fire, reload, disable-all, and acknowledge the trust prompt for the hooks of a live session. Hooks are session-scoped: every call requires a live session_id, and every guarded mutation (upsert, delete, toggle, disable-all) requires a single-use nonce minted by begin-write.


Lists the lifecycle hooks for a live session. Returns the live + on-disk hook summaries (live, session), drift detection (stale), the per-scope settings files, and the execution-trust probe. This is not a paginated list envelope — the daemon payload is surfaced verbatim. A per-request realm header is rejected because this is an active-only RPC.

NameInTypeRequiredDescription
session_idquerystringNoLive session id (hooks are session-scoped; required by the daemon RPC). Query alias of the body session_id (the body value wins).
realmquerystringNoPer-request realm selector — alias of X-Hoody-Realm (read only when the header is absent): "global" or a 24-hex id. Rejected on active-only routes.
X-Hoody-CwdheaderstringNoPer-request working-directory scope: .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves.
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: "global" or a 24-hex id. Rejected on active-only routes.
FieldTypeRequiredDescription
session_idstringNoLive session id (hooks are session-scoped). May be supplied here OR as the ?session_id query alias; the body value wins.
{
"live": [
{
"name": "lint-on-save",
"description": "Run project linter before persisting any record",
"event": "PreRecordSave",
"matcher": "*.go",
"command": "gofmt -l .",
"enabled": true,
"timeout": 30
}
],
"session": [
{
"name": "lint-on-save",
"description": "Run project linter before persisting any record",
"event": "PreRecordSave",
"matcher": "*.go",
"command": "gofmt -l .",
"enabled": true,
"timeout": 30
}
],
"stale": [],
"files": [
{
"scope": "project",
"path": "/workspace/.hoody/settings.json",
"exists": true
}
],
"trust": {
"acknowledged": true,
"required": false
}
}
Terminal window
curl -X GET "https://abc123-def456-agent-1.us-east-1.containers.hoody.icu/api/v1/agent/hooks?session_id=sess_8f2c1a" \
-H "Authorization: Bearer <token>"

Issues the two-step write nonce required before every guarded hook mutation — not just upsert/delete but also toggle and disable-all. The returned nonce binds to the session + op + scope tuple and is single-use; the nonce for op:toggle is not accepted by upsert, and so on.

NameInTypeRequiredDescription
realmquerystringNoPer-request realm selector — alias of X-Hoody-Realm (read only when the header is absent): "global" or a 24-hex id. Rejected on active-only routes.
X-Hoody-CwdheaderstringNoPer-request working-directory scope. Required by routes that resolve a cwd.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: "global" or a 24-hex id. Rejected on active-only routes.
FieldTypeRequiredDescription
session_idstringYesLive session id (hooks are session-scoped).
opstringYesThe write the nonce authorizes; one of: upsert, delete, toggle, set_disabled. The nonce is rejected by any other op.
scopestringYesScope of the settings file the write targets (e.g. project/user); the nonce binds to its resolved path.
{
"session_id": "sess_8f2c1a",
"op": "upsert",
"scope": "project"
}
{
"nonce": "nonce_a9b8c7d6e5f40392",
"scope": "project",
"op": "upsert",
"session_id": "sess_8f2c1a",
"expires_at": "2026-03-04T12:34:56Z"
}
Terminal window
curl -X POST "https://abc123-def456-agent-1.us-east-1.containers.hoody.icu/api/v1/agent/hooks/begin-write" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"session_id": "sess_8f2c1a",
"op": "upsert",
"scope": "project"
}'

Creates or updates a hook (hooks.upsert). Requires the begin-write nonce minted for op:upsert and a live session_id. Defining a hook persists an arbitrary command that fires on lifecycle events. Creating a new hook requires non-empty name and description (the daemon rejects an undocumented create); updating an existing hook may omit them to preserve the current values.

NameInTypeRequiredDescription
realmquerystringNoPer-request realm selector — alias of X-Hoody-Realm (read only when the header is absent): "global" or a 24-hex id. Rejected on active-only routes.
X-Hoody-CwdheaderstringNoPer-request working-directory scope. Required by routes that resolve a cwd.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: "global" or a 24-hex id. Rejected on active-only routes.
FieldTypeRequiredDescription
session_idstringYesLive session id (hooks are session-scoped).
noncestringYesThe single-use write nonce from beginHookWrite minted for op:upsert + this scope; the RPC fails closed without it.
scopestringNoScope of the settings file to write (must match the nonce’s scope).
eventstringNoLifecycle event the hook fires on.
matcherstringNoMatcher selecting when the hook fires.
commandstringNoCommand to run when the hook fires.
timeoutintegerNoPer-fire timeout (optional).
namestringNoShort human label shown in the Hooks tab (required when creating a new hook; omit to preserve on update).
descriptionstringNoShort description of what the hook does (required when creating a new hook; omit to preserve on update).
{
"session_id": "sess_8f2c1a",
"nonce": "nonce_a9b8c7d6e5f40392",
"scope": "project",
"event": "PreRecordSave",
"matcher": "*.go",
"command": "gofmt -l .",
"timeout": 30,
"name": "lint-on-save",
"description": "Run project linter before persisting any record"
}
{
"ok": true,
"hook": {
"name": "lint-on-save",
"description": "Run project linter before persisting any record",
"event": "PreRecordSave",
"matcher": "*.go",
"command": "gofmt -l .",
"enabled": true,
"timeout": 30
}
}
Terminal window
curl -X PUT "https://abc123-def456-agent-1.us-east-1.containers.hoody.icu/api/v1/agent/hooks" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"session_id": "sess_8f2c1a",
"nonce": "nonce_a9b8c7d6e5f40392",
"scope": "project",
"event": "PreRecordSave",
"matcher": "*.go",
"command": "gofmt -l .",
"timeout": 30,
"name": "lint-on-save",
"description": "Run project linter before persisting any record"
}'

Deletes a hook (hooks.delete). Requires the begin-write nonce minted for op:delete and a live session_id.

NameInTypeRequiredDescription
realmquerystringNoPer-request realm selector — alias of X-Hoody-Realm (read only when the header is absent): "global" or a 24-hex id. Rejected on active-only routes.
X-Hoody-CwdheaderstringNoPer-request working-directory scope. Required by routes that resolve a cwd.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: "global" or a 24-hex id. Rejected on active-only routes.
FieldTypeRequiredDescription
session_idstringYesLive session id (hooks are session-scoped).
noncestringYesThe single-use write nonce from beginHookWrite minted for op:delete + this scope; the RPC fails closed without it.
scopestringNoScope of the settings file to write (must match the nonce’s scope).
{
"session_id": "sess_8f2c1a",
"nonce": "nonce_a9b8c7d6e5f40392",
"scope": "project"
}
{
"ok": true,
"deleted": "lint-on-save"
}
Terminal window
curl -X DELETE "https://abc123-def456-agent-1.us-east-1.containers.hoody.icu/api/v1/agent/hooks" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"session_id": "sess_8f2c1a",
"nonce": "nonce_a9b8c7d6e5f40392",
"scope": "project"
}'

Toggles a single hook’s enabled state (hooks.toggle). Requires the begin-write nonce minted for op:toggle and a live session_id.

NameInTypeRequiredDescription
realmquerystringNoPer-request realm selector — alias of X-Hoody-Realm (read only when the header is absent): "global" or a 24-hex id. Rejected on active-only routes.
X-Hoody-CwdheaderstringNoPer-request working-directory scope. Required by routes that resolve a cwd.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: "global" or a 24-hex id. Rejected on active-only routes.
FieldTypeRequiredDescription
session_idstringYesLive session id (hooks are session-scoped).
noncestringYesThe single-use write nonce from beginHookWrite minted for op:toggle + this scope; the RPC fails closed without it.
scopestringNoScope of the settings file to write (must match the nonce’s scope).
{
"session_id": "sess_8f2c1a",
"nonce": "nonce_a9b8c7d6e5f40392",
"scope": "project"
}
{
"ok": true,
"name": "lint-on-save",
"enabled": false
}
Terminal window
curl -X POST "https://abc123-def456-agent-1.us-east-1.containers.hoody.icu/api/v1/agent/hooks/toggle" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"session_id": "sess_8f2c1a",
"nonce": "nonce_a9b8c7d6e5f40392",
"scope": "project"
}'

Disables (or re-enables) all hooks at once (hooks.set_disabled). Requires the begin-write nonce minted for op:set_disabled and a live session_id.

NameInTypeRequiredDescription
realmquerystringNoPer-request realm selector — alias of X-Hoody-Realm (read only when the header is absent): "global" or a 24-hex id. Rejected on active-only routes.
X-Hoody-CwdheaderstringNoPer-request working-directory scope. Required by routes that resolve a cwd.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: "global" or a 24-hex id. Rejected on active-only routes.
FieldTypeRequiredDescription
session_idstringYesLive session id (hooks are session-scoped).
noncestringYesThe single-use write nonce from beginHookWrite minted for op:set_disabled + this scope; the RPC fails closed without it.
scopestringNoScope of the settings file to write (must match the nonce’s scope).
{
"session_id": "sess_8f2c1a",
"nonce": "nonce_a9b8c7d6e5f40392",
"scope": "project"
}
{
"ok": true,
"disabled": true,
"scope": "project"
}
Terminal window
curl -X POST "https://abc123-def456-agent-1.us-east-1.containers.hoody.icu/api/v1/agent/hooks/disable-all" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"session_id": "sess_8f2c1a",
"nonce": "nonce_a9b8c7d6e5f40392",
"scope": "project"
}'

Reloads the hook configuration from disk (hooks.reload). Pass a live session_id to also receive the reloaded summary.

NameInTypeRequiredDescription
realmquerystringNoPer-request realm selector — alias of X-Hoody-Realm (read only when the header is absent): "global" or a 24-hex id. Rejected on active-only routes.
X-Hoody-CwdheaderstringNoPer-request working-directory scope. Required by routes that resolve a cwd.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: "global" or a 24-hex id. Rejected on active-only routes.

This endpoint does not declare body fields. The request is forwarded to the daemon hooks.reload RPC; reserved _-prefixed keys are ignored and the request scope (cwd/config_dir) is applied automatically. All other keys are passed through. Pass session_id to receive the reloaded summary.

{}
{
"ok": true,
"reloaded": 4,
"files": [
{
"scope": "project",
"path": "/workspace/.hoody/settings.json",
"exists": true
}
]
}
Terminal window
curl -X POST "https://abc123-def456-agent-1.us-east-1.containers.hoody.icu/api/v1/agent/hooks/reload" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{}'

Test-fires a hook command (hooks.test). This executes an arbitrary command now. Requires a live session_id (hooks are session-scoped).

NameInTypeRequiredDescription
realmquerystringNoPer-request realm selector — alias of X-Hoody-Realm (read only when the header is absent): "global" or a 24-hex id. Rejected on active-only routes.
X-Hoody-CwdheaderstringNoPer-request working-directory scope. Required by routes that resolve a cwd.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: "global" or a 24-hex id. Rejected on active-only routes.

This endpoint does not declare body fields. The request is forwarded to the daemon hooks.test RPC; reserved _-prefixed keys are ignored and the request scope (cwd/config_dir) is applied automatically. All other keys are passed through. Pass session_id to identify the live session.

{}
{
"ok": true,
"exit_code": 0,
"stdout": "main.go\nutils.go\n",
"stderr": "",
"duration_ms": 47
}
Terminal window
curl -X POST "https://abc123-def456-agent-1.us-east-1.containers.hoody.icu/api/v1/agent/hooks/test" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{}'

Acknowledges the hook-trust prompt (hooks.trust_ack). Requires a live session_id (hooks are session-scoped).

NameInTypeRequiredDescription
realmquerystringNoPer-request realm selector — alias of X-Hoody-Realm (read only when the header is absent): "global" or a 24-hex id. Rejected on active-only routes.
X-Hoody-CwdheaderstringNoPer-request working-directory scope. Required by routes that resolve a cwd.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: "global" or a 24-hex id. Rejected on active-only routes.

This endpoint does not declare body fields. The request is forwarded to the daemon hooks.trust_ack RPC; reserved _-prefixed keys are ignored and the request scope (cwd/config_dir) is applied automatically. All other keys are passed through. Pass session_id to identify the live session.

{}
{
"ok": true,
"acknowledged": true,
"session_id": "sess_8f2c1a"
}
Terminal window
curl -X POST "https://abc123-def456-agent-1.us-east-1.containers.hoody.icu/api/v1/agent/hooks/trust/ack" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{}'