Skip to content
Hoody.com

The agent hook endpoints manage the lifecycle hooks that fire shell commands on agent session events. The hook system is session-scoped: every operation takes a live session_id, and write operations (upsert, delete, toggle, set_disabled) additionally require a single-use nonce minted by the begin-write route. Use these endpoints when you want to inspect the live hook state, define or remove hooks, toggle individual hooks, test-fire a hook command, reload the on-disk configuration, disable all hooks at once, or acknowledge the hook-trust prompt.

All endpoints live under the agent container’s public hostname of the form https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com. Requests must reach the agent through the Hoody proxy — direct container connections are rejected with forbidden.

Returns the live and on-disk hook summaries, the per-scope settings files, and the execution-trust probe. hooks.list is session-scoped — supply session_id in the body or as the ?session_id query alias (the body value wins). The daemon payload is surfaced verbatim, so this is not a paginated envelope.

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).
X-Hoody-CwdheaderstringNoPer-request working-directory scope: the .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 with 400 on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: global or a 24-hex id (also accepted as ?realm=). Rejected with 400 realm_scope_unsupported on active-only routes.
realmquerystringNoPer-request realm selector — the query alias of the X-Hoody-Realm header (read only when the header is absent).
FieldTypeRequiredDescription
session_idstringNoLive session id (hooks are session-scoped). May be supplied here OR as the ?session_id query alias; the body value wins.
{
"session_id": "sess_8f3c2a1b9d4e5f60a1b2c3d4"
}
{
"live": [
{
"name": "format-on-pre-tool",
"description": "Run prettier on files before any tool call",
"event": "PreToolUse",
"matcher": "Write|Edit",
"enabled": true,
"command": "npx prettier --write \"$HOODY_FILE_PATH\"",
"timeout": 15000
}
],
"session": {
"id": "sess_8f3c2a1b9d4e5f60a1b2c3d4",
"scope": "project"
},
"stale": [],
"files": [
{
"scope": "project",
"path": "/repo/.hoody/settings.json",
"hook_count": 1
}
],
"trust": {
"pending": false,
"acknowledged_at": "2026-01-15T18:22:04Z"
}
}
Terminal window
curl -X GET "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/hooks" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "session_id": "sess_8f3c2a1b9d4e5f60a1b2c3d4" }'

Issues the two-step write nonce required before every guarded hook mutation. Pass the live session_id, the target op (one of upsert, delete, toggle, set_disabled), and the scope path. The returned nonce binds to that session + op + scope tuple and is single-use; the nonce for op:toggle is not accepted by upsert, and so on.

NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope: the .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 with 400 on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: global or a 24-hex id (also accepted as ?realm=). Rejected with 400 realm_scope_unsupported on active-only routes.
realmquerystringNoPer-request realm selector — the query alias of the X-Hoody-Realm header (read only when the header is absent).
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_8f3c2a1b9d4e5f60a1b2c3d4",
"op": "upsert",
"scope": "project"
}
{
"nonce": "nb_nE4kM2xR8pWq3vT7sJ9aB6cF1dL5hY",
"op": "upsert",
"scope": "project",
"session_id": "sess_8f3c2a1b9d4e5f60a1b2c3d4",
"expires_at": "2026-01-15T18:27:04Z"
}
Terminal window
curl -X POST "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/hooks/begin-write" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "session_id": "sess_8f3c2a1b9d4e5f60a1b2c3d4", "op": "upsert", "scope": "project" }'

Creates or updates a hook (hooks.upsert). Requires the begin-write nonce for op:upsert and a live session_id. Defining a hook persists an arbitrary command that fires on lifecycle events.

NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope: the .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 with 400 on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: global or a 24-hex id (also accepted as ?realm=). Rejected with 400 realm_scope_unsupported on active-only routes.
realmquerystringNoPer-request realm selector — the query alias of the X-Hoody-Realm header (read only when the header is absent).
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_8f3c2a1b9d4e5f60a1b2c3d4",
"nonce": "nb_nE4kM2xR8pWq3vT7sJ9aB6cF1dL5hY",
"scope": "project",
"event": "PreToolUse",
"matcher": "Write|Edit",
"command": "npx prettier --write \"$HOODY_FILE_PATH\"",
"timeout": 15000,
"name": "format-on-pre-tool",
"description": "Run prettier on files before any tool call"
}
{
"ok": true,
"hook": {
"name": "format-on-pre-tool",
"description": "Run prettier on files before any tool call",
"event": "PreToolUse",
"matcher": "Write|Edit",
"enabled": true,
"command": "npx prettier --write \"$HOODY_FILE_PATH\"",
"timeout": 15000,
"scope": "project"
}
}
Terminal window
curl -X PUT "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/hooks" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"session_id": "sess_8f3c2a1b9d4e5f60a1b2c3d4",
"nonce": "nb_nE4kM2xR8pWq3vT7sJ9aB6cF1dL5hY",
"scope": "project",
"event": "PreToolUse",
"matcher": "Write|Edit",
"command": "npx prettier --write \"$HOODY_FILE_PATH\"",
"timeout": 15000,
"name": "format-on-pre-tool",
"description": "Run prettier on files before any tool call"
}'

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

NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope: the .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 with 400 on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: global or a 24-hex id (also accepted as ?realm=). Rejected with 400 realm_scope_unsupported on active-only routes.
realmquerystringNoPer-request realm selector — the query alias of the X-Hoody-Realm header (read only when the header is absent).
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_8f3c2a1b9d4e5f60a1b2c3d4",
"nonce": "nb_Z8rQ5yN1kP4tV9wX3mC7sL2bH6jF0dG",
"scope": "project"
}
{
"ok": true,
"deleted": "format-on-pre-tool",
"scope": "project"
}
Terminal window
curl -X DELETE "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/hooks" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"session_id": "sess_8f3c2a1b9d4e5f60a1b2c3d4",
"nonce": "nb_Z8rQ5yN1kP4tV9wX3mC7sL2bH6jF0dG",
"scope": "project"
}'

Toggles a single hook’s enabled state (hooks.toggle). This is a guarded write: it requires the begin-write nonce minted for op:toggle (the daemon RPC fails closed without it) plus a live session_id.

NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope: the .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 with 400 on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: global or a 24-hex id (also accepted as ?realm=). Rejected with 400 realm_scope_unsupported on active-only routes.
realmquerystringNoPer-request realm selector — the query alias of the X-Hoody-Realm header (read only when the header is absent).
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_8f3c2a1b9d4e5f60a1b2c3d4",
"nonce": "nb_T3gH7vL2mK9pQ5wX4nR1sJ8bC6dF0yN",
"scope": "project"
}
{
"ok": true,
"toggled": "format-on-pre-tool",
"enabled": false,
"scope": "project"
}
Terminal window
curl -X POST "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/hooks/toggle" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"session_id": "sess_8f3c2a1b9d4e5f60a1b2c3d4",
"nonce": "nb_T3gH7vL2mK9pQ5wX4nR1sJ8bC6dF0yN",
"scope": "project"
}'

Disables (or re-enables) all hooks at once (hooks.set_disabled). This is a guarded write: it requires the begin-write nonce minted by beginHookWrite for op:set_disabled (the daemon RPC fails closed without it) plus a live session_id.

NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope: the .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 with 400 on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: global or a 24-hex id (also accepted as ?realm=). Rejected with 400 realm_scope_unsupported on active-only routes.
realmquerystringNoPer-request realm selector — the query alias of the X-Hoody-Realm header (read only when the header is absent).
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_8f3c2a1b9d4e5f60a1b2c3d4",
"nonce": "nb_D1sA6bF8cJ2kM4nP7qR5tV9wX3yL0hG",
"scope": "project"
}
{
"ok": true,
"disabled": true,
"scope": "project",
"affected_hooks": 3
}
Terminal window
curl -X POST "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/hooks/disable-all" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"session_id": "sess_8f3c2a1b9d4e5f60a1b2c3d4",
"nonce": "nb_D1sA6bF8cJ2kM4nP7qR5tV9wX3yL0hG",
"scope": "project"
}'

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

NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope: the .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 with 400 on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: global or a 24-hex id (also accepted as ?realm=). Rejected with 400 realm_scope_unsupported on active-only routes.
realmquerystringNoPer-request realm selector — the query alias of the X-Hoody-Realm header (read only when the header is absent).

This endpoint takes no parameters.

{
"session_id": "sess_8f3c2a1b9d4e5f60a1b2c3d4"
}
{
"ok": true,
"reloaded_from": [
"/repo/.hoody/settings.json"
],
"summary": {
"live_count": 4,
"stale_count": 0
}
}
Terminal window
curl -X POST "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/hooks/reload" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "session_id": "sess_8f3c2a1b9d4e5f60a1b2c3d4" }'

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

NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope: the .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 with 400 on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: global or a 24-hex id (also accepted as ?realm=). Rejected with 400 realm_scope_unsupported on active-only routes.
realmquerystringNoPer-request realm selector — the query alias of the X-Hoody-Realm header (read only when the header is absent).

This endpoint takes no parameters.

{
"session_id": "sess_8f3c2a1b9d4e5f60a1b2c3d4"
}
{
"ok": true,
"hook": "format-on-pre-tool",
"exit_code": 0,
"stdout": "src/index.ts 120ms\n",
"stderr": "",
"duration_ms": 612
}
Terminal window
curl -X POST "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/hooks/test" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "session_id": "sess_8f3c2a1b9d4e5f60a1b2c3d4" }'

Acknowledges the hook-trust prompt (hooks.trust_ack). Requires a live session_id (hooks are session-scoped). Call this after the user has reviewed the pending hook changes and agreed to let them run.

NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope: the .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 with 400 on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: global or a 24-hex id (also accepted as ?realm=). Rejected with 400 realm_scope_unsupported on active-only routes.
realmquerystringNoPer-request realm selector — the query alias of the X-Hoody-Realm header (read only when the header is absent).

This endpoint takes no parameters.

{
"session_id": "sess_8f3c2a1b9d4e5f60a1b2c3d4"
}
{
"ok": true,
"acknowledged_at": "2026-01-15T18:31:12Z",
"session_id": "sess_8f3c2a1b9d4e5f60a1b2c3d4"
}
Terminal window
curl -X POST "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/hooks/trust/ack" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "session_id": "sess_8f3c2a1b9d4e5f60a1b2c3d4" }'