A connector doing the work itself no longer caps how many workers run at once. Every request gets a worker as it arrives.
basecamp connect --max-workers N sets a cap for the operator who wants one: at most N workers run at once, and a request past the cap waits its turn.
Kept for the profile. Like the orchestrator, the worker and the permissions, a cap a start names is kept in runner.json (as max_workers), so --run starts with it.
Taking it off.--max-workers 0 removes a kept cap. A start that does not name the flag leaves the kept one alone, including one written into runner.json by hand.
Seeing it.basecamp connect workers list says "at most N at once" for a running connector that has a cap, and carries it as max_workers in its JSON.
Why
The runner ran at most four workers at once. Nobody chose that number, and the only way to change it was a hand edit to runner.json and a restart. The cap is now a control the operator reaches for, not a default everyone gets.
Behavior changes to know about
Existing connectors go from four at once to no cap when they update, unless their runner.json already has max_workers. The first start afterwards continues every worker a stop interrupted at once, not four at a time.
max_workers above 64 is accepted. It was refused before. With no cap as the default, a ceiling on the cap has nothing to protect.
A connector that is stopping starts no worker turn. A worker reaching its turn as the run ended could be started only to be stopped. Waiting for a place under the cap avoided that about half the time; with no cap it would have happened every time.
Worth a reviewer's attention
The cap is read once, at a start. I tried re-reading it as the connector runs, the way the rules and the permissions are, and dropped it: waiting workers lost their arrival order, and a file caught mid-save could lift the cap. For an optional setting that was not worth the machinery. The help, the skill and AGENTS.md say it is read at a start.
A flag given at the start wins again at basecamp connect restart, because a restart re-runs the original command line. A connector started with --max-workers 3 keeps 3 through a restart even if runner.json was edited in between. --permissions already behaves this way; the help text now says so for the cap.
The --shadow refusal named only the orchestrator and worker flags. It now names every flag that asks for the runner, this one included.
Verified
bin/ci on this branch.
Unit tests for: no cap by default (more than four workers at once), a cap from runner.json, a cap from the start over the file's, a start that takes the cap off, an edit during a run not changing the running cap, and the flag being kept, left alone and removed across starts.
The built binary refuses a value that is not a number, a negative one, and the flag with --shadow.
Not verified
A live connector started with the flag. The one profile available had its connector running throughout, and a profile runs one connector at a time.
macOS.
The skill's model evals. The skill gains one bullet.
Summary by cubic
Lifts the connector's built-in four-worker cap: every request now gets a worker as it arrives unless a start sets one with --max-workers N. The cap is kept in runner.json as max_workers and shown by basecamp connect workers list.
Behavior changes
Existing connectors update to no cap unless their runner.json already has max_workers.
A cap is read once at start, so editing runner.json while the connector runs applies at the next start.
--max-workers 0 removes a kept cap; a start without the flag leaves the kept cap alone.
Caps above 64 are accepted, and negative values are refused.
A connector that is stopping starts no worker turn, and a worker whose run is ending asks nothing of the hold.
basecamp connect restart re-runs the original flags, so a cap set at start survives a restart.
Confidence Score: 5/5
This PR appears safe to merge; no actionable issues were found.
Summary
Removes the default four-worker cap and adds --max-workers. The chosen cap is saved in runner.json, applied at startup, and shown by workers list.
The built-in runner starts workers without a default cap.
Workers stop starting new turns as the connector shuts down.
Reviewed the source and related SDK references. No runtime tests were run.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["Start connector"] --> B{"--max-workers given?"}
B -->|Yes| C["Save the supplied cap"]
B -->|No| D["Keep the saved cap"]
C --> E["Choose the cap once"]
D --> E
E --> F{"Cap is zero?"}
F -->|Yes| G["Workers start without waiting for a slot"]
F -->|No| H["Workers wait for one of N slots"]