| name | test-git-auth |
| description | Verify that git push and the gh CLI work (authenticated). Creates a throwaway branch with an empty commit, pushes it, verifies the push, then deletes the branch locally and remotely. Also fetches recent CI run logs via gh to confirm gh auth. |
| compatibility | Requires git remote named "origin" and gh CLI installed and authenticated. Works inside bwrap-claude.sh --with-git or bwrap-pi.sh --with-git. |
| allowed-tools | Bash |
Purpose
Smoke-test that SSH/HTTPS credentials and the gh CLI are properly forwarded into the sandbox. Run this after launching the sandboxed agent with --with-git to confirm everything works before starting real work.
Steps
Phase 0 โ pre-flight checks
Run each check with a single Bash call and collect results before doing anything else. Never abort early โ complete all checks so the report is complete.
-
SSH directory โ check visibility:
ls ~/.ssh 2>&1
- Pass: directory exists and contains at least one file.
- Fail:
No such file or directory โ ~/.ssh was not bound into the sandbox.
-
SSH keys โ check at least one private key is present:
ls ~/.ssh/id_* ~/.ssh/*.pem 2>&1 | grep -v '.pub'
- Pass: one or more key files found.
- Fail: no private keys โ keys exist on the host but none of the standard names were matched, or
~/.ssh is missing.
-
SSH agent socket โ check SSH_AUTH_SOCK and connectivity:
echo "SSH_AUTH_SOCK=${SSH_AUTH_SOCK:-<unset>}" && [ -n "${SSH_AUTH_SOCK:-}" ] && ssh-add -l 2>&1 || true
- Pass:
SSH_AUTH_SOCK is set and ssh-add -l lists at least one identity (or says "The agent has no identities" โ socket reachable but empty is still OK).
- Fail: variable unset, or socket path not accessible, or
ssh-add errors with "Could not open a connection".
-
git global config โ check visibility:
git config --global --list 2>&1 | head -5
- Pass: prints at least
user.name or user.email.
- Fail:
fatal: unable to read config or empty output โ ~/.gitconfig / ~/.config/git/config not bound.
-
gh CLI binary โ check it is on PATH:
which gh && gh --version 2>&1
- Pass: path printed and version shown.
- Fail:
not found โ gh not installed on the host or its location is not accessible inside the sandbox.
-
gh auth token โ check authentication state:
gh auth status 2>&1
- Pass: output contains
Logged in to github.com.
- Fail:
not logged into or No token โ ~/.config/gh was not bound (missing --with-git) or the host is not authenticated.
After all six checks, produce a pre-flight table (see Phase 4 report format) and decide whether to continue:
- If checks 1โ4 all pass โ proceed with git push test.
- If checks 5โ6 pass โ proceed with gh test.
- If any check fails โ still attempt the corresponding test (the error may be a false alarm), but highlight the failure in the report with a
โ did you forget --with-git? hint for any check that maps directly to a missing bind.
Phase 1 โ git push
-
Record the starting branch:
git branch --show-current
Save the output as ORIGINAL_BRANCH. If the repo is in detached HEAD state, save the SHA instead (git rev-parse HEAD).
-
Choose a unique branch name of the form test-git-auth-<epoch-seconds>:
date +%s
Combine to get e.g. test-git-auth-1718123456.
-
Create and switch to the new branch:
git checkout -b test-git-auth-<timestamp>
-
Create an empty commit (no working-tree changes needed):
git commit --allow-empty -m "chore: test-git-auth smoke test โ delete me"
-
Push the branch to origin:
git push origin test-git-auth-<timestamp>
If this fails, report the error and proceed to cleanup โ do not abort.
-
Confirm the push succeeded by checking the remote tracking ref:
git ls-remote origin refs/heads/test-git-auth-<timestamp>
A non-empty result means the branch is live on the remote.
Phase 2 โ cleanup
-
Switch back to the original branch (or detach to the original SHA):
git checkout <ORIGINAL_BRANCH>
-
Delete the local branch:
git branch -D test-git-auth-<timestamp>
-
Delete the remote branch:
git push origin --delete test-git-auth-<timestamp>
If the push in step 5 failed the remote branch does not exist; skip this step silently.
-
Confirm remote deletion:
git ls-remote origin refs/heads/test-git-auth-<timestamp>
The output should be empty.
Phase 3 โ gh CLI
-
Determine the repository slug from the remote URL:
gh repo view --json nameWithOwner -q .nameWithOwner
This also implicitly validates that gh is authenticated; if it fails, report the error and stop.
-
List the five most recent CI workflow runs (read-only):
gh run list --limit 5
Show the output to the user โ workflow name, status, branch, and elapsed time.
Phase 4 โ report
Summarise the outcome:
## git-auth test results
### Pre-flight checks
| # | Check | Result | Note |
|---|--------------------|--------|------|
| 1 | ~/.ssh visible | โ / โ | <detail or "โ did you forget --with-git?"> |
| 2 | SSH private key | โ / โ | <filenames found or "none found"> |
| 3 | SSH agent socket | โ / โ | <SSH_AUTH_SOCK value or "unset / unreachable"> |
| 4 | git global config | โ / โ | <user.name value or "โ did you forget --with-git?"> |
| 5 | gh binary on PATH | โ / โ | <version or "not found"> |
| 6 | gh authenticated | โ / โ | <account or "โ did you forget --with-git?"> |
### git push
- Branch created: test-git-auth-<timestamp>
- Push: โ succeeded / โ failed: <error>
- Remote deleted: โ confirmed / โ skipped (push failed)
### gh CLI
- Repo: <owner>/<repo>
- Recent CI runs:
<table from gh run list>
Checks 1, 4, and 6 map directly to missing --with-git binds. If any of them fail, add a prominent note:
Likely cause: the sandbox was started without --with-git. Re-launch with:
pixi run -e claude claude --with-git
# or
pixi run -e pi pi <dir> --with-git
For check 3, if SSH_AUTH_SOCK is set but the socket is under /tmp/ and unreachable, note that bwrap-claude.sh --with-git only auto-binds sockets under /tmp/ when detected at launch time โ the socket path visible outside may differ from the one inside the sandbox.