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:

  1. Startup Resolution – The session hook reads process.env.LETTA_HOME immediately upon invocation.
  2. Directory Mapping – getDurableStateDir(cwd) returns either $LETTA_HOME/.letta/claude or <cwd>/.letta/claude based on the environment variable.
  3. Agent Loading – agent_config.ts loads the global config from the LETTA_HOME location, reusing a single Letta agent across projects.
  4. Session Mapping – getConversationsFile(cwd) creates or updates the local conversations.json inside each project root, maintaining isolated session-to-conversation mappings.
  5. 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_MODE configuration.

Summary

  • LETTA_HOME redirects durable state from per-project directories to a single global location.
  • scripts/conversation_utils.ts contains the central getDurableStateDir function that implements this logic.
  • Global agent config (config.json) is stored under LETTA_HOME, while conversation mappings remain isolated in each project.
  • Setting LETTA_HOME=$HOME enables 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →