Skip to content

Bootstrap states the NO_PROXY recipe but only points at the ref-scoped broker consequence #255

Description

@jlevy

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:

  1. HTTPS_PROXY is set, and
  2. 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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions