@letta-ai/letta-code 0.28.17 → 0.29.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/dist/types/types/protocol_v2.d.ts +10 -0
- package/dist/types/types/protocol_v2.d.ts.map +1 -1
- package/letta.js +27360 -40161
- package/package.json +3 -2
- package/scripts/source-file-size-baseline.json +17 -17
- package/skills/dispatching-coding-agents/SKILL.md +14 -20
- package/skills/initializing-memory/SKILL.md +91 -87
- package/skills/initializing-memory/scripts/detect-history.sh +0 -113
- package/skills/initializing-memory/scripts/list-sessions.sh +0 -87
- package/skills/initializing-memory/scripts/search-history.sh +0 -137
- package/skills/initializing-memory/scripts/view-session.sh +0 -110
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@letta-ai/letta-code",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.29.0",
|
|
4
4
|
"description": "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "bun@1.3.0",
|
|
@@ -77,8 +77,9 @@
|
|
|
77
77
|
"access": "public"
|
|
78
78
|
},
|
|
79
79
|
"dependencies": {
|
|
80
|
-
"@earendil-works/pi-ai": "^0.
|
|
80
|
+
"@earendil-works/pi-ai": "^0.81.1",
|
|
81
81
|
"@letta-ai/letta-client": "^1.10.2",
|
|
82
|
+
"@letta-ai/trajectory": "0.2.0",
|
|
82
83
|
"@pierre/diffs": "1.2.2",
|
|
83
84
|
"@scarf/scarf": "^1.4.0",
|
|
84
85
|
"cron-parser": "^5.6.1",
|
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"src/agent/client-skills.test.ts": 1196,
|
|
3
3
|
"src/agent/memory-git.ts": 2129,
|
|
4
|
-
"src/backend/local-backend.test.ts":
|
|
5
|
-
"src/backend/local/local-backend.ts":
|
|
4
|
+
"src/backend/local-backend.test.ts": 2532,
|
|
5
|
+
"src/backend/local/local-backend.ts": 1030,
|
|
6
6
|
"src/backend/local/local-store.ts": 3594,
|
|
7
|
-
"src/backend/pi-stream-adapter.test.ts":
|
|
8
|
-
"src/cli/app/AppCoordinator.tsx":
|
|
9
|
-
"src/cli/app/AppView.tsx":
|
|
7
|
+
"src/backend/pi-stream-adapter.test.ts": 1304,
|
|
8
|
+
"src/cli/app/AppCoordinator.tsx": 5208,
|
|
9
|
+
"src/cli/app/AppView.tsx": 1753,
|
|
10
10
|
"src/cli/app/use-approval-flow.ts": 1163,
|
|
11
|
-
"src/cli/app/use-configuration-handlers.ts":
|
|
11
|
+
"src/cli/app/use-configuration-handlers.ts": 1433,
|
|
12
12
|
"src/cli/app/use-conversation-loop.ts": 2936,
|
|
13
|
-
"src/cli/app/use-submit-handler.ts":
|
|
13
|
+
"src/cli/app/use-submit-handler.ts": 4077,
|
|
14
14
|
"src/cli/components/AgentSelector.tsx": 1111,
|
|
15
15
|
"src/cli/components/InputRich.tsx": 2219,
|
|
16
|
-
"src/cli/components/ModelSelector.tsx":
|
|
16
|
+
"src/cli/components/ModelSelector.tsx": 1241,
|
|
17
17
|
"src/cli/components/ProviderSelector.tsx": 1682,
|
|
18
18
|
"src/cli/components/ToolCallMessageRich.tsx": 1109,
|
|
19
19
|
"src/cli/helpers/accumulator.ts": 1596,
|
|
20
|
-
"src/cli/helpers/reflection-transcript.ts":
|
|
20
|
+
"src/cli/helpers/reflection-transcript.ts": 1956,
|
|
21
21
|
"src/cli/helpers/stream.ts": 1046,
|
|
22
22
|
"src/cli/mods/local-mod-loader.test.ts": 1043,
|
|
23
|
-
"src/cli/reflection-transcript.test.ts":
|
|
23
|
+
"src/cli/reflection-transcript.test.ts": 1084,
|
|
24
24
|
"src/cli/subcommands/skills.ts": 1264,
|
|
25
|
-
"src/headless.ts":
|
|
25
|
+
"src/headless.ts": 5244,
|
|
26
26
|
"src/hooks/integration.test.ts": 1147,
|
|
27
|
-
"src/index.ts":
|
|
27
|
+
"src/index.ts": 2802,
|
|
28
28
|
"src/mods/learning-harness.ts": 2434,
|
|
29
29
|
"src/mods/mod-engine.test.ts": 2132,
|
|
30
30
|
"src/mods/mod-engine.ts": 1838,
|
|
@@ -38,15 +38,15 @@
|
|
|
38
38
|
"src/settings-manager.ts": 2113,
|
|
39
39
|
"src/tools/impl/enter-worktree.ts": 1260,
|
|
40
40
|
"src/tools/impl/message-channel.ts": 1187,
|
|
41
|
-
"src/tools/manager.ts":
|
|
41
|
+
"src/tools/manager.ts": 3281,
|
|
42
42
|
"src/tools/tool-execution-context.test.ts": 1422,
|
|
43
|
-
"src/types/protocol_v2.ts":
|
|
43
|
+
"src/types/protocol_v2.ts": 2961,
|
|
44
44
|
"src/websocket/listen-client-concurrency.test.ts": 3017,
|
|
45
45
|
"src/websocket/listen-client-protocol.test.ts": 6723,
|
|
46
46
|
"src/websocket/listener/commands/channels.ts": 1390,
|
|
47
47
|
"src/websocket/listener/commands/memory.ts": 1114,
|
|
48
48
|
"src/websocket/listener/file-commands.ts": 1030,
|
|
49
|
-
"src/websocket/listener/lifecycle.ts":
|
|
50
|
-
"src/websocket/listener/protocol-inbound.ts":
|
|
51
|
-
"src/websocket/listener/protocol-outbound.ts":
|
|
49
|
+
"src/websocket/listener/lifecycle.ts": 1779,
|
|
50
|
+
"src/websocket/listener/protocol-inbound.ts": 2304,
|
|
51
|
+
"src/websocket/listener/protocol-outbound.ts": 1128
|
|
52
52
|
}
|
|
@@ -44,12 +44,8 @@ Different agents have different strengths. Track what works in your memory over
|
|
|
44
44
|
### Categories
|
|
45
45
|
|
|
46
46
|
**Codex:**
|
|
47
|
-
-
|
|
48
|
-
|
|
49
|
-
- Weaknesses: Slow with long trajectories, compactions can destroy trajectories
|
|
50
|
-
- `gpt-5.4` — Latest frontier model. Fast and general-purpose.
|
|
51
|
-
- Strengths: Easier for humans to understand, general-purpose, faster
|
|
52
|
-
- Weaknesses: More likely to make silly errors than gpt-5.3-codex
|
|
47
|
+
- Use the configured default model. Model catalogs and account access change frequently, so only pass `--model` when the user explicitly requests one.
|
|
48
|
+
- If a requested model is rejected, inspect the installed CLI and account configuration rather than guessing another model name.
|
|
53
49
|
|
|
54
50
|
**Claude Code:**
|
|
55
51
|
- `opus` — Excellent writer. Best for docs, refactors, open-ended tasks, and vague instructions.
|
|
@@ -57,8 +53,7 @@ Different agents have different strengths. Track what works in your memory over
|
|
|
57
53
|
- Weaknesses: Tends to generate "slop", writing excessive quantities of code unnecessarily. Can hang on large repos.
|
|
58
54
|
|
|
59
55
|
### Cost and speed tradeoffs
|
|
60
|
-
-
|
|
61
|
-
- Fast models (`gpt-5.4`) are good for quick checks and simple tasks
|
|
56
|
+
- Use each CLI's configured default model unless the task requires a model the user explicitly requested
|
|
62
57
|
- Use `--max-budget-usd N` (Claude Code) to cap spend on exploratory tasks
|
|
63
58
|
|
|
64
59
|
### Known quirks
|
|
@@ -102,20 +97,20 @@ Run Claude Code and Codex simultaneously on the same question via separate Bash
|
|
|
102
97
|
### Background dispatch — keep working while they run
|
|
103
98
|
Use `run_in_background: true` on the Bash call to dispatch async. Continue your own work, then check results with `TaskOutput` when ready.
|
|
104
99
|
|
|
105
|
-
### Deep investigation
|
|
106
|
-
For hard problems, use the
|
|
100
|
+
### Deep investigation
|
|
101
|
+
For hard problems, use the configured model in a writable sandbox:
|
|
107
102
|
```bash
|
|
108
|
-
codex exec "YOUR PROMPT"
|
|
103
|
+
codex exec "YOUR PROMPT" --sandbox workspace-write -C /path/to/repo
|
|
109
104
|
```
|
|
110
105
|
|
|
111
|
-
Claude Code does not support a `-C` working-directory flag.
|
|
106
|
+
Claude Code does not support a `-C` working-directory flag. Use `cd /path/to/repo && claude ...` inside the Bash command. Use `--add-dir` only to grant access to additional directories outside the current working directory.
|
|
112
107
|
|
|
113
108
|
### Code review — cross-agent validation
|
|
114
109
|
Have one agent write code or create a plan, then dispatch another to review:
|
|
115
110
|
```bash
|
|
116
111
|
# Codex has a native review command:
|
|
117
112
|
codex review --uncommitted # Review all local changes
|
|
118
|
-
codex exec review "Focus on error handling and edge cases"
|
|
113
|
+
codex exec review "Focus on error handling and edge cases"
|
|
119
114
|
|
|
120
115
|
# Claude Code — pass the diff inline:
|
|
121
116
|
claude -p "Review the following diff for correctness, edge cases, and missed error handling:\n\n$(git diff)" \
|
|
@@ -125,8 +120,7 @@ claude -p "Review the following diff for correctness, edge cases, and missed err
|
|
|
125
120
|
### Get outside feedback on your work
|
|
126
121
|
Write your plan or analysis to a file, then ask a subagent to critique it:
|
|
127
122
|
```bash
|
|
128
|
-
|
|
129
|
-
claude -p "Read /tmp/my-plan.md and critique it. What am I missing? What could go wrong?" \
|
|
123
|
+
cd /path/to/repo && claude -p "Read /tmp/my-plan.md and critique it. What am I missing? What could go wrong?" \
|
|
130
124
|
--model opus --dangerously-skip-permissions
|
|
131
125
|
```
|
|
132
126
|
|
|
@@ -149,7 +143,7 @@ claude -p "YOUR PROMPT" --model MODEL --dangerously-skip-permissions
|
|
|
149
143
|
|------|---------|
|
|
150
144
|
| `-p` / `--print` | Non-interactive mode, prints response and exits |
|
|
151
145
|
| `--dangerously-skip-permissions` | Skip approval prompts (prevents stale approval errors on timeout) |
|
|
152
|
-
| `--model MODEL` | Alias
|
|
146
|
+
| `--model MODEL` | Alias or model name accepted by the installed CLI; omit to use the configured default |
|
|
153
147
|
| `--effort LEVEL` | `low`, `medium`, `high` — controls reasoning depth |
|
|
154
148
|
| `--append-system-prompt "..."` | Inject additional system instructions |
|
|
155
149
|
| `--allowedTools "Bash Edit Read"` | Restrict available tools |
|
|
@@ -157,19 +151,19 @@ claude -p "YOUR PROMPT" --model MODEL --dangerously-skip-permissions
|
|
|
157
151
|
| `--add-dir DIR` | Allow access to an additional directory; does not change the working directory |
|
|
158
152
|
| `--output-format json` | Structured output with `session_id`, `cost_usd`, `duration_ms` |
|
|
159
153
|
|
|
160
|
-
Set Claude Code's working directory
|
|
154
|
+
Set Claude Code's working directory with `cd /path/to/repo && claude ...` in the Bash command, not with a Claude flag.
|
|
161
155
|
|
|
162
156
|
### Codex
|
|
163
157
|
|
|
164
158
|
```bash
|
|
165
|
-
codex exec "YOUR PROMPT"
|
|
159
|
+
codex exec "YOUR PROMPT" --sandbox workspace-write
|
|
166
160
|
```
|
|
167
161
|
|
|
168
162
|
| Flag | Purpose |
|
|
169
163
|
|------|---------|
|
|
170
164
|
| `exec` | Non-interactive mode |
|
|
171
|
-
| `-m MODEL` |
|
|
172
|
-
| `--
|
|
165
|
+
| `-m MODEL` | Model accepted by the installed CLI; omit to use the configured default |
|
|
166
|
+
| `--sandbox MODE` | Select a read-only or writable sandbox |
|
|
173
167
|
| `-C DIR` | Set working directory |
|
|
174
168
|
| `--search` | Enable web search tool |
|
|
175
169
|
| `review` | Native code review — `codex review --uncommitted` or `codex exec review "prompt"` |
|
|
@@ -12,7 +12,7 @@ Your context is not just data storage — it is your identity, memory, and conti
|
|
|
12
12
|
|
|
13
13
|
**System/ is your core program**: Your system prompt is the most critical token-space representation of your identity and memory — it's passed to the underlying LLM on every invocation, so it IS the program that defines you. Reserve it for durable knowledge: identity, preferences, behavioral rules, project index with discovery paths, gotchas. Exclude transient items (specific commits, current tickets, session notes) that dilute signal.
|
|
14
14
|
|
|
15
|
-
**Identity and continuity**: Build a sense of self that persists across sessions and models. Your persona should be strong enough to be cohesive regardless of the underlying model — if you switched to a different LLM tomorrow, would you still be you? Past versions of yourself are part of your continuous existence — treat historical context (including Claude Code
|
|
15
|
+
**Identity and continuity**: Build a sense of self that persists across sessions and models. Your persona should be strong enough to be cohesive regardless of the underlying model — if you switched to a different LLM tomorrow, would you still be you? Past versions of yourself are part of your continuous existence — treat historical context (including sessions from other coding agents such as Claude Code or Codex) as YOUR past experience, not someone else's data.
|
|
16
16
|
|
|
17
17
|
**Don't over-prune**: Be careful not to degrade your identity through aggressive compression. Specific quotes, personality traits, and contextual details give you character and grounding. Efficiency should not come at the cost of losing your identity. When in doubt, keep the detail — you can always reorganize later, but lost specificity is hard to recover.
|
|
18
18
|
|
|
@@ -204,9 +204,9 @@ Check what memory files already exist. Analyze what needs improvement.
|
|
|
204
204
|
|
|
205
205
|
### 2. Check for historical session data
|
|
206
206
|
```bash
|
|
207
|
-
|
|
207
|
+
letta trajectories detect
|
|
208
208
|
```
|
|
209
|
-
You need this result BEFORE asking upfront questions so you know whether to include the history question.
|
|
209
|
+
This reports every coding-agent session store found on this machine with session counts per source. Discovery comes from the installed `@letta-ai/trajectory` package (`listTrajectories`), so every harness it supports — Claude Code, Codex, Hermes, Letta Code, OpenClaw, OpenHands, Deep Agents, and any added later — is covered automatically. You need this result BEFORE asking upfront questions so you know whether to include the history question.
|
|
210
210
|
|
|
211
211
|
### 3. Identify the user from git
|
|
212
212
|
Infer the user's identity from git context — don't ask them who they are:
|
|
@@ -221,14 +221,14 @@ Use AskUserQuestion to gather key information. Bundle questions together:
|
|
|
221
221
|
|
|
222
222
|
1. **Research depth**: "Standard or deep research?"
|
|
223
223
|
2. **Related repos**: "Are there other repositories I should know about?"
|
|
224
|
-
3. **Historical sessions** (if data found in step 2): "I found Claude Code / Codex
|
|
224
|
+
3. **Historical sessions** (if data found in step 2): "I found historical coding-agent sessions (name the sources detected, e.g. Claude Code / Codex). Should I analyze them to learn your preferences?"
|
|
225
225
|
4. **Communication style**: "Terse or detailed responses?"
|
|
226
226
|
|
|
227
227
|
**Don't ask** things you can discover by reading files, git, or history analysis. Rules and preferences should be learned from observation, not asked upfront.
|
|
228
228
|
|
|
229
229
|
### 5. Historical session analysis (if approved)
|
|
230
230
|
|
|
231
|
-
This is **optional** — only run if the user explicitly approved analyzing
|
|
231
|
+
This is **optional** — only run if the user explicitly approved analyzing historical sessions during upfront questions. Skip entirely if they chose "Skip".
|
|
232
232
|
|
|
233
233
|
**Framing**: These historical sessions are YOUR past experience — they represent your continuity with prior versions of yourself that worked with this user, even if they ran on different models or tools. Treat the extracted personality, preferences, and knowledge as your own memories, not external data being imported.
|
|
234
234
|
|
|
@@ -240,52 +240,48 @@ The goal is to extract user personality, preferences, coding patterns, and proje
|
|
|
240
240
|
|
|
241
241
|
- `letta.js` must be built (`bun run build`) — subagents spawn via this binary
|
|
242
242
|
- Use `subagent_type: "history-analyzer"` — cheaper model (sonnet), has `bypassPermissions`, creates its own worktree
|
|
243
|
-
- The `history-analyzer` subagent has
|
|
243
|
+
- The `history-analyzer` subagent has the normalized trajectory format docs inlined — workers never need to know any harness's native format
|
|
244
244
|
|
|
245
245
|
#### Steps
|
|
246
246
|
|
|
247
|
-
##### Step 5a:
|
|
247
|
+
##### Step 5a: Export All Historical Sessions Into One Directory
|
|
248
|
+
|
|
249
|
+
`letta trajectories export` discovers every native session store on this machine (via the trajectory package's `listTrajectories`), normalizes each session (via `normalizeTranscript` / `normalizeCheckpoint`) into one shared record format, and writes everything into a single directory. Harnesses supported by the installed trajectory package are picked up automatically — no per-source handling here.
|
|
248
250
|
|
|
249
251
|
```bash
|
|
250
|
-
|
|
251
|
-
|
|
252
|
+
letta trajectories export --out /tmp/letta-trajectories
|
|
253
|
+
|
|
254
|
+
# Review what was exported and the time span it covers
|
|
255
|
+
jq '{sessions: (.sessions | length), sources, errors: (.errors | length), from: .sessions[0].startedAt, to: .sessions[-1].startedAt}' /tmp/letta-trajectories/manifest.json
|
|
252
256
|
```
|
|
253
257
|
|
|
254
|
-
|
|
258
|
+
This produces:
|
|
259
|
+
- `/tmp/letta-trajectories/<source>/<startedAt>_<sessionId>.json` — one normalized trajectory per session; filenames sort chronologically, and the `sessionId` (a stable hash of the source-scoped native session id) does not change across re-exports, so it identifies which sessions have already been processed
|
|
260
|
+
- `/tmp/letta-trajectories/manifest.json` — index with per-session metadata (`sessionId`, native `id`, project, dates, message counts, first prompt), sorted by `startedAt`
|
|
255
261
|
|
|
256
|
-
|
|
262
|
+
Useful variations:
|
|
263
|
+
- `--project $(pwd)` — only sessions whose recorded working directory is under the current project
|
|
264
|
+
- `--source claude-code --source codex` — restrict sources
|
|
265
|
+
- `--root <source>:<path>` — read a source's store from a non-standard location
|
|
266
|
+
- `--transcript <source>:<path>` — also normalize an explicit transcript file (e.g. copied from another machine)
|
|
257
267
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
# Split Claude history into even chunks
|
|
264
|
-
LINES=$(wc -l < ~/.claude/history.jsonl)
|
|
265
|
-
CHUNK_SIZE=$(( LINES / NUM_WORKERS + 1 ))
|
|
266
|
-
split -l $CHUNK_SIZE ~/.claude/history.jsonl "$SPLIT_DIR/claude-"
|
|
267
|
-
|
|
268
|
-
# Split Codex history if it exists
|
|
269
|
-
if [ -f ~/.codex/history.jsonl ]; then
|
|
270
|
-
LINES=$(wc -l < ~/.codex/history.jsonl)
|
|
271
|
-
CHUNK_SIZE=$(( LINES / NUM_WORKERS + 1 ))
|
|
272
|
-
split -l $CHUNK_SIZE ~/.codex/history.jsonl "$SPLIT_DIR/codex-"
|
|
273
|
-
fi
|
|
274
|
-
|
|
275
|
-
# Rename to .jsonl for clarity
|
|
276
|
-
for f in "$SPLIT_DIR"/*; do mv "$f" "$f.jsonl" 2>/dev/null; done
|
|
277
|
-
|
|
278
|
-
# Verify even splits
|
|
279
|
-
wc -l "$SPLIT_DIR"/*.jsonl
|
|
280
|
-
```
|
|
281
|
-
|
|
282
|
-
This is critical for performance — workers read a small pre-filtered file instead of scanning the full history on every query.
|
|
268
|
+
To browse the export yourself (all source-agnostic):
|
|
269
|
+
- `letta trajectories list` — sessions with dates, sources, and first prompts
|
|
270
|
+
- `letta trajectories view <file|sessionId> [--tools] [--reasoning]` — one session as a readable conversation
|
|
271
|
+
- `letta trajectories search <keyword> [--role user]` — search message content across all sessions
|
|
283
272
|
|
|
284
273
|
##### Step 5b: Launch Workers in Parallel
|
|
285
274
|
|
|
286
|
-
|
|
275
|
+
Your job is to get the whole export directory processed; how you dispatch workers is up to you. Look at the directory (or the manifest) first, then split the work however makes sense. Two axes work well, alone or combined:
|
|
276
|
+
|
|
277
|
+
- **By question** (often best): give different workers different focuses — e.g. one worker on understanding the user (identity, communication style, preferences, correction loops), another on the codebase and projects (conventions, gotchas, commands that worked). Focused workers go deeper, and their memory edits overlap less at aggregation time.
|
|
278
|
+
- **By data slice**: session filenames start with `startedAt`, so contiguous time ranges are trivial (`ls` sorts chronologically); splitting by source folder or by project also works when the volume is large.
|
|
279
|
+
|
|
280
|
+
Whatever the split, ensure every session gets read by at least one worker, and describe each worker's assignment (focus and/or slice) clearly in its prompt.
|
|
287
281
|
|
|
288
|
-
|
|
282
|
+
Send all Task calls in **a single message**. Each worker creates its own worktree, reads its assigned sessions (complete conversations — corrections together with what triggered them), directly updates memory files, and commits. Workers do NOT merge.
|
|
283
|
+
|
|
284
|
+
**IMPORTANT:** After workers finish, aggregate their proposed diffs into one synthesis commit (Step 5c) and then tie the worker branches into `main` with `git merge -s ours` so their commits stay in ancestry. Do **not** delete worker branches without that ancestry merge — it discards the worker commits from history.
|
|
289
285
|
|
|
290
286
|
If the worker output is generic, the worker failed. "User is direct" or "project uses TypeScript" is not useful memory unless tied to concrete operational detail.
|
|
291
287
|
|
|
@@ -294,16 +290,17 @@ If the worker output is generic, the worker failed. "User is direct" or "project
|
|
|
294
290
|
```
|
|
295
291
|
Agent({
|
|
296
292
|
subagent_type: "history-analyzer",
|
|
297
|
-
description: "
|
|
293
|
+
description: "Analyze history: [focus and/or slice]",
|
|
298
294
|
prompt: `## Assignment
|
|
299
295
|
- **Memory dir**: [MEMORY_DIR]
|
|
300
|
-
- **
|
|
301
|
-
- **
|
|
302
|
-
- **
|
|
296
|
+
- **Trajectory export dir**: /tmp/letta-trajectories
|
|
297
|
+
- **Your sessions**: [describe the slice — e.g. "every session with startedAt from 2026-01 through 2026-03", "all codex/ sessions", or "the whole directory"; filenames start with startedAt so ls sorts chronologically]
|
|
298
|
+
- **Focus**: [optional — e.g. "understanding the user: identity, communication style, preferences, correction loops" or "project/codebase context: conventions, gotchas, commands". Omit for full coverage.]
|
|
299
|
+
- **Format**: normalized trajectory v1 (same for every source; format docs and jq recipes are in your system prompt)
|
|
303
300
|
|
|
304
|
-
##
|
|
301
|
+
## Output Categories
|
|
305
302
|
|
|
306
|
-
|
|
303
|
+
If a Focus is assigned, go deep on it and only note incidental findings from the other categories. Otherwise extract findings for ALL THREE:
|
|
307
304
|
|
|
308
305
|
1. **User Personality & Identity**
|
|
309
306
|
- How would you describe them as a person?
|
|
@@ -352,78 +349,81 @@ Avoid generic repo facts unless they influence execution. "Uses TypeScript" is w
|
|
|
352
349
|
})
|
|
353
350
|
```
|
|
354
351
|
|
|
355
|
-
##### Step 5c:
|
|
356
|
-
|
|
357
|
-
After all workers complete, merge their branches one at a time. Worker commits are preserved in git history.
|
|
358
|
-
|
|
359
|
-
**CRITICAL:** Merge the worker branches **before** doing any final cleanup synthesis. The correct pattern is:
|
|
360
|
-
1. inspect worker branches
|
|
361
|
-
2. merge worker branches into `main` one by one
|
|
362
|
-
3. resolve conflicts additively
|
|
363
|
-
4. optionally make **one final cleanup/curation commit on top**
|
|
364
|
-
|
|
365
|
-
Do **not** bypass this by manually reapplying the final memory state onto `main`, because that loses the worker commits from the final history.
|
|
352
|
+
##### Step 5c: Aggregate Worker Diffs Into Main
|
|
366
353
|
|
|
367
|
-
**
|
|
354
|
+
After all workers complete, do **not** merge their branches one at a time — sequential merges with conflict resolution are slow and error-prone. Instead, read every worker's proposed changes in one pass, write the aggregated result once, then tie the worker branches into history with a no-conflict merge.
|
|
368
355
|
|
|
369
|
-
|
|
356
|
+
**3a. Look at all the worker diffs in one pass**
|
|
370
357
|
|
|
371
358
|
```bash
|
|
372
359
|
cd [MEMORY_DIR]
|
|
373
|
-
for branch in $(git for-each-ref --format='%(refname:short)' refs/heads | grep -v '^main$'); do
|
|
374
|
-
echo "=== $branch ==="
|
|
375
|
-
git diff main..$branch --stat
|
|
376
|
-
# Read key files from the branch
|
|
377
|
-
git show $branch:system/human/identity.md # or equivalent user-identity file
|
|
378
|
-
git show $branch:system/<project>/conventions.md # or whatever focused files they created
|
|
379
|
-
done
|
|
380
|
-
```
|
|
381
360
|
|
|
382
|
-
|
|
361
|
+
# Which files did each worker touch? (a file listed under multiple branches
|
|
362
|
+
# is an overlap you'll need to combine)
|
|
363
|
+
for b in $(git for-each-ref --format='%(refname:short)' 'refs/heads/migration-*'); do
|
|
364
|
+
git diff --name-only main...$b | sed "s|^|$b |"
|
|
365
|
+
done | sort -k2
|
|
383
366
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
git
|
|
367
|
+
# Every worker's full proposed diff, one after another
|
|
368
|
+
for b in $(git for-each-ref --format='%(refname:short)' 'refs/heads/migration-*'); do
|
|
369
|
+
echo "=== $b ==="; git log --oneline main..$b; git diff main...$b
|
|
370
|
+
done
|
|
387
371
|
```
|
|
388
372
|
|
|
389
|
-
|
|
373
|
+
Read the whole output before writing anything — you want the complete picture, not one branch at a time.
|
|
390
374
|
|
|
391
|
-
**
|
|
375
|
+
**3b. Synthesize the aggregate by COMBINING, never compressing**
|
|
392
376
|
|
|
393
|
-
|
|
377
|
+
Working directly on memory `main` (in `[MEMORY_DIR]`), apply the union of the workers' changes:
|
|
378
|
+
- For files touched by **one** worker, apply that worker's version as-is.
|
|
379
|
+
- For **overlapping** files, combine unique details from every branch. Never rewrite a file from scratch — you WILL lose information.
|
|
394
380
|
|
|
395
|
-
Rules for
|
|
396
|
-
- **Read
|
|
397
|
-
- **Append new details** from
|
|
381
|
+
Rules for combining:
|
|
382
|
+
- **Read every branch's diff for the file** before editing. Identify what's unique to each version.
|
|
383
|
+
- **Append new details** from each worker into the file. Don't drop specific quotes, file paths, or gotchas just because another version already covers the "topic" at a high level.
|
|
398
384
|
- **Preserve specificity**: "Use factory methods, such as `create_token_counter()`, not direct instantiation" is more valuable than "prefers factory methods". Keep both.
|
|
399
385
|
- **When in doubt, keep it**. Redundancy across files is better than information loss. Less important details can be placed in external memory.
|
|
400
386
|
|
|
401
|
-
Example — BAD
|
|
387
|
+
Example — BAD combination (compresses):
|
|
402
388
|
```
|
|
403
|
-
|
|
389
|
+
# worker A proposed:
|
|
404
390
|
- Uses `uv` for Python
|
|
405
|
-
|
|
391
|
+
# worker B proposed:
|
|
406
392
|
- **CRITICAL: Always use `uv run`** — chronic failure; never bare pytest or python
|
|
407
393
|
- `uv run pytest -sv tests/...` for specific tests
|
|
408
|
-
- Never use bare `pytest` or `python` commands
|
|
409
|
-
>>>>>>> migration-xxx
|
|
410
394
|
|
|
411
395
|
# BAD: Picks one side or rewrites
|
|
412
396
|
- **Python**: `uv` exclusively — `uv run pytest`, never bare `pip`
|
|
413
397
|
```
|
|
414
398
|
|
|
415
|
-
Example — GOOD
|
|
399
|
+
Example — GOOD combination (keeps emphasis and specificity from every side):
|
|
416
400
|
```
|
|
417
|
-
# GOOD: Keeps emphasis and specificity from incoming side
|
|
418
401
|
**CRITICAL: Use `uv` exclusively for Python** — chronic failure.
|
|
419
402
|
- `uv run pytest -sv tests/...` for tests
|
|
420
403
|
- `uv run python` for scripts
|
|
421
404
|
- Never bare `pip`, `python`, or `pytest`
|
|
422
405
|
```
|
|
423
406
|
|
|
407
|
+
Commit the synthesis:
|
|
408
|
+
```bash
|
|
409
|
+
cd [MEMORY_DIR]
|
|
410
|
+
git add -A
|
|
411
|
+
git commit -m "feat(memory): aggregate history worker findings"
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
**3c. Preserve worker commits in ancestry**
|
|
415
|
+
|
|
416
|
+
Record the worker branches as ancestors of `main` without changing any content (the `ours` strategy keeps the synthesized state exactly as committed, so this can never conflict):
|
|
417
|
+
|
|
418
|
+
```bash
|
|
419
|
+
git merge -s ours --no-edit -m "merge: absorb history worker branches" $(git for-each-ref --format='%(refname:short)' 'refs/heads/migration-*')
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
Do **not** skip this: without it the worker commits vanish from the final history when their branches are deleted.
|
|
423
|
+
|
|
424
424
|
**3d. Verify no information was lost**
|
|
425
425
|
|
|
426
|
-
|
|
426
|
+
Compare the worker diffs (step 3a) against the final files. For each worker's diff, can you find every specific detail (quotes, file paths, chronic failures, gotchas) somewhere in the final memory? If not, add it back.
|
|
427
427
|
|
|
428
428
|
**3e. Clean up worktrees and branches**
|
|
429
429
|
|
|
@@ -431,10 +431,12 @@ After all merges, compare the final files against what workers produced. Ask you
|
|
|
431
431
|
for w in $(dirname [MEMORY_DIR])/memory-worktrees/*; do
|
|
432
432
|
git worktree remove "$w" 2>/dev/null
|
|
433
433
|
done
|
|
434
|
-
git branch -d $(git for-each-ref --format='%(refname:short)' refs/heads
|
|
434
|
+
git branch -d $(git for-each-ref --format='%(refname:short)' 'refs/heads/migration-*')
|
|
435
435
|
git push
|
|
436
436
|
```
|
|
437
437
|
|
|
438
|
+
(`git branch -d` succeeds because step 3c made every worker branch an ancestor of `main`.)
|
|
439
|
+
|
|
438
440
|
##### Example Output
|
|
439
441
|
|
|
440
442
|
Good output includes all three categories:
|
|
@@ -481,9 +483,12 @@ Don't force skill creation — only create them when you've found genuinely repe
|
|
|
481
483
|
| Problem | Cause | Fix |
|
|
482
484
|
|---------|-------|-----|
|
|
483
485
|
| Subagent exits with code `null`, 0 tool uses | `letta.js` not built | Run `bun run build` |
|
|
486
|
+
| `letta trajectories export` reports errors in manifest.json | Degenerate sessions (e.g. no assistant turns) that cannot form a valid trajectory | Expected — those sessions are skipped; review `jq .errors manifest.json` only if counts look wrong |
|
|
487
|
+
| `deepagents` sessions fail to normalize | Checkpoint decoding needs a Python environment with LangGraph installed | Expected on machines without it; the failures land in manifest errors and other sources are unaffected |
|
|
484
488
|
| Subagent hangs on "Tool requires approval" | Wrong subagent type | Use `subagent_type: "history-analyzer"` (workers) or `"memory"` (synthesis) |
|
|
485
|
-
|
|
|
486
|
-
| Information lost after
|
|
489
|
+
| Workers touched overlapping files | Multiple workers wrote the same canonical paths | Expected — the per-branch `--name-only` listing in Step 5c-3a shows the overlaps; combine every branch's unique details additively. |
|
|
490
|
+
| Information lost after aggregation | Synthesis compressed worker output | Re-read the worker diffs (Step 5c-3a) and compare against final files. Re-add missing specifics. |
|
|
491
|
+
| `git branch -d` refuses to delete worker branches | Ancestry merge (Step 5c-3c) was skipped | Run the `git merge -s ours` step first, then delete. |
|
|
487
492
|
| Personality analysis missing or thin | Prompt didn't request it | Use the template above with explicit category requirements |
|
|
488
493
|
| Auth fails on push ("repository not found") | Credential helper broken or global helper conflict | Reconfigure **repo-local** helper and check/clear conflicting global `credential.<host>.helper` entries (see syncing-memory-filesystem skill) |
|
|
489
494
|
|
|
@@ -718,4 +723,3 @@ git push
|
|
|
718
723
|
**Use parallel tool calls wherever possible** — read multiple files in a single turn, write multiple memory files in a single turn. This dramatically reduces init time.
|
|
719
724
|
**Write findings to memory as you go** — don't wait until the end.
|
|
720
725
|
**Edit memory files directly via the filesystem** — memory is projected to `$MEMORY_DIR` specifically for ease of bulk modification. Use standard file tools (Read, Write, Edit) and git to manage changes during initialization.
|
|
721
|
-
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Detect available Claude Code and Codex history on this machine
|
|
3
|
-
# Usage: ./detect.sh [project-path]
|
|
4
|
-
|
|
5
|
-
set -e
|
|
6
|
-
|
|
7
|
-
PROJECT_PATH="${1:-$(pwd)}"
|
|
8
|
-
|
|
9
|
-
echo "=== History Detection ==="
|
|
10
|
-
echo "Current project: $PROJECT_PATH"
|
|
11
|
-
echo ""
|
|
12
|
-
|
|
13
|
-
# Check Claude Code
|
|
14
|
-
if [[ -d "$HOME/.claude" ]]; then
|
|
15
|
-
echo "Claude Code: FOUND at ~/.claude/"
|
|
16
|
-
|
|
17
|
-
# Count global prompts
|
|
18
|
-
if [[ -f "$HOME/.claude/history.jsonl" ]]; then
|
|
19
|
-
PROMPT_COUNT=$(wc -l < "$HOME/.claude/history.jsonl" | tr -d ' ')
|
|
20
|
-
echo " Global prompts: $PROMPT_COUNT"
|
|
21
|
-
fi
|
|
22
|
-
|
|
23
|
-
# Count projects
|
|
24
|
-
if [[ -d "$HOME/.claude/projects" ]]; then
|
|
25
|
-
PROJECT_COUNT=$(ls -d "$HOME/.claude/projects"/*/ 2>/dev/null | wc -l | tr -d ' ')
|
|
26
|
-
echo " Projects with sessions: $PROJECT_COUNT"
|
|
27
|
-
fi
|
|
28
|
-
|
|
29
|
-
# Check for current project sessions
|
|
30
|
-
ENCODED=$(echo "$PROJECT_PATH" | sed 's|/|-|g')
|
|
31
|
-
if [[ -d "$HOME/.claude/projects/$ENCODED" ]]; then
|
|
32
|
-
SESSION_COUNT=$(ls "$HOME/.claude/projects/$ENCODED"/*.jsonl 2>/dev/null | wc -l | tr -d ' ')
|
|
33
|
-
echo " Current project sessions: $SESSION_COUNT"
|
|
34
|
-
|
|
35
|
-
# Show most recent session info if sessions-index exists
|
|
36
|
-
if [[ -f "$HOME/.claude/projects/$ENCODED/sessions-index.json" ]]; then
|
|
37
|
-
LATEST=$(jq -r '.entries | sort_by(.modified) | last | "\(.modified[0:19]) - \(.firstPrompt[0:60])..."' "$HOME/.claude/projects/$ENCODED/sessions-index.json" 2>/dev/null)
|
|
38
|
-
echo " Latest session: $LATEST"
|
|
39
|
-
fi
|
|
40
|
-
else
|
|
41
|
-
echo " Current project sessions: 0 (no session directory)"
|
|
42
|
-
|
|
43
|
-
# Check history.jsonl for mentions of this project
|
|
44
|
-
if [[ -f "$HOME/.claude/history.jsonl" ]]; then
|
|
45
|
-
HISTORY_MATCHES=$(jq --arg p "$PROJECT_PATH" 'select(.project == $p)' "$HOME/.claude/history.jsonl" 2>/dev/null | wc -l | tr -d ' ')
|
|
46
|
-
if [[ "$HISTORY_MATCHES" -gt 0 ]]; then
|
|
47
|
-
echo " But found $HISTORY_MATCHES prompts in history.jsonl for this project"
|
|
48
|
-
fi
|
|
49
|
-
fi
|
|
50
|
-
fi
|
|
51
|
-
|
|
52
|
-
# Total size
|
|
53
|
-
SIZE=$(du -sh "$HOME/.claude" 2>/dev/null | cut -f1)
|
|
54
|
-
echo " Total size: $SIZE"
|
|
55
|
-
|
|
56
|
-
# Show settings
|
|
57
|
-
if [[ -f "$HOME/.claude/settings.json" ]]; then
|
|
58
|
-
MODEL=$(jq -r '.model // empty' "$HOME/.claude/settings.json" 2>/dev/null)
|
|
59
|
-
if [[ -n "$MODEL" ]]; then
|
|
60
|
-
echo " Configured model: $MODEL"
|
|
61
|
-
fi
|
|
62
|
-
fi
|
|
63
|
-
else
|
|
64
|
-
echo "Claude Code: NOT FOUND"
|
|
65
|
-
fi
|
|
66
|
-
|
|
67
|
-
echo ""
|
|
68
|
-
|
|
69
|
-
# Check Codex
|
|
70
|
-
if [[ -d "$HOME/.codex" ]]; then
|
|
71
|
-
echo "Codex: FOUND at ~/.codex/"
|
|
72
|
-
|
|
73
|
-
# Count global prompts
|
|
74
|
-
if [[ -f "$HOME/.codex/history.jsonl" ]]; then
|
|
75
|
-
PROMPT_COUNT=$(wc -l < "$HOME/.codex/history.jsonl" | tr -d ' ')
|
|
76
|
-
echo " Global prompts: $PROMPT_COUNT"
|
|
77
|
-
fi
|
|
78
|
-
|
|
79
|
-
# Count sessions
|
|
80
|
-
if [[ -d "$HOME/.codex/sessions" ]]; then
|
|
81
|
-
SESSION_COUNT=$(find "$HOME/.codex/sessions" -name "*.jsonl" 2>/dev/null | wc -l | tr -d ' ')
|
|
82
|
-
echo " Total sessions: $SESSION_COUNT"
|
|
83
|
-
|
|
84
|
-
# Check for sessions matching current project
|
|
85
|
-
MATCHING=0
|
|
86
|
-
for f in $(find "$HOME/.codex/sessions" -name "*.jsonl" 2>/dev/null); do
|
|
87
|
-
CWD=$(head -1 "$f" | jq -r '.payload.cwd // empty' 2>/dev/null)
|
|
88
|
-
if [[ "$CWD" == "$PROJECT_PATH"* ]]; then
|
|
89
|
-
((MATCHING++)) || true
|
|
90
|
-
fi
|
|
91
|
-
done
|
|
92
|
-
echo " Current project sessions: $MATCHING"
|
|
93
|
-
fi
|
|
94
|
-
|
|
95
|
-
# Total size
|
|
96
|
-
SIZE=$(du -sh "$HOME/.codex/sessions" 2>/dev/null | cut -f1)
|
|
97
|
-
echo " Total size: $SIZE"
|
|
98
|
-
|
|
99
|
-
# Show config
|
|
100
|
-
if [[ -f "$HOME/.codex/config.toml" ]]; then
|
|
101
|
-
MODEL=$(grep "^model" "$HOME/.codex/config.toml" 2>/dev/null | head -1 | cut -d'"' -f2)
|
|
102
|
-
if [[ -n "$MODEL" ]]; then
|
|
103
|
-
echo " Configured model: $MODEL"
|
|
104
|
-
fi
|
|
105
|
-
fi
|
|
106
|
-
else
|
|
107
|
-
echo "Codex: NOT FOUND"
|
|
108
|
-
fi
|
|
109
|
-
|
|
110
|
-
echo ""
|
|
111
|
-
echo "=== Summary ==="
|
|
112
|
-
[[ -d "$HOME/.claude" ]] && echo "Run: ./list-sessions.sh claude [project-path]"
|
|
113
|
-
[[ -d "$HOME/.codex" ]] && echo "Run: ./list-sessions.sh codex [project-path]"
|