Routing and spend
Which model runs a task, and what a cap can actually stop. Some of the controls here do real work. Two of them do nothing, and this page says which.
DeckSpace does not host a model and never sees your provider bill. Every pane runs an agent CLI you installed, on your own key. Routing here means one narrow thing: which model argument DeckSpace puts on the command line it types into the pane, and which reasoning-effort variable it exports first. Everything past that point is between your CLI and your provider.
The controls, and which are connected
| Control | Where | What it does | Connected |
|---|---|---|---|
| Plan-gate routing | Orchestrator plan card | Assigns a model and effort per task; you can edit both before accepting | yes |
| Fast Mode | Status bar, composer, command palette | Appends the CLI’s own fast-model flag | yes 2 of 11 CLIs |
| Effort Std / High / Ultra | Status bar, composer, command palette | Exports MAX_THINKING_TOKENS before launch | yes Claude panes only |
| Model / Effort pane chips | Pane header, running Claude pane | Types /model and /effort into that session | yes Claude panes only |
| Agent run cap | Status bar counter | Refuses launches past N runs this session | yes |
| Auto | Helm composer, Settings “auto route” | Nothing | not wired |
| Token budget | Mission API only | Compares a budget against an iteration count | cannot enforce |
The Auto chip is not connected
The router behind the chip is real, finished code. Nothing calls it. The single function that would apply a routing decision to a launch, launchAgentRouted, has no callers anywhere in the app, so no launch path ever asks the router for an answer.
For the record, this is what is sitting there unused. An instant keyword pass reads the prompt: a prompt under 220 characters containing words like typo, docs, readme, rename or changelog routes to haiku / std; anything mentioning architecture, refactor, debug, race, deadlock, security or migration routes to opus / ultra; everything else routes to sonnet / high. That answer ships immediately, and a one-shot claude --model haiku classifier running in plan mode in a temp directory gets 20 seconds to upgrade it. Any failure — no CLI, timeout, unparseable reply, a model name outside opus|sonnet|haiku|fable — leaves the keyword answer standing.
There is one visible side effect of switching Auto on, and it is misleading. The status bar’s reasoning chip stops showing your effort level and shows the word Auto instead. The effort actually exported at launch is still the manual one you last set. Auto hides the setting in force without changing it.
The voice-and-settings registry exposes this as auto route, described as picking each Claude launch’s model and effort from the task itself. It writes the same flag as the chip and has the same effect: none. Auto is deliberately absent from the command palette, which does carry Fast Mode, Plan Mode, Walk-away and the effort cycle.
How a model reaches the command line
A launch builds one flag string, in a fixed order: pinned model, then fast, then plan, then walk-away, then auto-edit. Two rules matter for cost.
- A pinned model wins over Fast Mode. If a plan task pins
haikuand Fast Mode is on, the fast flag is dropped — on Claude both drive the same--modelflag and emitting it twice breaks the launch. - A pin is only emitted if that CLI declares a model flag. There is no translation layer and no error. For a CLI with no model flag, the pin is silently discarded and the CLI runs its own default model.
| Agent CLI | Model flag | Fast Mode flag |
|---|---|---|
| Claude Code | --model | --model haiku |
| Antigravity | --model | --model "Gemini 3.5 Flash (Low)" |
| Codex | -m | none — Fast Mode is a no-op |
| OpenCode | -m | none — Fast Mode is a no-op |
| Grok CLI | -m | none — Fast Mode is a no-op |
| Aider | none — a pin is dropped | none — Fast Mode is a no-op |
| Cursor Agent | none — a pin is dropped | none — Fast Mode is a no-op |
| Droid | none — a pin is dropped | none — Fast Mode is a no-op |
| Copilot CLI | none — a pin is dropped | none — Fast Mode is a no-op |
| Amp | none — a pin is dropped | none — Fast Mode is a no-op |
| Qwen Code | none — a pin is dropped | none — Fast Mode is a no-op |
So Fast Mode changes the model for two of the eleven built-in CLIs, and a model pin lands on five. A custom CLI you register yourself supplies its own model and fast flags, and gets both behaviours if you fill those fields in.
The plan brain is held to the same reality. For a claude task it may only name opus, sonnet, haiku, fable or default; anything else degrades to the provider default rather than failing the plan. For other providers the hint is passed through lowercased, and their CLI validates it.
Effort is two different ladders
At launch, DeckSpace exports an extended-thinking budget into the pane before typing the command. This is the Std / High / Ultra chip.
| Level | MAX_THINKING_TOKENS | Notes |
|---|---|---|
| Std | not exported | Leaves the model’s own default |
| High | 16000 | — |
| Ultra | 31999 | The default for a fresh install |
Two limits. The variable is only exported for Claude panes — every other CLI launches with no effort setting at all, whatever the chip says. And the default is Ultra, so an untouched install runs every Claude launch at the top of the ladder until you lower it.
A running Claude pane has a second, unrelated pair of chips in its header. They type slash commands into that live session: /model with opus, sonnet, haiku, fable or default, and /effort with low, medium, high, xhigh or max. Note that this is a different vocabulary from the launch-time ladder. These chips retarget a session that is already running; they do not change what the next launch does.
The plan gate’s dollar figure is arithmetic, not billing
Accept a plan in the Orchestrator and the card shows a figure like ~$4.20. That number is computed locally from the plan’s routing and two hard-coded tables. It is an order-of-magnitude sanity check, not a measurement.
| Model | $ / M input tokens | $ / M output tokens | Assumed tier |
|---|---|---|---|
| fable | 25 | 100 | heavy |
| opus | 15 | 75 | heavy |
| sonnet | 3 | 15 | medium |
| haiku | 1 | 5 | light |
| Tier | Assumed input tokens per task | Assumed output tokens per task |
|---|---|---|
| heavy | 1,500,000 | 40,000 |
| medium | 600,000 | 20,000 |
| light | 150,000 | 8,000 |
A model the table does not know is priced as sonnet-class. Injected reviewer tasks are excluded from the plan total, because they re-read diffs the workers already paid for. The assumed token volumes are stated in the source as guesses from watching real runs, not measurements.
DeckSpace spawns CLIs as child processes and cannot read a usage figure back out of them, so the estimate is never reconciled against what a run actually cost. Each accepted plan’s estimate is also folded into a running session total — which no screen in the app displays. Your provider’s own dashboard is the only true number.
The cap that works counts runs, not money
The status bar shows N runs for this session. Click it, type a number, press Enter. That is a soft cap on agent launches: at the cap, the next launch is refused outright with a warning telling you to raise or clear it, and the counter does not advance.
| Fact | Value |
|---|---|
| Setting name | agent run cap (run_cap) |
| Range | 0 to 500 runs |
| 0 means | unlimited — not “block everything” |
| Scope | This session. Quitting resets the counter. |
| Counts | Every launch through the normal launch path, Maestro workers included |
Be clear about what this measures. It counts launches, so five haiku runs and five opus runs cost the counter exactly the same. Every Maestro worker relaunch after reviewer feedback counts as another run, so a review-heavy Maestro run burns the cap faster than the task count suggests. And a mission running on the headless driver spawns its agent from the app’s Rust side, which never passes through this counter at all.
Concurrency is a separate control with a separate setting: orchestrator_hard_cap, default 8, clamped to 1–12. It bounds how many workers run at once, not how many run in total. See Maestro.
The token budget cannot enforce anything
The mission loop’s judge accepts a token_budget and a tokens_spent, and fails a mission with “token budget exhausted” when spend meets budget. The value passed as tokens_spent is the iteration number — in both the Rust headless loop and the in-app loop. No provider usage figure is read anywhere in the backend.
What that means in practice:
- The in-app mission loop hard-codes
token_budget: 0, which is “unlimited”, so the check never fires there. - Where a budget is set through the mission API, it is compared against a counter that goes 1, 2, 3… and stops at the iteration cap, which is clamped to a maximum of 50. A budget of 200,000 tokens can never be reached.
- A small number does fire — a budget of 5 fails the mission at iteration 5. That is a second iteration cap wearing the wrong label, not a spend cap.
- No screen in the app sets a token budget. The field is reachable only through the mission API.
What actually lowers a bill
- Edit the plan card before you accept it. The per-task model and effort chips are editable, the estimate recomputes as you change them, and the values you leave are the ones dispatched. This is the only routing surface that both decides and applies.
- Drop the effort chip off Ultra. It ships at Ultra, which exports 31,999 thinking tokens on every Claude launch including trivial ones.
- Set the run cap before an unattended session. It is the one limit that will refuse a launch. Pair it with walk-away, which removes the prompts that would otherwise have slowed a runaway down.
- Use Fast Mode on Claude or Antigravity panes. On the other nine CLIs the toggle changes nothing, so do not count it as a saving.
- Read your provider dashboard. Nothing in DeckSpace knows what a run cost.