How jcode Handles Memory Isolation Between Concurrent Sessions

jcode ensures memory isolation between concurrent sessions by using UUID-scoped on-disk directories and exclusive in-process caches owned by each Session instance, with no shared mutable state between sessions.

The jcode repository implements a robust concurrency model that guarantees strict memory isolation between concurrent sessions through filesystem separation and strict ownership patterns. This article examines the Rust source code to explain exactly how the system prevents cross-session data leakage while maintaining high performance.

Per-Session On-Disk Storage Architecture

UUID-Based Session Identification

When a new session initializes, jcode generates a unique identifier via new_memorable_session_id and creates a dedicated directory for that session's persistent data. This design ensures that each session operates within its own filesystem sandbox, with separate storage for journals, snapshots, and environment data.

Path Isolation via Storage Helpers

The path helpers defined in src/storage_paths.rs enforce this isolation by requiring a session ID for all file operations. Functions like session_journal_path and session_path construct paths that incorporate the session UUID, making it impossible for one session to resolve another session's file paths. Because these helpers always take a session ID as an argument, two sessions can never read or write each other's files.

Isolated In-Process Memory Caches

The Session Struct Design

Each Session instance maintains its own SessionMemoryProfileCache and dirty flag, explicitly excluded from serialization to prevent accidental persistence:

pub struct Session {

    #[serde(skip)]
    memory_profile_cache: SessionMemoryProfileCache,
    #[serde(skip)]
    memory_profile_dirty: bool,
    …}

(see src/session.rs lines 30-38)

Cache Lifetime and Ownership

These fields are not shared across Session objects; they live only for the lifetime of that specific Session value. The #[serde(skip)] attribute prevents the cache from being written to disk, ensuring that in-memory data structures never outlive their owning session or leak into other instances.

Server-Side Concurrency Model

SessionControlHandle Architecture

The server maintains isolation through SessionControlHandle structures defined in src/server/state.rs. Each active session maps to a handle containing an Arc<Mutex<Session>>:

pub struct SessionControlHandle {
    pub id: String,
    pub session: Arc<Mutex<Session>>,

}

Task Isolation

When processing concurrent requests, the server looks up the handle by session ID in a HashMap<String, SessionControlHandle>, clones the associated Session, and executes turn logic within its own async task. Because each Session clone includes independent caches and the journal file remains exclusively open for that session, no mutable state spans across concurrent tasks.

UI Layer Session References

Higher-level components in src/tui/workspace_client.rs reference sessions only by their IDs. Functions such as queue_resume_session manipulate workspace maps without accessing other sessions' memory caches:

pub fn queue_resume_session(session_id: String) {
    state.pending_resume_session = Some(session_id);
}

(see src/tui/workspace_client.rs lines 106-108)

This ID-only reference pattern ensures that UI operations cannot accidentally traverse into another session's isolated memory space.

Practical Implementation Examples

Creating isolated sessions and running them concurrently:

// Create a new session – a fresh UUID is assigned and a new folder is allocated.
let sess = Session::new()?;               // generates a unique `id`
sess.persist_state.save()?;               // writes only to this session’s files

// Run two sessions concurrently – each gets its own lock and cache.
let handle_a = server.state.get_handle("session_a")?;
let handle_b = server.state.get_handle("session_b")?;

tokio::join!(
    run_turn(handle_a.clone()),
    run_turn(handle_b.clone()),
);

Modifying session-specific memory profiles:

// The memory profile cache lives only inside the Session struct.
fn add_memory_stats(sess: &mut Session, block_id: &str, stats: ContentBlockMemoryStats) {
    sess.memory_profile_cache.insert(block_id.to_owned(), stats);
    sess.memory_profile_dirty = true;
}

Key Source Files

The isolation mechanism spans these critical components:

Summary

  • jcode generates unique UUID-based session IDs via new_memorable_session_id to create isolated on-disk directories
  • Path helpers in src/storage_paths.rs ensure sessions cannot resolve each other's file paths by requiring session ID parameters
  • Each Session owns exclusive SessionMemoryProfileCache and memory_profile_dirty fields marked with #[serde(skip)] to prevent cross-session persistence
  • The server uses SessionControlHandle with Arc<Mutex<Session>> to isolate concurrent async tasks, with each session operating on its own cloned data
  • UI components reference sessions only by ID, preventing accidental cache traversal between sessions

Frequently Asked Questions

How does jcode prevent sessions from accessing each other's files?

jcode enforces filesystem isolation through UUID-based directory structures and path helper functions in src/storage_paths.rs. Methods like session_journal_path and session_path always incorporate the session ID into the file path, ensuring that path resolution is scoped to the requesting session's exclusive directory.

What happens to session memory caches when a session ends?

The SessionMemoryProfileCache lives only within the Session struct instance and is marked with #[serde(skip)] to exclude it from serialization. When the Session value drops out of scope, the cache is automatically deallocated, leaving no residual data in memory or on disk.

Is jcode's session isolation thread-safe for concurrent requests?

Yes, the server implementation in src/server/state.rs uses Arc<Mutex<Session>> within SessionControlHandle structures. Each concurrent request operates on its own locked Session clone, ensuring that mutable state never overlaps between simultaneous tasks executing on different sessions.

How does the server manage multiple active sessions simultaneously?

The server maintains a HashMap<String, SessionControlHandle> keyed by session ID. When a request arrives, the server looks up the handle by ID and spawns an async task with the cloned session data, ensuring that each active session operates within its own isolated execution context.

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 →