No description
Find a file
TJC d82056a986 feat(claude-code-passthrough): add global config passthrough (#4)
* Validate VERSION input before npm install

Reject version strings containing shell metacharacters to prevent
command injection via the feature option. Allows 'latest', semver,
and npm dist-tags ([A-Za-z0-9._-]+).

* Add ShellCheck job to test workflow

Lints all install scripts, helper scripts, and test scripts. Runs as
a prerequisite for the devcontainer test job so style/correctness
issues fail fast before the slower image build.

* Add failure-mode test for missing host credentials

Exercises link-credentials.sh in two failure modes that the helper
already handles but were not previously tested:
  - Staging files entirely absent (warn + exit 0).
  - Staging path is a directory because Docker auto-mkdir'd a missing
    host file (exit 1 with actionable message).
Runs inside the built container so it tests the helper as installed.

* Add NOTES.md with troubleshooting section

The README is auto-generated from devcontainer-feature.json; per the
generator, additional content lives in NOTES.md and is appended to
README.md by the release workflow.

Documents the host pre-auth requirement, the directory-vs-file
failure mode (the most common support case), the native-installer
shim, and the Windows HOME fallback.

* Use 'set -euo pipefail' in test scripts

Match the robustness of install.sh and link-credentials.sh — catch
unset variables and pipeline failures, not just non-zero exits.
lint-mounts.sh already used the strict form.

* Rename feature option 'version' to 'claudeVersion'

The bare name 'version' is ambiguous next to the feature's own
version field and the node feature's version. 'claudeVersion'
matches the existing 'nodeVersion' option for symmetry.

Per the devcontainer spec, the option key is uppercased to form
the env var passed to install.sh, so VERSION becomes CLAUDEVERSION.
The internal shell variable is renamed to CLAUDE_VERSION for
readability.

* Remove dead nodeVersion option, document node override in NOTES

The nodeVersion option was never wired to anything — install.sh
didn't read it and the dependsOn block hard-coded 'lts'. The
devcontainer spec evaluates dependsOn statically before option
values bind, so forwarding the option value was never possible.
A user setting nodeVersion=20 would silently get LTS, which is
worse than no option at all.

Replace the fake knob with a NOTES.md section showing how to
override the node version by declaring the node feature directly
in devcontainer.json.

* Relocate feature staging dir to /opt/claude-code-passthrough

/usr/local/share is conventionally for shared application data; feature
staging fits /opt better as a self-contained third-party install root.

* Warn instead of silently swallowing chown failure on launcher symlink

* Add CI job to detect drift between devcontainer-feature.json and generated READMEs

* Test bidirectional credential sync via symlink and copy semantics for account state

* Test pre-existing ~/.claude collisions and read-only HOME failure mode

* Document uninstall and cleanup procedure in NOTES

* fix pull request errors

* incremented version number

* Fix HELPER variable not available in bash -c subshells in test scenarios

The missing-host-file and collisions test scenarios embed functions via
declare -f into bash -c blocks, but HELPER was only defined in the
parent script scope. This caused cp "${HELPER}" to expand to cp "" and
fail with "cannot stat ''".

* feat(claude-code-passthrough): add opt-in global config passthrough

- new passthroughHostConfig option (default false) copies a curated
  ~/.claude subset: CLAUDE.md, settings.json, keybindings.json,
  commands/, skills/, agents/
- copied not linked, so container edits stay container-local
- bind-mount host ~/.claude to staging; seed gated on its own flag,
  independent of passthroughHostAuth
- add with-global-config scenario; seed config files in CI
- document in NOTES.md and regenerate README

Co-authored-by: AI <ai@noreply.git.tjc.fyi>
2026-06-05 12:21:52 +01:00
.github/workflows feat(claude-code-passthrough): add global config passthrough (#4) 2026-06-05 12:21:52 +01:00
src/claude-code-passthrough feat(claude-code-passthrough): add global config passthrough (#4) 2026-06-05 12:21:52 +01:00
test/claude-code-passthrough feat(claude-code-passthrough): add global config passthrough (#4) 2026-06-05 12:21:52 +01:00
.gitignore Add claude-code-passthrough dev container feature 2026-04-07 22:03:39 +01:00
LICENSE Initial commit 2026-04-07 21:46:44 +01:00
README.md Add claude-code-passthrough dev container feature 2026-04-07 22:03:39 +01:00

timcane/devcontainer-features

Personal collection of dev container features.

Features

Feature Description
claude-code-passthrough Installs Anthropic Claude Code and bind-mounts the host's ~/.claude/.credentials.json so you don't re-auth in the container.

Usage

"features": {
    "ghcr.io/timcane/devcontainer-features/claude-code-passthrough:0": {}
}

Repo layout

.
├── src/<feature-id>/        # one directory per feature
│   ├── devcontainer-feature.json
│   ├── install.sh
│   └── README.md
├── test/<feature-id>/       # smoke tests + scenarios
└── .github/workflows/
    ├── release.yaml         # publishes to ghcr.io on push to main
    └── test.yaml            # runs `devcontainer features test` on PRs