@lcvbeek/patina 0.3.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 (57) hide show
  1. package/README.md +186 -87
  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 +100 -72
  5. package/dist/commands/apply.js.map +1 -1
  6. package/dist/commands/capture.d.ts +1 -1
  7. package/dist/commands/capture.d.ts.map +1 -1
  8. package/dist/commands/capture.js +35 -26
  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 +12 -12
  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 +24 -61
  15. package/dist/commands/init.js.map +1 -1
  16. package/dist/commands/layers.d.ts.map +1 -1
  17. package/dist/commands/layers.js +50 -34
  18. package/dist/commands/layers.js.map +1 -1
  19. package/dist/commands/onboard.d.ts +1 -1
  20. package/dist/commands/onboard.d.ts.map +1 -1
  21. package/dist/commands/onboard.js +85 -68
  22. package/dist/commands/onboard.js.map +1 -1
  23. package/dist/commands/reflect.d.ts +2 -0
  24. package/dist/commands/reflect.d.ts.map +1 -0
  25. package/dist/commands/reflect.js +95 -0
  26. package/dist/commands/reflect.js.map +1 -0
  27. package/dist/commands/run.d.ts +8 -6
  28. package/dist/commands/run.d.ts.map +1 -1
  29. package/dist/commands/run.js +147 -212
  30. package/dist/commands/run.js.map +1 -1
  31. package/dist/commands/status.d.ts.map +1 -1
  32. package/dist/commands/status.js +17 -25
  33. package/dist/commands/status.js.map +1 -1
  34. package/dist/index.js +48 -46
  35. package/dist/index.js.map +1 -1
  36. package/dist/lib/claude.d.ts.map +1 -1
  37. package/dist/lib/claude.js +25 -20
  38. package/dist/lib/claude.js.map +1 -1
  39. package/dist/lib/git.js +3 -3
  40. package/dist/lib/lint.js +14 -14
  41. package/dist/lib/metrics.d.ts +1 -1
  42. package/dist/lib/metrics.d.ts.map +1 -1
  43. package/dist/lib/metrics.js +9 -12
  44. package/dist/lib/metrics.js.map +1 -1
  45. package/dist/lib/parser.d.ts +1 -1
  46. package/dist/lib/parser.d.ts.map +1 -1
  47. package/dist/lib/parser.js +36 -36
  48. package/dist/lib/parser.js.map +1 -1
  49. package/dist/lib/questions.d.ts +14 -0
  50. package/dist/lib/questions.d.ts.map +1 -0
  51. package/dist/lib/questions.js +58 -0
  52. package/dist/lib/questions.js.map +1 -0
  53. package/dist/lib/storage.d.ts +52 -10
  54. package/dist/lib/storage.d.ts.map +1 -1
  55. package/dist/lib/storage.js +126 -60
  56. package/dist/lib/storage.js.map +1 -1
  57. package/package.json +4 -2
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,7 +5,7 @@
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
 
@@ -19,18 +17,18 @@ Patina helps you observe what's working, trim what isn't, and keep your context
19
17
 
20
18
  ```text
21
19
  patina capture # anyone on the team, anytime
22
- → records a notable moment to .patina/captures/
23
- → 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)
24
24
 
25
- patina run # when you're ready for a retro
25
+ patina run # when the team is ready
26
26
  → auto-ingests Claude Code JSONL logs
27
- → loads all captures since the last cycle
28
- 6 reflection questions (~10 min)
29
- → Claude synthesises session data + captures + your answers
27
+ → loads all captures and reflections since the last cycle
28
+ Claude synthesises session data + captures + reflections
30
29
  → coaching insight + proposed instruction diff
31
30
 
32
- patina diff # review the proposed change
33
- patina buff # apply it to .patina/patina.md
31
+ patina buff # review the diff and apply it to .patina/PATINA.md
34
32
  ```
35
33
 
36
34
  Next session, the whole team works from an updated set of shared instructions.
@@ -67,9 +65,8 @@ npm install -g @lcvbeek/patina
67
65
  ```bash
68
66
  cd your-project
69
67
  patina init # set up scaffolding
70
- patina run # answer onboarding questions
71
- patina diff # review proposed changes
72
- patina buff # apply the changes
68
+ patina run # answer onboarding questions (first time only)
69
+ patina buff # review and apply proposed changes
73
70
  git commit -m "First patina layer"
74
71
  ```
75
72
 
@@ -79,16 +76,24 @@ If you have no prior Claude Code session data, `patina run` will still work —
79
76
 
80
77
  ## Commands
81
78
 
82
- | Command | What it does |
83
- |---|---|
84
- | `patina init` | Scaffold `.patina/` in the current directory, create `patina.md` |
85
- | `patina capture [text]` | Capture a notable moment while it's fresh — feeds into the next retro |
86
- | `patina run` | Full retro session auto-ingests logs, loads captures, asks reflection questions, calls Claude for synthesis |
87
- | `patina diff` | Review the proposed instruction change from the last `patina run` |
88
- | `patina buff` | Apply the pending diff to `patina.md` or spoke file (`patina apply` also works) |
89
- | `patina 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 |
90
- | `patina 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 |
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,63 +105,155 @@ 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.
106
156
 
107
157
  ### patina ingest
108
158
 
109
- 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.
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.
110
164
 
111
- To include sessions from additional repos (e.g. a backend and frontend that share the same patina), add partial slug patterns to `.patina/config.json`:
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:
112
185
 
113
186
  ```json
114
187
  {
115
- "include": ["my-backend-repo", "my-frontend-repo"]
188
+ "include": [],
189
+ "exclude": [],
190
+ "dataDir": "../our-patina-data"
116
191
  }
117
192
  ```
118
193
 
119
- Patterns are matched as substrings against the project slug, so they work across machines with different home directories. `config.json` is committed — it's a team decision, not a personal one.
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 |
120
199
 
121
- Run `patina status` to see a breakdown by project and confirm what's being counted.
200
+ You can also set `PATINA_DATA_DIR` as an environment variable to override `dataDir` per-session (useful for testing).
122
201
 
123
202
  ---
124
203
 
125
204
  ## Team retros
126
205
 
127
- Patina works for a single developer, but it's designed for teams. The `patina.md` constitution, cycle reports, and captures all live in git everyone shares the same document, and anyone can contribute a capture.
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.
128
225
 
129
- To include teammates' session data in a retro:
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.
130
227
 
131
- 1. Each person runs `patina ingest` on their machine before the retro
132
- 2. They commit and push their session files from `.patina/sessions/`
133
- 3. Everyone pulls
134
- 4. Whoever runs `patina run` gets the full team's sessions in the synthesis
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`:
135
229
 
136
- Sessions are gitignored by default. To opt in, remove `.patina/sessions/` from your `.gitignore`. Sessions are UUID-named JSON files (~500 bytes each) with no conversation content — safe to commit, no merge conflicts.
230
+ ```json
231
+ {
232
+ "include": ["my-backend", "my-frontend"],
233
+ "dataDir": "../our-patina-data"
234
+ }
235
+ ```
137
236
 
138
- If your team prefers not to commit sessions to the production repo, a future `dataDir` config option will let you point session storage at a dedicated repo instead.
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.
139
238
 
140
239
  ---
141
240
 
142
241
  ## What gets committed
143
242
 
144
- `.patina/` is partially tracked:
243
+ Everything in `.patina/` is committed — there's nothing to gitignore:
244
+
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 |
145
251
 
146
- | Path | Committed | Why |
147
- |---|---|---|
148
- | `.patina/patina.md` | Yes | The shared AI operating document (slim core) |
149
- | `.patina/config.json` | Yes | Project include list — team decision, shared across machines |
150
- | `.patina/context/` | Yes | Spoke files — extended context loaded on demand |
151
- | `.patina/cycles/` | Yes | Each layer — full cycle reports |
152
- | `.patina/captures/` | Yes | In-the-moment observations from anyone on the team |
153
- | `.patina/sessions/` | Optional | Session metadata from all team members — safe to commit, UUID-named so no merge conflicts |
154
- | `.patina/metrics.json` | No | Derived from sessions, not a source of truth |
155
- | `.patina/pending-diff.json` | No | Ephemeral — consumed by `patina buff` |
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.
156
253
 
157
254
  ---
158
255
 
159
- ## What `patina.md` is
256
+ ## What `PATINA.md` is
160
257
 
161
258
  Your team's AI operating constitution. The slim core (~50 lines) has
162
259
  sections for working agreements, a behavior contract, and hard guardrails —
@@ -174,12 +271,12 @@ Claude during synthesis.
174
271
  `patina init` adds the following line to your project's `CLAUDE.md` (creating it if it doesn't exist):
175
272
 
176
273
  ```text
177
- @.patina/patina.md
274
+ @.patina/PATINA.md
178
275
  ```
179
276
 
180
277
  Claude Code's `@filename` import syntax means every Claude Code session in
181
- the project automatically gets the contents of `patina.md` — no manual
182
- 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
183
280
  change in the next session.
184
281
 
185
282
  ---
@@ -206,7 +303,7 @@ What is never sent to Claude:
206
303
 
207
304
  `/insights` produces a personal HTML report in `~/.claude/` — useful
208
305
  analysis, but it belongs to one person and doesn't persist between sessions.
209
- 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,
210
307
  is versioned with git, and accumulates layers across cycles. The goal isn't
211
308
  better analysis — it's a shared artifact your team actually owns and
212
309
  maintains together.
@@ -215,11 +312,11 @@ maintains together.
215
312
 
216
313
  ## Early software
217
314
 
218
- This is v0.3.0. It works, but expect rough edges:
315
+ This is early software. It works, but expect rough edges:
219
316
 
220
317
  - The `claude` CLI call in `patina run` has a 120-second timeout; if Claude
221
- is slow the command will fail (your reflection answers are saved to
222
- `.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)
223
320
  - Session ingestion parses Claude Code's JSONL format — if Anthropic changes
224
321
  that format, ingestion will break
225
322
  - Token estimates are heuristic, not exact
@@ -234,7 +331,7 @@ Patina uses a **hub+spoke** model to keep agent context lean:
234
331
 
235
332
  ```text
236
333
  .patina/
237
- patina.md ← slim core (~50 lines, ~500 tokens). Always loaded.
334
+ PATINA.md ← slim core (~50 lines, ~500 tokens). Always loaded.
238
335
  context/
239
336
  autonomy-detail.md ← full autonomy map with routine scenarios
240
337
  incident-log.md ← past agent incidents
@@ -243,9 +340,9 @@ Patina uses a **hub+spoke** model to keep agent context lean:
243
340
  opportunity-backlog.md ← improvement ideas
244
341
  ```
245
342
 
246
- The **core** (`patina.md`) contains only the highest-value content: working
343
+ The **core** (`PATINA.md`) contains only the highest-value content: working
247
344
  agreements, a behavior contract, and hard guardrails. It's loaded into
248
- every Claude Code session via `@.patina/patina.md` in `CLAUDE.md`.
345
+ every Claude Code session via `@.patina/PATINA.md` in `CLAUDE.md`.
249
346
 
250
347
  **Spoke files** hold content that's useful during specific activities
251
348
  (debugging, testing, retro reviews) but would waste tokens if loaded every
@@ -254,7 +351,7 @@ comment index pointing to each spoke file.
254
351
 
255
352
  `patina buff` automatically routes proposed changes to the correct file
256
353
  based on section number. `patina migrate` splits an existing monolithic
257
- `patina.md` into the hub+spoke layout.
354
+ `PATINA.md` into the hub+spoke layout.
258
355
 
259
356
  ### Why this matters
260
357
 
@@ -273,50 +370,52 @@ are flagged for removal each cycle.
273
370
  ## Design decisions
274
371
 
275
372
  <details>
276
- <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>
277
374
 
278
- `patina.md` is a structured format Patina can reliably parse, section-match,
279
- and append to. `patina init` wires it into your `CLAUDE.md` via
280
- `@.patina/patina.md`, so agents always get the latest version. Keeping it
281
- separate means Patina never risks corrupting your hand-written `CLAUDE.md`
282
- content.
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.
376
+
377
+ Everything operational lives in `~/.patina/projects/<slug>/` (or a shared `dataDir`) and is never committed. Nothing in `.patina/` needs to be gitignored.
283
378
 
284
379
  </details>
285
380
 
286
381
  <details>
287
- <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>
288
383
 
289
- A monolithic `patina.md` grows unboundedly as cycles accumulate. After 10+
290
- cycles, sections like incident log and cycle history add hundreds of tokens
291
- that are rarely relevant. The hub+spoke model keeps always-loaded context at
292
- ~500 tokens while preserving all data in spoke files for when it's needed.
293
- 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.
294
385
 
295
386
  </details>
296
387
 
297
388
  <details>
298
- <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>
299
390
 
300
- No separate API key needed it respects your existing Claude Code
301
- authentication and model access. If you don't have the CLI, set
302
- `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.
303
392
 
304
393
  </details>
305
394
 
306
395
  <details>
307
- <summary><b>Why six reflection questions?</b></summary>
396
+ <summary><b>Why the <code>claude</code> CLI instead of the API directly?</b></summary>
308
397
 
309
- The reflection questions supplement sparse log data and give Claude
310
- qualitative signal the JSONL doesn't contain — what felt frustrating, what
311
- nearly went wrong. Both matter for the synthesis. The first cycle asks 9
312
- 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.
313
399
 
314
400
  </details>
315
401
 
316
402
  <details>
317
- <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
+ ```
318
418
 
319
- Multiple teammates capturing on the same day would produce merge conflicts
320
- 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.
321
420
 
322
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":"AAqCA;;;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,CA4HlD"}
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"}