| name | memory-maintain |
| description | Maintain memory database — deduplicate accumulative records, consolidate near-duplicate episodics, remove junk procedurals and low-value patterns, and split large multi-topic memories into focused units.
|
| argument-hint | [optional: 'dedup only', 'episodic only', 'split only', 'full'] |
Memory Maintenance
Clean up noise, deduplicate records, and reorganize large memories. Run this after upgrading the plugin, when search quality degrades, or when memories have grown large and unfocused.
Steps
1. Assess
Run memory_health to get current counts, types, and staleness stats.
2. Deduplicate accumulative records
These records should exist at most once each. Search for duplicates and merge them.
Tech-stack:
memory_search("Technology stack used", type="semantic")
- If multiple records have the
tech-stack tag AND content starts with Technology stack used::
- Collect all technology items from each record's comma-separated list
memory_update the most comprehensive record with the union of all items (sorted alphabetically)
memory_delete all other duplicates
- Tag collision check: If any record has the
tech-stack tag but does NOT start with Technology stack used: (e.g., a detailed dependencies description from memory-init), rename its tag from tech-stack to tech-stack-detail via memory_update to prevent merge conflicts.
Active modules:
memory_search("Active modules directories", type="semantic")
- If multiple records have the
active-modules tag AND content starts with Active modules/directories::
- Same approach: union all items, update the best, delete the rest
- Tag collision check: Same as above — rename non-accumulative records' tag to
active-modules-detail.
3. Fix episodic titles
Episodic memories created before v1.2 often have no title, causing their content (starting with **Task:** or **Files modified:**) to be used as the label. This makes them indistinguishable in graphs and lists.
memory_list(type="episodic", limit=100) — scan all episodic records
- For each record that has no title (title is null/empty):
- If content starts with
**Task:** — extract the task text after the marker, strip markdown bold, and use first ~80 chars as the title
- If content starts with
**Files modified:** — derive a title like "Session: N files in dir1, dir2"
- If content contains both
**Task:** and **Files modified:** lines — prefer the task text for the title
memory_update(id, { title: derivedTitle })
- Skip records that already have a meaningful title
4. Consolidate episodic records
memory_list(type="episodic", limit=50) — scan through all episodic records
- Delete meaningless records that match ANY of:
- Task is
[Request interrupted by user for tool use] with no tools AND no files AND no memory ops
- Content is just a task summary under 15 characters with no tools or files
- Content is empty or contains only boilerplate markers
- Consolidate near-duplicate session-end records: Group episodic records by tag:
session-end records: If multiple have the same or near-identical task text (e.g., all say [Request interrupted by user for tool use] with similar tool lists), keep only the one with the highest importance. Delete the rest.
session-files records: If multiple have the same or near-identical file list (>80% overlap), keep only the most recent. Delete the rest.
session-errors records: Same approach — deduplicate near-identical error records.
5. Clean procedural records
memory_list(type="procedural", limit=50) — scan through all procedural records
- Delete junk procedurals that match ANY of:
- Content is over 500 characters (real workflows are short command chains, not test scripts)
- Commands contain
mktemp, sqlite3, manual test setup, or multi-line heredocs — these are test/debug artifacts, not reusable workflows
- Commands contain hardcoded temp paths (
/var/folders/, /tmp/tmp.)
- Deduplicate by category: Group procedural records by their category tag (
build, test, lint, install, deploy). If multiple records share the same category:
- Keep the one with the cleanest, shortest command chain
- Delete the rest
6. Clean low-value patterns
memory_list(type="pattern", limit=50) — scan through all pattern records
- Delete low-value patterns that match ANY of:
- Content is just a list of tool names with no actionable insight (e.g.,
**Tools:** TaskCreate, TaskUpdate, Edit, Bash)
- Content is just a list of file paths with no context about what was done or why
- Title is a generic auto-generated name like
"X Y Z pattern: Tools" and content provides no real pattern
- Keep patterns that:
- Describe a recurring behavioral theme (e.g., "Claude not using memory proactively")
- Identify frequently co-modified files with context about why
- Capture genuine recurring workflows or decisions
7. Split large multi-topic memories
For each type (semantic, procedural, pattern), run memory_list with a reasonable limit (20-50). Identify memories that are:
- Over 500 characters
- Contain multiple distinct topics (headers, bold sections, or topic shifts)
For each candidate:
- Read it with
memory_get
- Identify natural topic boundaries
- For each topic section:
- Store as a new memory with
memory_store using the same type, tags, context, and source
- Title:
"{original title}: {section topic}" (or just the section topic if no original title)
- Content: just the section's content
- Create
relates_to relations between sibling sections using memory_relate
- Delete the original monolithic memory with
memory_delete
Edge cases:
- Prose paragraphs: Identify where the topic shifts even without headers. Create separate memories for each topic.
- Mixed content: If a memory contains both facts and procedures, split by type (store as
semantic and procedural separately).
- Lists: If a memory is a long list, group related items together.
8. Report
Summarize what was done:
- Accumulative records deduplicated (before -> after count)
- Tag collisions fixed
- Episodic titles fixed (count)
- Episodic records consolidated (deleted count)
- Procedural records cleaned (deleted count)
- Patterns cleaned (deleted count)
- Large memories split (count processed, new memories created, relations created)
- Final memory count from
memory_health
Guidelines
- Default scope is steps 2-7 (full maintenance). Use the argument to narrow scope if needed.
- Be conservative with deletion. If unsure whether a record is junk, keep it.
- Preserve the best record when deduplicating — pick the one with the most items, highest importance, or most recent date.
- Don't split small memories — Only process memories >500 chars with multiple topics.
- Preserve metadata — Keep the same type, tags, context, and source on split pieces.
- Maintain relations — Create
relates_to between sibling sections.
- Check before storing — Use
memory_search to avoid creating duplicates of existing memories.
- Respect the argument filter — If the user specified a scope (e.g.,
'episodic only'), only run that step.
$ARGUMENTS