fix(cli): relay init keeps the machine-wide active workspace

Merged
KH
1d ago
+363-12

Problem

relay init saved its workspace via persistWorkspaceSession({ name, workspaceKey }), which always calls switchWorkspace(name). On a machine already using another workspace (e.g. active = "ghsub-live" read by a fleet node's start script), running relay init in any project silently moved the whole machine to the new local workspace.

Change

  • persistWorkspaceSession gains activate?: 'always' | 'if-none' (default 'always') and reports keptActiveWorkspace when it leaves another workspace active. 'if-none' activates only when there is no active workspace, the active name has no saved entry, or the active workspace is the one being (re)selected.
  • relay init uses 'if-none' on every path: local (default), --hosted, --url/--key, and the guided wizard (all go through setupServer). The workspace is still saved under its name and bound to the project (.agentworkforce/relay/workspace-key.json). When another workspace stays active, init prints:
    This project now uses workspace "local"; "ghsub-live" stays active machine-wide. To make "local" the default everywhere, run: relay workspace switch local
  • Other callers are unchanged: workspace join/create/switch/restore and MCP create_workspace are explicit selections that are meant to switch; local-agent and MCP rebind pass no name.

Resolution after init

Verified on main: resolveWorkspaceSelection checks --workspace-key → env → project pin → global active, and agent register, message ... (resolveWorkspaceTransport) and relay mcp (resolveWorkspaceSessionKey) all use it. So no resolver change was needed; a new test runs relay init then relay agent register alice and asserts the transport is the local key at http://127.0.0.1:8787 with source project, while active stays ghsub-live.

Tests

  • workspace-session.test.ts: if-none on fresh machine (active set), different active (kept, project pinned, resolves to new key), re-selecting the active workspace, dangling active name.
  • init.test.ts: fresh machine → active set; existing different active → unchanged + message; re-run → idempotent; --hosted; --url/--key; guided flow; init then agent register uses the project workspace.
  • npx vitest run packages/cli: 2432 passed. npx tsc --noEmit -p packages/cli: clean.

End-to-end (isolated AGENT_RELAY_HOME / AGENT_RELAY_INSTALL_DIR)

Pre-seeded workspaces.json with active: "ghsub-live" (dummy key). Built relay init --yes --tools none --port 8799: downloaded engine, started server, printed the kept-active line; active stayed ghsub-live, local added, project workspace-key.json == local key. relay agent register alice / bob, relay message dm send bob ... --as alice, relay message inbox check --as bob showed the unread DM. Re-running init left the store unchanged; relay init --stop stopped the server.

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Agent Relay sessions

  • claude session a7f8c11e · opened via gh pr create · last active 2026-10-27
  • claude session 5a4f854b · contributor · ran gh pr commands · last active 2026-10-28