Keep Claude's harness buffed.

Patina is the compounding retro loop for Claude Code that layers every session, near-miss, and team agreement into PATINA.md: an AI constitution owned by the whole team, polished one cycle at a time. It minimizes context bloat, instruction drift and staleness, while maintaining the most important agreements and guardrails.

★ Star on GitHub
Open-source · No telemetry · MIT licensed
cycle 01 baseline
non-inferable

Things only humans witness.

Near-misses, frustrations, team agreements – context your codebase can never explain to an agent. patina capture logs them while they're fresh.

every voice

Synthesised, not averaged.

Each teammate runs patina reflect on their own machine before the retro to capture their perspective. patina run weaves all of it into a new layer.

human curated

Nothing lands without review.

Claude proposes one concrete diff. A human reads it, approves it, commits it. The file stays 50 lines (or 500 tokens) max. Trimming is as common as adding.

10 min

to first value — just run patina init and patina run to get started

rework

less back-and-forth re-explaining conventions the agent already agreed to last sprint

bloat

optimized core for machine inference, proactive bloat alerts

drift

every layer is reevaluated continuously, preventing model and context drift

how it works

A feedback loop that actually sticks.

Anyone can capture. Everyone reflects. One person runs the synthesis and commits the update. The next session picks up the change automatically, for everyone.

01 anyone · anytime

patina capture

Record a notable moment while it's fresh. UUID-named JSON — no merge conflicts.

$ patina capture --tag near-miss "almost pushed to main"
✓ captured
02 each person · ~10 min

patina reflect

Answer the questions your team picked. Async. Every voice lands in the shared data dir.

$ patina reflect
  how did this cycle feel?
  what went well?
✔ answers saved
03 one person · when ready

patina run

Claude ingests logs, captures, and reflections and applies the next layer.

$ patina run
✔ 12 sessions · 5 captures
✔ updated PATINA.md

Use the Claude Skill /patina to run the commands from within Claude Code sessions.

patina layers

Watch the layers build.

Each retro cycle, Claude proposes a change to your shared Patina. It optimises for quality and machine inference. Trimming is as common as adding, so the file stays tight.

Cycle 1 2026-01-15

Foundation — onboarding cycle

Cycle 2 2026-01-20 24% rework

Top 3 rework patterns identified

Cycle 3 2026-02-01 18% rework (↓6)

Token discipline working; rework dropping

Cycle 4 2026-02-28 ↓8% system prompt

Approval gates added after near-miss

Cycle 5 2026-03-31 ↓12% tokens

Context creep surfaced early; pre-flight rule added

Run patina layers in your project to see your last 5 cycles and their improvements.

.patina/PATINA.md
slim core
500 token limit

Loaded into every session through CLAUDE.md.

hub + spoke

Core always loaded, spokes on demand: detailed autonomy scenarios, incident logs, and cycle history give deeper context when needed.

owned by

the whole team.
versioned in git.

why it's different

Not a report. Not a draft.
Patina is the record.

/insights disappears when the session ends. CLAUDE.md rots while nobody's watching. However, PATINA.md compounds. Every retro adds one deliberate layer, based on the previous layer and the whole team's learnings.

/insights CLAUDE.md PATINA.md
Lives in your machine your repo your repo
Owned by you alone whoever last edited the whole team
Based on all your previous sessions some outdated best practice project-specific sessions and your team's learnings
Tailored to you the project your team
Evolves with use one-off, doesn't persist decays silently one deliberate layer per retro
Changes reviewed N/A sometimes always
Loaded into sessions no yes yes
Stays small N/A grows unbounded 500 token limit, spokes on demand
get started

First layer deposited in ten minutes.

Free. MIT licensed. Node 18+. Uses your existing Claude Code auth, no separate API key needed. If you don't have the CLI, set ANTHROPIC_API_KEY and Patina falls back to the SDK.

first run
$ npm install -g @lcvbeek/patina
$ cd your-project
$ patina init        # scaffolds .patina/
$ patina run         # onboarding on first run
$ git commit -m "first patina layer"
faq

Any questions?

What's a harness and why does it need maintenance? +

As Vivek Trivedi puts it: "if you're not the model, you're the harness." System prompts, tool definitions, approval gates, skills, MCPs, orchestration, working agreements — everything around the model that turns it into an agent.

Models ship every few months; your harness doesn't update itself. Two things go wrong when no one tends it. First, capability gets absorbed: guardrails and workarounds written for an older model's failure modes turn into dead weight the next model has to work around. Second, the harness overfits — tool descriptions, prompts, and constraints quietly get shaped to one model's quirks, and a new release exposes the mismatch as regressions.

Patina is the maintenance loop. Each cycle it reads your session logs, surfaces what's actually tripping the agent up, and proposes a reviewed edit to PATINA.md — so the harness keeps pace with the model instead of fossilizing around it.

Can I use Patina solo? +
Absolutely. Your personal PATINA.md gets sharper over time: fewer repeated mistakes, less wasted context — a record of what worked for you, continuously refined. You can also reuse the same PATINA.md across all your repos. Your working style stays consistent, not tied to any single codebase.
How does this work for a team? +
Point dataDir in .patina/config.json to a shared location (a small dedicated repo works well — no secrets, UUID-named files, never a merge conflict). Then: anyone captures notable moments with patina capture throughout the cycle; each person runs patina reflect before the retro (~10 min, on their own machine); one person runs patina run, which ingests Claude Code logs from all team members and synthesizes every voice into a proposed change. Commit the updated PATINA.md and context files to sync with your team.
Why not just edit CLAUDE.md directly? +
PATINA.md is a structured format Patina can reliably parse, section-match, and append to. patina init wires it into your CLAUDE.md via @.patina/PATINA.md, so agents always get the latest version. Keeping it separate means Patina never risks corrupting your hand-written CLAUDE.md content.
How does PATINA.md load into Claude Code? +
Every session loads the slim core (max ~500 tokens) automatically via the import line in CLAUDE.md. Extended context lives in .patina/context/ as spoke files, indexed inside PATINA.md so agents can pull them when relevant. More context actively reduces model precision — keeping the core tight matters.
Why the reflection questions? +
The reflection questions supplement the session log data and give Claude qualitative signal the JSONL doesn't contain: what felt frustrating, what nearly went wrong, etc. Run patina reflect before the retro — each person on their own machine — then patina run aggregates all answers.
Won't PATINA.md get outdated as best practices evolve? +
Probably. But each cycle refines the context, so it stays relevant. Because Patina uses Claude to synthesize, it can take new patterns and capabilities into account automatically.