Skip to content

feat(coder/agent-relay-cursor)!: make additional_args a list of strings - #1206

Merged
matifali merged 3 commits into
mainfrom
claude/agent-relay-cursor-args-list
Oct 23, 2026
Merged

matifali merged 3 commits into
mainfrom
claude/agent-relay-cursor-args-list

Conversation

@matifali

Copy link
Copy Markdown
Member

Description

Changes additional_args, added in v0.6.0 (coder/registry#1199), from a map(string) of flag to value into a list(string) with one element per argument. coder/registry#1205 makes the same change to agent-relay-claude-code.

Why: a map can't repeat a flag, as 35C4n0r pointed out on coder/registry#1202. Worse, Terraform doesn't reject a repeated key: { "--header" = "a", "--header" = "b" } silently becomes { "--header" = "b" }. A list also reads like the command line and keeps the order you write.

module "cursor_worker" {
  source          = "registry.coder.com/coder/agent-relay-cursor/coder"
  version         = "0.7.0"
  agent_id        = coder_agent.main.id
  additional_args = ["--some-flag", "value", "--some-flag", "another value", "--another-flag"]
}
  • Verbatim, in order: each element is passed to agent worker as exactly one argument, in the order written, after the flags the module sets and before the start subcommand. As before, it's base64-encoded into the start script and shell-quoted with printf %q into the supervisor.
  • Validation: elements must be non-empty and must not contain newlines.
  • Flags the module sets are still rejected: --pool, --idle-release-timeout, --auth-token-file, --auth-token, --computer-use, --share-desktop. Each element is checked with any =value stripped, so --pool=x is caught too. The keep-in-sync comments are unchanged.
  • The README still warns that a flag with an optional value should be given --flag=value, so it doesn't consume start.

Type of Change

  • New module
  • New template
  • Bug fix
  • Feature/enhancement
  • Documentation
  • Other

Module Information

Path: registry/coder/modules/agent-relay-cursor
New version: v0.7.0
Breaking change: [x] Yes [ ] No — additional_args changes type from map(string) to list(string). To migrate, rewrite { "--flag" = "value", "--bare" = "" } as ["--flag", "value", "--bare"]. The module is pre-1.0, so this ships as a minor bump; v0.6.0 has only been out a few hours, and its tag is left as it is.

Testing & Validation

  • Tests pass: terraform test, 16 passed. Updated: empty default; base64 encoding of a repeated flag in order; rejecting a newline; rejecting --pool=2.
  • Container test in main.test.ts updated to cover a repeated flag with spaces and quotes, with start last. It can't run here because the runner has no Docker daemon.
  • Code formatted (bun fmt); ./scripts/terraform_validate.sh passes
  • Changes tested locally: rendered the start script with terraform console and ran it against a stub agent. The argv was worker --pool p --idle-release-timeout 600 --auth-token-file … --name <two words $HOME \id`> --name <it's "q"> --verbose start`, with each element unchanged and in order.

Related Issues

Follows up the review on coder/registry#1202.


Generated by Claude Code

matifali and others added 2 commits October 23, 2026 03:03
additional_args was a map of flag to value, which cannot repeat a flag:
a repeated key silently keeps only the last value. It is now a list with
one element per argument, passed in order before `start`, so a flag can
repeat. Flags the module sets are still rejected, with or without =value.

BREAKING CHANGE: additional_args changes type from map(string) to
list(string). Rewrite { "--flag" = "value" } as ["--flag", "value"].

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R2TMgCPW8SL8kUCB28L4dt
…gs test

Rewriting the additional_args container test left the tail of the old
test behind, a syntax error that failed both the format and TypeScript
checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R2TMgCPW8SL8kUCB28L4dt
@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Module Scorecard Check

coder/agent-relay-cursor: 58 → 66

✅ Score improvement: 58 → 66 (+8).

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

Presentation & Onboarding — 12 / 17

Criterion Max Score Notes
Configuration-mode examples 12 12 Main example shows default (install_cli = true); README comment documents install_cli = false for baked-in CLI; additional_args has its own Terraform example; computer_use and share_desktop are documented in the Requirements section with prerequisites and image requirements. All major modes have sensible defaults and are documented.
Visual preview 5 0 No image, GIF, or video embedded in the README. The frontmatter icon field is a registry listing icon, not a visual preview of the module in action.

Credential Hygiene — 20 / 20

Criterion Max Score Notes
Secrets marked sensitive 16 16 agent_relay_credential is declared with ephemeral = true and mask_input = true in styling. README states "the credential is masked." No README example inlines a literal or placeholder secret; the main example only shows agent_id and install_cli.
Non-hardcoded auth path 4 4 The "Worker credential" section documents that the pool's service-account API key never leaves Agent Relay; Cursor mints a per-claim session token that is stamped as an ephemeral parameter. The user never pastes a raw key into the template.

Restricted-Environment Readiness — 13.5 / 20

Criterion Max Score Notes
Mirrorable artifact source 5 0 The install URL https://cursor.com/install is hardcoded in install.sh.tftpl. No module input variable overrides this download URL. cli_binary overrides the binary path, not the source URL; install_cli is a skip-install toggle, not a mirror override.
Bring-your-own binary 10 10 install_cli = false (documented in README: "Bake the CLI into the image and set this to false for faster workspaces") disables the download entirely. The install script checks command -v and skips if the binary is already on PATH. The README explicitly recommends baking the CLI into the image as the fastest path.
Egress transparency 3 1.5 No dedicated network/air-gapped/offline README section. The install URL (cursor.com/install) appears in the install_cli variable description and the install script; app URLs (cursor.com/agents/, cursor://anysphere.cursor-deeplink/) appear in the main README section. These are scattered mentions without a consolidated endpoint enumeration or restricted-environment notes.
Runs without sudo 2 2 install.sh.tftpl installs to ~/.local/bin via curl | bash (no sudo). start.sh.tftpl writes to $HOME/.coder-modules/... (no sudo). status.sh.tftpl only reads files. No script invokes sudo.

Engineering Quality — 10 / 10

Criterion Max Score Notes
Input quality 6 6 All 9 module variables have clear descriptions and sensible defaults. cli_binary has a regex validation rejecting shell metacharacters. share_desktop validates that computer_use is true. serving_log_pattern rejects empty strings. additional_args rejects empty elements, newlines, and reserved flags (--pool, --idle-release-timeout, --auth-token-file, etc.).
Test coverage 4 4 main.tftest.hcl (14 test runs) covers the parameter contract (names, ephemeral flags, styling/masking), worker wiring (env var names, script content, coder-utils ordering), and all flag combinations. main.test.ts (15+ test cases) exercises the actual install/start scripts in containers with a stub agent binary, verifying supervisor lifecycle (idle, working, serving, done, failed, orphaned), token file handling, shell-injection resistance, and restart idempotency.

Agent Integration — 5 / 25

Criterion Max Score Notes
AI governance 10 0 No mention of Coder AI Gateway or Agent Firewall in the README or code. The credential path is Agent Relay → Cursor session token, but there is no documented AI Gateway routing or Agent Firewall policy enforcement.
Dashboard entry point 5 5 Two coder_app resources are declared: cursor_web ("Open in Cursor Web" → https://cursor.com/agents/<id>) and cursor_desktop ("Open in Cursor Desktop" → cursor://anysphere.cursor-deeplink/...). Both are conditional on agent_relay_session_id being set and are documented in the README.
Session continuity 5 0 The README documents worker process restart idempotency (re-running the start step leaves a live worker alone), but does not document resuming a Cursor agent session across reconnects or using a persistent session manager (tmux, screen, boo). Session continuity is handled externally by Agent Relay/Cursor, not by this module.
Managed configuration 5 0 No documentation of managed MCP servers, settings, policies, or workdir configuration. The module's scope is running the Cursor CLI worker; it does not configure Cursor's agent settings or MCP.

Overall — 66 / 100

Raw 60.5 / 92 → round(60.5 / 92 × 100) = 66

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 requested review from 35C4n0r and dluman October 23, 2026 06:06
@matifali
matifali merged commit 55c2d00 into main Oct 23, 2026
5 checks passed
@matifali
matifali deleted the claude/agent-relay-cursor-args-list branch October 23, 2026 10:51
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.

2 participants