elliot-stack 1.0.29 → 1.0.33
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/LICENSE +21 -21
- package/README.md +5 -0
- package/bin/install.cjs +981 -950
- package/hooks/repo-search-nudge.js +32 -32
- package/package.json +1 -1
- package/skills/estack-active-learning-tutor/SKILL.md +339 -339
- package/skills/estack-better-title/SKILL.md +64 -64
- package/skills/estack-better-title/scripts/rename.sh +55 -55
- package/skills/estack-chris-voss/SKILL.md +80 -80
- package/skills/estack-chris-voss/references/elliot-notes.md +120 -120
- package/skills/estack-chris-voss/references/voss-principles.md +210 -210
- package/skills/estack-customer-discovery/SKILL.md +60 -60
- package/skills/estack-flight-planner/SKILL.md +332 -332
- package/skills/estack-flight-planner/references/config_schema.md +156 -156
- package/skills/estack-flight-planner/references/flight_history_schema.md +97 -97
- package/skills/estack-flight-planner/references/shuttle_schedules.md +98 -98
- package/skills/estack-flight-planner/scripts/check_setup.sh +89 -89
- package/skills/estack-flight-planner/scripts/fetch_flights.py +99 -99
- package/skills/estack-flight-planner/scripts/filter_flights.py +265 -265
- package/skills/estack-flight-planner/scripts/pair_shuttles.py +173 -173
- package/skills/estack-github-issue-tracker/SKILL.md +322 -322
- package/skills/estack-github-issue-tracker/bin/tracker-tools.cjs +1358 -1358
- package/skills/estack-github-issue-tracker/references/gh-cli-patterns.md +124 -124
- package/skills/estack-github-issue-tracker/references/result-file-schema.md +156 -156
- package/skills/estack-github-issue-tracker/references/tracker-schema.md +96 -96
- package/skills/estack-github-issue-tracker/tracker-template.md +58 -58
- package/skills/estack-leadership-coach/SKILL.md +235 -0
- package/skills/estack-leadership-coach/adding-references.md +280 -0
- package/skills/estack-leadership-coach/frameworks/delegation/flows/post-mortem.md +120 -0
- package/skills/estack-leadership-coach/frameworks/delegation/flows/pre-delegation.md +138 -0
- package/skills/estack-leadership-coach/frameworks/delegation/phases/1-intake.md +145 -0
- package/skills/estack-leadership-coach/frameworks/delegation/phases/2-trm-assessment.md +119 -0
- package/skills/estack-leadership-coach/frameworks/delegation/phases/3-enrollment.md +132 -0
- package/skills/estack-leadership-coach/frameworks/delegation/phases/4-build-brief.md +171 -0
- package/skills/estack-leadership-coach/frameworks/delegation/phases/5-monitoring.md +134 -0
- package/skills/estack-leadership-coach/frameworks/delegation/phases/6-reverse-delegation.md +118 -0
- package/skills/estack-leadership-coach/frameworks/delegation/phases/7-diagnose.md +200 -0
- package/skills/estack-leadership-coach/references/.source-files/deci-ryan_self-determination-theory__deci-olafsen-ryan-2017-self-determination-theory-in-work-organizations.md +1881 -0
- package/skills/estack-leadership-coach/references/.source-files/deci-ryan_self-determination-theory__gagne-deci-2005-self-determination-theory-and-work-motivation.md +2058 -0
- package/skills/estack-leadership-coach/references/.source-files/deci-ryan_self-determination-theory__selfdeterminationtheory-org-theory-overview-page.md +61 -0
- package/skills/estack-leadership-coach/references/.source-files/gallup_engagement-research__gallup-3-key-insights-into-the-global-workplace-2024.md +57 -0
- package/skills/estack-leadership-coach/references/.source-files/gallup_engagement-research__gallup-managers-account-for-70-percent-of-variance-in-employee-engagement-2015.md +40 -0
- package/skills/estack-leadership-coach/references/.source-files/gallup_engagement-research__gallup-state-of-the-global-workplace-2026-global-data-summary.md +73 -0
- package/skills/estack-leadership-coach/references/.source-files/gallup_engagement-research__gallup-state-of-the-global-workplace-2026-report-landing.md +42 -0
- package/skills/estack-leadership-coach/references/.source-files/hormozi-leila_4-stages__leila-hormozi-the-art-of-delegation-blog-post.md +91 -0
- package/skills/estack-leadership-coach/references/.source-files/oncken-wass_monkeys-hbr-1974__oncken-wass-management-time-whos-got-the-monkey-hbr-classic-1974.md +969 -0
- package/skills/estack-leadership-coach/references/.source-files/sanchez_main-street-millionaire__codie-sanchez-afford-anything-podcast-ep-565-show-notes.md +89 -0
- package/skills/estack-leadership-coach/references/.source-files/sullivan_who-not-how__dan-sullivan-impact-filter-tool-and-guide-booklet.md +565 -0
- package/skills/estack-leadership-coach/references/.source-files/van-edwards_cues__vanessa-van-edwards-lewis-howes-school-of-greatness-ep-1231-show-notes.md +122 -0
- package/skills/estack-leadership-coach/references/.source-files/van-edwards_cues__vanessa-van-edwards-roger-dooley-cues-interview.md +194 -0
- package/skills/estack-leadership-coach/references/deci-ryan_self-determination-theory.md +166 -0
- package/skills/estack-leadership-coach/references/doerr_measure-what-matters.md +154 -0
- package/skills/estack-leadership-coach/references/ferriss_4hww.md +189 -0
- package/skills/estack-leadership-coach/references/gallup_engagement-research.md +105 -0
- package/skills/estack-leadership-coach/references/gerber_e-myth-revisited.md +118 -0
- package/skills/estack-leadership-coach/references/grove_high-output-management.md +95 -0
- package/skills/estack-leadership-coach/references/hormozi-alex_followthrough.md +152 -0
- package/skills/estack-leadership-coach/references/hormozi-leila_4-stages.md +146 -0
- package/skills/estack-leadership-coach/references/oncken-wass_monkeys-hbr-1974.md +128 -0
- package/skills/estack-leadership-coach/references/sanchez_main-street-millionaire.md +196 -0
- package/skills/estack-leadership-coach/references/sullivan_who-not-how.md +137 -0
- package/skills/estack-leadership-coach/references/van-edwards_cues.md +189 -0
- package/skills/estack-migrate-claude-session-history/SKILL.md +226 -0
- package/skills/estack-migrate-claude-session-history/references/path-encoding.md +55 -0
- package/skills/estack-migrate-claude-session-history/references/troubleshooting.md +96 -0
- package/skills/estack-migrate-claude-session-history/scripts/migrate-claude-history.js +1123 -0
- package/skills/estack-migrate-claude-session-history/scripts/test-append-note.js +48 -0
- package/skills/estack-migrate-claude-session-history/scripts/test-validate-migration.py +326 -0
- package/skills/estack-migrate-claude-session-history/scripts/validate-migration.py +493 -0
- package/skills/estack-pdf-to-md/SKILL.md +180 -0
- package/skills/estack-pdf-to-md/scripts/pdf_to_md.py +596 -0
- package/skills/estack-productivity-prioritization-coach/SKILL.md +124 -0
- package/skills/estack-productivity-prioritization-coach/sources/01-tony-robbins-rpm.md +39 -0
- package/skills/estack-productivity-prioritization-coach/sources/02-justin-sung-task-prioritization.md +34 -0
- package/skills/estack-prompt-builder-coach/SKILL.md +81 -81
- package/skills/estack-prompt-builder-coach/definition-of-done-generator.md +42 -42
- package/skills/estack-prompt-builder-coach/prompt-builder.md +37 -37
- package/skills/estack-prompt-builder-coach/task-shaper.md +36 -36
- package/skills/estack-prompt-builder-coach/vague-ask-auditor.md +37 -37
- package/skills/estack-read-claude-session-history/SKILL.md +204 -204
- package/skills/estack-read-claude-session-history/references/jsonl-schema.md +126 -126
- package/skills/estack-read-claude-session-history/references/modes.md +423 -423
- package/skills/estack-read-claude-session-history/references/recipes.md +271 -271
- package/skills/estack-read-claude-session-history/scripts/lib/__init__.py +1 -1
- package/skills/estack-read-claude-session-history/scripts/lib/parser.py +460 -460
- package/skills/estack-read-claude-session-history/scripts/lib/paths.py +234 -234
- package/skills/estack-read-claude-session-history/scripts/lib/search.py +179 -179
- package/skills/estack-read-claude-session-history/scripts/lib/subagents.py +88 -88
- package/skills/estack-read-claude-session-history/scripts/lib/tools.py +144 -144
- package/skills/estack-read-claude-session-history/scripts/read_transcript.py +1776 -1776
- package/skills/estack-read-claude-session-history/scripts/tests/conftest.py +40 -40
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/README.md +20 -20
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/all-noise.jsonl +4 -4
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/basic-session.jsonl +2 -2
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/engagement-gaps.jsonl +9 -9
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/engagement-noise.jsonl +7 -7
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/engagement-parallel-a.jsonl +3 -3
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/engagement-parallel-b.jsonl +3 -3
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/engagement-waiting.jsonl +5 -5
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/interrupted.jsonl +2 -2
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/multi-compact.jsonl +8 -8
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/pending-user.jsonl +2 -2
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/subagent-no-meta/subagents/agent-aaa.jsonl +2 -2
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/subagent-no-meta.jsonl +2 -2
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/subagent-parent/subagents/agent-xyz123.jsonl +2 -2
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/subagent-parent/subagents/agent-xyz123.meta.json +1 -1
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/subagent-parent.jsonl +4 -4
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/time-spread.jsonl +6 -6
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/timeline-day-test.jsonl +5 -5
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/tool-zoo.jsonl +10 -10
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/truncated.jsonl +2 -2
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/unicode.jsonl +2 -2
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/with-advisor.jsonl +3 -3
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/with-compact.jsonl +5 -5
- package/skills/estack-read-claude-session-history/scripts/tests/fixtures/with-thinking.jsonl +2 -2
- package/skills/estack-read-claude-session-history/scripts/tests/test_backup_roots.py +56 -56
- package/skills/estack-read-claude-session-history/scripts/tests/test_engagement.py +239 -239
- package/skills/estack-read-claude-session-history/scripts/tests/test_json_format.py +201 -201
- package/skills/estack-read-claude-session-history/scripts/tests/test_modes.py +199 -199
- package/skills/estack-read-claude-session-history/scripts/tests/test_parser.py +195 -195
- package/skills/estack-read-claude-session-history/scripts/tests/test_paths.py +133 -133
- package/skills/estack-read-claude-session-history/scripts/tests/test_search.py +78 -78
- package/skills/estack-read-claude-session-history/scripts/tests/test_subagents.py +43 -43
- package/skills/estack-read-claude-session-history/scripts/tests/test_timeline.py +179 -179
- package/skills/estack-read-claude-session-history/scripts/tests/test_timezone_and_project.py +212 -212
- package/skills/estack-read-claude-session-history/scripts/tests/test_tools.py +80 -80
- package/skills/estack-repo-search/SKILL.md +65 -65
- package/skills/estack-vscode-file-recovery/SKILL.md +188 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: estack-migrate-claude-session-history
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
description: (migrate-claude-session-history) Use whenever the user wants to move a Claude Code session (the .jsonl transcript plus its subagent sidecar files) from one project to another so that /resume picks it up under the new project. Triggers on phrases like "migrate this session", "move this session to <project>", "convert session X to be in project Y instead of Z", "transfer chat history to another project", "this session belongs under <project>", or when the user names a session UUID and a different target project. Handles the full workflow: backup, sidecar-aware copying, rewriting all 9 path-encoding variants in every entry, appending a visible user-message migration note, and end-to-end verification. Use this even if the user only describes the intent loosely (e.g. "this conversation should live under the personal-health project") — do not try to do this by hand with raw file moves; subtle cwd / encoded-path bugs will break /resume.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Migrate Claude Session History
|
|
8
|
+
|
|
9
|
+
## When this skill applies
|
|
10
|
+
|
|
11
|
+
The user wants a specific session (or a handful of sessions) that currently lives under Project A in `~/.claude/projects/` to instead live under Project B, so that `claude --resume` and `/resume` find it under B and the conversation's recorded working directory matches B.
|
|
12
|
+
|
|
13
|
+
This is **not** the right skill for:
|
|
14
|
+
|
|
15
|
+
- Listing / searching / reading sessions → use `read-claude-session-history`
|
|
16
|
+
- Recovering deleted sessions from backups → use the `.claude-backups` snapshots via `read-claude-session-history`
|
|
17
|
+
- Renaming a project's working directory and moving **all** of its sessions at once → use `scripts/migrate-claude-history.js` directly without the `--session` flag (it has a full-project mode)
|
|
18
|
+
- A brand-new conversation in a different folder → just start a fresh Claude Code session there
|
|
19
|
+
|
|
20
|
+
## Why this is not a one-liner
|
|
21
|
+
|
|
22
|
+
A Claude Code session is keyed by the project's working directory, which gets encoded into the project folder name under `~/.claude/projects/`. The session's `.jsonl` transcript contains hundreds of references to that directory across **nine** path-encoding variants (JSON-escaped backslash, plain backslash, forward slash, MSYS, hyphenated project-dir name — each in upper/lower drive-letter forms). A `cwd` field exists on most entries. There is also a sidecar directory (`<uuid>/subagents/`) holding subagent transcripts that must move together.
|
|
23
|
+
|
|
24
|
+
Just `mv` will not work. The bundled script handles all of this; the workflow below ties it together with a backup, a visible migration note, and verification.
|
|
25
|
+
|
|
26
|
+
See `references/path-encoding.md` for the encoding reference.
|
|
27
|
+
|
|
28
|
+
## Workflow
|
|
29
|
+
|
|
30
|
+
Work through these steps in order. Skipping the plan / backup / verification steps is exactly how a migration goes wrong silently — the script reports success, but `/resume` fails to find the session or loads it under the wrong project.
|
|
31
|
+
|
|
32
|
+
### 1. Resolve the inputs
|
|
33
|
+
|
|
34
|
+
You need three things. Treat the conversation as the primary source — only ask the user for what is genuinely missing.
|
|
35
|
+
|
|
36
|
+
| Input | How to resolve |
|
|
37
|
+
|---|---|
|
|
38
|
+
| **Session UUID** | If the user gave a UUID, use it. If they gave a session file path, take the basename without `.jsonl`. If they only described the session ("the one where we did X"), use `read-claude-session-history --mode search --all-projects --query "<keywords>"` to find candidates and confirm with the user. |
|
|
39
|
+
| **Source project path** (the real cwd) | Run `python <read-claude-session-history>/scripts/read_transcript.py --mode lookup --uuid <prefix>` to get the source `.jsonl` path. Reverse the encoded folder name back into a real Windows path: drop the leading `C--` (becomes `C:\`) and convert each `-` between path segments back to `\`. Confirm by reading the `cwd` field of any entry in the file. |
|
|
40
|
+
| **Target project path** (where the session should live) | Ask the user, unless the conversation already named it (e.g. "move it to `~\Foo\Bar`"). The target project directory under `~/.claude/projects/` does **not** need to exist yet — the script creates it. The encoded folder name is derived from the path. |
|
|
41
|
+
|
|
42
|
+
If the source and target encoded folder names are identical, the migration is a no-op — tell the user.
|
|
43
|
+
|
|
44
|
+
### 2. Present the plan and confirm
|
|
45
|
+
|
|
46
|
+
Before touching anything, show the user a short plan with:
|
|
47
|
+
|
|
48
|
+
- Source `.jsonl` path
|
|
49
|
+
- Target `.jsonl` path
|
|
50
|
+
- Old cwd → New cwd (the values that will be rewritten)
|
|
51
|
+
- Backup location (default: `<source-real-path>\session-backups\<timestamp>-pre-migration\`, or a path the user prefers)
|
|
52
|
+
- A note that the script will also append a visible user-message migration note to the migrated transcript (on by default; see step 6)
|
|
53
|
+
|
|
54
|
+
Wait for explicit "go ahead." Migrations touch files Claude Code reads on every `/resume`; a wrong target is annoying to recover from. The backup is the safety net, but confirming first means we usually don't need to use it.
|
|
55
|
+
|
|
56
|
+
### 3. Back up both project directories — full copies, both sides
|
|
57
|
+
|
|
58
|
+
Robocopy is the right tool on Windows — fast and resilient with large dirs:
|
|
59
|
+
|
|
60
|
+
```powershell
|
|
61
|
+
$ts = Get-Date -Format "yyyy-MM-dd-HHmmss"
|
|
62
|
+
$backupRoot = "<chosen-backup-root>\$ts-pre-migration"
|
|
63
|
+
New-Item -ItemType Directory -Force -Path $backupRoot | Out-Null
|
|
64
|
+
robocopy "<source-project-dir>" "$backupRoot\<source-folder-name>" /E /NFL /NDL /NJH /NJS /NP /MT:8 | Out-Null
|
|
65
|
+
robocopy "<target-project-dir>" "$backupRoot\<target-folder-name>" /E /NFL /NDL /NJH /NJS /NP /MT:8 | Out-Null
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Back up the **entire** source project dir **and** the **entire** target project dir, even if the target only has one or two unrelated sessions. These backups serve two purposes, and the second one is the one people forget:
|
|
69
|
+
|
|
70
|
+
1. **Rollback safety net.** If anything in the migration goes wrong, you can restore both sides to their pre-migration state in one command.
|
|
71
|
+
2. **Ground truth for validation.** The backup of the source dir is the only authoritative record of what the original transcript looked like — every entry, every path string, every sidecar file. After migration, step 7 will diff the migrated content against the backup to prove that **every** old-path occurrence was rewritten (no encoding variant was missed) and **no** entries were lost, duplicated, or reordered. The backup of the target dir proves you only **added** files to it — you didn't accidentally overwrite anything that was already there. Without both backups, "the migration worked" is hope, not verification.
|
|
72
|
+
|
|
73
|
+
Robocopy's exit codes are non-standard — exit 1 means "files copied successfully," not an error. After it finishes, report the file counts and sizes from `Get-ChildItem ... -Recurse | Measure-Object` so the user sees the backup actually contains something.
|
|
74
|
+
|
|
75
|
+
### 4. Dry-run, then execute
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
node <skill-dir>/scripts/migrate-claude-history.js \
|
|
79
|
+
--old-repo "<source-project-real-path>" \
|
|
80
|
+
--new-repo "<target-project-real-path>" \
|
|
81
|
+
--session <session-uuid> \
|
|
82
|
+
--dry-run
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The dry-run prints:
|
|
86
|
+
|
|
87
|
+
- Which `.jsonl` plus how many sidecar files would be copied
|
|
88
|
+
- Replacement counts per path-encoding variant (most sessions hit only pattern A — JSON-escaped backslash, upper-drive — because that's what `cwd` fields use)
|
|
89
|
+
|
|
90
|
+
If the dry-run output looks wrong (zero sidecar files when there should be subagents, wildly different replacement counts than expected, or zero replacements at all), stop and investigate before running for real. See `references/troubleshooting.md`.
|
|
91
|
+
|
|
92
|
+
Then run without `--dry-run` to execute. The script:
|
|
93
|
+
|
|
94
|
+
- Copies the `<uuid>.jsonl` to the target project dir, applying all 9 path replacements
|
|
95
|
+
- Copies the entire `<uuid>/subagents/` sidecar tree (subagent transcripts + meta files) with the same replacements
|
|
96
|
+
- Appends a visible migration note as a regular user message to the main `.jsonl` (see step 6)
|
|
97
|
+
- Runs its own stale-reference verifier and reports any matches
|
|
98
|
+
|
|
99
|
+
### 5. Handle the "stale reference" warning
|
|
100
|
+
|
|
101
|
+
When the **new** project path contains the **old** project path as a prefix (e.g. moving from `Other Claude Code` → `Other Claude Code\Personal-Health-Project`), the script's verifier will warn about "stale references" in the migrated file. These are **false positives**: every occurrence of the old path is now actually inside a new-path string (since the new path begins with the old path).
|
|
102
|
+
|
|
103
|
+
Confirm it really is a false positive by counting genuine stale references — occurrences of the old path that are **not** followed by the new path's added segment. A Python check is in `references/troubleshooting.md`. If true-stale count is zero, ignore the warning.
|
|
104
|
+
|
|
105
|
+
If true-stale count is non-zero, **do not** declare success. Investigate which pattern the script missed and either fix the script or hand-patch the file.
|
|
106
|
+
|
|
107
|
+
### 6. The migration note
|
|
108
|
+
|
|
109
|
+
By default, the script appends a `type: "user"` entry (no `isMeta`) as the last entry of the migrated `.jsonl`. This entry:
|
|
110
|
+
|
|
111
|
+
- Tells future-Claude (and the user, when scrolling the conversation) that the session was migrated, what was rewritten, and how to recover when a rewritten path no longer exists on disk
|
|
112
|
+
- Is intentionally **not** `isMeta: true` — the user wants both themselves and the AI to see it on `/resume`
|
|
113
|
+
- Is duplicate-safe — the script's append routine checks the last few entries for an existing `<session-migration-note>` block and refuses to add a second
|
|
114
|
+
|
|
115
|
+
Users can opt out with `--no-migration-note`, but the script prints a warning that this is strongly discouraged. Do not pass `--no-migration-note` unless the user has explicitly asked for it.
|
|
116
|
+
|
|
117
|
+
### 7. Verify end-to-end — and validate against the backup
|
|
118
|
+
|
|
119
|
+
Run the bundled validation script. It consolidates every structural, schema, path-consistency, sidecar, and (optional) backup-cross-validation check into one invocation, prints a per-check PASS/FAIL table, and exits non-zero on any failure.
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
python <skill-dir>/scripts/validate-migration.py \
|
|
123
|
+
"<target-project-encoded-dir>/<uuid>.jsonl" \
|
|
124
|
+
--old-repo "<source-real-path>" \
|
|
125
|
+
--new-repo "<target-real-path>" \
|
|
126
|
+
--source-backup "<backup-root>/<source-folder-name>/<uuid>.jsonl" \
|
|
127
|
+
--target-backup-dir "<backup-root>/<target-folder-name>"
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
The script runs these checks in order — most of them require no flags, the path checks need `--old-repo` and `--new-repo`, and the cross-validation checks need `--source-backup` (with `--target-backup-dir` enabling the "target untouched" sub-check):
|
|
131
|
+
|
|
132
|
+
| Check | What it validates | Needs flags |
|
|
133
|
+
|---|---|---|
|
|
134
|
+
| JSONL parse integrity | Every line is valid JSON | — |
|
|
135
|
+
| Schema consistency | Each entry has `type`; user/assistant entries have well-formed `message`; uuids and parentUuids are UUID-shaped | — |
|
|
136
|
+
| Session ID consistency | Every entry's `sessionId` matches the file's UUID | — |
|
|
137
|
+
| Parent UUID chains | Every non-null `parentUuid` resolves to a uuid present in the file | — |
|
|
138
|
+
| CWD field consistency | All non-empty `cwd` values are identical (and equal `--new-repo` if passed) | optionally `--new-repo` |
|
|
139
|
+
| Migration note present | Exactly one `<session-migration-note>` entry exists, is `type: "user"`, no `isMeta` | — |
|
|
140
|
+
| Stale path references | No "truly-stale" old-path references in entries that existed at migration time (post-note entries are skipped — those are later activity that can legitimately reference the old path) | `--old-repo` + `--new-repo` |
|
|
141
|
+
| Sidecar integrity | Every subagent `.jsonl` in `<uuid>/` parses and shares the parent `sessionId` | — |
|
|
142
|
+
| Backup cross-validation | Source backup parses; entry count = source + 1; every source uuid present in order; sidecar count matches; pre-existing target files unchanged | `--source-backup` (+ `--target-backup-dir`) |
|
|
143
|
+
|
|
144
|
+
If anything fails, stop. Read the failed check's detail line — it points at the specific entry index or file. The backup is right there; if recovery is needed: `robocopy <backup-dir> <live-dir> /MIR`.
|
|
145
|
+
|
|
146
|
+
All checks must pass before declaring success. The script's final line is the summary you report back to the user.
|
|
147
|
+
|
|
148
|
+
### 8. Tell the user what's next, and tear down the safety net
|
|
149
|
+
|
|
150
|
+
After verification, the user still has work to do. Walk them through these in order — each one unlocks the next.
|
|
151
|
+
|
|
152
|
+
1. **Test `/resume` in the new project's working directory.** This is the real validation. The migrated session should appear in the resume picker and load with the full conversation history. If it doesn't, **stop** — do not delete anything. See `references/troubleshooting.md` → "/resume doesn't show the session under the new project" for diagnosis.
|
|
153
|
+
|
|
154
|
+
Give the user a ready-to-run command they can copy directly. Format it in a fenced code block:
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
cd "<target-project-real-path>";claude -r <session-uuid>
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Example: `cd "C:\Users\2supe\Other Claude Code\Personal-Health-Project";claude -r ef382169-d56b-4850-b092-8084a52983ef`
|
|
161
|
+
|
|
162
|
+
2. **Once `/resume` works, delete the original session from the source project.** Until they do, `--mode lookup` will report the UUID as ambiguous, and Claude Code may still find the session under the old project. Ask the user before running these yourself — deletion is irreversible:
|
|
163
|
+
```powershell
|
|
164
|
+
Remove-Item "<source-project-encoded-dir>\<uuid>.jsonl"
|
|
165
|
+
Remove-Item -Recurse "<source-project-encoded-dir>\<uuid>" # sidecar dir
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### 9. Clean up the backups — the final step
|
|
169
|
+
|
|
170
|
+
Once both of the above are done, **the migration is locked in** and the pre-migration backup folder created in step 3 is just bloat. Robocopy backups of `.claude/projects/` directories run hundreds of megabytes; do not let them accumulate. Delete the entire backup folder created for this migration:
|
|
171
|
+
|
|
172
|
+
```powershell
|
|
173
|
+
Remove-Item -Recurse -Force "<backup-root>"
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Confirm with the user before deleting and report the freed size. Do **not** skip this step or default to "keep it for a few days" — if `/resume` worked and the source copy is gone, the backup has done its job. Keeping it costs disk and clutters the workspace.
|
|
177
|
+
|
|
178
|
+
The only reason to keep a backup is if you have not yet verified `/resume` works **or** you have not yet deleted the source copy. In either of those cases, you are still in steps 1-2, not step 9.
|
|
179
|
+
|
|
180
|
+
## Common pitfalls
|
|
181
|
+
|
|
182
|
+
These are the failure modes that have actually happened — read `references/troubleshooting.md` for the fixes.
|
|
183
|
+
|
|
184
|
+
- Forgetting the sidecar dir — the main `.jsonl` migrates but the subagent transcripts get left behind, so the migrated brief shows `subagents: 0` even though the original had many. The script's `--session` mode now handles this automatically, but verify with the subagent-list check.
|
|
185
|
+
- Treating "stale reference" warnings as real when the new path is a subdir of the old path.
|
|
186
|
+
- Running the migration without `--session`, which migrates **every** session in the source project (the constants/CLI default is full-project mode).
|
|
187
|
+
- Source-path encoding mismatch — Claude Code creates `C--Foo` on Windows but case-insensitive filesystems can produce `c--Foo`. The script tries both.
|
|
188
|
+
- Forgetting to rewrite `gitBranch` / `version` consistency on the appended note — the script copies these from the last uuid-bearing entry; do not invent values.
|
|
189
|
+
|
|
190
|
+
## Files in this skill
|
|
191
|
+
|
|
192
|
+
- `scripts/migrate-claude-history.js` — the migration script. Supports full-project and single-session modes, CLI overrides for old/new repo, auto-append of the migration note (on by default), `--no-migration-note` opt-out, and `--dry-run`. Run `node scripts/migrate-claude-history.js --help` for the full CLI.
|
|
193
|
+
- `scripts/validate-migration.py` — post-migration validator. Runs structural, schema, path-consistency, sidecar, and (optional) backup-cross-validation checks on a migrated `.jsonl`. Exits 0 if every check passes, 1 otherwise. Run `python scripts/validate-migration.py --help` for the full CLI. Use this in step 7 instead of writing ad-hoc Python.
|
|
194
|
+
- `scripts/test-append-note.js` — a self-contained smoke test for the note-append routine. Run with `node scripts/test-append-note.js`. Useful if you edit the migration script and want to sanity-check the duplicate-detection and non-meta entry shape.
|
|
195
|
+
- `references/path-encoding.md` — the 9 path-encoding variants, why each exists, which entries use which form.
|
|
196
|
+
- `references/troubleshooting.md` — recoveries for stale-reference false positives, missed sidecars, ambiguous lookups, and the true-stale grep recipe.
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## Skill Feedback
|
|
200
|
+
|
|
201
|
+
If the user shares feedback about this skill — a bug, something confusing, a missing feature, or a suggestion — ask them to describe it in a bit more detail (what they expected, what happened, and any relevant context). Then file the issue using whichever method is available:
|
|
202
|
+
|
|
203
|
+
**If `gh` is installed** (`gh --version` succeeds), create the issue directly:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
gh issue create \
|
|
207
|
+
--repo ElliotDrel/e-stack \
|
|
208
|
+
--title "estack-migrate-claude-session-history: <concise summary>" \
|
|
209
|
+
--body "<description from user feedback — expected vs. actual behavior and context>"
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
**If `gh` is not installed**, build a pre-filled URL:
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
python3 -c "
|
|
216
|
+
import urllib.parse
|
|
217
|
+
title = 'estack-migrate-claude-session-history: <concise summary>'
|
|
218
|
+
body = '<description from user feedback — expected vs. actual behavior and context>'
|
|
219
|
+
base = 'https://github.com/ElliotDrel/e-stack/issues/new'
|
|
220
|
+
print(base + '?title=' + urllib.parse.quote(title) + '&body=' + urllib.parse.quote(body))
|
|
221
|
+
"
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Share the printed URL with the user and offer to open it in their browser.
|
|
225
|
+
|
|
226
|
+
They can also click it directly, review the pre-filled title and body, and click **Submit new issue**.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Path Encoding Reference
|
|
2
|
+
|
|
3
|
+
Why session migration needs **nine** path replacements instead of one.
|
|
4
|
+
|
|
5
|
+
A Claude Code project's working directory shows up inside session transcripts in several different encodings depending on which subsystem wrote it. Missing even one variant produces a transcript that *looks* migrated but breaks on `/resume` or shows the wrong project name. The migration script applies all nine; this file documents what each one is, and where it tends to appear.
|
|
6
|
+
|
|
7
|
+
The script sorts the nine pairs longest-first before substitution, which prevents partial overlaps (e.g. matching the forward-slash form inside the JSON-escaped backslash form).
|
|
8
|
+
|
|
9
|
+
## The nine variants
|
|
10
|
+
|
|
11
|
+
For an old path `C:\Users\name\old\repo` migrating to `C:\Users\name\new\repo`, the script rewrites all of these:
|
|
12
|
+
|
|
13
|
+
| Key | Encoding | Example old form | Where it appears |
|
|
14
|
+
|---|---|---|---|
|
|
15
|
+
| A | JSON-escaped backslash, uppercase drive | `C:\\Users\\name\\old\\repo` | `cwd` field on most entries; tool inputs serialized as JSON strings. This is usually the highest-count replacement by far. |
|
|
16
|
+
| B | JSON-escaped backslash, lowercase drive | `c:\\Users\\name\\old\\repo` | Rare; only when something on the system normalized the drive to lowercase. |
|
|
17
|
+
| C | Forward slash, uppercase drive | `C:/Users/name/old/repo` | Tool outputs from Unix-ish utilities running on Windows (e.g. `find`, `grep` via Git Bash). |
|
|
18
|
+
| D | Hyphenated project-dir name, lowercase drive | `c--Users-name-old-repo` | References to the encoded project dir under `.claude/projects/` in lowercase. |
|
|
19
|
+
| E | MSYS / Git Bash path | `/c/Users/name/old/repo` | Bash tool outputs from MSYS / Git Bash. |
|
|
20
|
+
| F | Hyphenated project-dir name, uppercase drive | `C--Users-name-old-repo` | References to the encoded project dir, the form Claude Code itself uses on Windows. |
|
|
21
|
+
| G | Forward slash, lowercase drive | `c:/Users/name/old/repo` | Rare lowercase-drive variant of C. |
|
|
22
|
+
| H | Plain backslash, uppercase drive | `C:\Users\name\old\repo` | Conversation text — when Claude prints a path inline, it usually uses this form. |
|
|
23
|
+
| I | Plain backslash, lowercase drive | `c:\Users\name\old\repo` | Rare lowercase-drive variant of H. |
|
|
24
|
+
|
|
25
|
+
## How the encoded project-dir name is built
|
|
26
|
+
|
|
27
|
+
Given a Windows path like `C:\Users\name\old\repo`:
|
|
28
|
+
|
|
29
|
+
1. Take the drive letter and colon → `C:`
|
|
30
|
+
2. Append each path segment separated by `\` → `C:\Users\name\old\repo`
|
|
31
|
+
3. Replace every `:`, `\`, `/`, space, and `'` with `-` → `C--Users-name-old-repo`
|
|
32
|
+
|
|
33
|
+
This is the folder name under `~/.claude/projects/`. Claude Code creates the uppercase-drive form on Windows; the lowercase form exists for case-insensitive filesystem quirks.
|
|
34
|
+
|
|
35
|
+
## Why this matters for migrations
|
|
36
|
+
|
|
37
|
+
Most replacements happen in the `cwd` field (variant A). But other variants show up in:
|
|
38
|
+
|
|
39
|
+
- Subagent transcripts that captured shell output (variants C, E, G)
|
|
40
|
+
- Tool result strings where Claude or a tool quoted a path (variant H)
|
|
41
|
+
- References to other sessions or the project dir itself (variants D, F)
|
|
42
|
+
|
|
43
|
+
The replacement count printed by the migration script's dry-run reveals which subsystems your session interacted with. A session that only ever talked to native Windows tools will show 100% pattern A; one that ran a lot of `git` or `bash` will show a mix.
|
|
44
|
+
|
|
45
|
+
## What does NOT get rewritten
|
|
46
|
+
|
|
47
|
+
- The new project's encoded folder name (`new-repo`'s `C--...` form). This is computed from `--new-repo` and used as the target directory name; it isn't substituted into entry bodies.
|
|
48
|
+
- File contents outside the session transcripts. The script operates only on text files inside the project directory under `~/.claude/projects/`.
|
|
49
|
+
- Anything that doesn't include the old path as a substring. The script does literal substring matching, not pattern matching.
|
|
50
|
+
|
|
51
|
+
## What to do when the new path is a substring of the old path (or vice versa)
|
|
52
|
+
|
|
53
|
+
This happens when you migrate a session into a subdirectory of its current project (e.g. `Other Claude Code` → `Other Claude Code\Sub-Project`). The script handles it correctly thanks to longest-first sorting, but its post-migration verifier will produce **false-positive** warnings because every occurrence of the new path also contains the old path as a substring.
|
|
54
|
+
|
|
55
|
+
See `references/troubleshooting.md` → "Stale reference false positive" for the recipe that distinguishes real stale references from prefix-containment artifacts.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Troubleshooting
|
|
2
|
+
|
|
3
|
+
Specific failure modes that have actually happened, with the diagnostic and the fix.
|
|
4
|
+
|
|
5
|
+
## Stale reference false positive
|
|
6
|
+
|
|
7
|
+
**Symptom.** The script prints, for the migrated file:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
Stale reference in: <new-path>\<uuid>.jsonl (matches: C:\\Users\\...)
|
|
11
|
+
WARNING: Found N file(s) in the new project dir that still contain old path references.
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
**When this is harmless.** When the **new** project path contains the **old** project path as a prefix (e.g. you migrated `C:\Users\me\Workspace` → `C:\Users\me\Workspace\Sub-Project`), every successfully rewritten occurrence of the new path also contains the old path as a substring. The verifier does naive substring matching, so it flags itself.
|
|
15
|
+
|
|
16
|
+
**Diagnostic — count GENUINELY stale occurrences.** Run the bundled validator with `--old-repo` and `--new-repo`; the "Stale path references" check uses a negative-lookahead that filters out the prefix-containment false positives. It also scopes the check to entries that existed at migration time, ignoring any later activity that legitimately references the old path:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
python <skill-dir>/scripts/validate-migration.py \
|
|
20
|
+
"<target-jsonl>" \
|
|
21
|
+
--old-repo "<source-real-path>" \
|
|
22
|
+
--new-repo "<target-real-path>"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
If that check passes, the migration script's own warning was a false positive — move on. If it fails, the failure detail names the specific entries and counts; figure out which encoding variant the migration script missed (see `path-encoding.md`) and either re-run with a fix or hand-patch the file.
|
|
26
|
+
|
|
27
|
+
## Sidecar / subagent files left behind
|
|
28
|
+
|
|
29
|
+
**Symptom.** The migrated session's brief shows `subagents: 0`, but the original had several. Or `--mode subagent-list` against the migrated file returns nothing.
|
|
30
|
+
|
|
31
|
+
**Cause.** In an older version of the script's single-session mode, only the top-level `<uuid>.jsonl` was copied — the `<uuid>/subagents/` sidecar directory was missed because the filter matched on basename only.
|
|
32
|
+
|
|
33
|
+
**Fix.** The current script copies the sidecar tree automatically when `--session` is set. If you see this symptom, you're running an out-of-date copy of the script. Use the bundled one at `scripts/migrate-claude-history.js`.
|
|
34
|
+
|
|
35
|
+
**Recovery if it already happened.** Just re-run the migration. The script's "skip if destination exists" check means the already-copied `.jsonl` won't be touched, and the sidecar files will be added on the second pass.
|
|
36
|
+
|
|
37
|
+
## Ambiguous UUID lookup
|
|
38
|
+
|
|
39
|
+
**Symptom.** After migration, `read-claude-session-history --mode lookup --uuid <prefix>` returns:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
Ambiguous prefix '<uuid>' matches 2 sessions:
|
|
43
|
+
<source-project>/<uuid>.jsonl
|
|
44
|
+
<target-project>/<uuid>.jsonl
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Cause.** This is expected and correct — the migration is non-destructive. The source copy is still in place as a safety net until the user confirms `/resume` works under the new project.
|
|
48
|
+
|
|
49
|
+
**Fix.** Once the user has confirmed the migrated session resumes correctly under the new project, delete the source copy:
|
|
50
|
+
|
|
51
|
+
```powershell
|
|
52
|
+
Remove-Item "<source-project-encoded-dir>\<uuid>.jsonl"
|
|
53
|
+
Remove-Item -Recurse "<source-project-encoded-dir>\<uuid>" # sidecar dir
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Never delete before the user confirms. The backup folder is a fallback if the user discovers something broken later, but the in-place source copy is the fastest recovery path.
|
|
57
|
+
|
|
58
|
+
## /resume doesn't show the session under the new project
|
|
59
|
+
|
|
60
|
+
**Symptom.** User runs `claude` in the new project's working directory, types `/resume`, and the migrated session doesn't appear in the list.
|
|
61
|
+
|
|
62
|
+
**Diagnosis — go through these in order.**
|
|
63
|
+
|
|
64
|
+
1. **Confirm the migrated `.jsonl` is in the right encoded folder.** The folder under `~/.claude/projects/` must exactly match the encoded form of the **real** path the user is `cd`'d into. Case differences (`C--Foo` vs `c--Foo`) and missing/added hyphens both break the match. Compare: get the real cwd → encode it (drop drive colon, replace separators with `-`) → ensure that's the folder name.
|
|
65
|
+
|
|
66
|
+
2. **Confirm the `cwd` field inside the entries matches.** A surprising amount of `/resume` logic keys off the entries' `cwd` field, not the folder name. Run the distinct-cwd check from SKILL.md step 7 — every entry should be the new path (or empty for marker entries).
|
|
67
|
+
|
|
68
|
+
3. **Confirm the `.jsonl` is not zero-byte or malformed.** Open it: `python -c "import json; [json.loads(l) for l in open(r'<path>', encoding='utf-8') if l.strip()]"` — if this errors, the migration corrupted something.
|
|
69
|
+
|
|
70
|
+
4. **Check whether Claude Code stripped or reordered entries.** Claude Code occasionally writes `permission-mode` and `ai-title` metadata entries when something opens a file. These are harmless. But if the count is far off from the original (say, more than +5), something else is wrong.
|
|
71
|
+
|
|
72
|
+
## "Cannot find old project directory" error from the script
|
|
73
|
+
|
|
74
|
+
**Symptom.** Script exits with: `Could not find old Claude project directory. Checked: ...`
|
|
75
|
+
|
|
76
|
+
**Cause.** The `--old-repo` value's encoded form doesn't match any folder under `~/.claude/projects/`. Most often this is because the user gave a real path that doesn't actually have any sessions yet (the project folder gets created lazily).
|
|
77
|
+
|
|
78
|
+
**Fix.** Run `ls ~/.claude/projects/` and find the folder name that corresponds to the user's intended source. Reverse-engineer the real path from the folder name and pass that as `--old-repo`. The encoding is: `C--<rest>` becomes `C:\<rest with hyphens turned back into backslashes>`.
|
|
79
|
+
|
|
80
|
+
## The migration note was accidentally appended twice
|
|
81
|
+
|
|
82
|
+
**Symptom.** Two `<session-migration-note>` blocks at the tail of the file.
|
|
83
|
+
|
|
84
|
+
**Cause.** Pre-fix versions of the append routine didn't dedupe; or the file was edited between two script runs.
|
|
85
|
+
|
|
86
|
+
**Fix.** The current script checks the last few entries for an existing `<session-migration-note>` and won't append a duplicate. To clean up an already-doubled note, hand-edit the file: remove the older note entry, keep the newer one. Always backup the file first.
|
|
87
|
+
|
|
88
|
+
## Forgetting `--session` and migrating the whole project
|
|
89
|
+
|
|
90
|
+
**Symptom.** Script copies hundreds of files, takes much longer than expected, prints replacement counts in the thousands. The target project dir suddenly has many `.jsonl` files.
|
|
91
|
+
|
|
92
|
+
**Cause.** Without `--session`, the script's default mode migrates **every** session in the source project — that's how the script was originally written, for the rename-a-project use case.
|
|
93
|
+
|
|
94
|
+
**Fix.** Stop the script (Ctrl-C if still running). Delete the unintended files from the target project dir (compare with the target backup to know what wasn't there before). Re-run with `--session <uuid>` this time.
|
|
95
|
+
|
|
96
|
+
This is why backing up the **target** dir matters as much as backing up the source — without it, recovering from this mistake is much harder.
|