Skip to content

feat(agent-relay-claude-code): support Anthropic-managed git - #1144

Draft
matifali wants to merge 1 commit into
matifali/agent-relay-claude-code-graceful-shutdownfrom
matifali/agent-relay-claude-code-git-proxy
Draft

matifali wants to merge 1 commit into
matifali/agent-relay-claude-code-graceful-shutdownfrom
matifali/agent-relay-claude-code-git-proxy

Conversation

@matifali

@matifali matifali commented Sep 24, 2026 •

Copy link
Copy Markdown
Member

Stacked on #1143 — base that, not main. Both touch the same four files, so a PR off main would conflict in all of them. Review #1143 first.

Relates to RELAY-26 (Claude Tag service session identities).

Why

use_anthropic_git_proxy authenticates clones server-side, so the workspace holds no git credentials. A session a person created uses their GitHub OAuth token; one a bot or agent created uses the organization's GitHub App installation token.

That second path is the only git auth that can work when the workspace owner is a service account. It has login_type = "none" and can never sign in, so it can never complete the OAuth flow a coder_external_auth block depends on — not a configuration problem, a dead end.

This is reachable today, not hypothetical: Agent Relay creates each workspace as the resolved session owner (CreateUserWorkspace(ctx, req.Owner.UserID…)), so a service-session identity lands here directly.

Policy is the template's, not the module's

The flag serves human and bot sessions alike, so the module defaults it off and takes no position. A template can gate it:

use_anthropic_git_proxy = data.coder_workspace_owner.me.login_type == "none"

or simply enable it everywhere. Both are documented.

On the detection: login_type == "none" is the indicator of a service-account owner, and coderd enforces that equivalence at creation in both directions — a service account may not use another login type, and login_type: none without service_account is rejected with "Login type 'none' requires a service account." The only runtime mutation path, UpdateUserLoginType, is the OIDC conversion flow, which requires the user to authenticate first and so can never apply to a none user.

Paired with the identity, overridable

configure_git defaults to following the proxy. The proxy replaces the HOME git config with credential settings only, so enabling it alone leaves no user.name/user.email and commits fail. Both overrides are supported and tested:

configure_git = false # image keeps its identity in /etc/gitconfig, which the proxy does not touch
configure_git = true  # sign commits as Claude without the proxy

Testing

terraform test: 16 pass, including that both flags are off by default, that the identity follows the proxy, and both override directions. bun test: 16 pass.

Note for reviewers

The flag is destructive by design — at startup and before every session the runner deletes ~/.gitconfig, the GIT_CONFIG_GLOBAL target and all of $XDG_CONFIG_HOME/git, with no backup. That isolation is the point for an ephemeral single-session workspace, and it is why it defaults off and the README says not to enable it on a workspace a person also works in. I have not exercised it against a live Anthropic-managed clone; that needs a pool credential.

Version: the bump stays 0.2.0 here because #1143 is unmerged, so the version-bump check sees one minor bump against main. Once #1143 lands and is tagged, this rebases onto main and becomes 0.3.0.

Generated with Claude Code using Claude Opus 4.5.

@linear-code

linear-code Bot commented Sep 24, 2026

Copy link
Copy Markdown

RELAY-26

@matifali
matifali force-pushed the matifali/agent-relay-claude-code-git-proxy branch from 1df0357 to 055232a Compare September 24, 2026 15:27
@github-actions

github-actions Bot commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Module Scorecard Check

coder/agent-relay-claude-code: 72 → 58

⚠️ Score regression: 72 → 58 (-14). Check the drilldown for which criteria dropped.

Theme Before After
Presentation & Onboarding 6 / 17 12 / 17
Integration 15 / 25 7.5 / 25
Credential Hygiene 20 / 20 12 / 20
Restricted-Environment 17 / 20 12 / 20
Engineering Quality 8 / 10 10 / 10
Overall 72 / 100 58 / 100
Full scorecard for this PR
Presentation & Onboarding Agent Integration Credential Hygiene Restricted-Environment Readiness Engineering Quality Overall
12 / 17 7.5 / 25 12 / 20 12 / 20 10 / 10 58 / 100
Drilldown

Track: Agent (self-hosted Claude Code CLI runner dispatched by Agent Relay)

Presentation & Onboarding — 12 / 17

Criterion Max Score Notes
Configuration-mode examples 12 12 README documents multiple real configuration modes with sensible defaults and code snippets: default download vs. bake-in-image (install_cli), the two use_anthropic_git_proxy/configure_git combinations, env-var passthrough (SELF_HOSTED_RUNNER_HOOKS_DIR example), and graceful-shutdown wiring (destroy_grace_seconds). Thorough for the module's scope.
Visual preview 5 0 No image, GIF, or video anywhere in the README.

Credential Hygiene — 12 / 20

Criterion Max Score Notes
Secrets marked sensitive 16 8 agent_relay_credential is ephemeral = true and masked via styling = { mask_input = true }, not the literal sensitive = true attribute the rubric asks for. README never shows inline secret values (placeholder-only UX), so the "no inline secrets in examples" half is met, but the masking mechanism itself diverges from the named criterion → half credit.
Non-hardcoded auth path 4 4 use_anthropic_git_proxy is documented as a server-side auth path (OAuth token for humans, GitHub App installation token for bots) so the workspace never holds raw git credentials — clearly documented with rationale and a login_type == "none" example.

Restricted-Environment Readiness — 12 / 20

Criterion Max Score Notes
Mirrorable artifact source 5 0 install.sh.tftpl hardcodes curl https://claude.ai/install.sh -fsSL | bash. No variable overrides this URL (cli_binary only selects the binary path/name, not the download source).
Bring-your-own binary 10 10 install_cli = false is explicitly documented ("Bake the CLI into the image and set this to false for faster workspaces"), with the start script falling back to ~/.local/bin or cli_binary cleanly — a fully working, documented BYO path.
Egress transparency 3 0 No dedicated network/offline/air-gapped section enumerating endpoints (claude.ai, Anthropic API, git remotes, Agent Relay). Endpoints are only inferable from scattered prose.
Runs without sudo 2 2 install.sh.tftpl, start.sh.tftpl, and stop.sh.tftpl never invoke sudo; all operations (curl, mkdir, setsid, kill) run as the unprivileged agent user.

Engineering Quality — 10 / 10

Criterion Max Score Notes
Input quality 6 6 Every variable has a detailed description with rationale; sensible defaults throughout; validation blocks on cli_binary (shell-metachar guard), exit_if_unused_min, and drain_wait_sec (whole-number guards).
Test coverage 4 4 Extensive .tftest.hcl covering parameter contract, script rendering, shutdown-budget math, and injection safety, plus a full TypeScript main.test.ts exercising install/start/stop lifecycle end-to-end in a container (idle, working, done, failed, orphaned states, SIGTERM drain, pid-recycle guard).

Agent Integration — 7.5 / 25

Criterion Max Score Notes
AI governance 10 0 No mention of Coder AI Gateway or Agent Firewall anywhere in the README; this module integrates with Anthropic's own Agent Relay dispatch system, not Coder's governance layer.
Dashboard entry point 5 0 No coder_app resource or documentation of a dashboard entry point; only a coder_agent metadata item (agent_relay_status) is exposed.
Session continuity 5 2.5 README documents that push_outcome_on_release preserves commits so "a resumed session continues from them," but this is indirect (git-branch based, driven by Agent Relay/Anthropic infra) rather than a native resume flag or persistent session manager documented by the module itself — half credit.
Managed configuration 5 5 base_dir documents a configurable workdir; README shows a worked example of passing arbitrary settings through (SELF_HOSTED_RUNNER_HOOKS_DIR via coder_env), documenting managed workdir/config passthrough.

Overall — 58 / 100

Raw 53.5 / 92 → round(53.5 / 92 × 100) = 58

Tip

You can run this locally by telling your agent: "review this module against .github/scorecard/SCORECARD.md".


Scored against SCORECARD.md with solstice-1. Language-model scores are advisory.

@matifali
matifali force-pushed the matifali/agent-relay-claude-code-git-proxy branch 2 times, most recently from d2d0be4 to 39651ee Compare September 24, 2026 16:43
@matifali
matifali force-pushed the matifali/agent-relay-claude-code-graceful-shutdown branch from e257dfc to 64d87b2 Compare September 24, 2026 16:49
@matifali
matifali force-pushed the matifali/agent-relay-claude-code-git-proxy branch from 39651ee to 5ba03f0 Compare September 24, 2026 16:50
Add use_anthropic_git_proxy, which authenticates clones server-side so
the workspace holds no git credentials. A session a person created uses
their GitHub OAuth token; one a bot or agent created uses the
organization's GitHub App installation token.

That second path is the only git auth that works when the workspace
owner is a service account: it has login_type "none", can never sign in,
and so can never complete the OAuth flow a coder_external_auth block
depends on. Agent Relay creates each workspace as the resolved session
owner, so this is reachable today rather than hypothetical.

The module takes no position on when to enable it. The flag serves human
and bot sessions alike, so a template can gate it on the owner's
login_type or turn it on everywhere; both are documented.

Pair it with configure_git, defaulting to follow it. The proxy replaces
the HOME git config with credentials only, so enabling it alone leaves
no identity and commits fail. Set configure_git explicitly to override:
false for an image that keeps its identity in /etc/gitconfig, which the
proxy does not touch, or true to sign commits without the proxy.
@matifali
matifali force-pushed the matifali/agent-relay-claude-code-git-proxy branch from 5ba03f0 to ded9a4a Compare September 26, 2026 04:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant