Codex plugin that injects local project rule files into model context through lifecycle hooks.
It ports the pi-rules rule injector to Codex:
SessionStartandUserPromptSubmitload static project instructions once per session.PostToolUsewatches Codexapply_patchby default, then injects matching file-specific rules as additional context.PostCompactclears the per-session injection cache after manual or automatic compaction so relevant rules can be reintroduced into the compacted conversation.- Session-level deduplication prevents the same rule from being repeated after it has been injected.
PostToolUse output is context-only: it emits hookSpecificOutput.additionalContext and does not rewrite tool output.
The runtime has no npm production dependencies, so a clean Codex marketplace copy can run without a follow-up npm install.
Project-level sources:
AGENTS.mdCLAUDE.mdCONTEXT.md.omo/rules/**/*.md.claude/rules/**/*.md.cursor/rules/**/*.md.github/instructions/**/*.md.github/copilot-instructions.md
User-home sources are also supported by the ported engine when available.
Markdown rule files may use frontmatter such as:
---
description: TypeScript defaults
globs: ["**/*.ts", "**/*.tsx"]
alwaysApply: false
---
Prefer strict TypeScript and keep runtime imports ESM-compatible.From the marketplace workspace:
codex plugin marketplace add /Users/yeongyu/local-workspaces/codex-plugins
node /Users/yeongyu/local-workspaces/codex-plugins/scripts/install-local.mjs /Users/yeongyu/local-workspaces/codex-pluginsThe local installer builds the plugin and copies a clean cache entry to:
~/.codex/plugins/cache/code-yeongyu-codex-plugins/codex-rules/0.1.0
It also enables:
[features]
plugins = true
plugin_hooks = true
[plugins."codex-rules@code-yeongyu-codex-plugins"]
enabled = trueUse CODEX_RULES_* environment variables:
| Variable | Values | Default |
|---|---|---|
CODEX_RULES_DISABLED |
1, true, yes, on |
unset |
CODEX_RULES_MODE |
both, static, dynamic, off |
both |
CODEX_RULES_MAX_RULE_CHARS |
positive integer | 12000 |
CODEX_RULES_MAX_RESULT_CHARS |
positive integer | 40000 |
CODEX_RULES_ENABLED_SOURCES |
comma-separated source names | auto |
For migration from pi-rules, equivalent PI_RULES_* variables are accepted as fallbacks.
Enable hook phase timing with NODE_DEBUG=codex-rules:
NODE_DEBUG=codex-rules node dist/cli.js hook post-tool-use < fixture.jsonDebug lines go to stderr and hook JSON stays on stdout. The log includes PostToolUse phases such as extract, fingerprint, load, persist, elapsed ms, target counts, pending counts, rule counts, and output bytes. It does not log rule bodies or tool response contents.
The default PostToolUse hook matcher is intentionally strict: it matches only Codex's canonical apply_patch hook tool name. Read tools, MCP filesystem tools, shell commands, and Claude-style Write/Edit aliases are not registered by default.
npm install
npm test
npm run check
npm run typecheck
npm pack --dry-runPerformance smoke test:
npm run benchBenchmark timings depend on the local machine. Use the relative counters and repeat-output checks when comparing runs.
Hook smoke test:
npm run build
printf '%s\n' '{"session_id":"s","transcript_path":null,"cwd":"/path/to/project","hook_event_name":"SessionStart","model":"gpt-5.5","permission_mode":"default","source":"startup"}' \
| PLUGIN_DATA=/tmp/codex-rules-data node dist/cli.js hook session-startcodex-rules runs locally. It reads local rule files and Codex hook payloads, writes per-session deduplication state under the Codex plugin data directory, and does not make network requests.