Migrating an existing setup¶
If you already have a Claude Code setup — vanilla (~/.claude/) or customized — lh migrate upgrades it to a lazy-harness installation without losing data.
What gets detected¶
The migration detector scans for:
| Target | Location | What happens |
|---|---|---|
| Vanilla Claude Code | ~/.claude/ |
Profile created, settings translated |
| Custom profile dirs | ~/.claude-<name>/ |
Each becomes a lazy-harness profile |
| Symlinks into other repos | ~/.claude-<name>/* |
Flattened into real files in the profile dir |
| Deployed scripts | ~/.local/bin/lcc-*, etc. |
Removed (superseded by lh) |
| LaunchAgents | ~/Library/LaunchAgents/com.* |
Cataloged; optionally replaced with lh scheduler jobs |
| Knowledge directories | Paths referenced in existing configs | Cataloged; pointed at, not moved |
| QMD collections | qmd status |
Reconfigured to point at the new knowledge path |
Detection is read-only and idempotent. You can run it as many times as you want without side effects.
The dry-run gate¶
lh migrate without --dry-run refuses to execute unless there is a dry-run marker less than one hour old in the backup directory. This is a safety rail: you must review the plan before running it.
lh migrate --dry-run
Output is a human-readable plan like:
Detected:
- 2 profile dirs: ~/.claude-personal, ~/.claude-work
- 8 deployed scripts in ~/.local/bin/
- 3 LaunchAgents (com.example.*)
- QMD with 5 collections
Plan:
1. Backup → ~/.config/lazy-harness/backups/migrate/<ts>/
2. Generate config.toml with 2 profiles
3. Relocate profiles to ~/.config/lazy-harness/profiles/
4. Translate hooks from settings.json
5. Replace 3 LaunchAgents with lh scheduler jobs
6. Remove 8 script symlinks
7. Point knowledge at ~/Documents/existing-knowledge
8. Reconfigure 5 QMD collections
9. Run lh selftest
Run `lh migrate` to execute this plan (within 1 hour).
Executing¶
lh migrate
Each step logs what it is about to do. The executor takes a backup snapshot first and writes a rollback log as it goes.
Rolling back¶
If something feels wrong after migration:
lh migrate --rollback
This reads the most recent rollback log and reverses every step in order. Rollback is idempotent — you can run it multiple times safely.
For an automatic rollback (if a step fails mid-execution), no action is needed — the executor does it for you and exits non-zero.
The backup taken before execution keys each entry by its full source path, so two profile files that happen to share a basename (settings.json under two different profile dirs) are backed up and restored independently — neither one can overwrite or stand in for the other. Symlinked targets are recorded as symlinks, not resolved into a copy of what they point to. A backup interrupted partway through is marked incomplete and refused for automatic restore rather than silently replaying whatever partial state made it to disk; the backup directory itself is left in place for manual recovery. Backups written before this behavior shipped (no manifest present) still restore, as long as the files being restored don't collide by basename with each other.
Post-migration checklist¶
- Run
lh selftest. Every check should pass. - Start an agent session with your first profile. Verify context injection works: the first message should include a banner like
Session context loaded: on main | Last session: .... - If you had recurring jobs (cron / launchd), verify they still run.
lh scheduler statuslists the ones the harness manages on every platform. - Version your profiles. Example with chezmoi:
cd ~/.config/lazy-harness
chezmoi add profiles/
- Keep the backup directory until you have used the migrated setup for at least a week without issues.
Known limitations¶
- Windows is not supported. The migration will refuse to run.
- Arbitrary custom hooks are best-effort translated. Complex hook chains may need manual review post-migration. Run
lh doctorto see hook warnings. - Profiles containing broken symlinks abort the migration with a clear error. Fix the underlying symlinks first, then retry.