docs(omo-codex): batch 88 (12 files)

This commit is contained in:
YeonGyu-Kim
2026-05-30 19:12:16 +09:00
parent d1532ba30f
commit d7f8df407b
12 changed files with 389 additions and 0 deletions
@@ -0,0 +1,13 @@
# Normalize line endings: store LF in git, check out LF on every platform.
# Required so biome's --check passes on Windows (default core.autocrlf=true).
* text=auto eol=lf
# Explicit binary types
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.ico binary
*.zip binary
*.tgz binary
*.gz binary
@@ -0,0 +1,6 @@
node_modules/
.DS_Store
*.log
coverage/
.vitest/
*.tgz
@@ -0,0 +1,34 @@
# Repository Conventions
Conventions for human contributors and AI agents working on this repository.
## Style
- Terse technical prose. No emojis in commits, issues, PR comments, or code.
- TypeScript strict mode. No `any`, no `@ts-ignore`, no `@ts-expect-error`, no enums.
- ESM modules with `.js` suffix in runtime import paths.
- Tabs for indentation. Double quotes for strings.
- Tests use vitest with `#given .. #when .. #then` descriptions or plain `// given / // when / // then` body comments.
## Commands
- `npm install` - install dependencies.
- `npm test` - run vitest once.
- `npm run typecheck` - strict TypeScript check.
- `npm run check` - type check, biome, and build.
- `npm pack --dry-run` - release package smoke test.
- `node dist/cli.js hook session-start < fixture.json` - smoke-test static rule injection.
- `node dist/cli.js hook post-tool-use < fixture.json` - smoke-test dynamic rule injection.
## Constraints
- No Bun APIs. Runtime is Node only because Codex launches plugin hooks with Node.
- Keep `SessionStart`, `UserPromptSubmit`, and `PostToolUse` hook behavior covered by tests.
- Keep Codex file path extraction for reads, edits, `apply_patch`, and shell-style tools covered by tests.
- Hook output must use the stable Codex hook JSON contract.
- Do not couple this package back to pi, omo, or senpi internal source paths.
## Don'ts
- No `git add -A` or `git add .`. Stage only the files you changed.
- No `git commit --no-verify`. No force pushes. No history rewriting on shared branches.
@@ -0,0 +1,19 @@
# Changelog
## Unreleased
- Restrict the default `PostToolUse` hook matcher to Codex's canonical `apply_patch` tool name.
- Add opt-in `NODE_DEBUG=codex-rules` phase timing logs for `PostToolUse` debugging.
- Harden dynamic hook coverage for additional-context JSON output, disabled/static modes, failed tool responses, and duplicate suppression.
- Remove redundant apply_patch path scanning and stale tracked-tool constants.
- Use portable Codex hook interpolation and add package smoke coverage for hook entrypoints.
- Cap recursive rule directory scans and run CI on Windows in addition to Ubuntu and macOS.
- Replace the external glob matcher dependency with an internal matcher so clean Codex plugin installs run without `node_modules`.
## 0.1.0 - 2026-05-15
- Port `pi-rules` rule loading, matching, formatting, truncation, and deduplication to a Codex plugin.
- Add `SessionStart`, `UserPromptSubmit`, and `PostToolUse` hooks for static and file-specific context injection.
- Add persistent per-session deduplication under Codex plugin data.
- Add Codex-aware path extraction for read, write, edit, multi-edit, `apply_patch`, and shell command payloads.
- Add tests, CI, release workflow, marketplace metadata, and local install support.
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 Yeongyu Kim
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -0,0 +1,15 @@
codex-rules
This package implements rule/context loading for Codex plugins.
Its behavior is ported from pi-rules in the pi coding-agent extension ecosystem
and inspired by oh-my-openagent (omo) at https://github.com/code-yeongyu/oh-my-openagent,
including omo's `.omo/rules/` workflow and rules-injector hook architecture.
omo is originally licensed under the Sustainable Use License 1.0.
Yeongyu Kim (https://github.com/code-yeongyu), author of omo, pi-rules, and this
package, licenses the source distributed in this repository under the MIT License.
If any source was ported from omo or pi-rules, that ported source is re-licensed
here under MIT for distribution as a Codex plugin. See LICENSE for terms.
picomatch is by Jon Schlinkert and contributors (https://github.com/micromatch/picomatch).
Distributed under the MIT License.
@@ -0,0 +1,124 @@
# codex-rules
Codex plugin that injects local project rule files into model context through lifecycle hooks.
It ports the `pi-rules` rule injector to Codex:
- `SessionStart` and `UserPromptSubmit` load static project instructions once per session.
- `PostToolUse` watches Codex `apply_patch` by default, then injects matching file-specific rules as additional context.
- `PostCompact` clears 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`.
## Rule Sources
Project-level sources:
- `AGENTS.md`
- `CLAUDE.md`
- `CONTEXT.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:
```md
---
description: TypeScript defaults
globs: ["**/*.ts", "**/*.tsx"]
alwaysApply: false
---
Prefer strict TypeScript and keep runtime imports ESM-compatible.
```
## Install Locally
```bash
bunx lazycodex install
```
The local installer builds the plugin and copies a clean cache entry to:
```text
~/.codex/plugins/cache/sisyphuslabs/omo/0.1.0
```
It also enables:
```toml
[features]
plugins = true
plugin_hooks = true
[plugins."omo@sisyphuslabs"]
enabled = true
```
## Configuration
Use `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.
## Debugging
Enable hook phase timing with `NODE_DEBUG=codex-rules`:
```bash
NODE_DEBUG=codex-rules node dist/cli.js hook post-tool-use < fixture.json
```
Debug 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.
## Development
```bash
npm install
npm test
npm run check
npm run typecheck
npm pack --dry-run
```
Performance smoke test:
```bash
npm run bench
```
Benchmark timings depend on the local machine. Use the relative counters and repeat-output checks when comparing runs.
Hook smoke test:
```bash
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-start
```
## Privacy
`codex-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.
## License
MIT. See [LICENSE](LICENSE) and [NOTICE](NOTICE).
@@ -0,0 +1,48 @@
{
"$schema": "https://biomejs.dev/schemas/2.4.15/schema.json",
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"style": {
"noDefaultExport": "error",
"noEnum": "error",
"noNonNullAssertion": "error",
"useImportType": "error",
"useConst": "error",
"useNodejsImportProtocol": "off"
},
"complexity": {
"useLiteralKeys": "off"
},
"suspicious": {
"noExplicitAny": "error",
"noTsIgnore": "error",
"noControlCharactersInRegex": "off",
"noEmptyInterface": "off"
}
}
},
"formatter": {
"enabled": true,
"formatWithErrors": false,
"indentStyle": "tab",
"indentWidth": 3,
"lineWidth": 120
},
"files": {
"includes": ["src/**/*.ts", "test/**/*.ts", "vitest.config.ts", "!**/node_modules/**/*", "!**/dist/**/*"]
},
"overrides": [
{
"includes": ["vitest.config.ts"],
"linter": {
"rules": {
"style": {
"noDefaultExport": "off"
}
}
}
}
]
}
@@ -0,0 +1,62 @@
{
"name": "@code-yeongyu/codex-rules",
"version": "0.1.0",
"description": "Codex plugin that injects project rule files into model context through lifecycle hooks.",
"type": "module",
"packageManager": "npm@11.12.1",
"license": "MIT",
"homepage": "https://github.com/code-yeongyu/codex-rules",
"repository": {
"type": "git",
"url": "git+https://github.com/code-yeongyu/codex-rules.git"
},
"bugs": {
"url": "https://github.com/code-yeongyu/codex-rules/issues"
},
"keywords": [
"codex",
"codex-plugin",
"rules",
"hooks",
"agents-md",
"context-injection",
"typescript"
],
"bin": {
"omo-rules": "./dist/cli.js"
},
"files": [
"bundled-rules",
"dist",
"hooks",
"skills",
".codex-plugin",
"LICENSE",
"NOTICE",
"README.md",
"CHANGELOG.md"
],
"scripts": {
"build": "tsc -p tsconfig.build.json",
"test": "vitest --run",
"test:watch": "vitest",
"bench": "npm run build --silent && node scripts/bench-codex-rules.mjs",
"typecheck": "tsc --noEmit",
"lint": "biome check .",
"lint:fix": "biome check --write .",
"check": "tsc --noEmit && biome check . && npm run build"
},
"dependencies": {
"picomatch": "^4.0.3"
},
"devDependencies": {
"@biomejs/biome": "2.4.15",
"@types/node": "^25.7.0",
"@types/picomatch": "^4.0.0",
"typescript": "^6.0.3",
"vitest": "^4.1.5"
},
"engines": {
"node": ">=20.0.0"
}
}
@@ -0,0 +1,12 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"allowImportingTsExtensions": false,
"declaration": true,
"outDir": "dist",
"rootDir": "src",
"noEmit": false
},
"include": ["src/**/*"],
"exclude": ["test/**/*"]
}
@@ -0,0 +1,27 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"lib": ["ES2022"],
"strict": true,
"exactOptionalPropertyTypes": true,
"noUncheckedIndexedAccess": true,
"noPropertyAccessFromIndexSignature": true,
"verbatimModuleSyntax": true,
"noImplicitOverride": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"esModuleInterop": true,
"allowImportingTsExtensions": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"useDefineForClassFields": false,
"types": ["node"],
"noEmit": true
},
"include": ["src/**/*", "test/**/*"]
}
@@ -0,0 +1,8 @@
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
environment: "node",
pool: "threads",
},
});