Implements the single browser tool per decisions.md §3.2.
Level 1 (packages/bcode-browser/src/):
- browser-execute.ts (~85 lines) — Effect factory spawning
uv run --project <HARNESS_DIR> python run.py -c <code>
via ChildProcessSpawner. BU_NAME=sessionID isolates daemons
per session (sub-agents → own browser). ENOENT on uv yields
the one-line install hint per decisions.md §4.4.
- harness.ts (5 lines) — HARNESS_DIR resolved from import.meta.url.
Phase-C TODO when binary packaging lands.
Level 2 (packages/opencode/src/tool/):
- browser-execute.ts (~25 lines) — Tool.define adapter, passes
through schema, translates Tool.Context.sessionID, Effect.orDie
for opencode's error contract.
- browser-execute.txt — description.
- registry.ts — 4 line additions (import + init + builtin entry).
Workspace wiring:
- packages/opencode/package.json — '@browser-use/bcode-browser':
'workspace:*'.
Replaces ROADMAP A3 (cache-dir bootstrap + manifest). Per decisions
§4.4 update: 'uv run --project <HARNESS_DIR>' builds the venv at
harness/.venv/ on first call (cold ~3s, warm ~50ms). No bootstrap
step, no manifest. Single source of truth for deps:
harness/pyproject.toml.
End-to-end verified: Effect.runPromise → spawned uv → python
'print(42)' → output '42\n', exit 0.
Typecheck: 5/5 packages pass via filtered turbo command.
Summary
Implements browser_execute — the single tool for all browser interaction (decisions.md §3.2). Three-level shape with minimal upstream-opencode diff.
What's added
Level 1 — packages/bcode-browser/src/
Level 2 — packages/opencode/src/tool/
Workspace wiring
Total upstream-opencode diff: 6 lines (tool import, init line, builtin entry, package.json dep). Everything else lives in our package.
Replaces ROADMAP A3
The original A3 plan was to bootstrap ~/.cache/bcode/venv/ on first bcode run with a manifest. Replaced 2026-04-26 (decisions.md §4.4 update): uv run --project <HARNESS_DIR> builds a per-package venv at packages/bcode-browser/harness/.venv/ (gitignored) on first call, caches every subsequent call.
No bootstrap step, no manifest, no first-run code path. Single source of truth for Python deps: harness/pyproject.toml. "Is uv on PATH?" is the only check, lazily evaluated via spawn ENOENT.
Verification
Typecheck: bun run typecheck (filtered F4) — 5/5 packages pass in ~5s. Pre-push hook runs clean without --no-verify.
End-to-end smoke test (no Chrome required):
Verifies the spawn pipeline: TS → uv → cached venv → python → captured stdout/exit-code.
A Chrome-required integration test (actually invoking goto(...)) is deferred; that needs the cloud-browser or a headed local Chrome and is the right thing for E1 (evals) to drive.
Out of scope (next PRs)