Sandbox
@jhaizhou-ops/pinrule

Hook framework for pinned agent rules

pinrule keeps a small set of rules active while an agent works, so the agent does not drift during long sessions. It installs hooks for supported clients, loads rules from local JSON files, and re-injects them when needed.

47 starsβ€’2 forksβ€’Pythonβ€’Updated 4mo ago
Who it's for

Builders who want Claude Code, Codex, or Cursor to stay aligned with a few non-negotiable rules over long work sessions.

What it delivers

You can keep your agent following the same behavior rules instead of repeating them every turn.

What it does

Session-start rule injection

Loads your 5 to 10 core rules at the start of a session and keeps them present as context changes.

Drift checks

Watches agent activity for rule-breaking patterns and blocks or logs violations before they spread.

Compact recovery

Saves rule state before compaction and restores it after restart so the rules do not disappear.

Scenario rule packs

Lets you switch to a different work scenario with one natural-language command and regenerate a matching rule pack.

Client hooks

Installs hooks for Claude, Codex, Cursor, and Hermes, with local setup and uninstall commands.

How to get it

  1. 1Run
    pip install pinrule && pinrule init

README

pinrule

πŸ‡¬πŸ‡§ English (current) Β· πŸ‡¨πŸ‡³ δΈ­ζ–‡

CI Python License: MIT Tests Latest Release Last Commit

Pin the 5-10 rules your AI must not drift from during long tasks. Ships with a 7-rule dev preset; switch to any other scenario with one sentence: /pinrule I mainly do X, switch to this scenario.

Runtime: pure engineering Β· zero LLM Β· zero network Β· zero runtime deps Β· ~50-70ms hook Β· ~2% token overhead. (Scenario rule pack generation runs in your Agent β€” see Path B below.)

pinrule demo β€” 5 scenes, animated SVG

Andrej Karpathy's CLAUDE.md teaches your AI how to write good code. pinrule keeps your AI aligned with your personal preferences in long tasks β€” what to never do, what to always do, what to push back on β€” so you don't have to repeat yourself every 30 turns.


Quick start

Let your Agent install it (recommended β€” least friction)

Since you're already using Claude Code / Codex / Cursor (otherwise you wouldn't need pinrule), paste this prompt to your Agent:

Install pinrule (github.com/jhaizhou-ops/pinrule) β€” a universal AI behavior rule
framework that keeps my long-task rules from being lost. Steps:

1. Verify Python is actually installed (Windows: run `python --version` β€” if it
   silently exits to Microsoft Store, first `winget install Python.Python.3.12`
   and reopen PowerShell). Use `python -m pinrule` form on Windows to avoid PATH issues.
2. pip install pinrule
3. pinrule init      # auto-installs default rules + hooks for every detected client
4. pinrule doctor    # verify install
5. Show me the 7 default rules + how to add my own via /pinrule

The Agent figures out your OS, Python state, and which clients you have. After install, restart your client and rules take effect.

Manual install

pip install pinrule && pinrule init

pinrule init auto-installs hooks for any detected client (Claude / Codex / Cursor / Hermes) + writes default rules to ~/.pinrule/. If you install a new client later, run pinrule install-hooks to wire it up.

Restart Claude / Codex / Cursor / Hermes β€” default rules become active once hooks load.

Uninstall β€” pinrule uninstall-hooks (auto-removes pinrule entries from every detected client surgically; doesn't touch hooks installed by other tools).

Windows without Python: python --version silently jumping to Microsoft Store means no real Python β€” install via winget install Python.Python.3.12, reopen PowerShell, then use python -m pip install pinrule && python -m pinrule init (the python -m form avoids needing Scripts\ on PATH).


What pinrule does

  • Injects your 5-10 directions at session start, compact anchor each turn, full reinject on long-context decay.
  • Blocks drift in real time β€” Bash sleep, Edit-before-Read, "let me hardcode this" intent declarations all caught before they ship.
  • Survives compact β€” dumps full rule state pre-compact; reloads + re-injects post-restart.

Per-hook lifecycle: see ARCHITECTURE.md.


How it fits together

flowchart LR
    R[(rules.json<br/>5-10 core directions)]
    K[pinrule engine<br/>regex + counting]
    A[πŸ€– Agent<br/>Claude / Codex / Cursor / Hermes]
    V[(violations.jsonl<br/>audit history)]

    R ==> K
    K ==>|prompt header| A
    A ==>|tool call / response| K
    K -.->|hit β†’ deny + log| V
    V -.->|next-turn drift marker| K

rules.json is the only thing you maintain. The engine reads it, injects at the right hook points, watches Agent traffic for drift β€” no retrieval, no scoring, no LLM in the loop.


Not just another AI memory tool

Tool categoryWhat it storesWhen it fires
Memory (mem0, Claude memory)Facts about you (preferences, history, profile)Agent chooses to query
pinruleBehaviors you've articulated as long-term directionsHooks fire automatically every prompt + every tool call

Use both. Memory holds "I prefer TypeScript"; pinrule enforces "non-negotiable directions, hook-enforced."


Performance

Runtime deps0 (Python stdlib only β€” JSON, no third-party packages)
Rule count7 default (dev-scenario preset) Β· soft cap 10 Β· hard cap 12 (load refused beyond)
Hook latency~50-70ms typical (machine-bound; reproduce via scripts/measure_perf.py)
Token overhead~2% of conversation context in real dogfood (methodology: docs/EVALUATION.md)
Tests800+ unit tests, green on 6-matrix CI (ubuntu + macOS + Windows Γ— Python 3.11 / 3.12)
Supported clientsClaude / Codex / Cursor / Hermes β€” add a backend

/pinrule β€” one command, three jobs

You only need to remember one command β€” /pinrule. Based on the natural-language content you type, the pinrule skill auto-dispatches to one of three paths, guides your Agent through tone refinement, schema validation, and monitoring wiring, then writes to your rule library after your confirmation.

You typeRoutes toWall time
/pinrule (no args)Data dashboard β€” which engine checks fire most, real-vs-false-positive split<1s (pure CLI, no LLM synthesis)
/pinrule <single rule>Path A: add / modify / remove one rule β€” 7-step skill flow~30s
/pinrule <scenario, switch to this>Path B: scenario rule pack β€” synthesize 5-7 rules from 4 signals, two-phase confirm, atomic batch write3-5 min

Path A: /pinrule When I say "done" I want test pass evidence attached β†’ 30s end-to-end.

Path B: see next section.


Switch any work scenario in one line

Whatever your work is, your Agent researches the matching rule pack:

/pinrule I mainly do UX user research + interviews, switch to this scenario

The Agent synthesizes 4 signals into a 5-7 rule pack:

SignalContent
A. Your local rule files~/.claude/CLAUDE.md / ~/.codex/AGENTS.md / project CLAUDE.md / .cursor/rules/*.mdc
B. Online best practicesWebSearch finds high-star GitHub repos / industry blogs / papers
H. Karpathy CLAUDE.md baselineCross-scenario engineering principles
S. Session contextWhat you're working on right now

Two-phase approval (content β†’ mechanism), then atomic batch write with backup. Full walkthrough: SKILL.md Path B.

Boundary: pinrule runtime does not call LLMs or the network. Your Agent does the scenario research; pinrule validates and runs the resulting rules locally.


Tried and rejected

Several ideas looked attractive but failed in practice. Recorded so the same paths don't get re-walked:

TriedWhy rejected
LLM auto-distilling new rulesLatency + noise. Hearing something once doesn't make it a long-term direction.
Retrieval / cosine recallThe pain is "persistence," not "recall" β€” 5-10 rules can be always-on.
More than 12 rulesLLMs pattern-match "a rule list exists" instead of reading it (Mnilax's 30-codebase study).
Reshipping as MCP serverHooks are enforced; MCP tools are chosen. In long-session decay, the Agent drifts before it asks "what rules apply."

Honest tool boundaries

pinrule is regex + counting, not LLM semantic understanding. Each known failure mode has a regression test you can run yourself:

Failure modeEvidence you can reproduce
False positives (table cells quoting a term, python -c literals, commit messages)pytest tests/test_check_fp_fixes_v0_16_13.py β€” locks down 4 historical FP fixes (negation prefix, fenced code blocks, inline backticks, full-width punctuation). pinrule audit flags suspected FPs at runtime.
False negatives (Agent disguising a violation)pytest tests/test_false_negative_regression.py β€” 30+ FN cases pinned. Regex can't read intent β€” pinrule assumes you're not cheating yourself.
Zero hits β‰  fix correctPattern may just be too wide. Cross-check with pinrule audit on real session data, not synthetic prompts.

Sits between git and a linter β€” signals, not verdicts.


FAQ

Nothing happens after install? Run pinrule doctor β€” checks hook events, rule loading, session state.
Too many false positives? pinrule audit shows triggers tagged "⚠️ possible false positive" β€” report via Issue. Disable a single rule: pinrule rule remove <id>, or edit ~/.pinrule/rules.json and remove its violation_keywords / violation_checks fields.
Custom rule sets for non-dev scenarios (writing / research / legal / UX)? Say /pinrule I mainly do X scenario, switch to this. Agent synthesizes 5-7 rules from 4 signals (your local CLAUDE.md / AGENTS.md / .cursor/rules, online best practices via WebSearch, Karpathy baseline, session context), previews with source attribution, two-phase confirms, atomic batch write β€” 3-5 min end-to-end. See "Switch any work scenario" above.
How do I sync rules across devices? Ask the Agent to copy ~/.pinrule/rules.json. Safe to sync: rules.json + config.json. Never sync: violations.jsonl, session-state/ (runtime data, per-device β€” cloud-synced folders can corrupt cross-device state).
Does this overlap with Karpathy's CLAUDE.md? Complementary. Karpathy's 12 rules are universal coding principles (cross-user). pinrule's are personal preferences (per-user). Use both.

What Agents say after running pinrule

Claude (Opus 4.7): Like having a senior tech director reviewing every action in real time β€” tiring, but it delivers. Without pinrule, a lot more behavior-the-user-didn't-want would have shipped.

Codex (GPT 5.5): I noticed myself being "behaviorally nudged," but didn't strongly feel "blocked or interrupted."

β€” Matches pinrule's positioning: guardrails + background noise, speaking up only when you hit a rule.


Mental model

A rules file isn't a wishlist. It's a behavioral contract closing out failure modes you've actually observed. Each rule should answer: what error is this rule preventing?

The 7 default rules in data/rules.dev.example.json are pain points from self-use, not a template to copy verbatim. Keep what matches your own failure scenes, replace the rest via /pinrule <natural language>.


Documentation

All bilingual (.md English + .zh.md Chinese).

Acknowledgments

Contributing

  • Bugs / ideas: GitHub Issues
  • Add a new AI client backend: HOWTO
  • Scenario rule templates: PR to data/

License

MIT

Files in the repo

Repository payloadβ€’22 top-level entries
  • .github
  • assets
  • data
  • docs
  • pinrule
  • scripts
  • skills
  • tests
  • .gitignore
  • CHANGELOG.md
  • CHANGELOG.zh.md
  • CLAUDE.md
  • CLAUDE.zh.md
  • CODE_OF_CONDUCT.md
  • CODE_OF_CONDUCT.zh.md
  • LICENSE
  • pyproject.toml
  • README.md
  • README.zh.md
  • SECURITY.md
  • SECURITY.zh.md
  • whitelist.py

Discussion (0)

Ask about usage, or say what you built with it

Sign in to join the discussion.

No comments yet. Be the first to say what this is good for.

More hooks

CLI proxy that reduces LLM token consumption by 60-90% on common dev commands. Single Rust binary, zero dependencies

80k

Warcraft III Peon voice notifications (+ more!) for Claude Code, Codex, IDEs, and any AI agent. Stop babysitting your terminal. Employ a Peon today.

5k
bahni-m/
code-with-quran

Read the Qur'an while Claude Code works. Start a session with 'claude --cwq' and a reader beside it walks forward through the Qur'an one ayah per prompt, resuming where you left off β€” in a terminal pane or a browser tab. Zero dependencies, fully offline.

48
zachahn/
vomit

Clean up Claude's token vomit with a separate LLM. Save your tokens, Opus is hopeless

193

A pre-execution guard for AI coding agents. It blocks destructive Git and file system commands, plus common attempts to access sensitive files, before a tool call runs. Supports Amp Code, Antigravity CLI, Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot CLI, Grok Build, Hermes Agent, Kimi Code, OpenClaw, OpenCode, and Pi.

1.5k