Skip to content

Commit 1825a02

Browse files
authored
Merge pull request #203 from gatezh/fix/git-safe-directory
fix(claude-code): set git safe.directory and gh credential helper via env
2 parents 8043fc0 + e8e3c0d commit 1825a02

3 files changed

Lines changed: 42 additions & 3 deletions

File tree

‎claude-code/.devcontainer/claude-sandbox/devcontainer.json‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,19 @@
128128
// Optional — only needed when the sandbox is used without the default variant, whose
129129
// sign-in lands on the shared ~/.claude volume. Resolves to "" when the host var is
130130
// unset. See "Sandbox Authentication" section in README.
131-
"CLAUDE_CODE_OAUTH_TOKEN": "${localEnv:CLAUDE_CODE_OAUTH_TOKEN}"
131+
"CLAUDE_CODE_OAUTH_TOKEN": "${localEnv:CLAUDE_CODE_OAUTH_TOKEN}",
132+
// Git config for every process, outranking the ~/.gitconfig the extension copies in:
133+
// trust /workspace, send git@github.com: remotes over HTTPS, and authenticate github.com
134+
// only through gh (the empty helper drops VS Code's, as `gh auth setup-git` does).
135+
"GIT_CONFIG_COUNT": "4",
136+
"GIT_CONFIG_KEY_0": "safe.directory",
137+
"GIT_CONFIG_VALUE_0": "/workspace",
138+
"GIT_CONFIG_KEY_1": "url.https://github.com/.insteadOf",
139+
"GIT_CONFIG_VALUE_1": "git@github.com:",
140+
"GIT_CONFIG_KEY_2": "credential.https://github.com.helper",
141+
"GIT_CONFIG_VALUE_2": "",
142+
"GIT_CONFIG_KEY_3": "credential.https://github.com.helper",
143+
"GIT_CONFIG_VALUE_3": "!gh auth git-credential"
132144
},
133145
// The find command chowns all node_modules volume mount points in one pass.
134146
// Chromium is baked into the sandbox image (firewall blocks runtime install).

‎claude-code/.devcontainer/devcontainer.json‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,19 @@
111111
"TZ": "${localEnv:TZ:America/Edmonton}",
112112
"DEVCONTAINER": "true",
113113
"NODE_OPTIONS": "--max-old-space-size=4096",
114-
"CLAUDE_CONFIG_DIR": "/home/node/.claude"
114+
"CLAUDE_CONFIG_DIR": "/home/node/.claude",
115+
// Git config for every process, outranking the ~/.gitconfig the extension copies in:
116+
// trust /workspace, send git@github.com: remotes over HTTPS, and authenticate github.com
117+
// only through gh (the empty helper drops VS Code's, as `gh auth setup-git` does).
118+
"GIT_CONFIG_COUNT": "4",
119+
"GIT_CONFIG_KEY_0": "safe.directory",
120+
"GIT_CONFIG_VALUE_0": "/workspace",
121+
"GIT_CONFIG_KEY_1": "url.https://github.com/.insteadOf",
122+
"GIT_CONFIG_VALUE_1": "git@github.com:",
123+
"GIT_CONFIG_KEY_2": "credential.https://github.com.helper",
124+
"GIT_CONFIG_VALUE_2": "",
125+
"GIT_CONFIG_KEY_3": "credential.https://github.com.helper",
126+
"GIT_CONFIG_VALUE_3": "!gh auth git-credential"
115127
},
116128
// sudo chown fixes volume ownership — safety net in case Docker volume population didn't apply.
117129
// The find command chowns all node_modules volume mount points in one pass.

‎claude-code/README.md‎

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ Copy these to your project's `.devcontainer/`:
6464
- [`.devcontainer/docker-compose.yml`](.devcontainer/docker-compose.yml) — image reference (kept fresh by the `initializeCommand` pull in `devcontainer.json`)
6565
- [`.devcontainer/devcontainer.json`](.devcontainer/devcontainer.json) — full config with VS Code extensions, zsh shell, OXC formatter, node_modules volume isolation, and lifecycle commands
6666

67-
**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).
67+
**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).
6868

6969
### Sandbox variant
7070

@@ -292,6 +292,21 @@ The template only mounts root `node_modules` by default. For monorepo projects,
292292
293293
The `sudo find` in `updateContentCommand` chowns all `node_modules` directories in one pass, so additional mounts are handled automatically.
294294
295+
## Git and GitHub Authentication
296+
297+
Both `devcontainer.json` variants set git config through `GIT_CONFIG_COUNT` / `GIT_CONFIG_KEY_<n>` / `GIT_CONFIG_VALUE_<n>` 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.
298+
299+
| Key | Value | Why |
300+
|-----|-------|-----|
301+
| `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. |
302+
| `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. |
303+
| `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. |
304+
| `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. |
305+
306+
**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.
307+
308+
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.
309+
295310
## Playwright Strategy
296311
297312
Both image variants ship the system `chromium` package (apt-installed)

0 commit comments

Comments
 (0)