# How `ai-memory install-hooks --session-aware` Enables Per-Session Auto-Scope Isolation

> Discover how ai-memory install-hooks --session-aware creates isolated workspaces for each Claude Code session using a stdio-to-HTTP bridge and custom headers.

- Repository: [Fabio Akita/ai-memory](https://github.com/akitaonrails/ai-memory)
- Tags: how-to-guide
- Published: 2026-08-20

---

**`ai-memory install-hooks --session-aware` installs a stdio-to-HTTP bridge that forwards Claude Code's session ID via a custom header, allowing the MCP server to isolate each concurrent session into its own auto-scope workspace.**

The `ai-memory` CLI provides hook installation for AI agents like Claude Code, but concurrent sessions can collide when sharing the same workspace and project mappings. The `--session-aware` flag solves this by injecting session metadata into every MCP request, enabling true per-session isolation. According to the `akitaonrails/ai-memory` source code, this mechanism relies on a hidden bridge subcommand and custom HTTP headers to route each Claude Code window to a distinct auto-scope.

## What `--session-aware` Adds to Normal Hook Installation

Without the flag, `ai-memory install-hooks` simply writes lifecycle hooks into the agent's settings file (e.g., `~/.claude/settings.json`). Adding `--session-aware` triggers two additional behaviors:

1. **Registers the `mcp-bridge` subcommand** as part of the install flow
2. **Configures the bridge to capture and forward session identifiers**

The bridge acts as a transparent proxy between Claude Code's stdio and the remote ai-memory HTTP MCP server. This design allows the server to distinguish requests originating from different Claude Code windows—even when they target the same repository.

## The Session-Aware Bridge Implementation

The core logic resides in [`crates/ai-memory-cli/src/commands/mcp_bridge.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-cli/src/commands/mcp_bridge.rs)【/crates/ai-memory-cli/src/commands/mcp_bridge.rs】. This file implements the hidden `mcp-bridge` command that `install-hooks --session-aware` configures Claude Code to invoke.

### Capturing the Claude Session ID

Claude Code sets the environment variable `CLAUDE_CODE_SESSION_ID` when launching a hook subprocess. The bridge reads this variable and attaches it to every outgoing HTTP request:

```rust
// Constant defined at crates/ai-memory-cli/src/commands/mcp_bridge.rs#L19-L20
const ACTOR_SESSION_HEADER: &str = "X-Memory-Actor-Session-Id";

```

The `upstream_config` helper function (lines 64-80) constructs the transport configuration by inserting this header along with optional authentication:

```rust
// From crates/ai-memory-cli/src/commands/mcp_bridge.rs#L64-L80
fn upstream_config(server_url: &str, token: Option<&str>) -> TransportConfig {
    let mut headers = HeaderMap::new();
    if let Some(session_id) = std::env::var("CLAUDE_CODE_SESSION_ID").ok() {
        headers.insert(
            ACTOR_SESSION_HEADER,
            HeaderValue::from_str(&session_id).unwrap(),
        );
    }
    // ... bearer token handling ...
    TransportConfig::Http { url: server_url.parse().unwrap(), headers }
}

```

This ensures every tool call, observation, and handoff carries the originating session's identity.

## How the MCP Server Uses Session Headers

When the ai-memory server receives a request with `X-Memory-Actor-Session-Id`, it tags all associated operations with that session identifier. The routing module in [`ai-memory-core/src/routing_snippet.rs`](https://github.com/akitaonrails/ai-memory/blob/main/ai-memory-core/src/routing_snippet.rs)【/crates/ai-memory-core/src/routing_snippet.rs】 then combines this tag with workspace/project resolution to compute the final auto-scope.

The routing snippet explicitly references this mode:

```rust
// Comment at crates/ai-memory-core/src/routing_snippet.rs#L46-L47
// When using session-aware bridge:
// [auto_scope] mode = "per_session"

```

Setting `mode = "per_session"` instructs the router to include the session ID as a scope boundary. This prevents concurrent Claude Code sessions from seeing each other's memory entries, even when working in the same directory.

## Practical Usage Examples

### Installing Session-Aware Hooks for Claude Code

```bash
ai-memory install-hooks --agent claude-code --apply --session-aware

```

This command:
- Writes the hook configuration to `~/.claude/settings.json`
- Includes the bridge invocation in Claude Code's MCP server settings
- Prints a confirmation that session-aware mode is active

### Manual Bridge Startup (Debugging/Development)

If you need to run the bridge independently—for debugging or custom server URLs:

```bash
ai-memory mcp-bridge --server-url http://127.0.0.1:49374/mcp

```

The bridge will:
1. Read `CLAUDE_CODE_SESSION_ID` from its environment
2. Connect to the specified ai-memory server
3. Proxy all stdio MCP traffic with the session header injected

### Verifying Session Header Extraction

From the bridge test code, here's how the server side extracts the session identifier:

```rust
let session = context
    .extensions
    .get::<axum::http::request::Parts>()
    .and_then(|parts| parts.headers.get(&ACTOR_SESSION_HEADER))
    .and_then(|value| value.to_str().ok())
    .map(str::to_string);

```

This pattern appears in [`crates/ai-memory-cli/src/commands/mcp_bridge.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-cli/src/commands/mcp_bridge.rs)【/crates/ai-memory-cli/src/commands/mcp_bridge.rs#L73-L78】, demonstrating the end-to-end header propagation.

## Key Source Files for the Session-Aware Flow

| File | Role in Session Isolation |
|------|---------------------------|
| [`crates/ai-memory-cli/src/cli.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-cli/src/cli.rs) | Defines the `--session-aware` flag and `mcp-bridge` subcommand registration |
| [`crates/ai-memory-cli/src/commands/install_hooks.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-cli/src/commands/install_hooks.rs) | Propagates the flag to bridge configuration during hook installation |
| [`crates/ai-memory-cli/src/commands/mcp_bridge.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-cli/src/commands/mcp_bridge.rs) | Implements stdio-to-HTTP bridging with session header injection |
| [`crates/ai-memory-core/src/routing_snippet.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-core/src/routing_snippet.rs) | Documents `per_session` auto-scope mode for session-tagged requests |

## Summary

- **`--session-aware` activates the `mcp-bridge`** hidden subcommand during hook installation
- **The bridge captures `CLAUDE_CODE_SESSION_ID`** and forwards it as `X-Memory-Actor-Session-Id`
- **The MCP server tags all operations** with the session header for routing decisions
- **`[auto_scope] mode = "per_session"`** isolates each Claude Code window's memory independently
- **Concurrent sessions no longer collide** when sharing the same workspace or project

## Frequently Asked Questions

### What happens if I run `--session-aware` but Claude Code isn't running?

The bridge will start but fail to detect `CLAUDE_CODE_SESSION_ID` in its environment. It will operate in non-session-aware mode, forwarding requests without the custom header. The MCP server will fall back to standard workspace/project resolution, and you won't get per-session isolation.

### Can I use `--session-aware` with agents other than Claude Code?

Currently, the bridge specifically looks for `CLAUDE_CODE_SESSION_ID`. Other agents would need to set this variable (or a configurable equivalent) for the session header injection to function. The architecture in [`mcp_bridge.rs`](https://github.com/akitaonrails/ai-memory/blob/main/mcp_bridge.rs) supports extending this to other session identifier sources.

### Does `--session-aware` affect where memory files are stored on disk?

No. The session header affects **logical scope resolution** within the ai-memory server's routing layer, not physical file paths. The `[auto_scope] mode = "per_session"` setting ensures the server computes distinct scope identifiers for each session, but the underlying storage mechanism remains unchanged.

### Can multiple `--session-aware` sessions share some memory while isolating others?

Not directly. The `per_session` mode creates complete isolation at the auto-scope level. To share memory across sessions, you would need to use explicit workspace or project identifiers that bypass the auto-scope mechanism, or switch to a different routing mode for those specific operations.