Skip to main content

Pin the 5-10 rules your AI must not drift from during long tasks — Claude / Codex / Cursor, pure engineering, zero LLM, ~50-70ms hook latency

Project description

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. Pure engineering · zero LLM · ~50-70ms hook · ~2% token overhead in typical dogfood.

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

pip install pinrule && pinrule init

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

Windows users: Windows doesn't ship Python by default. If python --version doesn't show a real version (just silently exits to Microsoft Store), install Python first:

winget install Python.Python.3.12
# close + reopen PowerShell so PATH refreshes
python -m pip install pinrule
python -m pinrule init
python -m pinrule doctor

The python -m pinrule form avoids needing Python's Scripts\ folder on PATH (which isn't there by default after pip install).

Restart Claude / Codex / Cursor — default rules become active once hooks load. To add a personal rule:

/pinrule When I say "done" I want test pass evidence attached.

The skill refines, validates, confirms with you, then writes — ~30 seconds.


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.yaml<br/>5-10 core directions)]
    K[pinrule engine<br/>regex + counting]
    A[🤖 Agent<br/>Claude / Codex / Cursor]
    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.yaml 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 category What it stores When it fires
Memory (mem0, Claude memory) Facts about you (preferences, history, profile) Agent chooses to query
pinrule Behaviors you've articulated as long-term directions Hooks fire automatically every prompt + every tool call

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


Performance

External deps 0 (only PyYAML, a Python-standard library)
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)
Tests 800+ unit tests, green on 6-matrix CI (ubuntu + macOS + Windows × Python 3.11 / 3.12)
Supported clients Claude / Codex / Cursor — add a backend

Per-client install + uninstall

Client Command Note
Claude (default) pinrule install-hooks
Codex pinrule install-hooks --backend codex
Cursor 1.7+ pinrule install-hooks --backend cursor /pinrule skill is project-scoped only
pinrule uninstall-hooks                                          # remove
cp ~/.claude/settings.json.before-pinrule ~/.claude/settings.json # restore

Codex details: docs/CODEX_BACKEND.md. Cursor's /pinrule skill is project-scoped (Cursor doesn't expose home-level global skills) — see post-install hint.


Tried and rejected

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

Tried Why rejected
LLM auto-distilling new rules Latency + noise. Hearing something once doesn't make it a long-term direction.
Retrieval / cosine recall The pain is "persistence," not "recall" — 5-10 rules can be always-on.
More than 12 rules LLMs pattern-match "a rule list exists" instead of reading it (Mnilax's 30-codebase study).
Reshipping as MCP server Hooks 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.

  • False positives happen. Table cells quoting a term, python -c literals, commit messages — all can hit. pinrule audit flags suspected false positives.
  • False negatives happen. Regex can't tell if you're disguising a violation. pinrule assumes you're not cheating yourself.
  • Zero hits after a fix doesn't prove the fix is correct. The pattern might just be too wide.

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.yaml and remove its violation_keywords / violation_checks fields.
Custom rule sets for non-dev scenarios (writing / research / legal)? The framework is cross-scenario; the 8 built-in violation_checks are dev-oriented. Write your own rules.yaml for other scenarios — preference text + custom keywords (no engine check needed).
How do I sync rules across devices? Ask the Agent to copy ~/.pinrule/rules.yaml. Safe to sync: rules.yaml + config.yaml. 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.yaml 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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pinrule-0.16.18.tar.gz (538.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pinrule-0.16.18-py3-none-any.whl (229.8 kB view details)

Uploaded Python 3

File details

Details for the file pinrule-0.16.18.tar.gz.

File metadata

  • Download URL: pinrule-0.16.18.tar.gz
  • Upload date:
  • Size: 538.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.12

File hashes

Hashes for pinrule-0.16.18.tar.gz
Algorithm Hash digest
SHA256 aa85a2e5a03557b90ee07a05a8de595d085c25d79546c87b7628471a650599a4
MD5 9cc0402cf48716431cbd4dc7a65da69f
BLAKE2b-256 c348bc910ae97047913a27a024a8ad8dfbad9b4b7a54a8f8f4bbb065ebf22247

See more details on using hashes here.

File details

Details for the file pinrule-0.16.18-py3-none-any.whl.

File metadata

  • Download URL: pinrule-0.16.18-py3-none-any.whl
  • Upload date:
  • Size: 229.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.12

File hashes

Hashes for pinrule-0.16.18-py3-none-any.whl
Algorithm Hash digest
SHA256 6fcb82adb6c6c05f9a12938d719c37d9e5f987a3e165e50b9591d44b51d27c0a
MD5 d2e4eee4bf7aef47910996c0a78f3179
BLAKE2b-256 f50be2f81483c658a3d01486defe945577604cc395c8e963bfb7b6a3d750f1a5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page