@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.
Files changed (61) hide show
  1. package/README.md +211 -78
  2. package/dist/commands/apply.d.ts +5 -3
  3. package/dist/commands/apply.d.ts.map +1 -1
  4. package/dist/commands/apply.js +106 -71
  5. package/dist/commands/apply.js.map +1 -1
  6. package/dist/commands/capture.d.ts +2 -1
  7. package/dist/commands/capture.d.ts.map +1 -1
  8. package/dist/commands/capture.js +46 -32
  9. package/dist/commands/capture.js.map +1 -1
  10. package/dist/commands/ingest.d.ts.map +1 -1
  11. package/dist/commands/ingest.js +22 -9
  12. package/dist/commands/ingest.js.map +1 -1
  13. package/dist/commands/init.d.ts.map +1 -1
  14. package/dist/commands/init.js +33 -33
  15. package/dist/commands/init.js.map +1 -1
  16. package/dist/commands/layers.d.ts +5 -1
  17. package/dist/commands/layers.d.ts.map +1 -1
  18. package/dist/commands/layers.js +115 -76
  19. package/dist/commands/layers.js.map +1 -1
  20. package/dist/commands/onboard.d.ts +1 -1
  21. package/dist/commands/onboard.d.ts.map +1 -1
  22. package/dist/commands/onboard.js +90 -73
  23. package/dist/commands/onboard.js.map +1 -1
  24. package/dist/commands/reflect.d.ts +2 -0
  25. package/dist/commands/reflect.d.ts.map +1 -0
  26. package/dist/commands/reflect.js +95 -0
  27. package/dist/commands/reflect.js.map +1 -0
  28. package/dist/commands/run.d.ts +8 -6
  29. package/dist/commands/run.d.ts.map +1 -1
  30. package/dist/commands/run.js +170 -209
  31. package/dist/commands/run.js.map +1 -1
  32. package/dist/commands/status.d.ts.map +1 -1
  33. package/dist/commands/status.js +17 -25
  34. package/dist/commands/status.js.map +1 -1
  35. package/dist/index.js +50 -56
  36. package/dist/index.js.map +1 -1
  37. package/dist/lib/claude.d.ts.map +1 -1
  38. package/dist/lib/claude.js +35 -24
  39. package/dist/lib/claude.js.map +1 -1
  40. package/dist/lib/git.d.ts +2 -0
  41. package/dist/lib/git.d.ts.map +1 -0
  42. package/dist/lib/git.js +9 -0
  43. package/dist/lib/git.js.map +1 -0
  44. package/dist/lib/lint.js +14 -14
  45. package/dist/lib/metrics.d.ts +1 -1
  46. package/dist/lib/metrics.d.ts.map +1 -1
  47. package/dist/lib/metrics.js +9 -12
  48. package/dist/lib/metrics.js.map +1 -1
  49. package/dist/lib/parser.d.ts +7 -1
  50. package/dist/lib/parser.d.ts.map +1 -1
  51. package/dist/lib/parser.js +46 -37
  52. package/dist/lib/parser.js.map +1 -1
  53. package/dist/lib/questions.d.ts +14 -0
  54. package/dist/lib/questions.d.ts.map +1 -0
  55. package/dist/lib/questions.js +58 -0
  56. package/dist/lib/questions.js.map +1 -0
  57. package/dist/lib/storage.d.ts +85 -12
  58. package/dist/lib/storage.d.ts.map +1 -1
  59. package/dist/lib/storage.js +165 -57
  60. package/dist/lib/storage.js.map +1 -1
  61. 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
  [![npm version](https://img.shields.io/npm/v/@lcvbeek/patina.svg)](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, `patina.md` builds up
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 to .patina/captures/
21
- → committed to the repo, visible to everyone
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 you're ready for a retro
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
- 6 reflection questions (~10 min)
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 diff # review the proposed change
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 # creates .patina/ and patina.md
68
- patina run # first cycle — answer 9 onboarding questions (~10 min)
69
- patina diff # review what Claude proposed
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 | What it does |
82
- |---|---|
83
- | `patina init` | Scaffold `.patina/` in the current directory, create `patina.md` |
84
- | `patina capture [text]` | Capture a notable moment while it's fresh — feeds into the next retro |
85
- | `patina run` | Full retro session auto-ingests logs, loads captures, asks reflection questions, calls Claude for synthesis |
86
- | `patina diff` | Review the proposed instruction change from the last `patina run` |
87
- | `patina buff` | Apply the pending diff to `patina.md` or spoke file (`patina apply` also works) |
88
- | `patina migrate` | Split a monolithic `patina.md` into slim core + spoke files |
89
- | `patina status` | Show metrics: token spend, rework rate, tool usage, trends across cycles |
90
- | `patina layers` | Visualise the patina you've builtone ASCII layer per retro cycle |
91
- | `patina ingest` | Manually parse Claude Code logs (optional — `patina run` does this automatically) |
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 `.patina/captures/` as individual JSON files
104
- (one per capture, to avoid merge conflicts) and committed to the repo.
105
- Author is read from `git config user.name`.
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 partially tracked:
243
+ Everything in `.patina/` is committed — there's nothing to gitignore:
112
244
 
113
- | Path | Committed | Why |
114
- |---|---|---|
115
- | `.patina/patina.md` | Yes | The shared AI operating document (slim core) |
116
- | `.patina/context/` | Yes | Spoke files extended context loaded on demand |
117
- | `.patina/cycles/` | Yes | Each layer full cycle reports |
118
- | `.patina/captures/` | Yes | In-the-moment observations from anyone on the team |
119
- | `.patina/sessions/` | No | Personal session data, machine-specific |
120
- | `.patina/metrics.json` | No | Derived from sessions, not a source of truth |
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 listteam 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 `patina.md` is
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, agent profiles, and hard guardrails —
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/patina.md
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 `patina.md` — no manual
148
- copying needed. When `patina buff` updates `patina.md`, Claude picks up the
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 `patina.md`, a structured document that lives in your repo,
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 v0.1.0. It works, but expect rough edges:
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 to
188
- `.patina/pending-reflection.json` so you can retry without re-answering)
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
- patina.md ← slim core (~50 lines, ~500 tokens). Always loaded.
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** (`patina.md`) contains only the highest-value content: working
213
- agreements, agent behavior contracts, and hard guardrails. It's loaded into
214
- every Claude Code session via `@.patina/patina.md` in `CLAUDE.md`.
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
- `patina.md` into the hub+spoke layout.
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 <code>patina.md</code> instead of editing CLAUDE.md directly?</b></summary>
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
- `patina.md` is a structured format Patina can reliably parse, section-match,
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 hub+spoke instead of one file?</b></summary>
382
+ <summary><b>Why <code>PATINA.md</code> instead of editing CLAUDE.md directly?</b></summary>
254
383
 
255
- A monolithic `patina.md` grows unboundedly as cycles accumulate. After 10+
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 the <code>claude</code> CLI instead of the API directly?</b></summary>
389
+ <summary><b>Why hub+spoke instead of one file?</b></summary>
265
390
 
266
- No separate API key needed it respects your existing Claude Code
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 six reflection questions?</b></summary>
396
+ <summary><b>Why the <code>claude</code> CLI instead of the API directly?</b></summary>
274
397
 
275
- The reflection questions supplement sparse log data and give Claude
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>Why individual capture files instead of one file?</b></summary>
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
- Multiple teammates capturing on the same day would produce merge conflicts
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>
@@ -1,11 +1,11 @@
1
1
  /**
2
- * Find the section header in patina.md and insert the diff text after it.
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 patina.md).
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(): Promise<void>;
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":"AAoCA;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CA+DzF;AAID;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CA6C/F;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAc7F;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAoHlD"}
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"}