Hooks settings: show responsibility names instead of numbered rows
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.4k
- PR merge metrics
- PR metrics pending
Description
Problem / outcome
The Codex App Hooks settings page labels every handler as Hook 1, Hook 2, and so on. Users with several safety, lifecycle, and automation hooks cannot identify each hook's responsibility until they expand it and inspect the command or status message.
Hook definitions currently support statusMessage, but that value is shown only in the expanded details and while a hook runs. There is no supported per-hook display-name field.
Evidence and current behavior
- Codex App:
26.820.60940(build7119) - Bundled CLI:
codex-cli 0.150.0-alpha.8 - Standalone CLI also checked:
codex-cli 0.151.0 - Platform:
Darwin 25.6.0 arm64 arm, macOS26.6.2(25G83)
Schemas generated from both installed CLIs with:
codex app-server generate-json-schema --experimental --out /tmp/codex-schema
ConfiguredHookHandler and HookMetadata expose statusMessage, but do not expose name, title, label, or displayName. The generated protocol does expose displayName for other resource types, so this is specific to hooks.
The installed App renderer uses the localized fallback Hook {index} for each hook row. The row title does not consume statusMessage; that field is rendered only in the expanded details.
Reproduction or baseline
- Add two command hooks under the same event in
~/.codex/hooks.json. - Give both handlers distinct, responsibility-oriented
statusMessagevalues. - Trust the hooks and open Settings > Hooks.
- Expand the event.
Observed: collapsed rows are titled Hook 1 and Hook 2. Their responsibilities are invisible until each row is expanded.
Example:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "./dangerous-delete-guard.sh",
"statusMessage": "Check dangerous recursive deletion"
},
{
"type": "command",
"command": "./package-manager-boundary-guard.sh",
"statusMessage": "Check package-manager ownership boundary"
}
]
}
]
}
}
Expected behavior
Each collapsed hook row should expose a stable, responsibility-oriented label without requiring the user to inspect its command.
Either of these backward-compatible contracts would satisfy the outcome:
- Add an optional
displayNameto configured hook handlers andHookMetadata, and render it as the row title. - Render a non-empty
statusMessageas the row title, falling back toHook {index}only when no stronger label is available.
If displayName is introduced, statusMessage should remain the runtime-progress message rather than being overloaded.
Scope
- App-server configured-hook schema and generated bindings.
hooks/listmetadata propagation.- Codex App Hooks settings row title.
- Backward-compatible fallback for existing hook files.
Non-goals
- Changing hook execution, trust hashing, matcher semantics, ordering, or permissions.
- Inferring a label from arbitrary shell commands.
- Renaming plugin groups, skills, or subagents.
Acceptance criteria
- AC-1: Given a hook with an explicit supported responsibility label, when Hooks settings are opened, then the collapsed row displays that label instead of
Hook {index}. - AC-2: Given an existing hook without the new label, when Hooks settings are opened, then it remains valid and receives a documented fallback title.
- AC-3: Given two hooks under the same event, when both rows are displayed, then each row can show a distinct responsibility label without parsing the command.
- AC-4: Hook trust hashes, execution behavior, ordering, and
statusMessageruntime behavior remain unchanged. - AC-5: Generated TypeScript and JSON Schema bindings expose the same supported contract used by the App.
Verification plan
| Criterion | Verification | Expected |
|---|---|---|
| AC-1 | App UI test with a labeled hook | Responsibility label is visible while collapsed |
| AC-2 | App UI test with an unlabeled legacy hook | Hook loads and documented fallback is visible |
| AC-3 | App UI test with two differently labeled hooks in one event | Two distinct labels are visible |
| AC-4 | Existing hook trust and execution test suites | No hash, ordering, or execution regression |
| AC-5 | Generate experimental JSON Schema and TypeScript bindings | Supported label field is present and matches the App consumer |
Risks, dependencies, rollout
The lowest-risk rollout is additive: introduce an optional field and retain Hook {index} as the final fallback. Clients should continue tolerating unknown protocol fields during version skew.
Clarifications and assumptions
- This request is based on locally generated schemas from the listed installed versions and on the shipped App UI behavior.
- No public Codex documentation or existing open/closed issue/PR was found that defines a supported per-hook display-name field.
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 by generating the experimental schema with codex app-server generate-json-schema --experimental --out /tmp/codex-schema, then trace the hooks/list metadata and the Codex App Hooks settings row title. Confirm how configured handlers and HookMetadata are represented before choosing the additive label contract. Done means labeled rows are visible when collapsed, legacy hooks retain a documented fallback, and existing trust, execution, ordering, and runtime status behavior remain unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust, typescript
- Domain
- api, frontend
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100