From 105b118ffa9f1641f1845b38830835eb3cbc52d2 Mon Sep 17 00:00:00 2001 From: ClaydeCode Date: Fri, 16 Oct 2026 06:16:27 +0000 Subject: [PATCH] compose: persist the clayde container's top-level Claude config CLAUDE_CONFIG_DIR was never set on the running container, so the CLI's top-level config file (project trust state among it) defaulted to $HOME/.claude.json, a path outside the ~/clayde-claude mount. Every container restart wiped it, surfacing as "Claude configuration file not found" on the next job and silently dropped settings.local.json permissions afterward, since headless runs can't re-accept the trust dialog. Set CLAUDE_CONFIG_DIR=/home/clayde/.claude to match the mount and the one-time host login, as the README already describes it. Co-Authored-By: Claude Sonnet 5 --- CLAUDE.md | 2 +- README.md | 7 +++++++ docker-compose.yml | 10 ++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/CLAUDE.md b/CLAUDE.md index dfa0e12..0b2aaff 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -230,7 +230,7 @@ Two backends, selected by `CLAYDE_CLAUDE_BACKEND`: - Session resumption: saves `session_id` from JSON output, resumes via `--resume ` - Rate/usage limit detection: text-pattern matching on stdout/stderr - No per-token cost tracking (returns `cost_eur=0.0`) -- Requires: a dedicated Claude config dir dir-mounted from the host (`~/clayde-claude` → `/home/clayde/.claude`); use a separate `CLAUDE_CONFIG_DIR=~/clayde-claude claude login`. Mount the directory, not the `.credentials.json` file — token refresh renames the file (new inode) and a single-file mount goes stale. See docker-compose.yml / README. +- Requires: a dedicated Claude config dir dir-mounted from the host (`~/clayde-claude` → `/home/clayde/.claude`); use a separate `CLAUDE_CONFIG_DIR=~/clayde-claude claude login`. Mount the directory, not the `.credentials.json` file — token refresh renames the file (new inode) and a single-file mount goes stale. The container itself must also set `CLAUDE_CONFIG_DIR=/home/clayde/.claude`, or the CLI's top-level config file (project trust state) defaults to the unmounted `$HOME/.claude.json` and is lost on every restart. See docker-compose.yml / README. --- diff --git a/README.md b/README.md index bd7ffda..73dcbb4 100644 --- a/README.md +++ b/README.md @@ -157,6 +157,13 @@ container as its Claude config dir. Two things matter here: that state to the container. A separate login also gives the container its own OAuth refresh-token lineage, so its token refreshes can't invalidate your host login (refresh tokens are single-use). +- **The container's `CLAUDE_CONFIG_DIR` must match the mount path + (`/home/clayde/.claude`).** This is set in `docker-compose.yml`, mirroring the + env var used for the one-time login above. Without it, the CLI falls back to + its default `$HOME/.claude.json` for top-level config (project trust state + among it) — a path that sits outside the mount and is wiped on every + container restart, surfacing as "Claude configuration file not found" on the + next run and a loss of trusted-project state after. ### 5. Start the container diff --git a/docker-compose.yml b/docker-compose.yml index e27a1b2..1d7d4d7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -41,6 +41,16 @@ services: - "8080" environment: - CLAYDE_ENABLED=true + # Must match the CLAUDE_CONFIG_DIR used for the one-time host login + # below, so the CLI reads/writes its top-level config file inside the + # mounted (persistent) directory instead of defaulting to $HOME/.claude.json + # — a path outside the mount that is wiped on every container restart. + # Without this, the CLI errors with "Claude configuration file not + # found" on the first run after a restart, and the recreated file lacks + # prior project-trust state, so settings.local.json's permissions.allow + # entries get silently ignored until a human re-accepts the trust dialog + # — impossible for a headless scheduled/Pebble run. + - CLAUDE_CONFIG_DIR=/home/clayde/.claude volumes: - ./data:/data # Dedicated Claude config dir for the container (required when