Skip to content

gh config volume #114

Description

@gatezh

Summary

The claude-code template persists Claude config (~/.claude), fish history
(~/.local/share/fish), and node_modules via named volumes, but it does not
persist the GitHub CLI's auth/state. gh is installed in the
ghcr.io/gatezh/devcontainers/claude-code image, and it stores credentials in
~/.config/gh/hosts.yml by default. That path lives on the container's ephemeral
writable layer, so every container rebuild wipes the GitHub login and the user
must re-run gh auth login. This is inconsistent with how .claude auth already
survives rebuilds and is a surprising paper-cut for anyone using gh for PRs/issues
from inside the container.

Reproduction

  1. Open the claude-code devcontainer.
  2. gh auth login and authenticate.
  3. Rebuild the container ("Dev Containers: Rebuild Container").
  4. gh auth status.
You are not logged into any GitHub hosts. To log in, run: gh auth login

Verification

# gh ships in the image, defaults its config to ~/.config/gh:
$ which gh && gh --version | head -1
/usr/bin/gh
gh version 2.46.0 (2025-01-13 Debian 2.46.0-3)

# But ~/.config is NOT on a named volume — only .claude / fish / node_modules are:
$ mount | grep -E '/home/node|/workspace'
/dev/sdf on /workspace type ext4 ...
/dev/sdd on /workspace/node_modules type ext4 ...
/dev/sdd on /home/node/.claude type ext4 ...
/dev/sdd on /home/node/.local/share/fish type ext4 ...
# (no entry for /home/node/.config) -> ephemeral, wiped on rebuild

Suggested fix

Add a dedicated named volume for gh's default config dir, alongside the existing
claude-config / fish-data mounts in
claude-code/.devcontainer/devcontainer.json:

"mounts": [
  // ...existing node_modules / claude-config / fish-data mounts...
  "source=myproject-fish-data-${localWorkspaceFolderBasename},target=/home/node/.local/share/fish,type=volume",
  // gh CLI auth/state (~/.config/gh/hosts.yml). Default gh config dir, so no
  // GH_CONFIG_DIR needed. Persists `gh auth login` across rebuilds like .claude does.
  "source=myproject-gh-config-${localWorkspaceFolderBasename},target=/home/node/.config/gh,type=volume"
],

And extend the updateContentCommand ownership safety-net (which already chowns
/home/node/.claude) so node can write to the root-owned mount point on first
create:

"updateContentCommand": "... && sudo chown -R node /home/node/.claude /home/node/.config/gh && ..."

A dedicated per-tool volume (rather than mounting all of ~/.config) keeps gh's
auth state on an independently resettable volume, matching the template's existing
per-concern convention. Same change applies to the claude-code-sandbox variant if
it should support authenticated gh too.

Affected files

  • claude-code/.devcontainer/devcontainer.json (mounts, updateContentCommand)
  • claude-code/.devcontainer/claude-sandbox/devcontainer.json (same change, if the
    sandbox variant should support gh auth persistence)

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions