Skip to content

feat(runner): take --workspace-id on every runner command - #1647

Open
Luke Parr (lukecparr) wants to merge 1 commit into
mainfrom
luke/runner-workspace-id
Open

Luke Parr (lukecparr) wants to merge 1 commit into
mainfrom
luke/runner-workspace-id

Conversation

@lukecparr

@lukecparr Luke Parr (lukecparr) commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator

This came from a request I made in Slack to support QAE tooling. Jon suggested I open a PR.

Overview of Changes

Every qawolf runner command now takes --workspace-id <id>. It applies to that one command and is never saved. Until now the only way to pick a workspace was qawolf auth switch, which saves it to the one token store every session on the machine reads. QAEs are moving their tooling onto qawolf runner and often have several Claude sessions open on different customers, so single-session switching sends the next runner command in every other session to the wrong workspace.

The API already supports this, every runner contract takes workspaceId, and the client only fills in the saved one when a call doesn't send its own. So the change is CLI-only: withAuthContext takes an optional workspace that wins over the saved one, and runner commands pass it through a small withRunnerContext wrapper.

The flag lives on the runner group rather than only on launch, run and terminate. Runner ids are scoped to a team, so a runner launched with --workspace-id is only reachable by commands that pass the same id. Leaving the flag off act or screenshot would send them looking in the saved workspace. Because the flag is on the group, a new runner sub-command gets it too, and a lint rule stops runner register files from importing withAuthContext directly, which would accept the flag and quietly ignore it.

A blank --workspace-id is refused. Without that check it would send no workspace at all instead of falling back to the saved one. Without the flag nothing changes. With an org or user API key, which saves no workspace, the flag gives it one.

help.test.ts used to replace each command's help config to set the width, which hid showGlobalOptions. It now merges, so the runner snapshots show what users actually see. That's most of the snapshot diff.

Testing

bun run typecheck
bun run lint
bun run format:check
bun run knip
bun run test
bun run build

New tests in runner/context.test.ts cover the flag before and after the subcommand, falling back to the saved workspace, a credential with no saved workspace, trimming, refusing a blank id, and the flag showing in every runner subcommand's help. Reverting the one-line precedence change in withAuthContext fails 5 of them. I also checked the lint guard by adding a withAuthContext import to a runner register file.

Smoke tested against prod with a team API key, read-only: qawolf runner list --workspace-id not-a-real-workspace comes back HTTP 400 ... Invalid ID format for kind at "workspaceId", so the flag reaches the request. Passing the key's own team id lists the same runners as no flag. Not yet tested with a browser session across two workspaces.

Checklist

  • Changes follow the code style of this project
  • Self-review completed
  • Tests added/updated (or not applicable)
  • No breaking changes (or described below)

The only way to pick a runner's workspace was `qawolf auth switch`, which
saves it for every session on the machine. Two sessions working on
different customers moved each other's next runner command to the wrong
workspace.

`--workspace-id` is declared once on the `runner` group, so every runner
subcommand takes it, and it is never saved. A lint rule keeps runner
commands on `withRunnerContext` so a new one can't accept the flag and
ignore it.

This branch has not been deployed

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

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants