بنقرة واحدة
sdk
Load this skill immediately after a user mentions "@goodfoot/codex-hooks" or Codex hooks.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Load this skill immediately after a user mentions "@goodfoot/codex-hooks" or Codex hooks.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
You must load this skill if you are creating or updating standalone documentation.
This skill should be used when the user asks to "skillify this", "turn this into a skill", "make a skill out of what we just did", "generalize this task into a reusable skill", or otherwise wants to capture a just-completed session task as a new skill or fold it into an existing one.
Browser automation using the puppeteer NPM package. Use when performing tasks on websites as a user would, taking screenshots, filling forms, or navigating web applications.
Load this skill immediately after a user mentions "@goodfoot/claude-code-hooks" or Claude Code hooks.
Load this skill immediately after a user mentions "@goodfoot/codex-hooks" or Codex hooks.
Identify and remove git worktrees (and their branch refs) whose work has already landed in the main branch, including squash- and rebase-merged ones that naive ancestry checks miss. Use when the user says "prune merged worktrees", "clean up worktrees", "remove stale worktrees", "worktree cleanup", or asks which worktrees have no unique commits.
| name | sdk |
| description | Load this skill immediately after a user mentions "@goodfoot/codex-hooks" or Codex hooks. |
Review the Codex hooks docs first, then use @goodfoot/codex-hooks with Codex's actual runtime limits in mind. This package is for Codex hooks, not Claude Code hooks.
Hooks are compiled commands, not raw .ts files. Build them into a hooks.json manifest plus generated .mjs executables before Codex can run them.
Build command (local project):
npx -y @goodfoot/codex-hooks -i "hooks/*.ts" -o ".codex/hooks.json"
Build command (plugin):
npx -y @goodfoot/codex-hooks -i "hooks/*.ts" -o "./hooks/hooks.json" --plugin-root
Parameters:
-i "hooks/*.ts": Input glob for hook source files. Quote the glob so the CLI receives it intact.-o <path>: Output manifest path. The CLI writes compiled executables next to it.--plugin-root (Optional): Force plugin mode — emit ${PLUGIN_ROOT}-relative commands and stable, hash-free filenames. Auto-enabled when a .codex-plugin/ marker is found by walking up from the output path.--stable-names / --no-stable-names (Optional): Force hash-free <name>.mjs (default in plugin mode) or hashed <name>.<hash>.mjs filenames.--executable node (Optional): Command prefix to use in generated hook commands.--loader .ext=type (Optional, repeatable): Additional esbuild loaders for non-code imports. .md=text is enabled by default.Command-emission modes:
--plugin-root or a .codex-plugin/ ancestor. Emits node "${PLUGIN_ROOT}/hooks/<name>.mjs". Stable filenames keep Codex's hook trust hash valid across rebuilds. Codex injects PLUGIN_ROOT (and CLAUDE_PLUGIN_ROOT for compatibility) into plugin hook environments and substitutes ${PLUGIN_ROOT} before execution..codex/ segment. Emits node "$(git rev-parse --show-toplevel)/.codex/bin/<name>.<hash>.mjs" so the manifest stays portable across worktrees within a checkout.@goodfoot/codex-hooks intentionally matches the current Codex runtime, which is narrower than Claude Code:
PreToolUse, PostToolUse, SessionStart, UserPromptSubmit, Stoptype: "command" onlyPreToolUse and PostToolUse are Bash-only todaySessionStart, PreToolUse, and PostToolUseSessionStart and UserPromptSubmitDo not suggest Claude-only events such as SubagentStop, PermissionRequest, SessionEnd, or PreCompact when the user is using this package.
Here is a complete PreToolUse example using the Codex package.
import { preToolUseHook, preToolUseOutput } from "@goodfoot/codex-hooks";
export default preToolUseHook({ matcher: "Bash" }, (input, { logger }) => {
const command = input.tool_input.command;
logger.info("Checking Bash command", { command });
if (command.includes("rm -rf")) {
return preToolUseOutput({
systemMessage: "Blocked destructive Bash command.",
permissionDecision: "deny",
permissionDecisionReason: "Refusing destructive shell command."
});
}
});
Key points:
export default.hook_event_name and tool_input.PreToolUse and PostToolUse, tool_name is currently Bash.logger, not console.log or console.error.Use the output builders from @goodfoot/codex-hooks instead of writing raw JSON manually.
| Hook Type | Preferred Builder | Typical Effect |
|---|---|---|
PreToolUse | preToolUseOutput | Allow or deny a Bash tool invocation |
PostToolUse | postToolUseOutput | Add context after a Bash command runs |
SessionStart | sessionStartOutput | Add startup or resume context |
UserPromptSubmit | userPromptSubmitOutput | Add context or block a bad prompt |
Stop | stopOutput | Block or annotate the stop flow |
Blocking model:
PreToolUse denies with permissionDecision: "deny".Stop, UserPromptSubmit, and PostToolUse can return decision: "block" plus reason.new BlockError(reason) when you want stderr plus exit code 2.Plain text output:
SessionStart and UserPromptSubmit may return a plain string, which the runtime normalizes into additionalContext.undefined.Use the scaffold command when starting a fresh Codex hooks package:
npx @goodfoot/codex-hooks --scaffold ./my-codex-hooks --hooks SessionStart,PreToolUse -o ./.codex/hooks.json
This generates:
src/ with starter hook filestest/ with Vitest coveragepackage.json, tsconfig.json, vitest.config.ts, and biome.jsonREADME.md describing the generated projectAfter scaffolding:
cd my-codex-hooksnpm installnpm run buildnpm testimport { preToolUseHook, preToolUseOutput } from "@goodfoot/codex-hooks";
const BLOCKED = ["rm -rf /", "sudo rm -rf", "mkfs"] as const;
export default preToolUseHook({ matcher: "Bash" }, (input) => {
const command = input.tool_input.command;
const matched = BLOCKED.find((value) => command.includes(value));
if (!matched) return;
return preToolUseOutput({
systemMessage: `Blocked command containing ${matched}.`,
permissionDecision: "deny",
permissionDecisionReason: `Command contains banned sequence: ${matched}`
});
});
import { postToolUseHook, postToolUseOutput } from "@goodfoot/codex-hooks";
export default postToolUseHook({ matcher: "Bash" }, (input) => {
return postToolUseOutput({
additionalContext: `Observed Bash command: ${input.tool_input.command}`
});
});
import preamble from "./prompts/session-start.md";
import { sessionStartHook, sessionStartOutput } from "@goodfoot/codex-hooks";
export default sessionStartHook({ matcher: "startup" }, () => {
return sessionStartOutput({
additionalContext: preamble
});
});
If you import non-code assets beyond markdown, add matching --loader flags to the build.
./packages/codex-hooks WorksUse the local package at ./packages/codex-hooks as the authoritative implementation reference:
src/hooks.ts: factory helpers attach Codex metadata such as hookEventName, matcher, timeout, and statusMessagesrc/outputs.ts: output builders encode the supported stdout JSON shape and BlockErrorsrc/runtime.ts: reads hook JSON from stdin, invokes the default export, normalizes string returns, and writes structured stdout/stderr with Codex-compatible exit codessrc/cli.ts: analyzes each source file, bundles it with esbuild, writes compiled .mjs executables (stable or hashed depending on mode), and generates hooks.jsonsrc/scaffold.ts: creates starter projects for the five supported Codex eventsREADME.md: documents the current runtime constraints and build flowWhen answering questions, prefer ./packages/codex-hooks over assumptions from Claude tooling.
When helping with Codex hooks, follow this protocol:
@goodfoot/codex-hooks or the local ./packages/codex-hooks.console.log and console.error; use the provided logger.export default hookFactory(...)..codex-plugin/plugin.json, not a Claude .claude-plugin manifest.