Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@

### Added

- `webcmd setup --mode local --browser chrome` detects and reuses an installed normal Google Chrome with an isolated `~/.webcmd/chrome/profiles` directory.
- Hosted mode can negotiate and run core validation, diagnostics, adapter lifecycle, profile lifecycle, and catalog-list commands advertised by Webcmd Cloud.
- `@agentrhq/webcmd/adapter-analysis` exposes platform-neutral validation and convention-audit rules for trusted hosted command inventories.
- `@agentrhq/webcmd/hosted/core-commands` exposes the `hosted-core-commands-v1` capability contract and canonical command IDs.
- `webcmd profile use` now stores a validated hosted profile preference locally.

### Changed

- `WEBCMD_BROWSER_BINARY_PATH` can select a compatible Chromium executable for local browser Sessions; it takes precedence over the existing `CLOAKBROWSER_BINARY_PATH` override and isolates each browser build's profile data from managed Cloak profiles.
- Hosted help and completion advertise Cloud-owned core commands only when the authenticated manifest advertises them.
- Hosted command lists retain excluded commands as `LOCAL` rows and return a local-only error instead of plugin-install guidance.
- Local auth commands initialize user CLI compatibility shims, and hosted auth uses the same native grammar, flags, choices, and help as local mode.
Expand Down
54 changes: 0 additions & 54 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -10,57 +10,3 @@ https://github.com/microsoft/playwright, licensed under Apache-2.0.
The browser snapshot capture, model, renderer, diff, and page-stability modules
in src/browser/snapshot/capture.ts, types.ts, render.ts, diff.ts, and
wait-for-page-stable.ts are derived from https://github.com/hamr0/barebrowse.

The browser snapshot capture, model, renderer, diff, and page-stability modules
in src/browser/snapshot/capture.ts, types.ts, render.ts, diff.ts, and
wait-for-page-stable.ts are also derived from libretto-browser-tools
(https://github.com/Skyvern-AI/libretto).

MIT License

Copyright (c) 2026 Libretto contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

The humanizer sources in src/browser/humanizer/actionability.ts, config.ts,
elementhandle.ts, index.ts, keyboard.ts, mouse.ts, and scroll.ts are derived
from CloakHQ/cloakbrowser@0.4.5, git commit
5176971f45d02845d3d1c0adbbda0bc93addf747.

MIT License

Copyright (c) 2026 CloakHQ

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
6 changes: 2 additions & 4 deletions PRIVACY.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
# webcmd Privacy

Local mode keeps Cloak as the bundled default browser. SLAB is a macOS alpha opt-in selected with `webcmd setup --mode local --browser slab`, and a compatible local Chromium fork can be selected with `webcmd setup --mode local --browser /absolute/path/to/browser`.

The SLAB browser communicates with webcmd through owner-scoped local IPC. webcmd does not expose a raw TCP debugging endpoint.
The webcmd-managed CloakBrowser runtime communicates only with the local Webcmd daemon on `localhost:9777`.

The runtime can access browser pages and cookies because browser automation requires those permissions. Webcmd does not send page contents or cookies to AgentR. Except for the site-memory seed lookup and the optional candidate public-IP lookup below, Webcmd does not send browser data to AgentR. Commands run locally, and command output is printed to the local CLI process.

Trace artifacts, cache files, plugins, user adapters, and site memory are stored under `~/.webcmd`. Custom browser selections keep their own local profile directories and do not overwrite the managed Cloak profiles.
Trace artifacts, cache files, plugins, user adapters, and site memory are stored under `~/.webcmd`.

## Local site-memory seed lookup

Expand Down
21 changes: 3 additions & 18 deletions TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@ npm test
The core package contains no site adapters; `npm test` runs the unit project.
Public adapter tests live in `agentrhq/webcmd-plugins`.

Local browser coverage stays split on purpose: Cloak remains the default and
bundled runtime, SLAB is the macOS alpha opt-in path, and custom absolute
executables reuse the Cloak-compatible runtime with separate profile data.

## Skill Sources

Bundled skills are generated from `skill-src/` with litprompt. After editing a
Expand All @@ -33,23 +29,12 @@ npx vitest run --project unit src/package-exports.test.ts
npx vitest run --project unit src/convention-audit.test.ts src/runtime-copy.test.ts
```

## SLAB Runtime Smoke

Run:

```bash
npx vitest run --project unit src/slab src/browser/runtime/local-slab
```

These tests use the local SLAB control contract and do not download or launch a browser.

## Browser Selection Checks
## Cloak Runtime Smoke

Run:

```bash
npx vitest run --project unit src/doctor.test.ts src/hosted/setup.test.ts
npx vitest run --project e2e tests/e2e/cloak-runtime.test.ts
```

These checks cover bundled Cloak fallback, explicit Cloak, custom absolute
browser paths, `setup --status`, and doctor output for the selected browser.
The first run may download the CloakBrowser Chromium binary. Browser-backed tests no longer require a Chrome extension.
6 changes: 2 additions & 4 deletions docs/cli-reference.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ webcmd --profile work \
webcmd --profile work session close work-project-k7
```

Local browser commands use the browser selected by `webcmd setup --mode local --browser ...`. Cloak stays bundled and default, `--browser chrome` reuses an installed Google Chrome, `--browser slab` is the macOS alpha opt-in, and an absolute path selects a compatible local Chromium fork. If Google Chrome is unavailable, setup links to the official installer and leaves the existing selection unchanged. Hosted browser commands use Webcmd Cloud and Browser Use; `web fetch` still runs locally.
Local browser commands use Cloak. Hosted browser commands use Webcmd Cloud and Browser Use; `web fetch` still runs locally.

## Browser Programs

Expand Down Expand Up @@ -140,7 +140,7 @@ Ordinary `curl` is neither required nor automatically authenticated.
| --- | --- |
| `list` | Show registered core, legacy user, plugin, and external commands. |
| `setup` | Choose local or hosted mode interactively. |
| `doctor` | Diagnose the selected local browser runtime and daemon connectivity. |
| `doctor` | Diagnose browser bridge and daemon connectivity. |
| `daemon` | Manage the local Webcmd daemon: status, stop, and restart. |
| `artifact` | Download a hosted execution artifact to `--output`. |
| `browser` | Agent-facing browser runtime for exploration and verification. |
Expand Down Expand Up @@ -185,8 +185,6 @@ webcmd profile list -f json

Each keeps its human-readable report as the `table` rendering, which stays the default. Pass another format to get the underlying result object instead — the validation report for `validate`, the verify report for `verify`, the diagnostic report for `doctor`, and a row set for `profile list`.

`webcmd setup --status` returns the configured local `browser` selection in JSON. `webcmd doctor` reports the live `Runtime` plus a `Selected browser` line so you can tell whether local mode is using bundled Cloak, installed Google Chrome, macOS-alpha SLAB, or a custom absolute executable path.

`daemon status -f json` returns `{ "running": false }` when no daemon is reachable, and otherwise reports `running`, `stale`, `pid`, `version`, `uptimeMs`, `runtimeConnected`, `profiles`, `memoryMB`, and `port`.

`profile list` returns one row per profile with `contextId`, `alias`, `default`, `connected`, and `runtimeVersion`, covering both connected profiles and saved aliases that are not currently connected. If the daemon is unreachable or stale, `profile list -f json`/`-f yaml` fails with a `DAEMON_UNAVAILABLE` error (exit 1) and a restart hint instead of returning `[]` — an empty list and an unreadable runtime are different facts.
Expand Down
16 changes: 0 additions & 16 deletions docs/troubleshooting.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ description: Prompt-based fixes for common Webcmd install, profile, auth, plugin

Most troubleshooting should be done by an agent. Give the symptom, the command, the expected output, and permission to diagnose.

For local browser selection, use `webcmd setup --mode local --browser cloak`, `webcmd setup --mode local --browser chrome`, `webcmd setup --mode local --browser slab`, or `webcmd setup --mode local --browser /absolute/path/to/browser`. Cloak remains the bundled default; Chrome reuses an installed normal Google Chrome, and SLAB is the macOS alpha opt-in.

## Basic Diagnosis

```text
Expand Down Expand Up @@ -144,17 +142,3 @@ Useful environment variables:
| `WEBCMD_CDP_TARGET` | Filter CDP targets by URL substring. |
| `WEBCMD_CACHE_DIR` | Browser state and network cache directory. |
| `WEBCMD_VERBOSE` | Enable verbose logs. |

`webcmd setup --mode local --browser chrome` uses an existing normal Google
Chrome installation and keeps its profiles under `~/.webcmd/chrome/profiles`.
Interactive setup labels Chrome as `installed` or `install required`. Webcmd
does not install Chrome automatically; when it is missing and selected, setup
links to `https://www.google.com/chrome/` and preserves the current browser
selection.

After changing the local browser with `webcmd setup --mode local --browser ...`,
restart the daemon and run `webcmd doctor`. `webcmd doctor` reports the live
runtime plus a `Selected browser` line, and `webcmd setup --status` returns the
configured `browser` object. Custom browser builds use their own profile
directory under `~/.webcmd/<browser>/profiles`, so their cookies and browser
state do not modify the managed Cloak profiles in `~/.webcmd/cloak/profiles`.
46 changes: 1 addition & 45 deletions src/browser.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
import * as fs from 'node:fs';
import * as os from 'node:os';
import * as path from 'node:path';
import { afterEach, describe, it, expect, vi } from 'vitest';
import { BrowserBridge, generateStealthJs } from './browser/index.js';
import { extractTabEntries, diffTabIndexes, appendLimited } from './browser/tabs.js';
Expand All @@ -9,20 +6,11 @@ import { __test__ as cdpTest } from './browser/cdp.js';
import { classifyBrowserError } from './browser/errors.js';
import * as daemonTransport from './browser/daemon-transport.js';
import * as daemonLifecycle from './browser/daemon-lifecycle.js';
import { makeLocalConfig, saveWebcmdConfig } from './hosted/config.js';

afterEach(() => {
vi.restoreAllMocks();
vi.unstubAllEnvs();
});

function useBrowserConfig(browser: Parameters<typeof makeLocalConfig>[1]): string {
const configDir = fs.mkdtempSync(path.join(os.tmpdir(), 'webcmd-browser-config-'));
vi.stubEnv('WEBCMD_CONFIG_DIR', configDir);
saveWebcmdConfig(makeLocalConfig(new Date('2026-08-31T00:00:00.000Z'), browser), { env: { WEBCMD_CONFIG_DIR: configDir } });
return configDir;
}

describe('browser helpers', () => {
it('extracts tab entries from string snapshots', () => {
const entries = extractTabEntries('Tab 0 https://example.com\nTab 1 Chrome Extension');
Expand Down Expand Up @@ -162,7 +150,6 @@ describe('BrowserBridge state', () => {
});

it('fails fast when daemon is running but runtime is disconnected (same version)', async () => {
const configDir = useBrowserConfig({ kind: 'cloak' });
const { PKG_VERSION } = await import('./version.js');
vi.spyOn(daemonTransport, 'getDaemonHealth').mockResolvedValue({
state: 'no-runtime',
Expand All @@ -181,38 +168,7 @@ describe('BrowserBridge state', () => {

const bridge = new BrowserBridge();

try {
await expect(bridge.connect({ timeout: 0.1 })).rejects.toThrow('Browser runtime is not ready');
} finally {
fs.rmSync(configDir, { recursive: true, force: true });
}
});

it('lets selected SLAB commands reach dispatch when the daemon is running but SLAB is not attached yet', async () => {
const configDir = useBrowserConfig({ kind: 'slab' });
const { PKG_VERSION } = await import('./version.js');
vi.spyOn(daemonTransport, 'getDaemonHealth').mockResolvedValue({
state: 'no-runtime',
status: {
ok: true,
pid: 999999,
uptime: 0,
daemonVersion: PKG_VERSION,
runtimeConnected: false,
runtimeName: 'SLAB',
pending: 0,
memoryMB: 0,
port: 0,
},
});

const bridge = new BrowserBridge();

try {
await expect(bridge.connect({ timeout: 0.1, session: 's1' })).resolves.toBeDefined();
} finally {
fs.rmSync(configDir, { recursive: true, force: true });
}
await expect(bridge.connect({ timeout: 0.1 })).rejects.toThrow('Browser runtime is not ready');
});

it('attempts stale daemon replacement when daemonVersion is missing', async () => {
Expand Down
50 changes: 0 additions & 50 deletions src/browser/browser-binary.test.ts

This file was deleted.

64 changes: 0 additions & 64 deletions src/browser/browser-binary.ts

This file was deleted.

Loading
Loading