AgentKit
DocsKitsCLI ReferenceDesktop App

Hooks and runtime

Marketing Hooks and runtime behavior

Understand the Marketing Kit automation that runs around tool use, how supporting files differ from active Hooks, and what each runtime can project.

Marketing Kit adds background checks and reminders around normal work. A Hook becomes active when the runtime connects an event to an entrypoint. Manifests, libraries, and utilities shipped beside that entrypoint are artifacts, not additional automatic behaviors.

Active outcomes

MomentWhat the active Hook graph does
Before tool useChecks descriptive naming before writes, checks file and shell operations for privacy-sensitive access, catches broad read or shell exploration that should be narrowed, checks how much content a read, search, or shell command can return, and substitutes ${secret:NAME} references in shell commands and fetch URLs.
After editsTracks supported edit activity and can remind the workflow to simplify and review substantial changes. Claude Code includes MultiEdit; Codex narrows this matcher to `Edit
When you submit a promptChecks for requests that could expose secrets and surfaces applicable development-rule guidance.

These behaviors can add guidance or stop an operation for review, depending on the event and runtime. They are workflow guardrails, not a general security boundary or a replacement for the runtime's own permission controls.

The reused context-firewall Hook runs before Bash, Read, Grep, and Glob calls. It warns about a whole-file read of 256 KB or more, a shell dump of 128 KB or more, an unbounded content search, and unbounded log, history, or recursive shell output. It blocks a whole-file read of 2 MB or more, a shell dump of 512 KB or more, and an unbounded content search with a broad pattern, and names a bounded alternative. The third intervention on the same operation in one session becomes a block. The Hook is on by default and fails open; set hooks.context-firewall to false to turn it off, as described in Managing Hook preferences.

Secret references in tool calls

The secrets-inject Hook runs before Bash and WebFetch calls. When a shell command or fetch URL contains a ${secret:NAME} reference, the Hook asks ak secrets resolve for the stored value and substitutes it in memory, so the model can compose the call without seeing the credential. Only Bash.command and WebFetch.url are scanned; file contents and prompts are left untouched. An ak secrets grant for the calling agent binary decides whether a value is released, and a grant restricted with --allow-host also checks the fetch destination.

Every failure blocks the tool call rather than passing the literal reference through, including a missing grant, an invalid name, or a value with shell-special characters bound for a Bash command. The Hook writes no copy of the value, but the substituted input still reaches the tool process and whatever the runtime records for an executed call, such as its transcript. Treat a released value as present on the host and rotate it when needed.

Claude Code and Grok register the Hook for Bash|WebFetch, and Codex narrows it to Bash. Cursor support for this Hook is not established in this release.

Background auto-update liveness

The session-heartbeat.cjs Hook is registered on SessionStart, UserPromptSubmit, Stop, and SessionEnd. It writes a per-session marker under the AgentKit home so the opt-in background auto-update skips a project with a live agent session, and removes that marker at SessionEnd. On SessionStart, it also prints a one-line notice for an unacknowledged background-update result, acknowledged with ak update --status --ack --json. The Hook never blocks a session and exits 0 even on its own failure.

Artifact entries are not behavior counts

The Marketing manifest declares nine Hook file exports:

  • The hooks.json manifest itself.
  • One Marketing-specific automatic entrypoint provides the post-edit reminder.
  • One manual Discord sender is shipped as a utility.
  • Six libraries support configuration and bounded runtime state.

The separate hooks.json manifest wires the Marketing entrypoint together with nine reused core entrypoints, including context-firewall, secrets-inject, and session-heartbeat. Support libraries do not run independently, and none of these entries is a Marketing command.

notifications/send-discord is not referenced by hooks.json. It runs only when a caller deliberately invokes it; installing Marketing Kit does not enable Discord notifications automatically. Its failure paths are non-blocking.

Runtime projection

RuntimeProjected behavior
Claude CodeActivates the configured event graph through native or plugin delivery. The separate Marketing statusline is also available here and can show directory, Git, model, context and usage, changed-work, configuration, and activity signals.
CodexTranslates representable groups into .codex/hooks.json. Its tool matcher set is narrower than Claude Code's, so some trigger coverage can be removed even when the rest of a group remains active. The Marketing statusline is not projected.
CursorTranslates supported registrations into .cursor/hooks.json. Source-level projection does not establish identical behavior across every provider setup. The Marketing statusline is not projected.

Codex behavior in this release

  • Marketing projects no fully dropped Codex group and five narrowed matchers. Shared Read|Write|Edit|Bash becomes Write|Edit|Bash; shared Bash|Read becomes Bash; shared Bash|Read|Grep|Glob becomes Bash; shared Bash|WebFetch becomes Bash; Marketing's Edit|Write|MultiEdit becomes Edit|Write. The original handlers remain active for the supported atoms.
  • Human output reports narrowing under Hook matchers narrowed (some tool matches unsupported on this target). Machine-readable output uses optional hookMatchersNarrowed and narrowedHookSummaries; full-drop fields remain absent for this projection.
  • On Windows, an eligible .cjs Hook under the Codex home can use a managed .cmd shim when an ordinary path contains spaces. A spaced .cjs path outside that home remains unshimmed. Paths with cmd.exe metacharacters, non-ASCII shim basenames, and unsafe or non-ASCII baked arguments also remain refused, so this is not a blanket compatibility guarantee.
  • A wrapper-managed Codex home may alias only its final hooks leaf to canonical ~/.codex/hooks, using a POSIX symlink or a Windows directory junction; writes, translated commands, rollback, and ownership use that canonical identity. Linked parents and other targets are refused.
  • Shared global Hook registration preserves user and foreign structures, supports matching ownership across Kits, and cleans up only exact stale claims. The stronger rollback and cleanup handling does not authorize deleting arbitrary content from ~/.codex/hooks.json.

These changes improve disclosure and ownership handling. They do not make Hook behavior identical across runtimes or turn Marketing Hooks into a security enforcement boundary.

Ownership and lifecycle

AgentKit records the Hook files, managed Windows shims, and registrations it emits. Refresh and uninstall act on matching owned outputs while preserving or reporting modified, foreign, and sibling-Kit content. Project and user installations can coexist, so inspect both scopes if an automation appears twice.

Review the install summary and warnings after every install or refresh. A successful install can still contain a runtime-specific projection limit.

For the wider compatibility model, see Runtime adapters. For lifecycle commands, see Installing kits.