Skip to content

feat(routing): auto-detect dario at startup, drop the manual env-var dance#26

Merged
askalf merged 1 commit into
mainfrom
feat/auto-detect-dario
Apr 29, 2026
Merged

feat(routing): auto-detect dario at startup, drop the manual env-var dance#26
askalf merged 1 commit into
mainfrom
feat/auto-detect-dario

Conversation

@askalf
Copy link
Copy Markdown
Owner

@askalf askalf commented Apr 29, 2026

Summary

When `ANTHROPIC_BASE_URL` isn't already set, probe `localhost:3456/health` at the start of `hands run`. If dario responds, set `ANTHROPIC_BASE_URL` so the Anthropic SDK routes through it for OAuth subscription billing. Operator override always wins: env-pre-set or `--no-dario` skip the probe.

Why

Today's E2E verification (dario #172 + dario #174) proved hands SDK mode + dario gives OAuth subscription billing instead of per-token API key cost. Friction was the only barrier left — users had to remember `export ANTHROPIC_BASE_URL=http://localhost:3456\` before every `hands run`. This makes the subscription path automatic when dario is up; silent fall-through to `api.anthropic.com` when it isn't.

Behavior

Condition Outcome
`ANTHROPIC_BASE_URL` already set Respect it, no probe
`--no-dario` flag Skip probe, no env var change
Dario reachable on `localhost:3456/health` Set env var, log info line
Dario not reachable (timeout / refused / non-OK) Silent fall-through to `api.anthropic.com`
`HANDS_DARIO_URL` env set Probe that URL instead of default

Probe target: dario's `/health` endpoint (already used by `hands doctor` — same shape, decoupled by route from any auth-bearing path). 2s timeout — dario's first `/health` on a cold proxy was observed at ~840ms (account pool + template state checks); subsequent hits much faster, but each `hands run` invocation runs the probe once so we budget for cold-path.

Test plan

  • Unit: `test/dario-detect.test.mjs` — 7 cases covering operator-override (env pre-set), explicit disable, successful probe, non-OK response, network error fall-through, `HANDS_DARIO_URL` override, trailing-slash trimming.
  • Live: ran `hands run` against a running dario without setting `ANTHROPIC_BASE_URL`. Auto-detected, routed through, `five_hour` billing on dario's log.
  • Local: `npm test` passes 56/56.
  • CI: standard hands checks.

Notes

  • Pure additive — three files modified (`run.ts` adds 12 lines, `cli.ts` adds 1 flag), one new file (`dario-detect.ts`), one new test file. No runtime path changes outside the new probe.
  • Operator-override semantics preserved across both pre-set env var and explicit `--no-dario` flag — there's no path where the auto-detect can override an operator's intent to use `api.anthropic.com`.

…dance

When ANTHROPIC_BASE_URL isn't already set, probe localhost:3456/health
at the start of `hands run`. If dario responds within 2s, set
ANTHROPIC_BASE_URL so the Anthropic SDK routes through dario for
OAuth subscription billing. Operator override always wins:
ANTHROPIC_BASE_URL set in env or via shell skips the probe; --no-dario
flag opts out explicitly even when dario is reachable.

Why: today's E2E verification proved hands SDK mode + dario gives
subscription billing instead of per-token API key cost (Discussion
#172 + dario PR #174). Friction was the only remaining barrier —
users had to remember `export ANTHROPIC_BASE_URL=http://localhost:3456`
before every run. This makes the subscription path automatic when
dario is up, falls through silently to api.anthropic.com when it's
not.

Probe details:
- Default target: http://localhost:3456 (dario's canonical port).
- HANDS_DARIO_URL env var overrides the target for non-default ports.
- Hits dario's /health endpoint (already used by hands doctor — same
  shape, decoupled by route from any auth-bearing path).
- 2s timeout — dario's first /health on a cold proxy was observed
  at ~840ms (account pool + template state checks); subsequent hits
  are much faster, but each `hands run` invocation runs the probe
  once so we budget for the cold path. Hands startup already takes
  a few seconds for screenshot + config, so 2s here is not the
  dominant latency.
- Network errors / non-OK responses fall through silently — the
  common "no dario running" case is normal, no warn/error noise.

Test coverage: test/dario-detect.test.mjs — 7 unit tests covering
operator-override (env var pre-set), explicit disable
(--no-dario), successful probe, non-OK response, network error
fall-through, HANDS_DARIO_URL override, trailing-slash trimming.
Live verified end-to-end against a running dario instance: info
line "auto-detected dario at http://localhost:3456 — routing
through it for subscription billing" prints, request reaches
dario, billing routes to five_hour.
@askalf askalf force-pushed the feat/auto-detect-dario branch from 7db3532 to 4046633 Compare April 29, 2026 23:28
@askalf askalf merged commit d6d5e0e into main Apr 29, 2026
5 checks passed
@askalf askalf deleted the feat/auto-detect-dario branch April 29, 2026 23:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant