Skip to content

Chat session list is wiped on container redeploy: session index lives in ephemeral /root/.claude-code-web #101

Description

@viniciussouzax

Summary

On a containerized deployment, redeploying the dashboard makes the entire
chat session list disappear
— the UI looks "reset to zero". The durable chat
history is not lost (the .jsonl logs survive), but the session index
that powers the conversation list is stored in an ephemeral path and is gone
after the container is recreated.

Root cause

SessionStore defaults its storage dir to the home directory:

// dashboard/terminal-server/src/utils/session-store.js
this.storageDir = options.storageDir || path.join(os.homedir(), '.claude-code-web');
this.sessionsFile = path.join(this.storageDir, 'sessions.json');

In the official container, os.homedir() is /root, so the index lives at
/root/.claude-code-web/sessions.json. That path is not under any of the
documented volumes, so a docker compose redeploy (new container) starts with
an empty index and loadSessions() returns an empty Map → the agent's session
list is empty.

The durable history is fine: ChatLogger writes to
workspace/ADWs/logs/chat/{agent}_{sessionId}.jsonl (under the workspace
volume), and sessions.json is explicitly described in the code as "a
fast-access cache; JSONL survives restarts and cleanups." The problem is only
that losing the cache makes the conversations unreachable from the UI,
because the list is built from the in-memory Map (seeded from sessions.json),
not by scanning the JSONL directory.

Steps to reproduce

  1. Run the dashboard in a container with the documented volumes mounted.
  2. Have one or more chat conversations with an agent.
  3. Recreate the container (docker compose up -d --force-recreate, or any
    redeploy via Coolify/Dokploy/etc.).
  4. Open the agent chat → the previous conversations are no longer listed.
    (/root/.claude-code-web/sessions.json was reset; the .jsonl files are
    still on disk in the workspace volume.)

Expected

Chat conversations remain listed across redeploys, as long as the data volumes
are intact.

Possible fixes (for maintainer discussion)

  1. Default storageDir to a persisted path, e.g. under the existing
    dashboard/data (or workspace) volume, so the index is durable by default.
  2. Honor an env var (e.g. SESSION_STORE_DIR) and mount it, documented in
    the deployment guide.
  3. Document that /root/.claude-code-web must be a named volume in any
    container deployment.
  4. Rebuild the index from JSONL on startup when sessions.json is missing
    (scan workspace/ADWs/logs/chat/*.jsonl, group by {agent}_{shortId}), so
    the list self-heals even if the cache is lost. This also makes the cache
    truly a cache.

Options 1 or 4 give the best out-of-the-box experience; (4) is the most robust
since it removes the cache as a single point of failure.

Workaround

Mount a volume at /root/.claude-code-web. To recover an already-lost list,
the index can be reconstructed from the surviving .jsonl files (filename
{agent}_{shortId}.jsonl) into sessions.json.

Environment

  • Deployment: Docker container (official image), reverse-proxied.
  • Affected file: dashboard/terminal-server/src/utils/session-store.js.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions