@lcvbeek/patina 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +211 -78
- package/dist/commands/apply.d.ts +5 -3
- package/dist/commands/apply.d.ts.map +1 -1
- package/dist/commands/apply.js +106 -71
- package/dist/commands/apply.js.map +1 -1
- package/dist/commands/capture.d.ts +2 -1
- package/dist/commands/capture.d.ts.map +1 -1
- package/dist/commands/capture.js +46 -32
- package/dist/commands/capture.js.map +1 -1
- package/dist/commands/ingest.d.ts.map +1 -1
- package/dist/commands/ingest.js +22 -9
- package/dist/commands/ingest.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +33 -33
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/layers.d.ts +5 -1
- package/dist/commands/layers.d.ts.map +1 -1
- package/dist/commands/layers.js +115 -76
- package/dist/commands/layers.js.map +1 -1
- package/dist/commands/onboard.d.ts +1 -1
- package/dist/commands/onboard.d.ts.map +1 -1
- package/dist/commands/onboard.js +90 -73
- package/dist/commands/onboard.js.map +1 -1
- package/dist/commands/reflect.d.ts +2 -0
- package/dist/commands/reflect.d.ts.map +1 -0
- package/dist/commands/reflect.js +95 -0
- package/dist/commands/reflect.js.map +1 -0
- package/dist/commands/run.d.ts +8 -6
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +170 -209
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +17 -25
- package/dist/commands/status.js.map +1 -1
- package/dist/index.js +50 -56
- package/dist/index.js.map +1 -1
- package/dist/lib/claude.d.ts.map +1 -1
- package/dist/lib/claude.js +35 -24
- package/dist/lib/claude.js.map +1 -1
- package/dist/lib/git.d.ts +2 -0
- package/dist/lib/git.d.ts.map +1 -0
- package/dist/lib/git.js +9 -0
- package/dist/lib/git.js.map +1 -0
- package/dist/lib/lint.js +14 -14
- package/dist/lib/metrics.d.ts +1 -1
- package/dist/lib/metrics.d.ts.map +1 -1
- package/dist/lib/metrics.js +9 -12
- package/dist/lib/metrics.js.map +1 -1
- package/dist/lib/parser.d.ts +7 -1
- package/dist/lib/parser.d.ts.map +1 -1
- package/dist/lib/parser.js +46 -37
- package/dist/lib/parser.js.map +1 -1
- package/dist/lib/questions.d.ts +14 -0
- package/dist/lib/questions.d.ts.map +1 -0
- package/dist/lib/questions.js +58 -0
- package/dist/lib/questions.js.map +1 -0
- package/dist/lib/storage.d.ts +85 -12
- package/dist/lib/storage.d.ts.map +1 -1
- package/dist/lib/storage.js +165 -57
- package/dist/lib/storage.js.map +1 -1
- package/package.json +6 -4
package/README.md
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
<img width="250" height="72" alt="Patina (2)" src="https://github.com/user-attachments/assets/77650975-b20b-4a65-b582-bb86ff6c2ae3" />
|
|
2
|
-
|
|
3
1
|
# Patina
|
|
4
2
|
|
|
5
3
|
[](https://www.npmjs.com/package/@lcvbeek/patina)
|
|
@@ -7,28 +5,30 @@
|
|
|
7
5
|
|
|
8
6
|
Patina is what forms naturally when you keep working with AI. Each retro
|
|
9
7
|
cycle deposits a thin layer — captured moments, reflection answers, Claude's
|
|
10
|
-
synthesis, a proposed instruction change. Over time, `
|
|
8
|
+
synthesis, a proposed instruction change. Over time, `PATINA.md` builds up
|
|
11
9
|
into something with real depth: a working record of how your team uses AI,
|
|
12
10
|
versioned in git, shared by everyone including new hires.
|
|
13
11
|
|
|
12
|
+
Patina helps you observe what's working, trim what isn't, and keep your context tight.
|
|
13
|
+
|
|
14
14
|
---
|
|
15
15
|
|
|
16
16
|
## How it works
|
|
17
17
|
|
|
18
18
|
```text
|
|
19
19
|
patina capture # anyone on the team, anytime
|
|
20
|
-
→ records a notable moment
|
|
21
|
-
|
|
20
|
+
→ records a notable moment
|
|
21
|
+
|
|
22
|
+
patina reflect # each person, before the retro
|
|
23
|
+
→ reflection questions (6 included, customizable)
|
|
22
24
|
|
|
23
|
-
patina run # when
|
|
25
|
+
patina run # when the team is ready
|
|
24
26
|
→ auto-ingests Claude Code JSONL logs
|
|
25
|
-
→ loads all captures since the last cycle
|
|
26
|
-
→
|
|
27
|
-
→ Claude synthesises session data + captures + your answers
|
|
27
|
+
→ loads all captures and reflections since the last cycle
|
|
28
|
+
→ Claude synthesises session data + captures + reflections
|
|
28
29
|
→ coaching insight + proposed instruction diff
|
|
29
30
|
|
|
30
|
-
patina
|
|
31
|
-
patina buff # apply it to .patina/patina.md
|
|
31
|
+
patina buff # review the diff and apply it to .patina/PATINA.md
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
Next session, the whole team works from an updated set of shared instructions.
|
|
@@ -64,11 +64,9 @@ npm install -g @lcvbeek/patina
|
|
|
64
64
|
|
|
65
65
|
```bash
|
|
66
66
|
cd your-project
|
|
67
|
-
patina init #
|
|
68
|
-
patina run #
|
|
69
|
-
patina
|
|
70
|
-
patina buff # apply the change
|
|
71
|
-
git add .patina/patina.md .patina/cycles/ .patina/captures/
|
|
67
|
+
patina init # set up scaffolding
|
|
68
|
+
patina run # answer onboarding questions (first time only)
|
|
69
|
+
patina buff # review and apply proposed changes
|
|
72
70
|
git commit -m "First patina layer"
|
|
73
71
|
```
|
|
74
72
|
|
|
@@ -78,17 +76,24 @@ If you have no prior Claude Code session data, `patina run` will still work —
|
|
|
78
76
|
|
|
79
77
|
## Commands
|
|
80
78
|
|
|
81
|
-
| Command
|
|
82
|
-
|
|
83
|
-
| `
|
|
84
|
-
| `
|
|
85
|
-
| `
|
|
86
|
-
| `
|
|
87
|
-
| `
|
|
88
|
-
| `
|
|
89
|
-
| `patina
|
|
90
|
-
| `
|
|
91
|
-
|
|
79
|
+
| Command | What it does |
|
|
80
|
+
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
81
|
+
| `init` | Scaffold `.patina/` in the current directory, create `PATINA.md` |
|
|
82
|
+
| `capture` | Capture a notable moment while it's fresh — feeds into the next retro |
|
|
83
|
+
| `reflect` | Answer reflection questions before the retro — saved locally, loaded by `patina run` |
|
|
84
|
+
| `run` | Run the retro — auto-ingests logs, loads captures + reflections, calls Claude for synthesis |
|
|
85
|
+
| `buff` (`apply`) | Review the proposed instruction change and apply it — shows diff, prompts for confirmation |
|
|
86
|
+
| `status` | Show metrics: token spend, rework rate, tool usage, trends across cycles. Shows a breakdown by project so you can verify which repos are being included |
|
|
87
|
+
| `layers` | Visualise the patina you've built — one ASCII layer per retro cycle. Shows 5 most recent by default; use `-n 10` for more or `-n 0` for all |
|
|
88
|
+
| `ingest` | Manually parse Claude Code logs (optional — `patina run` does this automatically) |
|
|
89
|
+
|
|
90
|
+
### patina init
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
patina init
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Creates `.patina/` with `PATINA.md`, `config.json`, `context/`, and `cycles/`. Adds `@.patina/PATINA.md` to `CLAUDE.md` (creating it if needed). Safe to run once per project.
|
|
92
97
|
|
|
93
98
|
### patina capture
|
|
94
99
|
|
|
@@ -100,32 +105,158 @@ patina capture # interactive mode
|
|
|
100
105
|
|
|
101
106
|
Tags: `near-miss` / `went-well` / `frustration` / `pattern` / `other`
|
|
102
107
|
|
|
103
|
-
Captures are written to
|
|
104
|
-
|
|
105
|
-
|
|
108
|
+
Captures are written to `~/.patina/projects/<slug>/captures/` as individual JSON files — one per capture, so there are never merge conflicts. Author is read from `git config user.name`.
|
|
109
|
+
|
|
110
|
+
### patina reflect
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
patina reflect
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Walks through the reflection questions and saves answers locally. Run this before `patina run`. On a team, each person reflects on their own machine — `patina run` aggregates all answers recorded since the last cycle.
|
|
117
|
+
|
|
118
|
+
Reflection questions can be customised by adding `.patina/questions.json` to the project (committed, so the whole team uses the same set).
|
|
119
|
+
|
|
120
|
+
### patina run
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
patina run
|
|
124
|
+
patina run --onboard # force onboarding questions
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Auto-ingests Claude Code logs, loads all captures and reflections since the last cycle, calls Claude for synthesis, and writes the result to `.patina/cycles/<date>.md` and a pending diff. On first run, asks onboarding questions to establish your baseline agreements instead.
|
|
128
|
+
|
|
129
|
+
### patina buff
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
patina buff # show diff, prompt to apply
|
|
133
|
+
patina buff --yes # apply without prompting
|
|
134
|
+
patina apply # alias
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Shows the pending instruction diff from the last `patina run` — rationale, target file, and the proposed addition — then prompts for confirmation. Applies to the correct file (core or spoke, based on section number) and clears the pending diff.
|
|
138
|
+
|
|
139
|
+
### patina status
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
patina status
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Shows token spend, rework rate, tool usage, and trends across cycles. Includes a per-project breakdown so you can verify which repos are contributing to your metrics.
|
|
146
|
+
|
|
147
|
+
### patina layers
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
patina layers # 5 most recent cycles
|
|
151
|
+
patina layers -n 10 # last 10
|
|
152
|
+
patina layers -n 0 # all
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Renders one ASCII layer per retro cycle — a quick visual of how your patina has built up over time.
|
|
156
|
+
|
|
157
|
+
### patina ingest
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
patina ingest
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Manually parses Claude Code JSONL logs and writes session summaries to the data dir. `patina run` does this automatically — use this to pre-populate metrics or debug ingestion. By default, only sessions from the **current project** are ingested — Patina derives the project slug from your working directory and matches it against `~/.claude/projects/`. This keeps metrics clean and prevents unrelated tools or automation from polluting your data.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Data directory
|
|
168
|
+
|
|
169
|
+
All operational data — sessions, captures, reflections, metrics, and pending diffs — lives outside the project repo. By default it goes to:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
~/.patina/projects/<slug>/
|
|
173
|
+
sessions/
|
|
174
|
+
captures/
|
|
175
|
+
reflections/
|
|
176
|
+
metrics.json
|
|
177
|
+
pending-diff.json
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
The slug is derived from your working directory path (e.g. `/Users/lcvbeek/work/api` → `-Users-lcvbeek-work-api`), mirroring how Claude Code stores its own session data in `~/.claude/projects/`. Each project on your machine is automatically isolated.
|
|
181
|
+
|
|
182
|
+
Nothing in `.patina/` needs to be gitignored — the project directory contains only committed artifacts.
|
|
183
|
+
|
|
184
|
+
**Overriding the data dir.** Set `dataDir` in `.patina/config.json` to redirect all data to a different location. The path is resolved relative to the project root, so it works across machines with different home directories:
|
|
185
|
+
|
|
186
|
+
```json
|
|
187
|
+
{
|
|
188
|
+
"include": [],
|
|
189
|
+
"exclude": [],
|
|
190
|
+
"dataDir": "../our-patina-data"
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
| Field | Type | Default | Description |
|
|
195
|
+
| --------- | ---------- | ---------------------------- | ---------------------------------------------------------------------------------------------------- |
|
|
196
|
+
| `include` | `string[]` | `[]` | Slug substrings of additional projects to ingest (e.g. `["api", "frontend"]`) |
|
|
197
|
+
| `exclude` | `string[]` | `[]` | Slug substrings to exclude — takes precedence over `include`. Useful when include patterns are broad |
|
|
198
|
+
| `dataDir` | `string` | `~/.patina/projects/<slug>/` | Path to shared data directory (relative to project root). Set this for team retros |
|
|
199
|
+
|
|
200
|
+
You can also set `PATINA_DATA_DIR` as an environment variable to override `dataDir` per-session (useful for testing).
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Team retros
|
|
205
|
+
|
|
206
|
+
Patina works for a single developer, but it's designed to support teams. Point `dataDir` in `.patina/config.json` to a shared location and everyone's captures, reflections, and session data land in the same place:
|
|
207
|
+
|
|
208
|
+
```json
|
|
209
|
+
{
|
|
210
|
+
"include": [],
|
|
211
|
+
"dataDir": "../our-patina-data"
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
The path is resolved relative to the project root, so it works across machines. A dedicated repo works well — files are small, contain no secrets, and are UUID-named so there are never merge conflicts.
|
|
216
|
+
|
|
217
|
+
**The retro flow for a team:**
|
|
218
|
+
|
|
219
|
+
1. Anyone captures notable moments throughout the cycle with `patina capture`
|
|
220
|
+
2. Before the retro, each person runs `patina reflect` (~10 min)
|
|
221
|
+
3. One person runs `patina run` — it loads all captures and reflections since the last cycle, calls Claude, and produces a synthesis with every team member's voice
|
|
222
|
+
4. Review and apply with `patina buff`, commit the updated `PATINA.md`
|
|
223
|
+
|
|
224
|
+
Without `dataDir`, all data stays local to each machine (`~/.patina/projects/<slug>/`). `patina run` will only see what's been captured and reflected on the machine it runs on — useful for solo use, but not a full team retro.
|
|
225
|
+
|
|
226
|
+
**Multiple projects on one machine.** Each project gets its own data directory automatically — the slug is derived from the working directory path, so `/Users/leo/work/api` and `/Users/leo/work/frontend` are always isolated from each other.
|
|
227
|
+
|
|
228
|
+
If a team works across multiple repos that share the same `PATINA.md` (e.g. a backend and a frontend), you can pull their session data into a single retro using the `include` list in `config.json`:
|
|
229
|
+
|
|
230
|
+
```json
|
|
231
|
+
{
|
|
232
|
+
"include": ["my-backend", "my-frontend"],
|
|
233
|
+
"dataDir": "../our-patina-data"
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Entries in `include` are matched as substrings against the project slug, so they work across machines regardless of home directory. `config.json` is committed — it's a team decision, not a personal one. Run `patina status` to see a breakdown by project and confirm what's being counted.
|
|
106
238
|
|
|
107
239
|
---
|
|
108
240
|
|
|
109
241
|
## What gets committed
|
|
110
242
|
|
|
111
|
-
`.patina/` is
|
|
243
|
+
Everything in `.patina/` is committed — there's nothing to gitignore:
|
|
112
244
|
|
|
113
|
-
| Path
|
|
114
|
-
|
|
115
|
-
| `.patina/
|
|
116
|
-
| `.patina/
|
|
117
|
-
| `.patina/
|
|
118
|
-
| `.patina/
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
| `.patina/pending-diff.json` | No | Ephemeral — consumed by `patina buff` |
|
|
245
|
+
| Path | Why |
|
|
246
|
+
| --------------------- | ------------------------------------------------------------ |
|
|
247
|
+
| `.patina/PATINA.md` | The shared AI operating document (slim core) |
|
|
248
|
+
| `.patina/config.json` | Project include list — team decision, shared across machines |
|
|
249
|
+
| `.patina/context/` | Spoke files — extended context loaded on demand |
|
|
250
|
+
| `.patina/cycles/` | Each layer — full cycle reports |
|
|
251
|
+
|
|
252
|
+
All operational data (sessions, reflections, captures, metrics, pending diffs) lives in `~/.patina/projects/<slug>/` — machine-local by default, never committed. Use `dataDir` in `config.json` to share it with your team.
|
|
122
253
|
|
|
123
254
|
---
|
|
124
255
|
|
|
125
|
-
## What `
|
|
256
|
+
## What `PATINA.md` is
|
|
126
257
|
|
|
127
258
|
Your team's AI operating constitution. The slim core (~50 lines) has
|
|
128
|
-
sections for working agreements,
|
|
259
|
+
sections for working agreements, a behavior contract, and hard guardrails —
|
|
129
260
|
always loaded into every Claude Code session. Extended sections (autonomy
|
|
130
261
|
map, incident log, eval framework, cycle history) live in
|
|
131
262
|
`.patina/context/` as spoke files loaded on demand.
|
|
@@ -140,12 +271,12 @@ Claude during synthesis.
|
|
|
140
271
|
`patina init` adds the following line to your project's `CLAUDE.md` (creating it if it doesn't exist):
|
|
141
272
|
|
|
142
273
|
```text
|
|
143
|
-
@.patina/
|
|
274
|
+
@.patina/PATINA.md
|
|
144
275
|
```
|
|
145
276
|
|
|
146
277
|
Claude Code's `@filename` import syntax means every Claude Code session in
|
|
147
|
-
the project automatically gets the contents of `
|
|
148
|
-
copying needed. When `patina buff` updates `
|
|
278
|
+
the project automatically gets the contents of `PATINA.md` — no manual
|
|
279
|
+
copying needed. When `patina buff` updates `PATINA.md`, Claude picks up the
|
|
149
280
|
change in the next session.
|
|
150
281
|
|
|
151
282
|
---
|
|
@@ -172,7 +303,7 @@ What is never sent to Claude:
|
|
|
172
303
|
|
|
173
304
|
`/insights` produces a personal HTML report in `~/.claude/` — useful
|
|
174
305
|
analysis, but it belongs to one person and doesn't persist between sessions.
|
|
175
|
-
Patina produces `
|
|
306
|
+
Patina produces `PATINA.md`, a structured document that lives in your repo,
|
|
176
307
|
is versioned with git, and accumulates layers across cycles. The goal isn't
|
|
177
308
|
better analysis — it's a shared artifact your team actually owns and
|
|
178
309
|
maintains together.
|
|
@@ -181,11 +312,11 @@ maintains together.
|
|
|
181
312
|
|
|
182
313
|
## Early software
|
|
183
314
|
|
|
184
|
-
This is
|
|
315
|
+
This is early software. It works, but expect rough edges:
|
|
185
316
|
|
|
186
317
|
- The `claude` CLI call in `patina run` has a 120-second timeout; if Claude
|
|
187
|
-
is slow the command will fail (your reflection answers are saved
|
|
188
|
-
|
|
318
|
+
is slow the command will fail (your reflection answers are already saved by
|
|
319
|
+
`patina reflect`, so you can retry `patina run` without re-answering)
|
|
189
320
|
- Session ingestion parses Claude Code's JSONL format — if Anthropic changes
|
|
190
321
|
that format, ingestion will break
|
|
191
322
|
- Token estimates are heuristic, not exact
|
|
@@ -200,7 +331,7 @@ Patina uses a **hub+spoke** model to keep agent context lean:
|
|
|
200
331
|
|
|
201
332
|
```text
|
|
202
333
|
.patina/
|
|
203
|
-
|
|
334
|
+
PATINA.md ← slim core (~50 lines, ~500 tokens). Always loaded.
|
|
204
335
|
context/
|
|
205
336
|
autonomy-detail.md ← full autonomy map with routine scenarios
|
|
206
337
|
incident-log.md ← past agent incidents
|
|
@@ -209,9 +340,9 @@ Patina uses a **hub+spoke** model to keep agent context lean:
|
|
|
209
340
|
opportunity-backlog.md ← improvement ideas
|
|
210
341
|
```
|
|
211
342
|
|
|
212
|
-
The **core** (`
|
|
213
|
-
agreements,
|
|
214
|
-
every Claude Code session via `@.patina/
|
|
343
|
+
The **core** (`PATINA.md`) contains only the highest-value content: working
|
|
344
|
+
agreements, a behavior contract, and hard guardrails. It's loaded into
|
|
345
|
+
every Claude Code session via `@.patina/PATINA.md` in `CLAUDE.md`.
|
|
215
346
|
|
|
216
347
|
**Spoke files** hold content that's useful during specific activities
|
|
217
348
|
(debugging, testing, retro reviews) but would waste tokens if loaded every
|
|
@@ -220,7 +351,7 @@ comment index pointing to each spoke file.
|
|
|
220
351
|
|
|
221
352
|
`patina buff` automatically routes proposed changes to the correct file
|
|
222
353
|
based on section number. `patina migrate` splits an existing monolithic
|
|
223
|
-
`
|
|
354
|
+
`PATINA.md` into the hub+spoke layout.
|
|
224
355
|
|
|
225
356
|
### Why this matters
|
|
226
357
|
|
|
@@ -239,50 +370,52 @@ are flagged for removal each cycle.
|
|
|
239
370
|
## Design decisions
|
|
240
371
|
|
|
241
372
|
<details>
|
|
242
|
-
<summary><b>Why
|
|
373
|
+
<summary><b>Why are cycle reports committed but captures and reflections are not?</b></summary>
|
|
374
|
+
|
|
375
|
+
The distinction is input vs. output. Captures, reflections, and session logs are raw material that feeds the synthesis — they're per-machine, per-person, and ephemeral once the cycle runs. Cycle reports (`.patina/cycles/<date>.md`) are the permanent team record: the synthesised insight, proposed instruction changes, and metrics for each retro. They're what `patina layers` visualises and what new team members read to understand how the team's AI practice has evolved. They belong in git for the same reason commit history does.
|
|
243
376
|
|
|
244
|
-
|
|
245
|
-
and append to. `patina init` wires it into your `CLAUDE.md` via
|
|
246
|
-
`@.patina/patina.md`, so agents always get the latest version. Keeping it
|
|
247
|
-
separate means Patina never risks corrupting your hand-written `CLAUDE.md`
|
|
248
|
-
content.
|
|
377
|
+
Everything operational lives in `~/.patina/projects/<slug>/` (or a shared `dataDir`) and is never committed. Nothing in `.patina/` needs to be gitignored.
|
|
249
378
|
|
|
250
379
|
</details>
|
|
251
380
|
|
|
252
381
|
<details>
|
|
253
|
-
<summary><b>Why
|
|
382
|
+
<summary><b>Why <code>PATINA.md</code> instead of editing CLAUDE.md directly?</b></summary>
|
|
254
383
|
|
|
255
|
-
|
|
256
|
-
cycles, sections like incident log and cycle history add hundreds of tokens
|
|
257
|
-
that are rarely relevant. The hub+spoke model keeps always-loaded context at
|
|
258
|
-
~500 tokens while preserving all data in spoke files for when it's needed.
|
|
259
|
-
See [Context architecture](#context-architecture) for details.
|
|
384
|
+
`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.
|
|
260
385
|
|
|
261
386
|
</details>
|
|
262
387
|
|
|
263
388
|
<details>
|
|
264
|
-
<summary><b>Why
|
|
389
|
+
<summary><b>Why hub+spoke instead of one file?</b></summary>
|
|
265
390
|
|
|
266
|
-
|
|
267
|
-
authentication and model access. If you don't have the CLI, set
|
|
268
|
-
`ANTHROPIC_API_KEY` and Patina falls back to the SDK.
|
|
391
|
+
A monolithic `PATINA.md` grows unboundedly as cycles accumulate. After 10+ cycles, sections like incident log and cycle history add hundreds of tokens that are rarely relevant. The hub+spoke model keeps always-loaded context at ~500 tokens while preserving all data in spoke files for when it's needed. See [Context architecture](#context-architecture) for details.
|
|
269
392
|
|
|
270
393
|
</details>
|
|
271
394
|
|
|
272
395
|
<details>
|
|
273
|
-
<summary><b>Why
|
|
396
|
+
<summary><b>Why the <code>claude</code> CLI instead of the API directly?</b></summary>
|
|
274
397
|
|
|
275
|
-
|
|
276
|
-
qualitative signal the JSONL doesn't contain — what felt frustrating, what
|
|
277
|
-
nearly went wrong. Both matter for the synthesis. The first cycle asks 9
|
|
278
|
-
onboarding questions instead, to establish your baseline agreements.
|
|
398
|
+
No separate API key needed — it respects your existing Claude Code authentication and model access. If you don't have the CLI, set `ANTHROPIC_API_KEY` and Patina falls back to the SDK.
|
|
279
399
|
|
|
280
400
|
</details>
|
|
281
401
|
|
|
282
402
|
<details>
|
|
283
|
-
<summary><b>
|
|
403
|
+
<summary><b>Solo vs. team vs. multi-project — how the same commands scale</b></summary>
|
|
404
|
+
|
|
405
|
+
**Solo, one project.** Run `patina reflect` then `patina run`. Everything stays in `~/.patina/projects/<slug>/`. No config needed.
|
|
406
|
+
|
|
407
|
+
**Team, one project.** Add `dataDir` to `.patina/config.json` pointing at a shared repo. Everyone's captures, reflections, and session data land in the same place. Each person runs `patina reflect` on their own machine before the retro; whoever runs `patina run` gets a synthesis with all voices included.
|
|
408
|
+
|
|
409
|
+
**Team, multiple repos sharing one constitution.** Add slugs to `include` in `config.json` so `patina ingest` pulls session data from all related repos into the same retro. Use `patina status` to verify what's being counted.
|
|
410
|
+
|
|
411
|
+
```json
|
|
412
|
+
{
|
|
413
|
+
"include": ["api", "frontend"],
|
|
414
|
+
"exclude": ["api-legacy"],
|
|
415
|
+
"dataDir": "../our-patina-data"
|
|
416
|
+
}
|
|
417
|
+
```
|
|
284
418
|
|
|
285
|
-
|
|
286
|
-
in a single file. One JSON file per capture means clean parallel commits.
|
|
419
|
+
The project repo (`PATINA.md`, `cycles/`, `config.json`) stays in git. The data repo (`dataDir`) is a separate, never-built repo that just accumulates JSON files.
|
|
287
420
|
|
|
288
421
|
</details>
|
package/dist/commands/apply.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Find the section header in
|
|
2
|
+
* Find the section header in PATINA.md and insert the diff text after it.
|
|
3
3
|
* Falls back to appending at the end of the section if the header isn't found exactly.
|
|
4
4
|
*/
|
|
5
5
|
export declare function applyDiffToDoc(content: string, section: string, diffText: string): string;
|
|
6
6
|
/**
|
|
7
7
|
* Update the Retro Cycle History table.
|
|
8
|
-
* Operates on the cycle-history spoke file content (not the core
|
|
8
|
+
* Operates on the cycle-history spoke file content (not the core PATINA.md).
|
|
9
9
|
* Keeps at most CYCLE_HISTORY_CAP rows — oldest rows are dropped when the cap
|
|
10
10
|
* is exceeded. Full cycle detail is preserved in .patina/cycles/.
|
|
11
11
|
*/
|
|
@@ -14,5 +14,7 @@ export declare function updateCycleHistory(content: string, insight: string, cha
|
|
|
14
14
|
* Update the cycle history spoke file on disk.
|
|
15
15
|
*/
|
|
16
16
|
export declare function updateCycleHistoryFile(cwd: string, insight: string, changeDesc: string): void;
|
|
17
|
-
export declare function applyCommand(
|
|
17
|
+
export declare function applyCommand(options?: {
|
|
18
|
+
yes?: boolean;
|
|
19
|
+
}): Promise<void>;
|
|
18
20
|
//# sourceMappingURL=apply.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../src/commands/apply.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../src/commands/apply.ts"],"names":[],"mappings":"AAqDA;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAkEzF;AAID;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CA8C/F;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAc7F;AAED,wBAAsB,YAAY,CAAC,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CA2IjF"}
|