# How to Use LETTA_HOME to Consolidate Claude-Subconscious State Across Multiple Projects

> Consolidate Claude-Subconscious state across projects using LETTA_HOME. This environment variable enables memory sharing and a unified agent ID, simplifying multi-project agent management.

- Repository: [Letta/claude-subconscious](https://github.com/letta-ai/claude-subconscious)
- Tags: how-to-guide
- Published: 2026-03-26

---

**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`](https://github.com/letta-ai/claude-subconscious/blob/main/./.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`](https://github.com/letta-ai/claude-subconscious/blob/main/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:

```ts
// 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`](https://github.com/letta-ai/claude-subconscious/blob/main/scripts/session_start.ts) also surfaces this configuration to the user:

```ts
// 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:

```bash

# ~/.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:

```ts
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:

```bash
cat "$LETTA_HOME/.letta/claude-subconscious/config.json"

```

Example output:

```json
{
  "agentId": "agent-a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "importedAt": "2024-09-12T15:23:00Z"
}

```

According to the [`agent_config.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/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`](https://github.com/letta-ai/claude-subconscious/blob/main/conversations.json) to map local Claude Code session IDs to Letta conversation IDs:

```json
{
  "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`](https://github.com/letta-ai/claude-subconscious/blob/main/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`](https://github.com/letta-ai/claude-subconscious/blob/main/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`](https://github.com/letta-ai/claude-subconscious/blob/main/scripts/conversation_utils.ts)** contains the central `getDurableStateDir` function that implements this logic.
- **Global agent config** ([`config.json`](https://github.com/letta-ai/claude-subconscious/blob/main/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`](https://github.com/letta-ai/claude-subconscious/blob/main/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`](https://github.com/letta-ai/claude-subconscious/blob/main/scripts/conversation_utils.ts) when multiple users attempt to write to the same [`conversations.json`](https://github.com/letta-ai/claude-subconscious/blob/main/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`](https://github.com/letta-ai/claude-subconscious/blob/main/scripts/conversation_utils.ts) respect this environment variable.