@letta-ai/letta-code 0.28.16 → 0.28.18

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letta-ai/letta-code",
3
- "version": "0.28.16",
3
+ "version": "0.28.18",
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",
@@ -12,6 +12,7 @@
12
12
  "README.md",
13
13
  "letta.js",
14
14
  "image-resize-worker.js",
15
+ "assets/tutor-profile.png",
15
16
  "scripts",
16
17
  "skills",
17
18
  "vendor",
@@ -78,6 +79,7 @@
78
79
  "dependencies": {
79
80
  "@earendil-works/pi-ai": "^0.80.6",
80
81
  "@letta-ai/letta-client": "^1.10.2",
82
+ "@letta-ai/trajectory": "0.2.0",
81
83
  "@pierre/diffs": "1.2.2",
82
84
  "@scarf/scarf": "^1.4.0",
83
85
  "cron-parser": "^5.6.1",
@@ -110,6 +112,7 @@
110
112
  "lint-staged": "16.2.4",
111
113
  "madge": "^8.0.0",
112
114
  "minimatch": "^10.0.3",
115
+ "openai": "^6.48.0",
113
116
  "picomatch": "^2.3.1",
114
117
  "typescript": "^5.0.0"
115
118
  },
@@ -5,24 +5,24 @@
5
5
  "src/backend/local/local-backend.ts": 1058,
6
6
  "src/backend/local/local-store.ts": 3594,
7
7
  "src/backend/pi-stream-adapter.test.ts": 1442,
8
- "src/cli/app/AppCoordinator.tsx": 5200,
8
+ "src/cli/app/AppCoordinator.tsx": 5204,
9
9
  "src/cli/app/AppView.tsx": 1750,
10
10
  "src/cli/app/use-approval-flow.ts": 1163,
11
- "src/cli/app/use-configuration-handlers.ts": 1392,
11
+ "src/cli/app/use-configuration-handlers.ts": 1390,
12
12
  "src/cli/app/use-conversation-loop.ts": 2936,
13
- "src/cli/app/use-submit-handler.ts": 4099,
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": 1204,
17
- "src/cli/components/ProviderSelector.tsx": 1672,
16
+ "src/cli/components/ModelSelector.tsx": 1213,
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": 2080,
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": 1118,
23
+ "src/cli/reflection-transcript.test.ts": 1084,
24
24
  "src/cli/subcommands/skills.ts": 1264,
25
- "src/headless.ts": 5242,
25
+ "src/headless.ts": 5241,
26
26
  "src/hooks/integration.test.ts": 1147,
27
27
  "src/index.ts": 2803,
28
28
  "src/mods/learning-harness.ts": 2434,
@@ -38,7 +38,7 @@
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": 3282,
41
+ "src/tools/manager.ts": 3281,
42
42
  "src/tools/tool-execution-context.test.ts": 1422,
43
43
  "src/types/protocol_v2.ts": 2943,
44
44
  "src/websocket/listen-client-concurrency.test.ts": 3017,
@@ -46,7 +46,7 @@
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": 1766,
49
+ "src/websocket/listener/lifecycle.ts": 1762,
50
50
  "src/websocket/listener/protocol-inbound.ts": 2279,
51
- "src/websocket/listener/protocol-outbound.ts": 1282
51
+ "src/websocket/listener/protocol-outbound.ts": 1278
52
52
  }
@@ -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/Codex sessions) as YOUR past experience, not someone else's data.
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
- ls ~/.claude/history.jsonl ~/.codex/history.jsonl 2>/dev/null
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 history. Should I analyze it to learn your preferences?"
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 Claude Code / Codex history during upfront questions. Skip entirely if they chose "Skip".
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 data format docs inlined (Claude/Codex JSONL field mappings, jq queries)
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: Detect Data and Pre-split Files
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
- ls ~/.claude/history.jsonl ~/.codex/history.jsonl 2>/dev/null
251
- wc -l ~/.claude/history.jsonl ~/.codex/history.jsonl 2>/dev/null
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
- Split the data across multiple workers for parallel processing — **the more workers, the faster it completes**. Use 2-4+ workers depending on data volume.
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
- **Pre-split the JSONL files by line count** so each worker reads only its chunk:
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
- ```bash
259
- SPLIT_DIR=/tmp/history-splits
260
- mkdir -p "$SPLIT_DIR"
261
- NUM_WORKERS=5 # adjust based on data volume
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
- Send all Task calls in **a single message**. Each worker creates its own worktree, reads its pre-split chunk, directly updates memory files, and commits. Workers do NOT merge.
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
- **IMPORTANT:** The parent agent should preserve those worker commits by merging the worker branches into memory `main`. Do **not** skip straight to a manual rewrite / `memory_apply_patch` synthesis that recreates the end state but discards the worker commits from ancestry.
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: "Process chunk [N] of [SOURCE] history",
293
+ description: "Analyze history: [focus and/or slice]",
298
294
  prompt: `## Assignment
299
295
  - **Memory dir**: [MEMORY_DIR]
300
- - **History chunk**: /tmp/history-splits/[claude-aa.jsonl | codex-aa.jsonl]
301
- - **Source format**: [Claude (.timestamp ms, .display) | Codex (.ts seconds, .text)]
302
- - **Session files**: [~/.claude/projects/ | ~/.codex/sessions/]
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
- ## Required Output Categories
301
+ ## Output Categories
305
302
 
306
- You MUST extract findings for ALL THREE categories:
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: Merge Worker Branches Into Main
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
- **3a. Pre-read worker output before merging**
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
- Before merging, read each worker's files from their branch to understand what they found. This prevents information loss during conflict resolution:
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
- **3b. Merge branches one at a time**
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
- ```bash
385
- cd [MEMORY_DIR]
386
- git merge [worker-branch] --no-edit -m "merge: worker N description"
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
- Repeat for each worker branch. After all worker branches are merged, make a separate cleanup commit only if needed for final curation.
373
+ Read the whole output before writing anything you want the complete picture, not one branch at a time.
390
374
 
391
- **3c. Resolve conflicts by COMBINING, never compressing**
375
+ **3b. Synthesize the aggregate by COMBINING, never compressing**
392
376
 
393
- **CRITICAL**: When resolving merge conflicts, be **additive**. Combine unique details from both sides. Never rewrite a file from scratch — you WILL lose information.
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 conflict resolution:
396
- - **Read both sides fully** before editing. Identify what's unique to each version.
397
- - **Append new details** from the incoming branch into the existing file. Don't drop specific quotes, file paths, or gotchas just because the existing version already covers the "topic" at a high level.
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 conflict resolution (compresses):
387
+ Example — BAD combination (compresses):
402
388
  ```
403
- <<<<<<< HEAD
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 conflict resolution (combines):
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
- After all merges, compare the final files against what workers produced. Ask yourself: for each worker's output, can I find every specific detail (quotes, file paths, chronic failures, gotchas) somewhere in the final memory? If not, add it back.
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 | grep -v '^main$')
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
- | Merge conflict during synthesis | Workers touched overlapping files | Read both sides fully, combine unique detailsnever rewrite from scratch. See Step 5c. |
486
- | Information lost after merge | Conflict resolution compressed worker output | Compare final files against each worker's branch output. Re-add missing specifics. See Step 5c. |
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]"
@@ -1,87 +0,0 @@
1
- #!/bin/bash
2
- # List sessions for a project from Claude Code or Codex
3
- # Usage: ./list-sessions.sh <claude|codex> [project-path]
4
-
5
- set -e
6
-
7
- SOURCE="${1:-claude}"
8
- PROJECT_PATH="${2:-$(pwd)}"
9
-
10
- if [[ "$SOURCE" == "claude" ]]; then
11
- ENCODED=$(echo "$PROJECT_PATH" | sed 's|/|-|g')
12
- PROJECT_DIR="$HOME/.claude/projects/$ENCODED"
13
-
14
- echo "=== Claude Code Sessions ==="
15
- echo "Project: $PROJECT_PATH"
16
- echo ""
17
-
18
- if [[ -d "$PROJECT_DIR" ]]; then
19
- # Session files exist - use them
20
- echo "Source: Session files"
21
- echo ""
22
-
23
- # Use sessions-index.json if available (faster)
24
- if [[ -f "$PROJECT_DIR/sessions-index.json" ]]; then
25
- jq -r '.entries | sort_by(.modified) | reverse | .[] | "\(.modified[0:19]) msgs:\(.messageCount|tostring|.[0:4]) \(.firstPrompt[0:70])..."' \
26
- "$PROJECT_DIR/sessions-index.json"
27
- else
28
- # Fall back to parsing each file
29
- for f in "$PROJECT_DIR"/*.jsonl; do
30
- [[ -f "$f" ]] || continue
31
- BASENAME=$(basename "$f")
32
- FIRST_PROMPT=$(jq -r 'select(.type == "user") | .message.content | if type == "string" then . else .[0].text // .[0].content // "?" end' "$f" 2>/dev/null | head -1 | cut -c1-70)
33
- MSG_COUNT=$(grep -c '"type"' "$f" 2>/dev/null || echo "?")
34
- MTIME=$(stat -f "%Sm" -t "%Y-%m-%d %H:%M" "$f" 2>/dev/null || stat -c "%y" "$f" 2>/dev/null | cut -c1-16)
35
- echo "$MTIME msgs:$MSG_COUNT $FIRST_PROMPT..."
36
- echo " -> $BASENAME"
37
- done
38
- fi
39
- else
40
- # No session files - fall back to history.jsonl
41
- echo "Source: history.jsonl (session files not found)"
42
- echo "Note: Only prompts available, not full conversations"
43
- echo ""
44
-
45
- if [[ -f "$HOME/.claude/history.jsonl" ]]; then
46
- MATCHES=$(jq -r --arg proj "$PROJECT_PATH" '
47
- select(.project == $proj) |
48
- "\(.timestamp / 1000 | strftime("%Y-%m-%d %H:%M")) \(.display[0:70])..."
49
- ' "$HOME/.claude/history.jsonl" 2>/dev/null)
50
-
51
- if [[ -n "$MATCHES" ]]; then
52
- echo "$MATCHES"
53
- else
54
- echo "No prompts found for this exact project path."
55
- echo "Try searching with a partial match:"
56
- echo " cat ~/.claude/history.jsonl | jq 'select(.project | contains(\"$(basename "$PROJECT_PATH")\"))'"
57
- fi
58
- else
59
- echo "No history.jsonl found"
60
- fi
61
- fi
62
-
63
- elif [[ "$SOURCE" == "codex" ]]; then
64
- echo "=== Codex Sessions ==="
65
- echo "Project: $PROJECT_PATH"
66
- echo ""
67
-
68
- FOUND=0
69
- for f in $(find "$HOME/.codex/sessions" -name "*.jsonl" 2>/dev/null | sort -r); do
70
- CWD=$(head -1 "$f" | jq -r '.payload.cwd // empty' 2>/dev/null)
71
- if [[ "$CWD" == "$PROJECT_PATH"* ]]; then
72
- ((FOUND++)) || true
73
- BASENAME=$(basename "$f")
74
- FIRST_PROMPT=$(jq -r 'select(.type == "event_msg" and .payload.type == "user_message") | .payload.message' "$f" 2>/dev/null | head -1 | cut -c1-70)
75
- TIMESTAMP=$(echo "$BASENAME" | sed 's/rollout-//' | cut -c1-19 | tr 'T' ' ')
76
- echo "$TIMESTAMP $FIRST_PROMPT..."
77
- echo " -> $f"
78
- fi
79
- done
80
-
81
- if [[ $FOUND -eq 0 ]]; then
82
- echo "No Codex sessions found for: $PROJECT_PATH"
83
- fi
84
- else
85
- echo "Usage: ./list-sessions.sh <claude|codex> [project-path]"
86
- exit 1
87
- fi