-
Fork and clone
-
Install the git hooks (one-time setup):
pip install pre-commit pre-commit install # runs on git commit pre-commit install --hook-type pre-push # runs on git push
If you open the repo in the devcontainer, this runs automatically.
-
Changes live in
src/claude-code/install.shandtest/claude-code/ -
Open a pull request against
develop
| Branch pattern | Purpose | PR target |
|---|---|---|
feat/* |
New features | develop |
fix/* |
Bug fixes | develop |
hotfix/* |
Critical production fixes | main |
- All feature and fix PRs target
develop. Use squash merges to keep history clean. hotfix/*branches are the only branches (besidesdevelop) allowed to open PRs directly tomain. This is enforced by CI (source-branch-check.yml).- Direct commits to
mainanddevelopare blocked by pre-commit hooks and branch protection rules.
The following checks run automatically on every git commit and git push:
| Hook | What it checks |
|---|---|
shellcheck |
Shell script correctness (warnings and above) |
shfmt |
Shell script formatting (-i 4 -ci) |
prettier |
JSON, YAML, and Markdown formatting |
markdownlint |
Markdown style rules |
check-json |
JSON syntax validity |
check-yaml |
YAML syntax validity |
trailing-whitespace |
No trailing whitespace |
detect-private-key |
No accidentally committed secrets |
no-commit-to-branch |
Blocks direct commits to main and develop |
Running manually:
pre-commit run --all-files # check everything
pre-commit run prettier # check one hook
pre-commit run --files src/claude-code/install.sh # check one fileIf a hook fails: fix the flagged issue and git add the changes before retrying.
Prettier and shfmt auto-fix in place — just stage the result. ShellCheck and markdownlint
report what to fix but won't rewrite your code.
When develop is ready for release, use the Advance main workflow:
- Go to Actions → Advance main → Run workflow
- The workflow fast-forwards
mainto the current tip ofdevelopvia the GitHub API (no merge commit is created) - It verifies that
mainanddeveloppoint to the same SHA before completing
-
Update the
versionfield insrc/claude-code/devcontainer-feature.jsonas part of the work merged todevelop— this must be done before tagging, as the release workflow validates that the tag version matches the JSON -
Advance
mainusing the workflow above -
Tag the release from the updated
main:git checkout main git pull origin main git tag v<VERSION> git push origin v<VERSION>
-
The
v*tag push triggers the Release workflow, which:- Runs ShellCheck validation
- Smoke-tests against 3 representative base images
- Verifies the tag version matches
devcontainer-feature.json - Publishes the feature to
ghcr.io/pkramek/claude-devcontainer/claude-code - Verifies the published feature is accessible
Tags are protected — no deletion or force-push.
For critical fixes that cannot wait for the normal develop cycle:
- Create a
hotfix/*branch frommain - Make the fix and open a PR targeting
main— the source-branch-check CI allowshotfix/*to bypass thedevelop-only gate - After the hotfix merges to
main, tag and release as described above - Open a second PR from
hotfix/*(or frommain) todevelopto keep the branches in sync
After the first tag push, the GHCR package is created as private. To make it public:
- Go to the repository's Packages tab
- Click the
claude-codepackage → Package settings - Under Danger Zone, change visibility to Public