Skip to content

spike(#610): WebDriver PoC on the routines fire API#623

Draft
suleimansh wants to merge 2 commits into
mainfrom
spike/610-web-driver
Draft

spike(#610): WebDriver PoC on the routines fire API#623
suleimansh wants to merge 2 commits into
mainfrom
spike/610-web-driver

Conversation

@suleimansh

@suleimansh suleimansh commented Jul 16, 2026

Copy link
Copy Markdown
Member

Spike for #610. Draft until a live-token /fire run happens; the mechanism and seam fit are proven.

What this is

A WebDriver that runs a task on Claude Code on the web behind the existing Driver seam, via the supported routines fire API (POST /v1/claude_code/routines/{id}/fire), not the browser UI.

  • prompt(text) fires the routine and returns the created session handle (id + url) as the turn.
  • collect() awaits the eventual result (the branch the cloud session pushes / its PR).
  • readCode is omitted (the workspace is a remote VM). dispose is a no-op (cloud session persists server-side).
  • Transport is an injectable fetch, so it is unit-tested with no network and no real token.

Why the API, not the browser or the CLI flag

  • Driving the claude.ai UI (Chrome extension / headless) is barred by the Usage Policy: no automated access outside an API key, and third-party agents using subscription credentials are banned. The routines API is explicitly permitted.
  • Verified claude --cloud is TTY-gated (CLI v2.1.211): run non-interactively (piped stdout) it exits 1 and would silently run locally. That is exactly the mode ClaudeCodeDriver uses, so --cloud cannot slot behind the non-interactive driver. --cloud stays the human-at-a-terminal path; the API is the programmatic one.

Async contract (decided: option A)

The web flow is fire-and-forget, so prompt resolves with the session handle, not a final turn. Rather than block the driver, the seam gains an optional collect() + DriverOutcome (only async/off-machine drivers implement it). Branch discovery is the caller's policy via an injectable resolveOutcome (the daemon, #605, polls GitHub), so the driver stays transport-only.

Tests

10 web-driver unit tests, full driver suite (60) green; pnpm typecheck clean. Covers fire + handle, framing fold, events, error-envelope on 429, unrecognized 200, aborted prompt, no readCode, and collect (no-resolver, injected-resolver, and pre-prompt guard).

Remaining before ready: one live /fire against a real routine token, then the changeset. No changeset yet, intentional.

Drive Claude Code on the web behind the existing Driver seam via the
supported routines fire API (POST /v1/claude_code/routines/{id}/fire),
not the browser UI. prompt() fires the routine and returns the created
session handle (id + url); readCode is omitted (remote workspace),
dispose is a no-op. Transport is an injectable fetch, unit-tested.

Spike only, no changeset: the fire-and-forget contract (prompt resolves
on session-created, not final turn) is an open seam-design question.
Decision on the async contract (option A): prompt stays fire-and-forget
and returns the session handle; the finished code is awaited separately.
Add optional DriverSession.collect() + DriverOutcome to the seam (only
async/off-machine drivers implement it), and wire WebSession.collect to
an injectable resolveOutcome so branch discovery stays the caller's
policy (the daemon polls GitHub), keeping the driver transport-only.

10 web-driver tests green; full driver suite (60) green.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant