Skip to content

fix(claude-code): fix template lifecycle wiring and persist gh config - #165

Merged
gatezh merged 4 commits into
masterfrom
fix/claude-code-template-lifecycle
Sep 23, 2026
Merged

gatezh merged 4 commits into
masterfrom
fix/claude-code-template-lifecycle

Conversation

@gatezh

@gatezh gatezh commented Sep 23, 2026

Copy link
Copy Markdown
Owner

What

Fixes three problems in the claude-code template's lifecycle config:

  • a dangling waitFor
  • bun install failing without a package.json
  • the gh login being lost on every rebuild

Why

Changes

  • Default devcontainer.json:
    • Removed the dangling waitFor. Its default, updateContentCommand, is correct.
    • Guarded bun install with if [ -f package.json ].
  • Sandbox devcontainer.json: the same bun install guard, plus init-plugins.sh (if present) at the end of postCreateCommand. That runs before postStartCommand brings up the firewall, matching the repo-root sandbox.
  • Both variants:
    • New myproject-gh-config-${localWorkspaceFolderBasename} volume at /home/node/.config/gh, shared between the variants by name.
    • The chown safety net now covers it too.
  • Dockerfile: pre-creates /home/node/.config/gh, owned by node, next to the other mount points. Docker then seeds a fresh volume with node ownership instead of root. Checked by experiment: without this the mount comes up root-owned.
  • CI verify (ci.yml, build-claude-code.yml): asserts stat -c %U /home/node/.config/gh is node for both variants.
  • README, init-plugins.sh header: document the gh volume and how init-plugins.sh runs in each variant.

Notes

Fixes #107
Fixes #114

…gh config

The default template set "waitFor": "postCreateCommand" but defined no
postCreateCommand, so init-plugins.sh never ran for consumers who copied
the template verbatim, despite the README, script header and Dockerfile
comments all assuming it did. Wire it in. The sandbox variant appends it
to its existing postCreateCommand, which runs before postStartCommand
brings the firewall up, so marketplace/plugin installs still have network.

bun install fails without a package.json, which aborted the rest of the
lifecycle for static or not-yet-scaffolded projects. Skip it until one
exists (updateContentCommand in default, postCreateCommand in sandbox).

gh stores auth in ~/.config/gh/hosts.yml on the ephemeral layer, so every
rebuild logged the user out. Add a shared myproject-gh-config volume to
both variants, extend the chown safety net to it, and pre-create the mount
point node-owned in the image so Docker seeds a fresh volume correctly
(otherwise Docker creates the missing dir as root). CI and post-build
verify now assert that ownership.

Fixes #107
Fixes #114
…ommand

The previous commit wired init-plugins.sh into the default variant's
postCreateCommand (#107 option a). That is the configuration #58 removed:
before #58 the repo-root default ran init-plugins.sh from postCreateCommand
with waitFor already set, and claude CLI calls there raced the Claude Code
extension's OAuth sign-in and corrupted auth state.

Apply #107 option (b) to the default variant instead: drop the dangling
waitFor (its default, updateContentCommand, is correct) and document
running the script once after sign-in. The sandbox keeps the script in
postCreateCommand, matching the repo-root sandbox, now guarded so a
consumer without the optional script doesn't fail container creation.
Missed by #163: the variant summary still said the token must be
injected from the host.
@gatezh
gatezh merged commit 7979439 into master Sep 23, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant