@geminix/gxpm 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +148 -0
- package/CANON.md +53 -0
- package/CLAUDE.md +60 -0
- package/CONTEXT.md +49 -0
- package/DEBUG.md +59 -0
- package/ISSUE_CONTEXT.md +25 -0
- package/README.md +143 -0
- package/VERSION +1 -0
- package/agents/cleanup-auditor/cleanup-auditor.md +56 -0
- package/agents/grill-master.md +26 -0
- package/agents/implementer.md +32 -0
- package/agents/review-army/accessibility-reviewer.md +54 -0
- package/agents/review-army/code-quality-reviewer.md +54 -0
- package/agents/review-army/security-reviewer.md +56 -0
- package/agents/review-army/spec-compliance-reviewer.md +51 -0
- package/agents/review-army/test-reviewer.md +55 -0
- package/agents/reviewer.md +59 -0
- package/agents/ship-audit-army/docs-auditor.md +53 -0
- package/agents/ship-audit-army/performance-auditor.md +52 -0
- package/agents/ship-audit-army/security-auditor.md +52 -0
- package/agents/specifier.md +55 -0
- package/agents/triage-officer.md +27 -0
- package/bin/gxpm +17 -0
- package/bin/gxpm-browser +17 -0
- package/bin/gxpm-config +15 -0
- package/bin/gxpm-eval +13 -0
- package/bin/gxpm-global-discover +15 -0
- package/bin/gxpm-init +38 -0
- package/bin/gxpm-investigate +194 -0
- package/bin/gxpm-uninstall +15 -0
- package/bin/gxpm-update-check +165 -0
- package/commands/build.md +40 -0
- package/commands/help.md +53 -0
- package/commands/plan.md +34 -0
- package/commands/refine.md +46 -0
- package/commands/review.md +34 -0
- package/commands/ship.md +37 -0
- package/core/ac-check.ts +20 -0
- package/core/agent-runtime.ts +363 -0
- package/core/artifact-validator.ts +151 -0
- package/core/artifacts.ts +313 -0
- package/core/autopilot.ts +250 -0
- package/core/capabilities.ts +779 -0
- package/core/checkpoint.ts +370 -0
- package/core/cleanup.ts +32 -0
- package/core/command-probe.ts +82 -0
- package/core/config.ts +533 -0
- package/core/contracts/behavior-spec.schema.ts +38 -0
- package/core/contracts/converter.ts +61 -0
- package/core/contracts/host.ts +43 -0
- package/core/converters/converter.ts +93 -0
- package/core/converters/index.ts +8 -0
- package/core/converters/managed-artifact.ts +119 -0
- package/core/converters/parser.ts +159 -0
- package/core/converters/template-renderer.ts +35 -0
- package/core/converters/writer.ts +61 -0
- package/core/dag-executor.ts +426 -0
- package/core/dag-loader.ts +292 -0
- package/core/dag-schemas.ts +150 -0
- package/core/dispatch.ts +125 -0
- package/core/evidence.ts +148 -0
- package/core/gate.ts +269 -0
- package/core/hook-engine.ts +566 -0
- package/core/host-probe.ts +64 -0
- package/core/implement.ts +16 -0
- package/core/isolation-errors.ts +174 -0
- package/core/isolation-resolver.ts +921 -0
- package/core/issue-context.ts +381 -0
- package/core/issue-readiness.ts +457 -0
- package/core/issue-sync.ts +427 -0
- package/core/issues.ts +132 -0
- package/core/land.ts +108 -0
- package/core/orchestrator.ts +54 -0
- package/core/phase-artifact.ts +32 -0
- package/core/phase-gates.ts +130 -0
- package/core/phase-rewind.ts +94 -0
- package/core/plan-lint.ts +61 -0
- package/core/plan.ts +77 -0
- package/core/port-allocation.ts +50 -0
- package/core/pr-check.ts +15 -0
- package/core/preset-system/preset-resolver.ts +221 -0
- package/core/project-init-status.ts +127 -0
- package/core/qa.ts +15 -0
- package/core/resilience.ts +165 -0
- package/core/runs.ts +288 -0
- package/core/safe-path.test.ts +80 -0
- package/core/safe-path.ts +60 -0
- package/core/sdd-gate.test.ts +98 -0
- package/core/sdd-gate.ts +134 -0
- package/core/self-review.ts +62 -0
- package/core/session.ts +70 -0
- package/core/ship.ts +86 -0
- package/core/specify.ts +173 -0
- package/core/state.ts +1002 -0
- package/core/template-engine.ts +152 -0
- package/core/template-resolver.test.ts +70 -0
- package/core/template-resolver.ts +156 -0
- package/core/triage.ts +26 -0
- package/core/verify.ts +15 -0
- package/core/wiki-native.ts +2423 -0
- package/core/wiki.ts +27 -0
- package/core/workflow-event-emitter.ts +163 -0
- package/core/workflows/engine.ts +273 -0
- package/core/workflows/expressions.ts +76 -0
- package/core/workflows/index.ts +38 -0
- package/core/workflows/steps/command.ts +43 -0
- package/core/workflows/steps/gate.ts +47 -0
- package/core/workflows/steps/gxpm.ts +44 -0
- package/core/workflows/steps/linear.ts +31 -0
- package/core/workflows/steps/shell.ts +65 -0
- package/core/workflows/types.ts +62 -0
- package/core/workspace-runtime.ts +227 -0
- package/core/worktree-init-steps.ts +647 -0
- package/core/worktree-init.ts +330 -0
- package/core/worktree-owner.ts +143 -0
- package/docs/GXPM_VERIFY.md +98 -0
- package/docs/INSTALL_FOR_AGENTS.md +113 -0
- package/docs/README.md +57 -0
- package/docs/adr/adr-005-multi-platform-skill-converter.md +72 -0
- package/docs/agents/domain.md +30 -0
- package/docs/agents/issue-tracker.md +30 -0
- package/docs/agents/triage-labels.md +32 -0
- package/docs/architecture/gxpm-architecture-diagram.md +265 -0
- package/docs/architecture/gxpm-current-architecture.md +175 -0
- package/docs/architecture/gxpm-current-flow.md +278 -0
- package/docs/architecture/gxpm-replacement-architecture.md +211 -0
- package/docs/architecture/gxpm-target-architecture.md +449 -0
- package/docs/architecture/gxpm-v0-contract.md +311 -0
- package/docs/architecture/layered-workflow-boundaries.md +193 -0
- package/docs/architecture/preset-system.md +126 -0
- package/docs/architecture/scaffold-northstar.md +23 -0
- package/docs/brainstorms/2026-05-14-bdd-then-tdd-design.md +320 -0
- package/docs/brainstorms/README.md +22 -0
- package/docs/brainstorms/docs-knowledge-system-requirements.md +29 -0
- package/docs/governance/beta-skill-promotion.md +39 -0
- package/docs/governance/development-contract.md +144 -0
- package/docs/governance/gherkin-style.md +90 -0
- package/docs/governance/host-adapter.md +56 -0
- package/docs/governance/skill-authoring.md +87 -0
- package/docs/governance/skill-testing.md +356 -0
- package/docs/governance/template-authoring.md +53 -0
- package/docs/migrations/v0.2.md +51 -0
- package/docs/plans/README.md +23 -0
- package/docs/plans/bdd-then-tdd-plan.md +1767 -0
- package/docs/plans/docs-knowledge-system-plan.md +31 -0
- package/docs/plans/spec-kit-sdd-adoption-plan.md +305 -0
- package/docs/research/agents-md-best-practices.md +207 -0
- package/docs/research/archon-study.md +351 -0
- package/docs/research/claude-hooks-study.md +440 -0
- package/docs/research/codex-hooks-study.md +624 -0
- package/docs/research/everything-claude-code-study.md +252 -0
- package/docs/research/from-skills-to-layered-workflow.md +322 -0
- package/docs/research/gsd-study.md +69 -0
- package/docs/research/kimi-hooks-study.md +274 -0
- package/docs/research/mattpocock-skills-comparison.md +429 -0
- package/docs/research/mattpocock-skills-study.md +275 -0
- package/docs/research/oh-my-codex-study.md +279 -0
- package/docs/research/perplexity-agent-skills-design.md +168 -0
- package/docs/research/pmc-gstack-skill-study.md +122 -0
- package/docs/research/spec-kit-study.md +224 -0
- package/docs/research/superpowers-study.md +209 -0
- package/docs/roadmap/initial-roadmap.md +53 -0
- package/docs/solutions/README.md +45 -0
- package/docs/solutions/artifact-nesting-recovery.md +58 -0
- package/docs/solutions/session-context-restore-practice.md +67 -0
- package/docs/solutions/workflow/version-drift-recovery.md +49 -0
- package/docs/solutions/worktree-gate-recovery.md +62 -0
- package/docs/specs/README.md +28 -0
- package/docs/specs/claude.md +45 -0
- package/docs/specs/codex.md +44 -0
- package/docs/specs/cursor.md +44 -0
- package/hosts/adapters/claude.ts +29 -0
- package/hosts/adapters/codex.ts +27 -0
- package/hosts/adapters/cursor.ts +27 -0
- package/hosts/adapters/kimi.ts +27 -0
- package/hosts/claude.ts +23 -0
- package/hosts/codex.ts +26 -0
- package/hosts/cursor.ts +19 -0
- package/hosts/index.ts +33 -0
- package/hosts/registry.test.ts +52 -0
- package/hosts/registry.ts +57 -0
- package/hosts/schema.ts +58 -0
- package/package.json +52 -0
- package/scripts/browser.ts +185 -0
- package/scripts/cleanup.ts +142 -0
- package/scripts/commands/artifact.ts +115 -0
- package/scripts/commands/autopilot.ts +143 -0
- package/scripts/commands/capability.ts +57 -0
- package/scripts/commands/config.ts +69 -0
- package/scripts/commands/dag.ts +126 -0
- package/scripts/commands/feedback.ts +123 -0
- package/scripts/commands/gate.ts +291 -0
- package/scripts/commands/helpers.ts +126 -0
- package/scripts/commands/hook.ts +66 -0
- package/scripts/commands/init.ts +515 -0
- package/scripts/commands/issue.ts +825 -0
- package/scripts/commands/phase.ts +61 -0
- package/scripts/commands/preset.ts +159 -0
- package/scripts/commands/runtime.ts +199 -0
- package/scripts/commands/specify.ts +71 -0
- package/scripts/commands/upgrade.ts +243 -0
- package/scripts/commands/verify.ts +183 -0
- package/scripts/commands/wiki.ts +242 -0
- package/scripts/commands/workflow.ts +131 -0
- package/scripts/dev-skill.ts +55 -0
- package/scripts/discover-skills.ts +116 -0
- package/scripts/doctor.ts +410 -0
- package/scripts/dogfood-check.ts +125 -0
- package/scripts/eval-functional.ts +218 -0
- package/scripts/eval.ts +246 -0
- package/scripts/gen-skill-docs.ts +201 -0
- package/scripts/global-discover.ts +217 -0
- package/scripts/governance-check.ts +75 -0
- package/scripts/gxpm-check.ts +12 -0
- package/scripts/gxpm.ts +216 -0
- package/scripts/host-config.ts +62 -0
- package/scripts/install-claude-hooks.ts +138 -0
- package/scripts/install-codex-hooks.ts +271 -0
- package/scripts/install-hooks.ts +128 -0
- package/scripts/install-kimi-hooks.ts +92 -0
- package/scripts/install-skill.ts +184 -0
- package/scripts/phase-artifact-commands.ts +100 -0
- package/scripts/post-land-sync.ts +46 -0
- package/scripts/scaffold-check.ts +85 -0
- package/scripts/skill-naming-check.ts +78 -0
- package/scripts/skill-structure-check.ts +157 -0
- package/scripts/skills-lock-check.ts +60 -0
- package/scripts/sync-markdown-artifacts.ts +172 -0
- package/scripts/uninstall.ts +162 -0
- package/scripts/version.ts +47 -0
- package/scripts/wait-pr-ready.ts +407 -0
- package/skills/gxpm/SKILL.md +485 -0
- package/skills/gxpm/SKILL.md.tmpl +422 -0
- package/skills/gxpm/references/CANON.md +53 -0
- package/skills/gxpm/references/key-rules.md +130 -0
- package/skills/gxpm-architecture/SKILL.md +106 -0
- package/skills/gxpm-architecture/references/DEEPENING.md +37 -0
- package/skills/gxpm-architecture/references/INTERFACE-DESIGN.md +44 -0
- package/skills/gxpm-autopilot/SKILL.md +116 -0
- package/skills/gxpm-autopilot/SKILL.md.tmpl +107 -0
- package/skills/gxpm-browser/SKILL.md +105 -0
- package/skills/gxpm-browser/SKILL.md.tmpl +41 -0
- package/skills/gxpm-browser/references/commands.md +43 -0
- package/skills/gxpm-browser/references/evidence-path.md +20 -0
- package/skills/gxpm-build/SKILL.md +78 -0
- package/skills/gxpm-cleanup/SKILL.md +76 -0
- package/skills/gxpm-debug-issue/SKILL.md +39 -0
- package/skills/gxpm-diagnose/SKILL.md +220 -0
- package/skills/gxpm-diagnose/SKILL.md.tmpl +31 -0
- package/skills/gxpm-diagnose/references/feedback-loop.md +34 -0
- package/skills/gxpm-diagnose/references/feedback-loops.md +43 -0
- package/skills/gxpm-diagnose/references/phases.md +60 -0
- package/skills/gxpm-eval/SKILL.md +78 -0
- package/skills/gxpm-explore-codebase/SKILL.md +36 -0
- package/skills/gxpm-explore-codebase/scripts/summarize-communities.ts +51 -0
- package/skills/gxpm-feedback/SKILL.md +122 -0
- package/skills/gxpm-grill/SKILL.md +159 -0
- package/skills/gxpm-grill/SKILL.md.tmpl +77 -0
- package/skills/gxpm-grill/references/documentation-templates.md +56 -0
- package/skills/gxpm-grill/references/process.md +25 -0
- package/skills/gxpm-handoff/SKILL.md +112 -0
- package/skills/gxpm-hygiene/SKILL.md +69 -0
- package/skills/gxpm-implementer/SKILL.md +142 -0
- package/skills/gxpm-implementer/SKILL.md.tmpl +141 -0
- package/skills/gxpm-linear/SKILL.md +282 -0
- package/skills/gxpm-linear/SKILL.md.tmpl +86 -0
- package/skills/gxpm-linear/references/commands.md +75 -0
- package/skills/gxpm-linear/references/workflows.md +120 -0
- package/skills/gxpm-planning/SKILL.md +134 -0
- package/skills/gxpm-prototype/SKILL.md +64 -0
- package/skills/gxpm-refactor-safely/SKILL.md +62 -0
- package/skills/gxpm-review-army/SKILL.md +117 -0
- package/skills/gxpm-review-changes/SKILL.md +36 -0
- package/skills/gxpm-setup/SKILL.md +101 -0
- package/skills/gxpm-specifier/SKILL.md +135 -0
- package/skills/gxpm-tdd/SKILL.md +187 -0
- package/skills/gxpm-tdd/references/interface-design.md +23 -0
- package/skills/gxpm-tdd/references/mocking.md +27 -0
- package/skills/gxpm-tdd/references/red-green-refactor.md +61 -0
- package/skills/gxpm-tdd/references/troubleshooting.md +28 -0
- package/skills/gxpm-tdd/references/workflow.md +50 -0
- package/skills/gxpm-tdd/testing-anti-patterns.tmpl +304 -0
- package/skills/gxpm-triage/SKILL.md +160 -0
- package/skills/gxpm-verify/SKILL.md +107 -0
- package/skills/gxpm-write-skill/SKILL.md +131 -0
- package/skills/gxpm-zoom-out/SKILL.md +69 -0
- package/skills/maintain-hygiene-skills-lock/SKILL.md +54 -0
- package/skills/maintain-hygiene-skills-lock/SKILL.md.tmpl +53 -0
- package/templates/constitution-template.md +63 -0
- package/templates/hooks/gxpm-commit-msg +16 -0
- package/templates/hooks/gxpm-post-checkout +19 -0
- package/templates/hooks/gxpm-post-commit +7 -0
- package/templates/hooks/gxpm-post-merge +29 -0
- package/templates/hooks/gxpm-pre-commit +39 -0
- package/templates/hooks/gxpm-pre-push +33 -0
- package/templates/plan-template.md.tmpl +46 -0
- package/templates/spec-template.md.tmpl +63 -0
- package/templates/specify-stub.tmpl +22 -0
- package/templates/tasks-template.md.tmpl +32 -0
|
@@ -0,0 +1,624 @@
|
|
|
1
|
+
# Codex CLI Hooks 机制研究
|
|
2
|
+
|
|
3
|
+
> 研究日期:2026-05-04
|
|
4
|
+
> 文档来源:https://developers.openai.com/codex/hooks(官方 Hooks 文档)
|
|
5
|
+
> 版本:Codex CLI v0.128.0(2026-04-24)
|
|
6
|
+
> 状态:Stable(需 feature flag `codex_hooks = true`)
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 1. 配置格式与位置
|
|
11
|
+
|
|
12
|
+
Codex 的 hooks 配置有两种形式:
|
|
13
|
+
1. **独立 `hooks.json` 文件**(推荐)
|
|
14
|
+
2. **`config.toml` 内联 `[hooks]` 表**
|
|
15
|
+
|
|
16
|
+
### 配置位置(按优先级)
|
|
17
|
+
|
|
18
|
+
| 位置 | 作用域 | 可提交到仓库 |
|
|
19
|
+
|------|--------|-------------|
|
|
20
|
+
| `~/.codex/hooks.json` | 全局所有项目 | ❌ |
|
|
21
|
+
| `~/.codex/config.toml` | 全局所有项目 | ❌ |
|
|
22
|
+
| `<repo>/.codex/hooks.json` | 单个项目 | ✅(需项目 `.codex/` 被信任) |
|
|
23
|
+
| `<repo>/.codex/config.toml` | 单个项目 | ✅(需项目 `.codex/` 被信任) |
|
|
24
|
+
|
|
25
|
+
**⚠️ 重要**:如果同一层同时存在 `hooks.json` 和内联 `[hooks]`,Codex 会合并两者并在启动时发出警告。建议每层只使用一种表示。
|
|
26
|
+
|
|
27
|
+
### Feature Flag
|
|
28
|
+
|
|
29
|
+
Hooks 默认关闭,必须在 `config.toml` 中显式启用:
|
|
30
|
+
|
|
31
|
+
```toml
|
|
32
|
+
[features]
|
|
33
|
+
codex_hooks = true
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Enterprise 管理员的 managed requirements 也可内联定义 hooks。
|
|
37
|
+
|
|
38
|
+
### JSON 格式(hooks.json)
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"hooks": {
|
|
43
|
+
"SessionStart": [
|
|
44
|
+
{
|
|
45
|
+
"matcher": "startup|resume",
|
|
46
|
+
"hooks": [
|
|
47
|
+
{
|
|
48
|
+
"type": "command",
|
|
49
|
+
"command": "python3 ~/.codex/hooks/session_start.py",
|
|
50
|
+
"statusMessage": "Loading session notes"
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
}
|
|
54
|
+
],
|
|
55
|
+
"PreToolUse": [
|
|
56
|
+
{
|
|
57
|
+
"matcher": "Bash",
|
|
58
|
+
"hooks": [
|
|
59
|
+
{
|
|
60
|
+
"type": "command",
|
|
61
|
+
"command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/pre_tool_use_policy.py\"",
|
|
62
|
+
"statusMessage": "Checking Bash command",
|
|
63
|
+
"timeout": 30
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
}
|
|
67
|
+
],
|
|
68
|
+
"PostToolUse": [
|
|
69
|
+
{
|
|
70
|
+
"matcher": "Bash",
|
|
71
|
+
"hooks": [
|
|
72
|
+
{
|
|
73
|
+
"type": "command",
|
|
74
|
+
"command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/post_tool_use_review.py\"",
|
|
75
|
+
"statusMessage": "Reviewing Bash output",
|
|
76
|
+
"timeout": 30
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
],
|
|
81
|
+
"UserPromptSubmit": [
|
|
82
|
+
{
|
|
83
|
+
"hooks": [
|
|
84
|
+
{
|
|
85
|
+
"type": "command",
|
|
86
|
+
"command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/user_prompt_submit.py\""
|
|
87
|
+
}
|
|
88
|
+
]
|
|
89
|
+
}
|
|
90
|
+
],
|
|
91
|
+
"Stop": [
|
|
92
|
+
{
|
|
93
|
+
"hooks": [
|
|
94
|
+
{
|
|
95
|
+
"type": "command",
|
|
96
|
+
"command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/stop_continue.py\"",
|
|
97
|
+
"timeout": 30
|
|
98
|
+
}
|
|
99
|
+
]
|
|
100
|
+
}
|
|
101
|
+
]
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### TOML 内联格式(config.toml)
|
|
107
|
+
|
|
108
|
+
```toml
|
|
109
|
+
[features]
|
|
110
|
+
codex_hooks = true
|
|
111
|
+
|
|
112
|
+
[[hooks.PreToolUse]]
|
|
113
|
+
matcher = "^Bash$"
|
|
114
|
+
|
|
115
|
+
[[hooks.PreToolUse.hooks]]
|
|
116
|
+
type = "command"
|
|
117
|
+
command = '/usr/bin/python3 "$(git rev-parse --show-toplevel)/.codex/hooks/pre_tool_use_policy.py"'
|
|
118
|
+
timeout = 30
|
|
119
|
+
statusMessage = "Checking Bash command"
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Enterprise Managed Hooks
|
|
123
|
+
|
|
124
|
+
```toml
|
|
125
|
+
[features]
|
|
126
|
+
codex_hooks = true
|
|
127
|
+
|
|
128
|
+
[hooks]
|
|
129
|
+
managed_dir = "/enterprise/hooks"
|
|
130
|
+
windows_managed_dir = 'C:\enterprise\hooks'
|
|
131
|
+
|
|
132
|
+
[[hooks.PreToolUse]]
|
|
133
|
+
matcher = "^Bash$"
|
|
134
|
+
|
|
135
|
+
[[hooks.PreToolUse.hooks]]
|
|
136
|
+
type = "command"
|
|
137
|
+
command = "python3 /enterprise/hooks/pre_tool_use_policy.py"
|
|
138
|
+
timeout = 30
|
|
139
|
+
statusMessage = "Checking managed Bash command"
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
- `managed_dir`:macOS/Linux 管理脚本目录
|
|
143
|
+
- `windows_managed_dir`:Windows 管理脚本目录
|
|
144
|
+
- 脚本不由 Codex 分发,需企业通过 MDM 等工具单独安装
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## 2. 事件类型(6 种)
|
|
149
|
+
|
|
150
|
+
Codex 当前支持 **6 个生命周期事件**,比 Claude Code 少但覆盖了核心场景:
|
|
151
|
+
|
|
152
|
+
| 事件 | 触发时机 | Matcher 支持 | 可 Block | 引入版本 |
|
|
153
|
+
|------|---------|-------------|---------|---------|
|
|
154
|
+
| `SessionStart` | 会话开始或恢复 | ✅ `source` 过滤 | ❌ | v0.114.0 |
|
|
155
|
+
| `PreToolUse` | 工具调用执行前 | ✅ tool name | ✅ | v0.114.0+ |
|
|
156
|
+
| `PermissionRequest` | 需要用户审批时 | ✅ tool name | ✅ | v0.114.0+ |
|
|
157
|
+
| `PostToolUse` | 工具调用完成后 | ✅ tool name | ⚠️(不撤销) | v0.114.0+ |
|
|
158
|
+
| `UserPromptSubmit` | 用户提交 prompt 前 | ❌ | ✅ | v0.116.0 |
|
|
159
|
+
| `Stop` | 一轮响应完成时 | ❌ | ✅(继续工作) | v0.114.0 |
|
|
160
|
+
|
|
161
|
+
**⚠️ 重要限制**:`PreToolUse` / `PostToolUse` 目前仅拦截 **简单 shell 调用** 和 `apply_patch`。`unified_exec` 机制下的 richer streaming stdin/stdout 拦截尚不完整,`WebSearch` 等非 shell 工具也不被拦截。
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## 3. Hook Handler 类型
|
|
166
|
+
|
|
167
|
+
Codex 目前仅支持 **`command` 类型** 的 hook handler:
|
|
168
|
+
|
|
169
|
+
| 字段 | 必需 | 默认值 | 说明 |
|
|
170
|
+
|------|------|--------|------|
|
|
171
|
+
| `type` | ✅ | — | 当前仅 `"command"` |
|
|
172
|
+
| `command` | ✅ | — | 执行的 shell 命令 |
|
|
173
|
+
| `timeout` | ❌ | `600` | 超时秒数 |
|
|
174
|
+
| `statusMessage` | ❌ | — | 运行时的状态消息 |
|
|
175
|
+
|
|
176
|
+
Commands 以会话 `cwd` 作为工作目录运行。对于仓库级 hooks,建议通过 `git rev-parse --show-toplevel` 解析路径,避免从子目录启动时相对路径失效。
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## 4. 输入/输出格式
|
|
181
|
+
|
|
182
|
+
### 公共输入字段
|
|
183
|
+
|
|
184
|
+
所有事件的 command hook 都通过 **stdin** 接收一个 JSON 对象:
|
|
185
|
+
|
|
186
|
+
| 字段 | 类型 | 说明 |
|
|
187
|
+
|------|------|------|
|
|
188
|
+
| `session_id` | `string` | 当前会话或线程 ID |
|
|
189
|
+
| `transcript_path` | `string \| null` | 会话转录文件路径 |
|
|
190
|
+
| `cwd` | `string` | 会话工作目录 |
|
|
191
|
+
| `hook_event_name` | `string` | 当前 hook 事件名 |
|
|
192
|
+
| `model` | `string` | 当前使用的模型 slug |
|
|
193
|
+
|
|
194
|
+
Turn-scoped 事件(`PreToolUse`, `PermissionRequest`, `PostToolUse`, `UserPromptSubmit`, `Stop`)额外包含:
|
|
195
|
+
|
|
196
|
+
| 字段 | 类型 | 说明 |
|
|
197
|
+
|------|------|------|
|
|
198
|
+
| `turn_id` | `string` | Codex 特有的当前 turn ID |
|
|
199
|
+
|
|
200
|
+
### 公共输出字段
|
|
201
|
+
|
|
202
|
+
`SessionStart`, `UserPromptSubmit`, `Stop` 共享以下 JSON 输出:
|
|
203
|
+
|
|
204
|
+
```json
|
|
205
|
+
{
|
|
206
|
+
"continue": true,
|
|
207
|
+
"stopReason": "optional",
|
|
208
|
+
"systemMessage": "optional",
|
|
209
|
+
"suppressOutput": false
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
| 字段 | 效果 |
|
|
214
|
+
|------|------|
|
|
215
|
+
| `continue` | `false` 标记该 hook 运行为 stopped |
|
|
216
|
+
| `stopReason` | 记录停止原因 |
|
|
217
|
+
| `systemMessage` | 在 UI 或事件流中显示为警告 |
|
|
218
|
+
| `suppressOutput` | 已解析但尚未实现 |
|
|
219
|
+
|
|
220
|
+
退出码语义:
|
|
221
|
+
- **Exit 0 + 无输出**:成功,Codex 继续
|
|
222
|
+
- **Exit 0 + 纯文本 stdout**:`SessionStart` 时作为额外开发者上下文;其他事件忽略纯文本
|
|
223
|
+
- **Exit 0 + JSON stdout**:解析为结构化输出
|
|
224
|
+
- **Exit 2 + stderr**:阻塞行为,stderr 文本作为反馈
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## 5. 各事件的详细 Schema
|
|
229
|
+
|
|
230
|
+
### SessionStart
|
|
231
|
+
|
|
232
|
+
**Matcher**:应用于 `source` 字段。
|
|
233
|
+
|
|
234
|
+
**额外输入字段**:
|
|
235
|
+
|
|
236
|
+
| 字段 | 类型 | 说明 |
|
|
237
|
+
|------|------|------|
|
|
238
|
+
| `source` | `string` | 启动方式:`startup` 或 `resume` |
|
|
239
|
+
|
|
240
|
+
**输出**:
|
|
241
|
+
|
|
242
|
+
- **纯文本 stdout**:作为额外开发者上下文注入
|
|
243
|
+
- **JSON stdout**:支持公共输出字段 + `hookSpecificOutput.additionalContext`
|
|
244
|
+
|
|
245
|
+
```json
|
|
246
|
+
{
|
|
247
|
+
"hookSpecificOutput": {
|
|
248
|
+
"hookEventName": "SessionStart",
|
|
249
|
+
"additionalContext": "Load the workspace conventions before editing."
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### PreToolUse
|
|
255
|
+
|
|
256
|
+
**Matcher**:应用于 `tool_name` 和 matcher 别名。`apply_patch` 可用 `Edit` 或 `Write` 匹配。
|
|
257
|
+
|
|
258
|
+
**额外输入字段**:
|
|
259
|
+
|
|
260
|
+
| 字段 | 类型 | 说明 |
|
|
261
|
+
|------|------|------|
|
|
262
|
+
| `turn_id` | `string` | Codex turn ID |
|
|
263
|
+
| `tool_name` | `string` | 规范工具名:`Bash`、`apply_patch`、MCP 名如 `mcp__fs__read` |
|
|
264
|
+
| `tool_use_id` | `string` | 本次调用的工具调用 ID |
|
|
265
|
+
| `tool_input` | `JSON` | 工具参数。`Bash` / `apply_patch` 用 `tool_input.command` |
|
|
266
|
+
|
|
267
|
+
**输出**:
|
|
268
|
+
|
|
269
|
+
- 纯文本 stdout **被忽略**
|
|
270
|
+
- JSON stdout 支持 `systemMessage` 和以下 hook-specific 形状:
|
|
271
|
+
|
|
272
|
+
```json
|
|
273
|
+
{
|
|
274
|
+
"hookSpecificOutput": {
|
|
275
|
+
"hookEventName": "PreToolUse",
|
|
276
|
+
"permissionDecision": "deny",
|
|
277
|
+
"permissionDecisionReason": "Destructive command blocked by hook."
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Codex 也接受旧版 block 形状:
|
|
283
|
+
|
|
284
|
+
```json
|
|
285
|
+
{
|
|
286
|
+
"decision": "block",
|
|
287
|
+
"reason": "Destructive command blocked by hook."
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
也可用 **exit 2 + stderr** 达到同样效果。
|
|
292
|
+
|
|
293
|
+
**⚠️ 已解析但尚不支持**:`permissionDecision: "allow"` / `"ask"`、旧版 `decision: "approve"`、`updatedInput`、`additionalContext`、`continue: false`、`stopReason`、`suppressOutput`。这些字段目前 fail open。
|
|
294
|
+
|
|
295
|
+
### PermissionRequest
|
|
296
|
+
|
|
297
|
+
**Matcher**:应用于 `tool_name` 和别名。支持 `Bash`、`apply_patch`、MCP 工具名。
|
|
298
|
+
|
|
299
|
+
**额外输入字段**:
|
|
300
|
+
|
|
301
|
+
| 字段 | 类型 | 说明 |
|
|
302
|
+
|------|------|------|
|
|
303
|
+
| `turn_id` | `string` | Codex turn ID |
|
|
304
|
+
| `tool_name` | `string` | 规范工具名 |
|
|
305
|
+
| `tool_input` | `JSON` | 工具参数 |
|
|
306
|
+
| `tool_input.description` | `string \| null` | 人工可读的审批原因 |
|
|
307
|
+
|
|
308
|
+
**输出**:
|
|
309
|
+
|
|
310
|
+
- 纯文本 stdout **被忽略**
|
|
311
|
+
- 批准:
|
|
312
|
+
|
|
313
|
+
```json
|
|
314
|
+
{
|
|
315
|
+
"hookSpecificOutput": {
|
|
316
|
+
"hookEventName": "PermissionRequest",
|
|
317
|
+
"decision": {
|
|
318
|
+
"behavior": "allow"
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
- 拒绝:
|
|
325
|
+
|
|
326
|
+
```json
|
|
327
|
+
{
|
|
328
|
+
"hookSpecificOutput": {
|
|
329
|
+
"hookEventName": "PermissionRequest",
|
|
330
|
+
"decision": {
|
|
331
|
+
"behavior": "deny",
|
|
332
|
+
"message": "Blocked by repository policy."
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
**多 hook 决策规则**:任何 `deny` 获胜;否则 `allow` 跳过审批提示;无决策则走正常审批流。
|
|
339
|
+
|
|
340
|
+
**⚠️ 不要返回**:`updatedInput`、`updatedPermissions`、`interrupt` — 这些字段目前 fail closed。
|
|
341
|
+
|
|
342
|
+
### PostToolUse
|
|
343
|
+
|
|
344
|
+
**Matcher**:应用于 `tool_name` 和别名。
|
|
345
|
+
|
|
346
|
+
**额外输入字段**:
|
|
347
|
+
|
|
348
|
+
| 字段 | 类型 | 说明 |
|
|
349
|
+
|------|------|------|
|
|
350
|
+
| `turn_id` | `string` | Codex turn ID |
|
|
351
|
+
| `tool_name` | `string` | 规范工具名 |
|
|
352
|
+
| `tool_use_id` | `string` | 工具调用 ID |
|
|
353
|
+
| `tool_input` | `JSON` | 工具参数 |
|
|
354
|
+
| `tool_response` | `JSON` | 工具输出。MCP 工具为 MCP 调用结果 |
|
|
355
|
+
|
|
356
|
+
**输出**:
|
|
357
|
+
|
|
358
|
+
- 纯文本 stdout **被忽略**
|
|
359
|
+
- JSON 支持 `systemMessage` 和:
|
|
360
|
+
|
|
361
|
+
```json
|
|
362
|
+
{
|
|
363
|
+
"decision": "block",
|
|
364
|
+
"reason": "The Bash output needs review before continuing.",
|
|
365
|
+
"hookSpecificOutput": {
|
|
366
|
+
"hookEventName": "PostToolUse",
|
|
367
|
+
"additionalContext": "The command updated generated files."
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
**⚠️ 重要**:`decision: "block"` **不会撤销已执行的 Bash 命令**。Codex 记录反馈,用该反馈替换工具结果,然后从 hook 提供的消息继续模型推理。
|
|
373
|
+
|
|
374
|
+
要停止原始工具结果的正常处理,返回 `continue: false`。Codex 将用反馈文本替换工具结果并继续。
|
|
375
|
+
|
|
376
|
+
也可用 **exit 2 + stderr**。
|
|
377
|
+
|
|
378
|
+
**已解析但尚不支持**:`updatedMCPToolOutput`、`suppressOutput`。
|
|
379
|
+
|
|
380
|
+
### UserPromptSubmit
|
|
381
|
+
|
|
382
|
+
**Matcher**:当前 **不使用**,任何配置的 matcher 都被忽略。
|
|
383
|
+
|
|
384
|
+
**额外输入字段**:
|
|
385
|
+
|
|
386
|
+
| 字段 | 类型 | 说明 |
|
|
387
|
+
|------|------|------|
|
|
388
|
+
| `turn_id` | `string` | Codex turn ID |
|
|
389
|
+
| `prompt` | `string` | 即将发送的用户 prompt |
|
|
390
|
+
|
|
391
|
+
**输出**:
|
|
392
|
+
|
|
393
|
+
- 纯文本 stdout:作为额外开发者上下文注入
|
|
394
|
+
- JSON 支持公共输出字段 + `hookSpecificOutput.additionalContext`
|
|
395
|
+
|
|
396
|
+
```json
|
|
397
|
+
{
|
|
398
|
+
"hookSpecificOutput": {
|
|
399
|
+
"hookEventName": "UserPromptSubmit",
|
|
400
|
+
"additionalContext": "Ask for a clearer reproduction before editing files."
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
阻止 prompt:
|
|
406
|
+
|
|
407
|
+
```json
|
|
408
|
+
{
|
|
409
|
+
"decision": "block",
|
|
410
|
+
"reason": "Ask for confirmation before doing that."
|
|
411
|
+
}
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
也可用 **exit 2 + stderr**。
|
|
415
|
+
|
|
416
|
+
### Stop
|
|
417
|
+
|
|
418
|
+
**Matcher**:当前 **不使用**。
|
|
419
|
+
|
|
420
|
+
**额外输入字段**:
|
|
421
|
+
|
|
422
|
+
| 字段 | 类型 | 说明 |
|
|
423
|
+
|------|------|------|
|
|
424
|
+
| `turn_id` | `string` | Codex turn ID |
|
|
425
|
+
| `stop_hook_active` | `boolean` | 该 turn 是否已被 `Stop` 继续过 |
|
|
426
|
+
| `last_assistant_message` | `string \| null` | 最新的 assistant 消息文本 |
|
|
427
|
+
|
|
428
|
+
**输出**:
|
|
429
|
+
|
|
430
|
+
- **纯文本 stdout 无效**(此事件要求 JSON 输出)
|
|
431
|
+
- 让 Codex 继续工作:
|
|
432
|
+
|
|
433
|
+
```json
|
|
434
|
+
{
|
|
435
|
+
"decision": "block",
|
|
436
|
+
"reason": "Run one more pass over the failing tests."
|
|
437
|
+
}
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
**⚠️ 语义反转**:`decision: "block"` 在这里**不拒绝 turn**,而是告诉 Codex **继续**,并用 `reason` 作为新的 continuation prompt 文本。
|
|
441
|
+
|
|
442
|
+
也可用 **exit 2 + stderr**。
|
|
443
|
+
|
|
444
|
+
如果任何匹配的 `Stop` hook 返回 `continue: false`,该决策优先于其他 continuation 决策。
|
|
445
|
+
|
|
446
|
+
---
|
|
447
|
+
|
|
448
|
+
## 6. Matcher 模式
|
|
449
|
+
|
|
450
|
+
Codex 的 `matcher` 是 **正则表达式字符串**:
|
|
451
|
+
|
|
452
|
+
| Matcher 值 | 效果 |
|
|
453
|
+
|-----------|------|
|
|
454
|
+
| `"*"`, `""`, 或省略 | 匹配所有 |
|
|
455
|
+
| 其他 | 作为正则表达式匹配 |
|
|
456
|
+
|
|
457
|
+
### 各事件的 Matcher 支持
|
|
458
|
+
|
|
459
|
+
| 事件 | Matcher 过滤目标 | 示例 |
|
|
460
|
+
|------|-----------------|------|
|
|
461
|
+
| `PreToolUse` | tool name | `Bash`, `^apply_patch$`, `Edit\|Write`, `mcp__filesystem__read_file` |
|
|
462
|
+
| `PermissionRequest` | tool name | `Bash`, `apply_patch`, `mcp__.*` |
|
|
463
|
+
| `PostToolUse` | tool name | `Bash`, `^apply_patch$`, `mcp__filesystem__.*` |
|
|
464
|
+
| `SessionStart` | 启动来源 | `startup`, `resume`, `clear`, `startup\|resume\|clear` |
|
|
465
|
+
| `UserPromptSubmit` | **无** | 任何 matcher 被忽略 |
|
|
466
|
+
| `Stop` | **无** | 任何 matcher 被忽略 |
|
|
467
|
+
|
|
468
|
+
**⚠️ 注意**:`apply_patch` 匹配时可用 `Edit` 或 `Write` 作为别名,但 hook 输入中 `tool_name` 仍报告为 `"apply_patch"`。
|
|
469
|
+
|
|
470
|
+
---
|
|
471
|
+
|
|
472
|
+
## 7. 并行执行与合并规则
|
|
473
|
+
|
|
474
|
+
- 多个配置文件中的 **所有匹配 hooks 都会运行**
|
|
475
|
+
- 同一事件的多个匹配 command hooks **并发启动**
|
|
476
|
+
- 一个 hook **不能阻止** 另一个匹配 hook 启动
|
|
477
|
+
- 高层配置 **不替换** 低层配置的 hooks(全部合并)
|
|
478
|
+
|
|
479
|
+
### 多 hook 决策规则
|
|
480
|
+
|
|
481
|
+
- **`PermissionRequest`**:任何 `deny` > `allow` > 无决策(走正常审批流)
|
|
482
|
+
- **`Stop`**:任何 `continue: false` > `decision: block`(continuation)
|
|
483
|
+
- 其他事件无多 hook 决策合并规则文档
|
|
484
|
+
|
|
485
|
+
---
|
|
486
|
+
|
|
487
|
+
## 8. 对 gxpm 的启示
|
|
488
|
+
|
|
489
|
+
### 8.1 gxpm 能力映射
|
|
490
|
+
|
|
491
|
+
| gxpm 能力 | Codex 实现 | 可行方案 |
|
|
492
|
+
|-----------|-----------|---------|
|
|
493
|
+
| 会话启动注入上下文 | `SessionStart` 返回 `additionalContext` | ✅ 可用。stdout 纯文本或 JSON `additionalContext` |
|
|
494
|
+
| Prompt 命中 GXPM-N 注入 issue 状态 | `UserPromptSubmit` 返回 `additionalContext` | ✅ 可用。纯文本 stdout 或 JSON `additionalContext` |
|
|
495
|
+
| 记录 `update_plan` | `PreToolUse` + matcher `"apply_patch"` | ⚠️ 部分可用。仅拦截简单调用,`unified_exec` 不完整 |
|
|
496
|
+
| 代码格式化后处理 | `PostToolUse` + matcher `"apply_patch"` / `"Bash"` | ⚠️ 可用但范围有限(`WebSearch` 等不拦截) |
|
|
497
|
+
| 危险命令拦截 | `PreToolUse` + matcher `"Bash"` | ✅ 可用 |
|
|
498
|
+
| 自动审批 | `PermissionRequest` + `decision.behavior: "allow"` | ✅ 可用 |
|
|
499
|
+
| Stop 继续工作 | `Stop` + `decision: block` | ✅ 可用 |
|
|
500
|
+
| Git hooks(pre-commit 等) | 独立机制 | ✅ 通用,不区分 host |
|
|
501
|
+
|
|
502
|
+
### 8.2 推荐适配路径
|
|
503
|
+
|
|
504
|
+
1. **SessionStart 注入**:Codex 的 `SessionStart` 支持 `additionalContext` JSON 输出,是注入项目约定和当前 issue 状态的有效方式。与 Claude Code 的 stdout 注入等价。
|
|
505
|
+
|
|
506
|
+
2. **UserPromptSubmit 动态上下文**:与 Claude Code 类似,Codex 的 `UserPromptSubmit` 支持 `additionalContext` 注入,是 prompt 命中 GXPM-N 时注入 issue 状态的理想机制。
|
|
507
|
+
|
|
508
|
+
3. **PreToolUse 审计与拦截**:`PreToolUse` 可以拦截 Bash 和 `apply_patch`(文件编辑),但对 `unified_exec` 和 `WebSearch` 等工具拦截不完整。gxpm 应将其作为**辅助防线**,不能依赖为唯一安全边界。
|
|
509
|
+
|
|
510
|
+
4. **Stop 继续工作**:Codex 的 `Stop` hook 语义特殊 — `decision: block` 实际上是让 Codex 继续工作。这对 gxpm 的 QA 验证场景有用:在 `Stop` 时运行测试,失败则让 Codex 继续修复。
|
|
511
|
+
|
|
512
|
+
5. **PermissionRequest 自动审批**:对于高频的 Bash/apply_patch 审批,可用 `PermissionRequest` 自动批准低风险操作。
|
|
513
|
+
|
|
514
|
+
### 8.3 配置示例(gxpm 用例)
|
|
515
|
+
|
|
516
|
+
```json
|
|
517
|
+
// .codex/hooks.json
|
|
518
|
+
{
|
|
519
|
+
"hooks": {
|
|
520
|
+
"SessionStart": [
|
|
521
|
+
{
|
|
522
|
+
"matcher": "startup|resume",
|
|
523
|
+
"hooks": [
|
|
524
|
+
{
|
|
525
|
+
"type": "command",
|
|
526
|
+
"command": "gxpm hook session-start",
|
|
527
|
+
"timeout": 5,
|
|
528
|
+
"statusMessage": "Loading gxpm session context"
|
|
529
|
+
}
|
|
530
|
+
]
|
|
531
|
+
}
|
|
532
|
+
],
|
|
533
|
+
"UserPromptSubmit": [
|
|
534
|
+
{
|
|
535
|
+
"hooks": [
|
|
536
|
+
{
|
|
537
|
+
"type": "command",
|
|
538
|
+
"command": "gxpm hook user-prompt-submit",
|
|
539
|
+
"timeout": 3
|
|
540
|
+
}
|
|
541
|
+
]
|
|
542
|
+
}
|
|
543
|
+
],
|
|
544
|
+
"PreToolUse": [
|
|
545
|
+
{
|
|
546
|
+
"matcher": "Bash",
|
|
547
|
+
"hooks": [
|
|
548
|
+
{
|
|
549
|
+
"type": "command",
|
|
550
|
+
"command": "gxpm hook pre-tool-use",
|
|
551
|
+
"timeout": 5,
|
|
552
|
+
"statusMessage": "Checking gxpm policy"
|
|
553
|
+
}
|
|
554
|
+
]
|
|
555
|
+
}
|
|
556
|
+
],
|
|
557
|
+
"Stop": [
|
|
558
|
+
{
|
|
559
|
+
"hooks": [
|
|
560
|
+
{
|
|
561
|
+
"type": "command",
|
|
562
|
+
"command": "gxpm hook stop",
|
|
563
|
+
"timeout": 30,
|
|
564
|
+
"statusMessage": "Running gxpm stop checks"
|
|
565
|
+
}
|
|
566
|
+
]
|
|
567
|
+
}
|
|
568
|
+
]
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
### 8.4 与 Claude Code 的关键差异
|
|
574
|
+
|
|
575
|
+
| 维度 | Codex | Claude Code |
|
|
576
|
+
|------|-------|------------|
|
|
577
|
+
| **SessionStart 上下文注入** | ✅ JSON `additionalContext` | ✅ stdout 纯文本 |
|
|
578
|
+
| **UserPromptSubmit 上下文注入** | ✅ JSON `additionalContext` | ✅ JSON `additionalContext` |
|
|
579
|
+
| **事件总数** | 6 种 | 28 种 |
|
|
580
|
+
| **Handler 类型** | 仅 `command` | 5 种 |
|
|
581
|
+
| **Async 支持** | ❌ | ✅ |
|
|
582
|
+
| **HTTP hooks** | ❌ | ✅ |
|
|
583
|
+
| **MCP tool hooks** | ❌ | ✅ |
|
|
584
|
+
| **Prompt/Agent hooks** | ❌ | ✅ |
|
|
585
|
+
| **Matcher 语法** | 正则表达式 | 精确字符串 / `\|` 列表 / JS 正则 |
|
|
586
|
+
| **`if` 字段** | ❌ | ✅(Permission rule 语法) |
|
|
587
|
+
| **去重** | ❌ | ✅ |
|
|
588
|
+
| **Plugin/Skill hooks** | ❌(Plugin 支持 hooks/hooks.json) | ✅ |
|
|
589
|
+
| **Stop `decision: block` 语义** | ✅ 继续工作 | ✅ 阻止停止 |
|
|
590
|
+
| **`PostToolUse` block** | ⚠️ 不撤销,替换结果 | ❌ 不支持 block |
|
|
591
|
+
| **工具拦截完整度** | ⚠️ 仅简单 shell / apply_patch | ✅ 完整 |
|
|
592
|
+
| **CLI 验证** | ❌ | ✅ `/hooks` 菜单 |
|
|
593
|
+
|
|
594
|
+
---
|
|
595
|
+
|
|
596
|
+
## 9. 已知限制与注意事项
|
|
597
|
+
|
|
598
|
+
1. **Feature flag 必需**:Hooks 默认关闭,必须设置 `codex_hooks = true`
|
|
599
|
+
2. **工具拦截不完整**:`unified_exec`、streaming shell、`WebSearch` 等不被 `PreToolUse` / `PostToolUse` 拦截
|
|
600
|
+
3. **`PreToolUse` 不支持 allow/ask**:`permissionDecision: "allow"` / `"ask"` 已解析但 fail open
|
|
601
|
+
4. **`Stop` 纯文本无效**:此事件要求 JSON 输出,纯文本 stdout 会导致错误
|
|
602
|
+
5. **`UserPromptSubmit` / `Stop` 无 matcher**:任何配置的 matcher 都被忽略
|
|
603
|
+
6. **Legacy notify 系统**:Codex 还有一个旧的 `notify = ["bash", "-lc", "script"]` 配置,在 `agent-turn-complete` 时触发。Hooks 系统稳定后将取代 notify。
|
|
604
|
+
7. **Config.toml hooks 回归**:OpenAI/codex#19199 和 #19300 记录了 config.toml 内联 hooks 的解析回归问题。建议优先使用独立的 `hooks.json`。
|
|
605
|
+
|
|
606
|
+
---
|
|
607
|
+
|
|
608
|
+
## 10. 待验证事项
|
|
609
|
+
|
|
610
|
+
- [ ] `PreToolUse` 的 `updatedInput` 重写何时正式支持
|
|
611
|
+
- [ ] `unified_exec` 启用后 `PreToolUse` 拦截行为的变化
|
|
612
|
+
- [ ] `PostToolUse` 的 `updatedMCPToolOutput` 支持时间线
|
|
613
|
+
- [ ] Codex Plugin 的 `hooks/hooks.json` 与 gxpm 的集成方式
|
|
614
|
+
- [ ] Codex CLI 是否有计划增加 `async` hook 支持
|
|
615
|
+
- [ ] `Stop` hook 的 `last_assistant_message` 字段在 continuation 场景中的实际行为
|
|
616
|
+
|
|
617
|
+
---
|
|
618
|
+
|
|
619
|
+
## 参考文档
|
|
620
|
+
|
|
621
|
+
- https://developers.openai.com/codex/hooks — Codex Hooks 官方文档(完整 schema、JSON I/O)
|
|
622
|
+
- https://developers.openai.com/codex/config-reference — Codex 配置参考(feature flags)
|
|
623
|
+
- https://github.com/openai/codex — Codex CLI 源码仓库(wire schema)
|
|
624
|
+
- https://github.com/openai/codex/issues/19199 — config.toml hooks 回归问题
|