How the Claude-Subconscious Plugin Handles Cleaning Up Legacy <letta> Content from CLAUDE.md
The Claude-Subconscious plugin automatically purges stale <letta> memory blocks from CLAUDE.md using the cleanLettaFromClaudeMd utility in scripts/conversation_utils.ts, preventing duplicate or obsolete data from persisting across sessions.
When upgrading the letta-ai/claude-subconscious plugin, existing CLAUDE.md files may contain outdated <letta> sections from previous versions. To maintain data integrity, the plugin implements an aggressive cleanup routine that executes during session initialization and memory synchronization. This article explains the exact mechanism for cleaning up legacy <letta> content from CLAUDE.md based on the source code implementation.
How Legacy Content Detection Works
The cleanup process begins by locating the target file and identifying specific marker patterns that denote plugin-generated content.
Locating the Target CLAUDE.md File
The cleanLettaFromClaudeMd function first determines which directory to process. It checks the LETTA_PROJECT environment variable, falling back to the provided project directory:
const base = process.env.LETTA_PROJECT || projectDir;
const claudeMdPath = path.join(base, CLAUDE_MD_PATH);
If the file does not exist at the resolved path, the function returns immediately without performing any filesystem operations.
Pattern Matching for Legacy Sections
Legacy content is delimited by markers defined as LETTA_SECTION_START and LETTA_SECTION_END in scripts/conversation_utils.ts. The code constructs a multiline RegExp that captures everything between these markers, including surrounding line breaks:
const lettaPattern = `^${escapeRegex(LETTA_SECTION_START)}[\\s\\S]*?^${escapeRegex(LETTA_SECTION_END)}\\n*`;
const lettaRegex = new RegExp(lettaPattern, 'gm');
The Step-by-Step Cleanup Algorithm
Once patterns are established, the algorithm executes a sequential removal process to ensure complete sanitization of the file.
Removing Main Blocks
The primary cleanup targets the main legacy blocks. The function resets the regex index and performs a global replace:
lettaRegex.lastIndex = 0;
let cleaned = content.replace(lettaRegex, '');
Stripping Orphaned <letta_message> Tags
Older plugin versions occasionally left stray <letta_message> elements. These are purged using a secondary multiline pattern:
const messagePattern = /^<letta_message>[\s\S]*?^<\/letta_message>\n*/gm;
cleaned = cleaned.replace(messagePattern, '');
Eliminating Auto-Generated Boilerplate
The routine removes specific auto-generated comments and headers injected by previous plugin versions:
cleaned = cleaned.replace(/<!-- Letta agent memory is automatically synced below -->\n*/g, '');
cleaned = cleaned.replace(/^# Project Context\n*/gm, '');
Handling Empty File Cleanup
After stripping content, the function evaluates the remaining text. If the file contains only whitespace or is empty, it deletes the file entirely rather than leaving a zero-length document:
if (cleaned.length === 0) {
fs.unlinkSync(claudeMdPath);
} else {
fs.writeFileSync(claudeMdPath, cleaned + '\n', 'utf-8');
}
Invocation Points in the Session Lifecycle
The plugin triggers cleanup at critical junctures to guarantee a clean state before writing new memory data.
Session Initialization Cleanup
In scripts/session_start.ts, the plugin invokes cleanup immediately after obtaining a conversation ID. It processes both the current working directory and the global ~/.claude directory when they differ:
cleanLettaFromClaudeMd(hookInput.cwd);
const homeDir = process.env.HOME || os.homedir();
if (homeDir !== hookInput.cwd) cleanLettaFromClaudeMd(homeDir);
Memory Synchronization Cleanup
Before writing fresh memory blocks, scripts/sync_letta_memory.ts calls the same utility to ensure no legacy sections remain:
cleanLettaFromClaudeMd(cwd);
This pre-write sanitization prevents the accumulation of duplicate memory sections across sync operations.
Implementing Manual Cleanup
For scenarios requiring explicit cleanup outside the automated session flow, import the utility directly:
import { cleanLettaFromClaudeMd } from '../scripts/conversation_utils';
import * as path from 'path';
const projectRoot = path.resolve(__dirname, '..');
cleanLettaFromClaudeMd(projectRoot);
Executing this code locates CLAUDE.md in the specified directory, removes all legacy markers, deletes the file if empty, or writes the cleaned content back to disk.
Summary
- The letta-ai/claude-subconscious plugin uses
cleanLettaFromClaudeMdinscripts/conversation_utils.tsto sanitizeCLAUDE.mdfiles. - Detection relies on multiline regular expressions matching
LETTA_SECTION_START/ENDmarkers and orphaned<letta_message>tags. - The algorithm removes auto-generated boilerplate including HTML comments and "Project Context" headers.
- Cleanup executes during session start (
session_start.ts) and memory sync (sync_letta_memory.ts) to prevent data duplication. - Empty files resulting from complete cleanup are automatically deleted via
fs.unlinkSync.
Frequently Asked Questions
What triggers the cleanup of legacy content?
The cleanup routine triggers automatically during two specific events: when a new session initializes in scripts/session_start.ts and before every memory synchronization in scripts/sync_letta_memory.ts. These dual invocation points ensure that CLAUDE.md is always sanitized before new content is written.
How does the plugin distinguish legacy content from user data?
The plugin identifies legacy content through strict marker-based pattern matching. It searches for text wrapped between LETTA_SECTION_START and LETTA_SECTION_END constants, orphaned <letta_message> XML tags, and specific auto-generated strings like the HTML comment <!-- Letta agent memory is automatically synced below -->. User content outside these markers remains untouched.
What happens to CLAUDE.md if all content is removed?
If the cleanup process results in an empty string—meaning the file contained only plugin-generated sections—the function deletes CLAUDE.md entirely using fs.unlinkSync. This prevents the accumulation of zero-length files in the project directory.
Can I run the cleanup manually outside of automated sessions?
Yes. You can import cleanLettaFromClaudeMd from scripts/conversation_utils.ts and invoke it with any directory path. This is useful for manual maintenance or custom automation scripts that need to ensure CLAUDE.md integrity before specific operations.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →