Summary
In a proxied remote session (Claude Code Cloud), an agent running a release hit a 403
pushing a v* tag, concluded it was an organization egress denial, and stopped the
release one step from done. The knowledge needed to resolve it was already in
tbd shortcut setup-github-cli under "Proxied Remote Sessions" — accurately, including
the exact symptom. The agent never opened it.
The shortcut is not the problem. The bootstrap surfaces a pointer to it at the one
moment it has already empirically proven the underlying fact.
What the bootstrap already knows
ensure-gh-cli.sh (as generated by tbd 0.7.1) reaches this branch only after
establishing two things at SessionStart:
HTTPS_PROXY is set, and
gh auth status succeeds on the direct channel with a scoped NO_PROXY.
That is precisely "the proxy intercepts GitHub, and direct egress is open" — the
condition under which the ref-scoped broker matters. It then prints:
[gh] GH_TOKEN is VALID, but this session's proxy intercepts GitHub API calls
[gh] To use gh in this session, bypass the proxy for GitHub hosts only
[gh] export NO_PROXY="api.github.com,github.com,..."
[gh] Details: tbd shortcut setup-github-cli (Proxied Remote Sessions)
The recipe is stated. The consequence is a pointer. .claude/skills/tbd/SKILL.md does
the same thing:
Remote/proxied session where GitHub seems blocked? … run
tbd shortcut setup-github-cli and follow "Proxied Remote Sessions" before concluding
gh is unavailable.
In practice the agent consumed the exports from the hook output, used gh successfully
all session, and never had a reason to open the shortcut — until a failure whose cause
was documented only inside it.
Why a pointer loses
At the moment of failure, two authoritative-sounding sources say the opposite, and both
are topically on point:
- The remote session's own system prompt: "You do NOT have access to the
gh CLI,
hub CLI, or direct GitHub API access. Instead, use the GitHub MCP server tools."
- The session proxy's README (
/root/.ccr/README.md): "403 / 407 from the proxy — The
destination host is not allowed by your organization's egress policy for this session.
Do not retry or route around it — report the blocked host."
The shortcut anticipates both of these explicitly, which is exactly why it works when
read. But an unread pointer cannot compete with two documents that are already in
context and appear to settle the question. A stated fact can.
Two further signals actively reinforced the wrong conclusion:
git push --dry-run origin v0.2.1 passed (the broker refuses at receive-pack,
after ref advertisement). The shortcut documents this; unread, it reads as
"the server would accept this, so the denial is upstream policy."
- The proxy's own status endpoint reported
recentRelayFailures: [] — no egress
failure recorded. This contradicted the egress-denial theory and was still not
enough to overturn it without the broker model to explain what else could 403.
Proposal
1. ensure-gh-cli.sh: state the consequence where the condition is proven.
In the existing proxy-detected branch, after the NO_PROXY recipe, add the operational
facts rather than a pointer:
[gh] This session's git remote may use a ref-scoped credential broker:
[gh] - pushes to refs/heads/* succeed; pushes to refs/tags/* fail with HTTP 403.
[gh] - `git push --dry-run` PASSES for tags the broker later refuses; it proves nothing.
[gh] - create tags on the direct channel instead:
[gh] gh api repos/OWNER/REPO/git/refs -f ref=refs/tags/vX.Y.Z -f sha=SHA
[gh] - a GitHub-host 403 with NO x-github-request-id header is proxy-manufactured,
[gh] not an egress denial. Run the egress test before reporting a block.
[gh] Details: tbd shortcut setup-github-cli (Proxied Remote Sessions)
This costs nothing in non-proxied sessions (the branch does not run) and puts the fact
in the agent's context from turn one, where it can compete with the contradicting
sources above.
2. SKILL.md: carry the two load-bearing facts, not just the referral.
Replace the current referral with something self-sufficient — tags 403 through the
broker, gh api .../git/refs is the remedy — keeping the pointer for the full
treatment.
3. Optional: teach tbd doctor the channel model.
tbd doctor is the natural place to run the egress test and report which channels are
live (broker: branches only; direct: open/closed), so an agent debugging a push failure
has a first-class command to ask instead of inferring from proxy docs.
The general pattern
Where the bootstrap has established a fact about the session, it should state the
operational consequence inline. A pointer is the right shape for background; it is the
wrong shape for a fact that will be contradicted by other documents at the moment it is
needed. This applies beyond gh: any hook that probes the environment and learns
something surprising is the cheapest possible place to put that knowledge, because it
lands in context before the agent forms a wrong model.
Context
Observed in jlevy/tryscript releasing v0.2.1, tbd 0.7.1, Claude Code Cloud. The
release completed once the shortcut was read: tag created via
gh api repos/jlevy/tryscript/git/refs, workflow published to npm with provenance.
Generated by Claude Code
Summary
In a proxied remote session (Claude Code Cloud), an agent running a release hit a
403pushing a
v*tag, concluded it was an organization egress denial, and stopped therelease one step from done. The knowledge needed to resolve it was already in
tbd shortcut setup-github-cliunder "Proxied Remote Sessions" — accurately, includingthe exact symptom. The agent never opened it.
The shortcut is not the problem. The bootstrap surfaces a pointer to it at the one
moment it has already empirically proven the underlying fact.
What the bootstrap already knows
ensure-gh-cli.sh(as generated by tbd 0.7.1) reaches this branch only afterestablishing two things at SessionStart:
HTTPS_PROXYis set, andgh auth statussucceeds on the direct channel with a scopedNO_PROXY.That is precisely "the proxy intercepts GitHub, and direct egress is open" — the
condition under which the ref-scoped broker matters. It then prints:
The recipe is stated. The consequence is a pointer.
.claude/skills/tbd/SKILL.mddoesthe same thing:
In practice the agent consumed the exports from the hook output, used
ghsuccessfullyall session, and never had a reason to open the shortcut — until a failure whose cause
was documented only inside it.
Why a pointer loses
At the moment of failure, two authoritative-sounding sources say the opposite, and both
are topically on point:
ghCLI,hubCLI, or direct GitHub API access. Instead, use the GitHub MCP server tools."/root/.ccr/README.md): "403 / 407 from the proxy — Thedestination host is not allowed by your organization's egress policy for this session.
Do not retry or route around it — report the blocked host."
The shortcut anticipates both of these explicitly, which is exactly why it works when
read. But an unread pointer cannot compete with two documents that are already in
context and appear to settle the question. A stated fact can.
Two further signals actively reinforced the wrong conclusion:
git push --dry-run origin v0.2.1passed (the broker refuses at receive-pack,after ref advertisement). The shortcut documents this; unread, it reads as
"the server would accept this, so the denial is upstream policy."
recentRelayFailures: []— no egressfailure recorded. This contradicted the egress-denial theory and was still not
enough to overturn it without the broker model to explain what else could 403.
Proposal
1.
ensure-gh-cli.sh: state the consequence where the condition is proven.In the existing proxy-detected branch, after the
NO_PROXYrecipe, add the operationalfacts rather than a pointer:
This costs nothing in non-proxied sessions (the branch does not run) and puts the fact
in the agent's context from turn one, where it can compete with the contradicting
sources above.
2.
SKILL.md: carry the two load-bearing facts, not just the referral.Replace the current referral with something self-sufficient — tags 403 through the
broker,
gh api .../git/refsis the remedy — keeping the pointer for the fulltreatment.
3. Optional: teach
tbd doctorthe channel model.tbd doctoris the natural place to run the egress test and report which channels arelive (broker: branches only; direct: open/closed), so an agent debugging a push failure
has a first-class command to ask instead of inferring from proxy docs.
The general pattern
Where the bootstrap has established a fact about the session, it should state the
operational consequence inline. A pointer is the right shape for background; it is the
wrong shape for a fact that will be contradicted by other documents at the moment it is
needed. This applies beyond gh: any hook that probes the environment and learns
something surprising is the cheapest possible place to put that knowledge, because it
lands in context before the agent forms a wrong model.
Context
Observed in
jlevy/tryscriptreleasing v0.2.1, tbd 0.7.1, Claude Code Cloud. Therelease completed once the shortcut was read: tag created via
gh api repos/jlevy/tryscript/git/refs, workflow published to npm with provenance.Generated by Claude Code