# Whisper Mode vs Full Mode in Claude Subconscious: Context Injection Differences

> Discover the key differences between Claude Subconscious whisper mode and full mode. Understand context injection for agent messages and memory blocks to enhance your AI's state synchronization.

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

---

**Whisper mode injects only the Letta agent’s messages into Claude’s context, while full mode injects both persistent memory blocks and agent messages, enabling complete state synchronization via the CLAUDE.md file.**

The `letta-ai/claude-subconscious` repository manages how Letta agent data reaches Claude Desktop during coding sessions. The **context injection** behavior is controlled by two primary operating modes—**whisper** and **full**—which determine whether Claude receives lightweight message streams or complete memory state including block updates.

## What Gets Injected into the Context

The fundamental difference between these modes lies in what XML-formatted data actually reaches Claude’s prompt window.

### Whisper Mode: Messages Only

In whisper mode (the default), the integration strips out all memory state and injects only conversational messages. The hook calls `formatMessagesForStdout()` in [`scripts/conversation_utils.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/scripts/conversation_utils.ts) (lines 669-684) to convert new Letta messages into `<letta_message>` XML blocks written to stdout.

- **No memory blocks** are added to the prompt
- **No CLAUDE.md updates** occur—the `<letta>` section is never written, and any existing section is cleaned out by `cleanLettaFromClaudeMd()`
- **Minimal token overhead** since only new utterances are transmitted

### Full Mode: Memory Blocks Plus Messages

When `LETTA_MODE=full` is set, the system injects both the agent’s persistent memory and its messages. According to the source code in [`scripts/sync_letta_memory.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/scripts/sync_letta_memory.ts) (lines 64-68), the script checks the mode and calls `formatAllBlocksForStdout()` for the initial prompt, or `formatChangedBlocksForStdout()` for subsequent prompts, before appending messages via `formatMessagesForStdout()`.

- **First prompt**: Receives the complete set of memory blocks wrapped in `<letta_memory_blocks>` XML via `formatAllBlocksForStdout()` (lines 561-604 in [`scripts/conversation_utils.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/scripts/conversation_utils.ts))
- **Subsequent prompts**: Receive only **diff updates**—changed blocks only—to minimize context window usage
- **CLAUDE.md persistence**: The `<letta>` section is written or updated with the full memory block XML, maintaining state between sessions

## How Mode Selection Works

The operating mode is determined by the `getMode()` function in [`scripts/conversation_utils.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/scripts/conversation_utils.ts) (lines 41-46). The logic defaults to `"whisper"` unless explicitly configured otherwise.

```typescript
// From scripts/conversation_utils.ts (lines 41-46)
export function getMode(): "whisper" | "full" | "off" {
  const mode = process.env.LETTA_MODE?.toLowerCase();
  if (mode === "full" || mode === "off") {
    return mode;
  }
  return "whisper"; // Default fallback
}

```

Configure your environment before launching Claude Desktop:

```bash

# Whisper mode (default behavior)

export LETTA_MODE=whisper

# Full mode with complete memory injection

export LETTA_MODE=full

```

## Technical Implementation of Context Injection

The divergence in behavior occurs in [`scripts/sync_letta_memory.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/scripts/sync_letta_memory.ts), where the mode check determines which formatting pipeline executes:

```typescript
// From scripts/sync_letta_memory.ts (lines 64-68)
if (getMode() === "full") {
  // First prompt gets all blocks, subsequent get diffs
  const blocksContent = isFirstPrompt 
    ? formatAllBlocksForStdout(agentId, blocks)
    : formatChangedBlocksForStdout(agentId, changedBlocks);
  process.stdout.write(blocksContent);
}

// Messages are always written in both modes
const messagesContent = formatMessagesForStdout(messages);
process.stdout.write(messagesContent);

```

The `formatAllBlocksForStdout()` function constructs a header containing the agent’s context window and serializes all memory blocks into `<letta_memory_blocks>` XML. In contrast, `formatMessagesForStdout()` (lines 669-684) produces plain `<letta_message>` entries without any persistent state attachments.

## Impact on CLAUDE.md State Synchronization

The modes handle the [`CLAUDE.md`](https://github.com/letta-ai/claude-subconscious/blob/main/CLAUDE.md) file differently, affecting whether memory persists across Claude restarts.

- **Whisper mode**: The file is left untouched or actively cleaned. The `cleanLettaFromClaudeMd()` function removes any existing `<letta>` sections, ensuring no stale memory blocks persist between sessions.
- **Full mode**: The memory injection path explicitly writes a `<letta>` block to [`CLAUDE.md`](https://github.com/letta-ai/claude-subconscious/blob/main/CLAUDE.md), enabling the Subconscious agent’s state to survive Claude Desktop restarts and maintain continuity across multiple coding sessions.

## Summary

- **Whisper mode** provides lightweight **message-only** injection, leaving [`CLAUDE.md`](https://github.com/letta-ai/claude-subconscious/blob/main/CLAUDE.md) unchanged and minimizing token usage.
- **Full mode** provides complete **memory block + message** injection, updating [`CLAUDE.md`](https://github.com/letta-ai/claude-subconscious/blob/main/CLAUDE.md) with persistent state and using diff updates for efficiency after the initial prompt.
- Mode selection occurs in `getMode()` at `scripts/conversation_utils.ts:41-46`, defaulting to whisper unless `LETTA_MODE=full` is explicitly exported.
- Full mode uses `formatAllBlocksForStdout()` for initial context and `formatChangedBlocksForStdout()` for subsequent diffs, while whisper mode skips these entirely.

## Frequently Asked Questions

### What happens if the LETTA_MODE environment variable is not set?

The system defaults to whisper mode. According to the implementation in [`scripts/conversation_utils.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/scripts/conversation_utils.ts) (lines 41-46), any unset value or value other than `"full"` or `"off"` causes `getMode()` to return `"whisper"`, ensuring safe, lightweight operation by default.

### Does full mode send all memory blocks on every message?

No. The first prompt in full mode receives the complete memory block set via `formatAllBlocksForStdout()`, but subsequent prompts receive only changed blocks through `formatChangedBlocksForStdout()`. This diff-based approach prevents context window bloat while maintaining synchronization.

### How does whisper mode affect the CLAUDE.md file?

Whisper mode never writes to [`CLAUDE.md`](https://github.com/letta-ai/claude-subconscious/blob/main/CLAUDE.md). If a previous session left a `<letta>` section in the file, the system calls `cleanLettaFromClaudeMd()` to remove it, ensuring no persistent memory state carries over between sessions.

### Can I switch between whisper and full mode mid-conversation?

While you can change the `LETTA_MODE` environment variable and restart Claude Desktop, the repository does not support hot-swapping modes within an active session. A restart ensures the `getMode()` check in [`sync_letta_memory.ts`](https://github.com/letta-ai/claude-subconscious/blob/main/sync_letta_memory.ts) evaluates the new setting and initializes the appropriate formatting pipeline.