@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.
- package/README.md +186 -87
- package/dist/commands/apply.d.ts +5 -3
- package/dist/commands/apply.d.ts.map +1 -1
- package/dist/commands/apply.js +100 -72
- package/dist/commands/apply.js.map +1 -1
- package/dist/commands/capture.d.ts +1 -1
- package/dist/commands/capture.d.ts.map +1 -1
- package/dist/commands/capture.js +35 -26
- package/dist/commands/capture.js.map +1 -1
- package/dist/commands/ingest.d.ts.map +1 -1
- package/dist/commands/ingest.js +12 -12
- package/dist/commands/ingest.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +24 -61
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/layers.d.ts.map +1 -1
- package/dist/commands/layers.js +50 -34
- 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 +85 -68
- 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 +147 -212
- 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 +48 -46
- package/dist/index.js.map +1 -1
- package/dist/lib/claude.d.ts.map +1 -1
- package/dist/lib/claude.js +25 -20
- package/dist/lib/claude.js.map +1 -1
- package/dist/lib/git.js +3 -3
- 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 +1 -1
- package/dist/lib/parser.d.ts.map +1 -1
- package/dist/lib/parser.js +36 -36
- 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 +52 -10
- package/dist/lib/storage.d.ts.map +1 -1
- package/dist/lib/storage.js +126 -60
- package/dist/lib/storage.js.map +1 -1
- 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
|
[](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, `
|
|
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
|
|
23
|
-
|
|
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
|
|
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
|
-
→
|
|
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
|
|
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
|
|
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
|
|
83
|
-
|
|
84
|
-
| `
|
|
85
|
-
| `
|
|
86
|
-
| `
|
|
87
|
-
| `
|
|
88
|
-
| `
|
|
89
|
-
| `
|
|
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,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
|
|
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.
|
|
106
156
|
|
|
107
157
|
### patina ingest
|
|
108
158
|
|
|
109
|
-
|
|
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
|
-
|
|
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": [
|
|
188
|
+
"include": [],
|
|
189
|
+
"exclude": [],
|
|
190
|
+
"dataDir": "../our-patina-data"
|
|
116
191
|
}
|
|
117
192
|
```
|
|
118
193
|
|
|
119
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
230
|
+
```json
|
|
231
|
+
{
|
|
232
|
+
"include": ["my-backend", "my-frontend"],
|
|
233
|
+
"dataDir": "../our-patina-data"
|
|
234
|
+
}
|
|
235
|
+
```
|
|
137
236
|
|
|
138
|
-
|
|
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
|
|
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
|
-
|
|
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 `
|
|
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/
|
|
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 `
|
|
182
|
-
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
|
|
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 `
|
|
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
|
|
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
|
|
222
|
-
|
|
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
|
-
|
|
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** (`
|
|
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/
|
|
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
|
-
`
|
|
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
|
|
373
|
+
<summary><b>Why are cycle reports committed but captures and reflections are not?</b></summary>
|
|
277
374
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
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
|
|
382
|
+
<summary><b>Why <code>PATINA.md</code> instead of editing CLAUDE.md directly?</b></summary>
|
|
288
383
|
|
|
289
|
-
|
|
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
|
|
389
|
+
<summary><b>Why hub+spoke instead of one file?</b></summary>
|
|
299
390
|
|
|
300
|
-
|
|
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
|
|
396
|
+
<summary><b>Why the <code>claude</code> CLI instead of the API directly?</b></summary>
|
|
308
397
|
|
|
309
|
-
|
|
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>
|
|
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
|
-
|
|
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>
|
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"}
|