diff --git a/claude-code/.devcontainer/claude-sandbox/devcontainer.json b/claude-code/.devcontainer/claude-sandbox/devcontainer.json index 2db7413..cf03d1e 100644 --- a/claude-code/.devcontainer/claude-sandbox/devcontainer.json +++ b/claude-code/.devcontainer/claude-sandbox/devcontainer.json @@ -128,7 +128,19 @@ // Optional — only needed when the sandbox is used without the default variant, whose // sign-in lands on the shared ~/.claude volume. Resolves to "" when the host var is // unset. See "Sandbox Authentication" section in README. - "CLAUDE_CODE_OAUTH_TOKEN": "${localEnv:CLAUDE_CODE_OAUTH_TOKEN}" + "CLAUDE_CODE_OAUTH_TOKEN": "${localEnv:CLAUDE_CODE_OAUTH_TOKEN}", + // Git config for every process, outranking the ~/.gitconfig the extension copies in: + // trust /workspace, send git@github.com: remotes over HTTPS, and authenticate github.com + // only through gh (the empty helper drops VS Code's, as `gh auth setup-git` does). + "GIT_CONFIG_COUNT": "4", + "GIT_CONFIG_KEY_0": "safe.directory", + "GIT_CONFIG_VALUE_0": "/workspace", + "GIT_CONFIG_KEY_1": "url.https://github.com/.insteadOf", + "GIT_CONFIG_VALUE_1": "git@github.com:", + "GIT_CONFIG_KEY_2": "credential.https://github.com.helper", + "GIT_CONFIG_VALUE_2": "", + "GIT_CONFIG_KEY_3": "credential.https://github.com.helper", + "GIT_CONFIG_VALUE_3": "!gh auth git-credential" }, // The find command chowns all node_modules volume mount points in one pass. // Chromium is baked into the sandbox image (firewall blocks runtime install). diff --git a/claude-code/.devcontainer/devcontainer.json b/claude-code/.devcontainer/devcontainer.json index 37fb196..44590ba 100644 --- a/claude-code/.devcontainer/devcontainer.json +++ b/claude-code/.devcontainer/devcontainer.json @@ -111,7 +111,19 @@ "TZ": "${localEnv:TZ:America/Edmonton}", "DEVCONTAINER": "true", "NODE_OPTIONS": "--max-old-space-size=4096", - "CLAUDE_CONFIG_DIR": "/home/node/.claude" + "CLAUDE_CONFIG_DIR": "/home/node/.claude", + // Git config for every process, outranking the ~/.gitconfig the extension copies in: + // trust /workspace, send git@github.com: remotes over HTTPS, and authenticate github.com + // only through gh (the empty helper drops VS Code's, as `gh auth setup-git` does). + "GIT_CONFIG_COUNT": "4", + "GIT_CONFIG_KEY_0": "safe.directory", + "GIT_CONFIG_VALUE_0": "/workspace", + "GIT_CONFIG_KEY_1": "url.https://github.com/.insteadOf", + "GIT_CONFIG_VALUE_1": "git@github.com:", + "GIT_CONFIG_KEY_2": "credential.https://github.com.helper", + "GIT_CONFIG_VALUE_2": "", + "GIT_CONFIG_KEY_3": "credential.https://github.com.helper", + "GIT_CONFIG_VALUE_3": "!gh auth git-credential" }, // sudo chown fixes volume ownership — safety net in case Docker volume population didn't apply. // The find command chowns all node_modules volume mount points in one pass. diff --git a/claude-code/README.md b/claude-code/README.md index 0317678..6a1dc64 100644 --- a/claude-code/README.md +++ b/claude-code/README.md @@ -64,7 +64,7 @@ Copy these to your project's `.devcontainer/`: - [`.devcontainer/docker-compose.yml`](.devcontainer/docker-compose.yml) — image reference (kept fresh by the `initializeCommand` pull in `devcontainer.json`) - [`.devcontainer/devcontainer.json`](.devcontainer/devcontainer.json) — full config with VS Code extensions, zsh shell, OXC formatter, node_modules volume isolation, and lifecycle commands -**Key settings included:** zsh + bash terminal profiles, OXC formatter (with comments for switching to Biome/Prettier), node_modules/Claude config/zsh history/gh CLI config volume mounts, and `updateContentCommand` for mise/bun setup (`bun install` is skipped until the project has a `package.json`). There is deliberately no `postCreateCommand`: see [`init-plugins.sh`](#optional-devcontainerinit-pluginssh). +**Key settings included:** zsh + bash terminal profiles, OXC formatter (with comments for switching to Biome/Prettier), node_modules/Claude config/zsh history/gh CLI config volume mounts, env-based git config (see [Git and GitHub Authentication](#git-and-github-authentication)), and `updateContentCommand` for mise/bun setup (`bun install` is skipped until the project has a `package.json`). There is deliberately no `postCreateCommand`: see [`init-plugins.sh`](#optional-devcontainerinit-pluginssh). ### Sandbox variant @@ -292,6 +292,21 @@ The template only mounts root `node_modules` by default. For monorepo projects, The `sudo find` in `updateContentCommand` chowns all `node_modules` directories in one pass, so additional mounts are handled automatically. +## Git and GitHub Authentication + +Both `devcontainer.json` variants set git config through `GIT_CONFIG_COUNT` / `GIT_CONFIG_KEY_` / `GIT_CONFIG_VALUE_` in `containerEnv`. Git reads these as [command scope](https://git-scm.com/docs/git-config#SCOPES): they apply to every git process in the container (terminal, VS Code's Git extension, Claude Code) and outrank `/etc/gitconfig` and `~/.gitconfig`, which the Dev Containers extension writes to on attach. + +| Key | Value | Why | +|-----|-------|-----| +| `safe.directory` | `/workspace` | Docker Desktop bind mounts can report `/workspace` as owned by another user, so git refuses it with `detected dubious ownership`. The Dev Containers extension adds this entry to `~/.gitconfig` only when its one-time check at attach detects the mismatch, so the error comes and goes. | +| `url.https://github.com/.insteadOf` | `git@github.com:` | Sends SSH-style GitHub remotes over HTTPS inside the container. The remotes themselves and the host's SSH setup don't change. | +| `credential.https://github.com.helper` | *(empty)* | Clears the helper list for github.com, including the helper VS Code injects, which answers with the host's possibly stale GitHub credential. Other hosts keep VS Code's helper. | +| `credential.https://github.com.helper` | `!gh auth git-credential` | Authenticates github.com through the container's `gh` login. The empty entry and this one are what `gh auth setup-git` writes. | + +**One-time setup:** run `gh auth login` in either variant. The login lives on the shared `myproject-gh-config-*` volume, so it survives rebuilds and covers both variants. After that, fetch, pull and push work from the terminal and from VS Code for both `https://github.com/` and `git@github.com:` remotes. + +To check what git sees, run `git config --show-scope --get-regexp 'safe|insteadof|credential'`. The entries above are listed with scope `command`. To add your own entries, append `GIT_CONFIG_KEY_4` / `GIT_CONFIG_VALUE_4` and so on, and raise `GIT_CONFIG_COUNT` to match. + ## Playwright Strategy Both image variants ship the system `chromium` package (apt-installed)