MoonshotAI / MoonshotAI/kimi-code
docs(hooks): per-event stdin payload fields are undocumented (tool_name, tool_input, tool_call_id, tool_output, agent_name, error_type, reason, notification_type, ...)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 7.5k
- Forks
- 1.2k
- Avg merge
- 11h 53m
- Merged PRs (30d)
- 350
Description
Summary
The hooks guide (docs/en/customization/hooks.md) documents the base stdin payload a hook receives, but never documents the per-event additional fields. The doc itself promises them — and the doc's own example relies on one — yet the field names appear nowhere in the docs, only in the engine source. A hook author has to read packages/agent-core to discover the JSON keys for each event.
(Filed as a documentation issue; runtime fields like version/plan/model/platform are N/A. Suggested label: documentation.)
Where the docs fall short
docs/en/customization/hooks.md, "Event Data Format" (lines 57–69) shows only the base payload:
{
"hook_event_name": "PreToolUse",
"session_id": "session_abc",
"cwd": "/path/to/project"
}
and then states (line 69):
Specific events will also include additional fields (such as tool name and command content); see the event reference below. All field names use snake_case.
But the "Event Reference" table (lines ~92–114) only documents what the matcher matches per event — it never lists the JSON keys each event adds to the payload. So "see the event reference below" points at a table that doesn't contain the promised fields. The only place a concrete field surfaces is the worked example at line 137, which reads payload.tool_input?.command — a field that is otherwise undocumented.
Why it matters
I hit this building a cross-platform MCP/hook adapter that has to write hooks targeting many CLIs. Because the per-event keys aren't documented, the field names have to be reverse-engineered from the engine; an integrator can easily reach for the wrong key (e.g. assuming UserPromptSubmit's prompt is a plain string, or guessing tool_response instead of tool_output for PostToolUse) and get a silent no-op with no diagnostic. Documenting the schema makes hooks usable without reading agent-core.
The actual fields (verified against main)
All keys are emitted camelCase in source and snake_cased by toHookInputData/camelToSnake (packages/agent-core/src/session/hooks/engine.ts:176-184). Per-event keys, with their trigger sites:
| Event | Added stdin fields | Source |
|---|---|---|
PreToolUse, PermissionRequest |
tool_name, tool_input, tool_call_id |
permission/policies/pre-tool-call-hook.ts:15-17; permission/index.ts:139-144 |
PostToolUse |
tool_name, tool_input, tool_call_id, tool_output (truncated to 2000 chars) |
agent/turn/index.ts:735-739 |
PostToolUseFailure |
tool_name, tool_input, tool_call_id, error (an object: code/message/name/details/retryable) |
agent/turn/index.ts:735-738 |
PermissionResult |
tool_name, tool_input, tool_call_id, result |
permission/index.ts:170-219 |
UserPromptSubmit |
prompt — a ContentPart[] array (e.g. [{ "type": "text", "text": "..." }]), not a plain string |
agent/turn/index.ts:568-571 |
SubagentStart |
agent_name, prompt (preview-truncated) |
session/subagent-host.ts:381-386 |
SubagentStop |
agent_name, response (preview-truncated) |
session/subagent-host.ts:392-396 |
StopFailure |
error_type, error_message |
agent/turn/index.ts:484-486 |
Interrupt |
reason |
agent/turn/index.ts:524-525 |
SessionStart |
source ("startup" | "resume") |
session/index.ts:685-686 |
SessionEnd |
reason ("exit") |
session/index.ts (triggerSessionEnd("exit")) |
PreCompact |
trigger ("manual" | "auto"), token_count |
agent/compaction/full.ts:373-378 |
PostCompact |
trigger, estimated_token_count |
agent/compaction/full.ts:388-392 |
Notification |
notification_type, title, body, severity, source_kind, source_id, sink |
agent/background/index.ts:130-140 |
(The doc already correctly notes the snake_case convention, so only the per-event field list is missing.)
Two fields are especially easy to get wrong and worth calling out explicitly in the docs:
UserPromptSubmit.promptis aContentPart[]array, not a string.PostToolUseemitstool_output; the failure variantPostToolUseFailureemitserrorinstead (and notool_output).
Related
Issue #345 ("PreToolUse hooks: input mutation via updatedInput") is about the same hook output surface — a clearer payload reference would complement that discussion. PR #578 also touches this file (anchor-link fix only), so a small rebase awareness is worth noting if both land.
Proposed fix
Add a "Per-event payload fields" subsection (or a column on the existing Event Reference table) to docs/en/customization/hooks.md listing the keys above, and mirror it in docs/zh/customization/hooks.md. Docs-only, so no changeset/tests per CONTRIBUTING.
I'm happy to open the PR (title docs(hooks): document per-event stdin payload fields) if a maintainer confirms the table format you'd prefer (separate subsection vs. an extra "Payload fields" column on the existing table).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the Event Data Format and Event Reference sections in docs/en/customization/hooks.md, then compare the listed fields with packages/agent-core/src/session/hooks/engine.ts and the trigger sites named in the issue. Add a per-event payload field reference, including the prompt array and tool_output/error distinction, and mirror it in docs/zh/customization/hooks.md. Done means both guides document the verified snake_case fields; CONTRIBUTING indicates no tests or changeset are needed.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- documentation
- Issue type
- Documentation
- Difficulty
- 2/5
- Estimated time
- Half a day
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100