Local browser client

September 9, 2026 ยท View on GitHub

deepcode web starts or reuses the local background service and opens its Web client. Closing or refreshing the page leaves admitted tasks and terminals in that service running. It uses the same Agent, tools, approvals, project trust, configuration, Session history and application services as Desktop.

Open the client

With a complete Python release installed and a model connection configured:

deepcode web
deepcode web --no-open
deepcode service status --json

The launcher prints the actual URL, including a single-use ticket valid for 60 seconds. The browser immediately removes the ticket from the address bar and exchanges it for an HttpOnly session cookie. No DeepCode account is required. A session lasts 12 hours; after expiration or service restart, run deepcode web again. Sign out revokes that browser session without stopping admitted tasks. The service binds to 127.0.0.1 only; use the printed host and port. Public hosting and arbitrary reverse-proxy origins are not supported.

--database PATH selects an isolated service database; --port 0 chooses an available port when starting it. A running instance keeps its existing port. To stop the service explicitly, use the service commands. macOS login startup is a separate, optional OS setting.

Open a project by entering its directory on the service machine, then trust it if appropriate. Create a thread, select a configured model and send a task. Approvals, settings, code editing, diff review and the terminal use the existing workspace UI. The browser's Reconnect action only reconnects its own socket.

Reconnection and uncertain results

The browser retries connection failures with bounded backoff, and retries RPCs only when the current service handshake explicitly permits it. It freezes the original request parameters for retries and checks the newly negotiated policy after reconnecting. Pending requests and frame sizes are bounded. Offline terminal keystrokes are never queued for later execution.

OperationRecovery behavior
Declared readsAt most three request attempts; reconnect and read current state.
Keyed Turn start/enqueue/input/SteerReuse the original messageId; existing receipts prevent duplicate submission. An uncertain Steer receipt is not reinjected.
Goal/Automation creation, configuration writes, approvals, file writes, terminal creation/input and other unlisted mutationsNo automatic resend. A lost response reports RESULT_UNKNOWN; inspect current state before deciding what to do next. Existing revision and approval CAS checks still apply.
Thread eventsRecover from the contiguous cursor with a fixed replay cutoff; repair gaps without dropping unseen events.
Terminal outputDiscover the existing terminal and read its bounded byte window. Refresh does not create a replacement terminal or replay its input.

There is no new universal mutation ledger. An RPC response ID is not a durable idempotency key. Successful reconnection does not prove that a timed-out write failed. Service restart restores durable application state using the existing recovery rules; it does not restore old OS terminal processes or promise to resume an interrupted shell command. Terminal limits and receipt semantics are specified in SERVICE_RUNTIME.md.

Files and host capabilities

Browser uploads become files in the selected, trusted server workspace. Returned server paths are attached to the task; browser-local paths are never submitted as if the server could read them. Each selection accepts up to eight files, 10 MiB each. Transfers share four slots; upload quota checks are serialized. The workspace upload budget is 64 MiB, including unfinished staging files. Uploads use private staging files and are published only after the full body is written; interruption cleans up the staging file. Crash leftovers count against the budget. Remove unused deepcode-upload-* files and orphan .deepcode-upload-*.part files from the workspace when no upload is active. There is no automatic retention policy for these workspace files.

Files can be downloaded from the inspector with authenticated, workspace-confined requests, capped at 32 MiB. Symlinks escaping the workspace and non-regular files are rejected. Browser diagnostics export the existing sanitized snapshot as a download. Copy configuration path copies only the service path; it does not export credentials. Software updates remain an installation/service operation. The browser cannot invoke native dialogs, open host applications or run the Desktop updater.

ClientRuntime is the shared interface. Separate entrypoints inject BrowserRuntime or TauriDesktopRuntime; shared components do not import Tauri APIs. Desktop retains native dialogs and its updater, and uses a native stdio relay to attach to the same service as Web and TUI. Exiting any of these clients detaches its connection without shutting down the service.

Build and distribution

For a source checkout with Git, uv, and Node.js 22+ installed, run from the repository root:

npm --prefix desktop ci
npm --prefix desktop run build:web
uv tool install --python 3.12 --force .
deepcode web

See installation for the full setup and Troubleshooting for startup or authentication errors.

The build writes app_server/web_assets, including a version/build manifest. The service serves those assets and its API from the same origin. Missing or incompatible assets produce an installation repair message. The browser checks its compiled build identity against the service handshake before business use. After changing frontend source, rebuild and reinstall the tool. Let active work finish, restart the service, and open a fresh deepcode web link to load the matching assets. Do not replace assets during an active acceptance test.

Python wheel and sdist releases include these generated assets. Release CI builds them before packaging, and scripts/verify_python_distribution.py checks the manifest and referenced files. Ordinary installed usage needs neither Node nor Vite. The [server] extra is supported; its runtime dependencies are already in the base package.

For release engineering, verify that the bundled App Server also includes the assets:

cd desktop
npm run setup:sidecar
npm run build:sidecar
build/sidecar/dist/deepcode-app-server/deepcode-app-server --web

The executable's --web launcher and --serve mode run without a system Python interpreter. Its default stdio relay attaches to the shared service; closing that relay disconnects the client without stopping the service. --verify-runtime reports webAssets along with the existing provider, document and Skill probes. Build verification requires bundled Web assets to be present.

Reproducible acceptance

cd desktop
npm run test
npm run lint
npx playwright install chromium
npm run test:web

test:web runs a real browser against an isolated local service and temporary workspace, using a deterministic Agent fixture. It covers an approval across refresh/reconnection, settings persistence, upload, diff, file download and a real terminal across refresh. It cleans up its service and workspace. CI uses this credential-free scenario.

Set DEEPCODE_TEST_PYTHON to an installed test interpreter when not using the repository .venv. DEEPCODE_CHROME_PATH can select a local Chrome binary. Set DEEPCODE_WEB_LIVE=1 only for an intentional live-provider test: the fixture copies the selected usable connection into a private temporary configuration, requests two small Python files, approves only those file writes and a constrained unit-test command, refreshes during execution, independently tests the result, and checks that only one Turn was admitted. This consumes the configured model's API quota. Code and test evidence are attached to the Playwright JSON report.

DEEPCODE_WEB_PACKAGE_DIR selects an installed wheel target outside the checkout; DEEPCODE_WEB_BINARY selects the standalone executable. Those modes run the browser engineering checks without a model call. These browser scenarios do not establish platform-wide release acceptance. Native Desktop packaging, operating-system service integration, and extended stability checks require their own validation; see the upgrade and acceptance guide.