Repository navigation
feat(coder/agent-relay-cursor)!: make additional_args a list of strings - #1206
Merged
Merged
Conversation
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
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R2TMgCPW8SL8kUCB28L4dt
3 of 9 tasks
…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
Contributor
Module Scorecard Check
|
| 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.
35C4n0r
approved these changes
Oct 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Changes
additional_args, added in v0.6.0 (coder/registry#1199), from amap(string)of flag to value into alist(string)with one element per argument. coder/registry#1205 makes the same change toagent-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.agent workeras exactly one argument, in the order written, after the flags the module sets and before thestartsubcommand. As before, it's base64-encoded into the start script and shell-quoted withprintf %qinto the supervisor.--pool,--idle-release-timeout,--auth-token-file,--auth-token,--computer-use,--share-desktop. Each element is checked with any=valuestripped, so--pool=xis caught too. The keep-in-sync comments are unchanged.--flag=value, so it doesn't consumestart.Type of Change
Module Information
Path:
registry/coder/modules/agent-relay-cursorNew version:
v0.7.0Breaking change: [x] Yes [ ] No —
additional_argschanges type frommap(string)tolist(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
terraform test, 16 passed. Updated: empty default; base64 encoding of a repeated flag in order; rejecting a newline; rejecting--pool=2.main.test.tsupdated to cover a repeated flag with spaces and quotes, withstartlast. It can't run here because the runner has no Docker daemon.bun fmt);./scripts/terraform_validate.shpassesterraform consoleand ran it against a stubagent. The argv wasworker --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