Skip to content

Commit 2929208

Browse files
committed
Move .claude config from /workspaces to home directory with named volume
- Change CLAUDE_CONFIG_DIR from /workspaces/.claude to ~/.claude - Add Docker named volume (per-instance via ${devcontainerId}) for persistence - Add CLAUDE_AUTH_TOKEN secret support with auto .credentials.json creation - Replace setup-symlink-claude.sh with setup-migrate-claude.sh (one-time migration) - Fix named volume root ownership via sudo chown on startup - Update scope guard allowlist to resolve $HOME dynamically - Update protected-files guard regex to cover .credentials.json - Update all feature heredocs, poststart hooks, and docs
1 parent d2ba55e commit 2929208

31 files changed

Lines changed: 186 additions & 81 deletions

.devcontainer/.env.example

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
# CodeForge Environment Configuration
22
# Copy to .env and customize. .env is gitignored.
33

4-
# Paths
5-
CLAUDE_CONFIG_DIR=/workspaces/.claude
6-
# CONFIG_SOURCE_DIR is derived from script location; uncomment to override:
4+
# Paths (defaults shown — uncomment to override)
5+
# CLAUDE_CONFIG_DIR=$HOME/.claude
76
# CONFIG_SOURCE_DIR=/custom/path/to/config
87

98
# Setup: copy config files to CLAUDE_CONFIG_DIR (per config/file-manifest.json)

.devcontainer/.secrets.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@ GH_EMAIL=
1010

1111
# NPM auth token for registry.npmjs.org
1212
NPM_TOKEN=
13+
14+
# Claude long-lived auth token (from 'claude setup-token')
15+
CLAUDE_AUTH_TOKEN=

.devcontainer/CHANGELOG.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,29 @@
11
# CodeForge Devcontainer Changelog
22

3+
## [Unreleased]
4+
5+
### Changed
6+
7+
#### Configuration
8+
- Moved `.claude` directory from `/workspaces/.claude` to `~/.claude` (home directory)
9+
- Added Docker named volume for persistence across rebuilds (per-instance isolation via `${devcontainerId}`)
10+
- `CLAUDE_CONFIG_DIR` now defaults to `/home/vscode/.claude`
11+
12+
#### Authentication
13+
- Added `CLAUDE_AUTH_TOKEN` support in `.secrets` for long-lived tokens from `claude setup-token`
14+
- Auto-creates `.credentials.json` from token on container start (skips if already exists)
15+
- Added `CLAUDE_AUTH_TOKEN` to devcontainer.json secrets declaration
16+
17+
#### Security
18+
- Protected-files-guard now covers `.credentials.json` (leading dot)
19+
20+
#### Scripts
21+
- Replaced `setup-symlink-claude.sh` with `setup-migrate-claude.sh` (one-time migration)
22+
- Auto-migrates from `/workspaces/.claude/` if `.credentials.json` present
23+
24+
### Removed
25+
- `setup-symlink-claude.sh` — no longer needed with native home directory location
26+
327
## [v1.14.2] - 2026-02-24
428

529
### Fixed

.devcontainer/CLAUDE.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ CodeForge devcontainer for AI-assisted development with Claude Code.
3131
| `devcontainer.json` | Container definition: image, features, mounts |
3232
| `.env` | Boolean flags controlling setup steps |
3333

34-
Config files deploy via `file-manifest.json` on every container start. Most deploy to `/workspaces/.claude/`; ccstatusline config deploys to `~/.config/ccstatusline/`. Each entry supports `overwrite`: `"if-changed"` (default, sha256), `"always"`, or `"never"`. Supported variables: `${CLAUDE_CONFIG_DIR}`, `${WORKSPACE_ROOT}`, `${HOME}`.
34+
Config files deploy via `file-manifest.json` on every container start. Most deploy to `~/.claude/`; ccstatusline config deploys to `~/.config/ccstatusline/`. Each entry supports `overwrite`: `"if-changed"` (default, sha256), `"always"`, or `"never"`. Supported variables: `${CLAUDE_CONFIG_DIR}`, `${WORKSPACE_ROOT}`, `${HOME}`.
3535

3636
## Commands
3737

@@ -76,7 +76,7 @@ Rules in `config/defaults/rules/` deploy to `.claude/rules/` on every container
7676

7777
| Variable | Value |
7878
|----------|-------|
79-
| `CLAUDE_CONFIG_DIR` | `/workspaces/.claude` |
79+
| `CLAUDE_CONFIG_DIR` | `/home/vscode/.claude` |
8080
| `ANTHROPIC_MODEL` | `claude-opus-4-6` |
8181
| `WORKSPACE_ROOT` | `/workspaces` |
8282

.devcontainer/README.md

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,20 @@ Get an API key from [console.anthropic.com](https://console.anthropic.com/).
4040

4141
### Credential Persistence
4242

43-
Authentication credentials are stored in `/workspaces/.claude/` and persist across container rebuilds.
43+
Authentication credentials are stored in `~/.claude/` and persist across container rebuilds via a Docker named volume.
44+
45+
### Long-Lived Token Authentication
46+
47+
For headless or automated environments, you can use a long-lived auth token instead of browser login:
48+
49+
1. Generate a token: `claude setup-token`
50+
2. Add to `.devcontainer/.secrets`:
51+
```bash
52+
CLAUDE_AUTH_TOKEN=sk-ant-oat01-your-token-here
53+
```
54+
3. On next container start, `setup-auth.sh` will create `~/.claude/.credentials.json` automatically.
55+
56+
You can also set `CLAUDE_AUTH_TOKEN` as a Codespaces secret for cloud environments.
4457

4558
For more options, see the [Claude Code documentation](https://docs.anthropic.com/en/docs/claude-code).
4659

@@ -111,7 +124,7 @@ Expected output shows your authenticated account and token scopes.
111124

112125
### Credential Persistence
113126

114-
GitHub CLI credentials are automatically persisted across container rebuilds. The container is configured to store credentials in `/workspaces/.gh/` (via `GH_CONFIG_DIR`), which is part of the bind-mounted workspace.
127+
GitHub CLI credentials are automatically persisted across container rebuilds. The container is configured to store credentials in `/workspaces/.gh/` (via `GH_CONFIG_DIR`), which is part of the bind-mounted workspace. Claude Code credentials persist via a Docker named volume mounted at `~/.claude/`.
115128

116129
**You only need to authenticate once.** After running `gh auth login` or configuring `.secrets`, your credentials will survive container rebuilds and be available in future sessions.
117130

@@ -199,7 +212,7 @@ Copy `.devcontainer/.env.example` to `.devcontainer/.env` and customize:
199212

200213
| Variable | Default | Description |
201214
|----------|---------|-------------|
202-
| `CLAUDE_CONFIG_DIR` | `/workspaces/.claude` | Claude configuration directory |
215+
| `CLAUDE_CONFIG_DIR` | `/home/vscode/.claude` | Claude configuration directory |
203216
| `SETUP_CONFIG` | `true` | Copy config files during setup (per `file-manifest.json`) |
204217
| `SETUP_ALIASES` | `true` | Add `cc`/`claude`/`ccraw` aliases to shell |
205218
| `SETUP_AUTH` | `true` | Configure Git/NPM auth from `.secrets` |
@@ -301,6 +314,8 @@ Three methods for providing GitHub/NPM credentials, in order of precedence:
301314

302315
All methods persist across container rebuilds via the bind-mounted `/workspaces/.gh/` directory.
303316

317+
4. **`.secrets` file with `CLAUDE_AUTH_TOKEN`** — Long-lived Claude auth token from `claude setup-token`. Auto-creates `~/.claude/.credentials.json` on container start.
318+
304319
## Agents & Skills
305320

306321
Agents and skills are distributed across focused plugins (replacing the former `code-directive` monolith).

.devcontainer/devcontainer.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,17 @@
55
"workspaceFolder": "/workspaces",
66
"workspaceMount": "source=${localWorkspaceFolder},target=/workspaces,type=bind",
77

8+
"mounts": [
9+
{
10+
"source": "codeforge-claude-config-${devcontainerId}",
11+
"target": "/home/vscode/.claude",
12+
"type": "volume"
13+
}
14+
],
15+
816
"remoteEnv": {
917
"WORKSPACE_ROOT": "/workspaces",
10-
"CLAUDE_CONFIG_DIR": "/workspaces/.claude",
18+
"CLAUDE_CONFIG_DIR": "/home/vscode/.claude",
1119
"GH_CONFIG_DIR": "/workspaces/.gh",
1220
"TMPDIR": "/workspaces/.tmp",
1321
"CLAUDECODE": null
@@ -27,6 +35,10 @@
2735
},
2836
"GH_EMAIL": {
2937
"description": "GitHub email for git config (optional)"
38+
},
39+
"CLAUDE_AUTH_TOKEN": {
40+
"description": "Claude long-lived auth token from 'claude setup-token' (optional - sk-ant-oat01-*)",
41+
"documentationUrl": "https://docs.anthropic.com/en/docs/claude-code/cli-reference#claude-setup-token"
3042
}
3143
},
3244

.devcontainer/docs/configuration-reference.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ These control what `setup.sh` does on each container start. Copy `.env.example`
2323

2424
| Variable | Default | Description |
2525
|----------|---------|-------------|
26-
| `CLAUDE_CONFIG_DIR` | `/workspaces/.claude` | Where Claude Code config files are stored |
26+
| `CLAUDE_CONFIG_DIR` | `/home/vscode/.claude` | Where Claude Code config files are stored |
2727
| `CONFIG_SOURCE_DIR` | `(auto-detected)` | Source directory for config defaults |
2828
| `SETUP_CONFIG` | `true` | Copy config files per `file-manifest.json` |
2929
| `SETUP_ALIASES` | `true` | Add cc/claude/ccraw/cc-tools aliases to shell |
@@ -42,7 +42,7 @@ These environment variables are set in every terminal session inside the contain
4242
| Variable | Value | Description |
4343
|----------|-------|-------------|
4444
| `WORKSPACE_ROOT` | `/workspaces` | Workspace root directory |
45-
| `CLAUDE_CONFIG_DIR` | `/workspaces/.claude` | Claude Code config directory |
45+
| `CLAUDE_CONFIG_DIR` | `/home/vscode/.claude` | Claude Code config directory |
4646
| `GH_CONFIG_DIR` | `/workspaces/.gh` | GitHub CLI config directory |
4747
| `TMPDIR` | `/workspaces/.tmp` | Temporary files directory |
4848
| `CLAUDECODE` | `null` (unset) | Unsets the variable to allow nested Claude Code sessions (claude-in-claude) |
@@ -88,6 +88,9 @@ GH_TOKEN=ghp_your_token_here
8888
GH_USERNAME=your-github-username
8989
GH_EMAIL=your-email@example.com
9090
NPM_TOKEN=npm_your_token_here
91+
CLAUDE_AUTH_TOKEN=sk-ant-oat01-your-token-here
9192
```
9293

94+
The `CLAUDE_AUTH_TOKEN` is a long-lived token from `claude setup-token`. When set, `setup-auth.sh` creates `~/.claude/.credentials.json` on container start (skips if already exists).
95+
9396
Environment variables with the same names take precedence over `.secrets` file values (useful for Codespaces).

.devcontainer/docs/keybindings.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ Edit `config/defaults/keybindings.json` to remap Claude Code actions to non-conf
7878
}
7979
```
8080

81-
The keybindings file is copied to `/workspaces/.claude/keybindings.json` on container start (controlled by `file-manifest.json`).
81+
The keybindings file is copied to `~/.claude/keybindings.json` on container start (controlled by `file-manifest.json`).
8282

8383
## Claude Code Keybinding Reference
8484

.devcontainer/docs/troubleshooting.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ Common issues and solutions for the CodeForge devcontainer.
3232
- Or configure `.devcontainer/.secrets` with `GH_TOKEN` for automatic auth on container start.
3333
- Credentials persist in `/workspaces/.gh/` across rebuilds.
3434

35+
**Problem**: Claude auth token not taking effect in Codespaces.
36+
37+
- When `CLAUDE_AUTH_TOKEN` is set via Codespaces secrets, it persists as an environment variable for the entire container lifetime. The `unset` in `setup-auth.sh` only clears it in the child process. This is a Codespaces platform limitation.
38+
- If `.credentials.json` already exists, the token injection is skipped (idempotent). Delete `~/.claude/.credentials.json` to force re-creation from the token.
39+
3540
**Problem**: Git push fails with permission error.
3641

3742
- Run `gh auth status` to verify authentication.
@@ -119,7 +124,7 @@ Common issues and solutions for the CodeForge devcontainer.
119124

120125
## How to Reset to Defaults
121126

122-
1. **Reset config files**: Delete `/workspaces/.claude/` and restart the container. `setup-config.sh` will recopy all files from `config/defaults/`.
127+
1. **Reset config files**: Delete `~/.claude/` and restart the container. `setup-config.sh` will recopy all files from `config/defaults/`.
123128

124129
2. **Reset aliases**: Delete the `# Claude Code environment and aliases` block from `~/.bashrc` and `~/.zshrc`, then run `bash /workspaces/.devcontainer/scripts/setup-aliases.sh`.
125130

.devcontainer/features/ccstatusline/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ You should see formatted output with powerline styling.
105105

106106
**3. Check Claude Code integration:**
107107
```bash
108-
cat /workspaces/.claude/settings.json | jq '.statusLine'
108+
cat ~/.claude/settings.json | jq '.statusLine'
109109
```
110110

111111
Should show:
@@ -204,7 +204,7 @@ cat ~/.config/ccstatusline/settings.json | jq .
204204
echo '{"model":{"display_name":"Test"}}' | npx -y ccstatusline@latest
205205

206206
# 3. Check Claude Code settings
207-
cat /workspaces/.claude/settings.json | jq '.statusLine'
207+
cat ~/.claude/settings.json | jq '.statusLine'
208208

209209
# 4. Manually run auto-config if needed
210210
configure-ccstatusline-auto

0 commit comments

Comments
 (0)