Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ Two backends, selected by `CLAYDE_CLAUDE_BACKEND`:
- Session resumption: saves `session_id` from JSON output, resumes via `--resume <session_id>`
- Rate/usage limit detection: text-pattern matching on stdout/stderr
- No per-token cost tracking (returns `cost_eur=0.0`)
- Requires: OAuth credentials mounted from host `~/.claude/.credentials.json` (see docker-compose.yml)
- 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.

---

Expand Down
21 changes: 18 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,17 +131,32 @@ Uses the Anthropic Python SDK with a tool-use loop. Pay-per-token.

Runs the Claude Code CLI as a subprocess. Uses your Claude Pro/Max subscription — no per-token cost.

1. On the host machine, log in to the CLI:
1. On the host machine, create a **dedicated** login for the container in its
own config directory (kept separate from your personal `~/.claude`):
```bash
claude login
CLAUDE_CONFIG_DIR=~/clayde-claude claude login
```
2. Set in `data/config.env`:
```
CLAYDE_CLAUDE_BACKEND=cli
```
(`CLAYDE_CLAUDE_API_KEY` is not required for the CLI backend.)

The `docker-compose.yml` mounts `~/.claude/.credentials.json` from the host directly into the container. Token refreshes, logouts, and account switches on the host are immediately reflected.
The `docker-compose.yml` mounts the `~/clayde-claude` **directory** into the
container as its Claude config dir. Two things matter here:

- **Mount the directory, not the `.credentials.json` file.** The CLI refreshes
its short-lived OAuth token by writing a new file and atomically renaming it
into place — which changes the file's inode. A single-file bind mount is
pinned to the original inode at container start, so it never sees the new
token and the container fails with "authentication expired" until you restart
the stack. A directory mount resolves the path live, so refreshes propagate
with no restart.
- **Use a dedicated login, not your personal `~/.claude`.** That directory
holds your interactive sessions, projects, and history; sharing it exposes
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).

### 5. Start the container

Expand Down
11 changes: 9 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,15 @@ services:
- CLAYDE_ENABLED=true
volumes:
- ./data:/data
# Mount Claude CLI OAuth credentials (required when CLAYDE_CLAUDE_BACKEND=cli)
- ~/.claude/.credentials.json:/home/clayde/.claude/.credentials.json
# Dedicated Claude config dir for the container (required when
# CLAYDE_CLAUDE_BACKEND=cli). Use a SEPARATE login here — see README:
# CLAUDE_CONFIG_DIR=~/clayde-claude claude login
# Mount the DIRECTORY, not the single .credentials.json file: the CLI
# refreshes its short-lived OAuth token via atomic rename (new inode),
# which a single-file bind mount pins to the stale inode at start —
# causing "authentication expired" until the stack is restarted. A
# directory mount resolves the path live, so refreshes are picked up.
- ~/clayde-claude:/home/clayde/.claude
# Pebble skill directories — mount one or more host dirs read-only
# under /skills/. Subdirectory layout is free; discovery is recursive.
- ~/skills/personal:/skills/personal:ro
Expand Down
Loading