Memory Cleanup — Manual Dream Process
Implements the 4-phase memory consolidation process modelled after Claude Code's Auto Dream feature. Run after major refactors, framework migrations, or every 5+ sessions in a repo.
The memory system lives at ~/.claude/projects/<encoded-cwd>/memory/ and consists of:
MEMORY.md— index file (must stay under 200 lines; lines after 200 are truncated by the harness).- Topic files — one Markdown file per memory entry with YAML frontmatter (
name,description,metadata.type).
The four memory types are user, feedback, project, reference (see global auto memory instructions for semantics). This skill never invents new types.
Argument Handling (Phase 0)
This skill accepts two optional flags. Default (no flag) runs the interactive 4-phase consolidation defined below.
| Flag | Behavior |
|---|---|
--dry-run | Run Phases 1-3 read-only; instead of mutating MEMORY.md / topic files, write a unified-diff proposal to .orchestrator/pending-dream.md (atomic). Exit 0. |
--apply-pending | Read .orchestrator/pending-dream.md; refuse if older than 14 days; apply diff; delete pending file; print auto-dream applied: -<X> lines, +<Y> entries. Exit 0. |
Flags are mutually exclusive — passing both is an error. Absence of both = legacy interactive mode (Phases 1-4 below).
--dry-run flow:
- Read MEMORY.md and topic files (read-only).
- Produce the same internal plan the interactive mode would (merges, prunes, rewrites).
- Serialise the plan as a unified diff body inside a fenced
```diffblock (or as a complete replacement body when full rewrite is simpler). - Call
writePendingDream({ repoRoot, diff, sourceSession, memoryLinesBefore, proposedLinesAfter })fromscripts/lib/auto-dream.mjs. - Print one-line status:
pending-dream written: <N> lines proposed(orno consolidation needed (MEMORY.md is healthy)when the plan is empty). - Exit 0 in both branches.
--apply-pending flow:
- Call
applyPendingDream({ repoRoot, memoryDir })fromscripts/lib/auto-dream.mjs. - Behavior matrix on the helper return:
applied: true→ printauto-dream applied: -<linesBefore-linesAfter> lines, +<entries> consolidated entriesand exit 0.applied: false, reason: 'missing'→ printno pending dream to applyand exit 1.applied: false, reason: 'stale'→ printpending dream is stale (>14d), re-run --dry-runand exit 1.
- The sidecar file is deleted on successful apply; staleness or missing sidecar never deletes anything.
Both flag-driven flows delegate atomicity and staleness enforcement to scripts/lib/auto-dream.mjs. The interactive Phases 1-4 below remain unchanged.
Phase 1: Orient
Understand the current memory state before making changes.
-
List all files in the memory directory:
ls -la ~/.claude/projects/*/memory/ 2>/dev/null | grep "$(basename "$(pwd)")"Or directly list the project's memory dir (the path is in the
auto memorysystem instructions). -
Read
MEMORY.md(the index file) — note its line count:wc -l <memory-dir>/MEMORY.md -
Skim each topic file referenced in the index. Build a mental map:
- Which topics are covered?
- Are there overlapping files?
- Any files not referenced in the index?
- Any index entries pointing to files that no longer exist?
Goal: Improve existing files, never create duplicates.
Phase 2: Gather Signal
Find what's changed since the last consolidation.
-
Git history — recent commits give the timeline for "did this fact change?":
git log --oneline -20 -
Stale references — for each file/function/symbol mentioned in memory, verify it still exists:
grep -rn "specific-file-or-function" src/ lib/ scripts/ 2>/dev/null -
Relative dates — find temporal references that need conversion:
grep -rni "yesterday\|today\|tomorrow\|last week\|this week\|gestern\|heute\|morgen\|letzte woche" <memory-dir>/ -
Version drift — package versions stored in memory vs reality:
cat package.json | grep '"version"' -
Test/issue-count drift — claims like "5001 passed" or "8 open issues" age fast. Cross-check with current state if mentioned.
Phase 3: Consolidate
Apply maintenance operations to memory files.
3a: Merge overlapping entries
If multiple files or entries describe the same thing, combine them into one authoritative entry. Update inbound [[wiki-link]]s accordingly.
3b: Convert relative dates to absolute
"Yesterday we decided X" → "On 2026-03-24 we decided X". Always use ISO date format (YYYY-MM-DD). This rule applies on write, but cleanup catches what slipped through.
3c: Remove stale references
- Delete entries about files that were removed during refactors.
- Remove debugging notes for bugs that are fixed.
- Update function/file paths that were renamed (
git log --diff-filter=Rsurfaces renames).
3d: Update outdated facts
- Package versions that have been bumped.
- Test counts, issue counts, line counts that changed.
- Feature flags that were toggled.
- Architecture decisions that were reversed (keep a
decisions.md-style note that the decision was reversed, with the reason — don't silently overwrite).
3e: Resolve contradictions
If two memory entries conflict, check the codebase to determine which is current. Delete the outdated entry. Never leave contradictions.
Phase 4: Prune & Index
Keep MEMORY.md clean and under the 200-line limit.
-
Check line count:
wc -l <memory-dir>/MEMORY.md -
If over 180 lines, extract detailed content into topic files. Suggested naming:
- Session summaries →
project_sessions.mdorsession-YYYY-MM-DD-<slug>.md - Architecture decisions →
reference_decisions.md - Package/tooling details →
reference_packages.md - Use the convention:
{type}_{topic}.md
- Session summaries →
-
Topic file frontmatter (required):
--- name: descriptive-name description: one-line description for relevance matching metadata: type: project # one of: user | feedback | project | reference --- -
Update the index:
MEMORY.mdis an index, not a dump.- One-line
- [Title](file.md) — hookentries. - Remove stale pointers to deleted files.
- Add links for new topic files.
- Reorder by relevance (most-accessed topics first).
-
Final verification:
wc -l <memory-dir>/MEMORY.md # must be < 200 # verify all index links resolve to existing files grep -oP '\]\(([^)]+\.md)\)' <memory-dir>/MEMORY.md | sed 's/](\(.*\))/\1/' | while read f; do [ -f "<memory-dir>/$f" ] || echo "BROKEN: $f" done
Phase 4.5: Worktree-Stale-Sweep (#575 P3.2)
Skip if
persistence: falsein Session Config. Silent no-op if no Auto-promoted sibling worktrees exist or none are stale.
Detect stale Auto-promoted worktrees (older than stale-branch-days from Session Config, default 7 days) and offer them for batch-removal alongside the other housekeeping prune actions from Phase 4. This sub-phase is additive — it appends candidates to the existing prune flow rather than introducing a separate independent confirmation cycle.
Detection: list candidate auto-promoted worktrees
Auto-promoted worktrees follow the layout <parentDir>/<repoName>-<sessionId>/, where <sessionId> is a semantic session-id (per parseSessionId() from scripts/lib/session-id.mjs). Random-suffix worktrees (UUID-format) are NOT auto-promoted and MUST be ignored.
Authoritative impl:
scripts/lib/memory-cleanup/worktree-sweep.mjs—listAutoPromotedWorktrees(repoRoot, mainCheckoutRoot, opts). Import and call; do NOT re-implement from this doc.Algorithm: split
git worktree list --porcelainon the blank-line delimiter; for eachworktreeentry, skip the main checkout, then require the basename to start with `<repoN