How to Use LETTA_HOME to Consolidate Claude-Subconscious State Across Multiple Projects
Setting the LETTA_HOME environment variable directs the Claude-Subconscious plugin to store all durable agent state in a single global directory, enabling memory sharing and a unified agent ID across multiple project repositories.
The Claude-Subconscious plugin maintains conversation bookkeeping and agent configuration in hidden .letta/claude/ directories. By default, each project creates its own isolated state folder, fragmenting memory and duplicating agent identities. Configuring LETTA_HOME redirects all durable data to a centralized location while preserving per-project conversation mappings.
Understanding the LETTA_HOME Environment Variable
LETTA_HOME is a shell environment variable that defines the base directory for the plugin's durable state. When unset, the plugin defaults to the current working directory (cwd), creating a local .letta/claude/ subtree inside every project. When defined, the plugin creates the .letta/claude/ path under the specified base and shares the global agent configuration across all invocations.
This distinction determines whether memory blocks and agent IDs are duplicated per repository or shared globally:
| State Type | Purpose | Path (LETTA_HOME unset) | Path (LETTA_HOME=$HOME) |
|---|---|---|---|
| Global Agent Config | Shared agent ID and metadata | ./.letta/claude-subconscious/config.json (per repo) |
~/.letta/claude-subconscious/config.json (shared) |
| Conversation Bookkeeping | Session-to-conversation ID mapping | <project>/.letta/claude/conversations.json |
<project>/.letta/claude/conversations.json (still isolated) |
| Memory Blocks | Persistent agent memory | Duplicated per repository | Single shared instance |
Core Implementation in conversation_utils.ts
The resolution logic lives in scripts/conversation_utils.ts. The getDurableStateDir function selects the state root by checking process.env.LETTA_HOME before falling back to the current working directory:
// scripts/conversation_utils.ts
// Get durable state directory – uses LETTA_HOME if defined
export function getDurableStateDir(cwd: string): string {
const base = process.env.LETTA_HOME || cwd; // <‑‑← picks LETTA_HOME or cwd
return path.join(base, '.letta', 'claude'); // → $BASE/.letta/claude
}
All durable I/O operations delegate to this helper. Functions such as getConversationsFile, getSyncStateFile, and ensureDurableStateDir rely on getDurableStateDir, meaning a single environment variable change affects every stateful operation in the plugin.
The session start hook in scripts/session_start.ts also surfaces this configuration to the user:
// scripts/session_start.ts (excerpt)
if (process.env.LETTA_HOME) {
writeTty(` Home: ${process.env.LETTA_HOME}\n`);
}
Step-by-Step Configuration
1. Export LETTA_HOME in Your Shell
Add the export to your shell configuration to consolidate state under your home directory:
# ~/.bashrc or ~/.zshrc
export LETTA_HOME="$HOME" # Consolidate all plugin state under $HOME/.letta/claude
export LETTA_API_KEY="your-api-key"
Reload your shell with source ~/.bashrc. Every subsequent Claude Code session in any repository will now reference the same durable state directory.
2. Verify the Resolved Path at Runtime
You can confirm the directory resolution by importing the utility function:
import { getDurableStateDir } from './conversation_utils.js';
const cwd = process.cwd();
const durableDir = getDurableStateDir(cwd);
console.log('Durable state directory →', durableDir);
Executing this from any project will output the consolidated path:
Durable state directory → /home/you/.letta/claude
3. Inspect the Shared Agent Configuration
With LETTA_HOME set, the global configuration file stores the shared agent ID:
cat "$LETTA_HOME/.letta/claude-subconscious/config.json"
Example output:
{
"agentId": "agent-a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"importedAt": "2024-09-12T15:23:00Z"
}
According to the agent_config.ts implementation, this file is read at startup to initialize the shared agent. All projects reference this single configuration, eliminating duplicate agent creation.
4. Per-Project Conversation Isolation
Despite shared global state, conversation bookkeeping remains isolated per project. Each repository maintains its own conversations.json to map local Claude Code session IDs to Letta conversation IDs:
{
"12345": {
"conversationId": "conv-xyz-123",
"agentId": "agent-a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
}
This file is stored at <project>/.letta/claude/conversations.json regardless of LETTA_HOME settings, ensuring session history does not leak between repositories.
Architecture Flow
The plugin handles state consolidation through a strict resolution sequence:
- Startup Resolution – The session hook reads
process.env.LETTA_HOMEimmediately upon invocation. - Directory Mapping –
getDurableStateDir(cwd)returns either$LETTA_HOME/.letta/claudeor<cwd>/.letta/claudebased on the environment variable. - Agent Loading –
agent_config.tsloads the global config from theLETTA_HOMElocation, reusing a single Letta agent across projects. - Session Mapping –
getConversationsFile(cwd)creates or updates the localconversations.jsoninside each project root, maintaining isolated session-to-conversation mappings. - Memory Sharing – All memory blocks attach to the single shared agent instance. When any project sends a message, the agent retrieves its persistent memory depending on the
LETTA_MODEconfiguration.
Summary
LETTA_HOMEredirects durable state from per-project directories to a single global location.scripts/conversation_utils.tscontains the centralgetDurableStateDirfunction that implements this logic.- Global agent config (
config.json) is stored underLETTA_HOME, while conversation mappings remain isolated in each project. - Setting
LETTA_HOME=$HOMEenables a shared memory context across multiple repositories without mixing conversation histories. - All state-dependent functions in the plugin automatically respect this variable without code changes.
Frequently Asked Questions
What happens if I unset LETTA_HOME after previously setting it?
If you unset LETTA_HOME, the plugin reverts to using the current working directory as the state root. The next time you run Claude Code in a project, it will create a fresh .letta/claude/ directory locally and generate a new agent configuration, effectively orphaning the previous shared state. To avoid losing context, migrate your existing config.json and memory blocks from the old LETTA_HOME location to your new target directory.
Can I use LETTA_HOME to share state between different user accounts?
No. LETTA_HOME defines a path on the local filesystem, and the plugin respects standard filesystem permissions. To share state between users, you would need to set LETTA_HOME to a directory with group-write permissions or a shared mount point, though this is not the intended use case and may cause permission conflicts in scripts/conversation_utils.ts when multiple users attempt to write to the same conversations.json or sync state files simultaneously.
How does LETTA_HOME interact with LETTA_MODE?
LETTA_HOME controls where state is stored, while LETTA_MODE controls how the agent behaves (e.g., sandboxed vs. shared memory). When LETTA_HOME is set to a global path and LETTA_MODE enables memory sharing, all projects reference the same physical memory blocks stored in the shared agent configuration. If LETTA_HOME is unset, each project maintains independent memory blocks even if LETTA_MODE is configured for sharing, because the agent IDs are isolated per directory.
Where does the plugin store temporary or non-durable data?
The getDurableStateDir function specifically handles durable state such as agent configurations and conversation mappings. Temporary session data that does not need to persist across restarts is typically managed in memory or standard temporary directories, and is not affected by the LETTA_HOME variable. Only the files referenced by getConversationsFile, getSyncStateFile, and ensureDurableStateDir in scripts/conversation_utils.ts respect this environment variable.
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 →