Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d89f41e
feat: make session a root cli selector
beubax Aug 11, 2026
85a945d
feat: persist local browser sessions
beubax Aug 11, 2026
821621b
feat: admit local browser work by session
beubax Aug 11, 2026
eea7848
feat: recover stale session leases
beubax Aug 11, 2026
4ed23a6
feat: isolate local browser sessions
beubax Aug 11, 2026
d2f48c0
feat: open local sessions in owned windows
beubax Aug 11, 2026
cb20e0c
feat: document and host browser sessions
beubax Aug 11, 2026
8550368
fix: partition adapter sessions by site
beubax Aug 12, 2026
3818d63
fix: enforce adapter admission scopes
beubax Aug 12, 2026
ee4685d
feat: isolate local sessions by cloak window
beubax Aug 12, 2026
a62dfdc
fix: close local session isolation escapes
beubax Aug 12, 2026
3236a09
fix: scope browser run dialogs to session
beubax Aug 12, 2026
06dafa4
fix: keep cloak profiles alive between sessions
beubax Aug 12, 2026
5413161
fix: harden cloak profile keeper lifecycle
beubax Aug 12, 2026
39b5489
feat: scope local auth handoff to sessions
beubax Aug 12, 2026
b0ff3a2
fix: block session close during auth handoff
beubax Aug 12, 2026
4a27ff8
docs: explain session-based browser work
beubax Aug 12, 2026
06923ee
fix: protect session leases during local concurrency
beubax Aug 12, 2026
285475b
chore: release webcmd v0.6.1
beubax Aug 12, 2026
2771f10
fix: finish session concurrency safety
beubax Aug 12, 2026
39be29a
Fix session concurrency review gaps
beubax Aug 12, 2026
d905912
Fix session review follow-ups
beubax Aug 12, 2026
ab53bad
fix hosted session list parity
beubax Aug 12, 2026
fd670ea
fix hosted session contract parity
beubax Aug 12, 2026
224bc74
fix daemon disconnect cancellation
beubax Aug 12, 2026
5e1cc7a
fix session review gaps
beubax Aug 12, 2026
2e28f1c
fix bounded session cancellation
beubax Aug 12, 2026
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: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "webcmd",
"version": "0.6.0",
"version": "0.6.1",
"description": "Turn websites, browser sessions, desktop apps, and local tools into deterministic CLI surfaces for humans and AI agents.",
"author": {
"name": "AgentRHQ",
Expand Down
2 changes: 1 addition & 1 deletion .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "webcmd",
"version": "0.6.0",
"version": "0.6.1",
"description": "Turn websites, browser sessions, desktop apps, and local tools into deterministic CLI surfaces for humans and AI agents.",
"author": {
"name": "AgentRHQ",
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ jobs:
run: ./scripts/collect-ci-diagnostics.ps1 -SelfTest

- name: Run real Cloak lifecycle smoke
run: npx vitest run --project e2e tests/e2e/cloak-runtime.test.ts
run: npx vitest run --project e2e tests/e2e/cloak-runtime.test.ts tests/e2e/cloak-session-concurrency.test.ts

- name: Collect sanitized diagnostics
if: failure()
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ jobs:
if: ${{ steps.release.outputs.release_created || inputs.publish_tag != '' }}
run: npm ci

- name: Install Playwright Chromium
if: ${{ steps.release.outputs.release_created || inputs.publish_tag != '' }}
run: npx playwright-core install chromium --with-deps

- name: Verify existing release tag
if: ${{ inputs.publish_tag != '' }}
run: test "${{ inputs.publish_tag }}" = "webcmd-v$(node -p "require('./package.json').version")"
Expand Down
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.6.0"
".": "0.6.1"
}
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,21 @@ On top of live browser control, Webcmd adds 3 layers of learnings. Each layer co
| 3. Extend existing CLIs | The workflow is deterministic enough to stop browsing. | Extend the `webcmd <site>` adapter with a tailored command so the workflow runs instantly with the least amount of tokens. |

For local, multi-step browser exploration, agents can send one sandboxed
Playwright-style program to an existing CloakBrowser session:
Playwright-style program to an explicit browser session:

```bash
webcmd browser work run --file explore.js
printf 'const page = await browser.currentPage(); return await page.title();' \
| webcmd browser work run --stdin
webcmd session create -f json
webcmd --session session_abc browser run --file explore.js
printf 'return await page.title();' \
| webcmd --session session_abc browser run --stdin
webcmd session close session_abc
```

Profiles are cookie jars; Sessions are independent browser windows within a
profile, so parallel agents should create separate Sessions. Adapter commands
use an adapter-default Session unless `--session` intentionally routes them to
an explicit one.

## Demo

https://github.com/user-attachments/assets/04eceadc-d398-4303-984d-ae3197bfa664
Expand Down
2 changes: 1 addition & 1 deletion docs/agents/claude-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ Denying these tools does not affect the Bash tool, which is how `webcmd` is driv
| Skill text looks out of date | `webcmd update` upgrades only the CLI. Run `claude plugin update webcmd@webcmd` to refresh plugin skills. |
| Claude Code still uses `WebFetch` / `WebSearch` | Confirm `permissions.deny` lists both in the active settings file, then restart `claude`. |
| `claude` requires permission prompts for `webcmd` | The Bash tool still asks before non-approved commands; run `claude --dangerously-skip-permissions` or allow the shell command if you accept the risk. |
| Browser sessions stop working after idle | Ask the agent to open a fresh session or re-bind with `tabs` and `bind --page`. |
| Browser Session idles or loses its window | Keep the same Session ID; the next `webcmd --session <session-id> browser ...` command reopens it. Use `webcmd session create -f json`, `webcmd session list`, and `webcmd session close <session-id>` for lifecycle. |

## See also

Expand Down
2 changes: 1 addition & 1 deletion docs/agents/codex-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ disabled_tools = ["navigate", "screenshot"]
| Search results look stale | `web_search` defaults to `"cached"`. Set `web_search = "live"` in `~/.codex/config.toml`, then restart `codex`. |
| `web_search` was disabled and search stopped working | Expected. Set it back to `"live"` or `"cached"` — Webcmd does not replace search. |
| `webcmd` not found in Codex shell | Confirm `webcmd` is on the PATH Codex uses; restart after installing the CLI. |
| Browser sessions stop working after idle | Ask the agent to open a fresh session or re-bind with `tabs` and `bind --page`. |
| Browser Session idles or loses its window | Keep the same Session ID; the next `webcmd --session <session-id> browser ...` command reopens it. Use `webcmd session create -f json`, `webcmd session list`, and `webcmd session close <session-id>` for lifecycle. |

## See also

Expand Down
6 changes: 3 additions & 3 deletions docs/agents/cursor.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ Use Webcmd for anything on the open web — fetching, authenticated
third-party sites, multi-step automation, workflows worth making reusable:

- Check `webcmd list -f json` for an adapter that covers the task; use it first.
- Otherwise drive a live browser with `webcmd browser <session> ...` via the shell tool.
- Run `webcmd doctor` first and keep the session lifecycle (`tabs`, `bind`, `snapshot`, `run`, `close`).
- Otherwise create a session, then drive it with `webcmd --session <session-id> browser ...` via the shell tool.
- Run `webcmd doctor` first; use `webcmd session list` to inspect state and `webcmd session close <session-id>` when finished.
- For login walls, use Webcmd's human handoff; never type passwords, OTPs, cookies, or credentials.

Use the native Browser tool only for the app being edited: localhost dev server,
Expand All @@ -77,7 +77,7 @@ Note that the rule is guidance, not a block. Cursor's Browser Automation has bee
| Cursor uses its Browser tool for external sites | Confirm `.cursor/rules/webcmd-browser.mdc` has `alwaysApply: true`; for a hard block, set Browser Automation to Off. |
| Browser Automation turns itself back on | Known behaviour — a prompt mentioning "browser" can re-enable it. Avoid the word, or turn it off in the agent window. |
| `webcmd` not found in Cursor shell | Confirm `webcmd` is on the PATH the Cursor shell uses; restart Cursor after installing the CLI. |
| Browser sessions stop working after idle | Ask the agent to open a fresh session or re-bind with `tabs` and `bind --page`. |
| Browser Session idles or loses its window | Keep the same Session ID; the next `webcmd --session <session-id> browser ...` command reopens it. Use `webcmd session create -f json`, `webcmd session list`, and `webcmd session close <session-id>` for lifecycle. |

## See also

Expand Down
4 changes: 2 additions & 2 deletions docs/agents/hermes.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Hermes' web surface spans three toolsets:

**Hermes toggles toolsets, not individual tools.** There is no way to drop `web_extract` while keeping `web_search`, so leave the `web` toolset on and steer the agent with instructions instead. Add this to your Hermes system prompt or project instructions:

> Use Webcmd (`webcmd list`, `webcmd browser <session> ...` via the `terminal` toolset) for anything on the open web: fetching, authenticated third-party sites, multi-step automation. Prefer it over `web_extract`. Use the `browser_*` tools only for the app being edited — localhost dev server, console and network triage, visual checks. Keep using `web_search` and `x_search` to find URLs.
> Use Webcmd (`webcmd list`, then `webcmd session create -f json` and `webcmd --session <session-id> browser ...` via the `terminal` toolset) for anything on the open web: fetching, authenticated third-party sites, multi-step automation. Prefer it over `web_extract`. Use the `browser_*` tools only for the app being edited — localhost dev server, console and network triage, visual checks. Keep using `web_search` and `x_search` to find URLs.

Also check the `computer_use` toolset. It drives the whole desktop rather than a browser, so it overlaps with Webcmd whenever it is aimed at a website. Disable it if the user does not need desktop control.

Expand Down Expand Up @@ -85,7 +85,7 @@ Do not disable the `terminal` toolset — that is how Hermes runs `webcmd`.
| Search disappeared after disabling `web` | Expected: `web_search` and `web_extract` share one toolset. Re-enable `web` and steer the agent with instructions instead. |
| `x_search` appeared on its own | Expected: it auto-registers when `XAI_API_KEY` or Grok OAuth is configured. Leave it — it is search. |
| `webcmd` not found in Hermes terminal | Confirm `webcmd` is on the host PATH that Hermes' `terminal` toolset uses; non-interactive shells may skip shell init files. |
| Browser sessions stop working after idle | Ask the agent to open a fresh session or re-bind with `tabs` and `bind --page`. |
| Browser Session idles or loses its window | Keep the same Session ID; the next `webcmd --session <session-id> browser ...` command reopens it. Use `webcmd session create -f json`, `webcmd session list`, and `webcmd session close <session-id>` for lifecycle. |

## See also

Expand Down
2 changes: 1 addition & 1 deletion docs/agents/openclaw.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ Or remove it entirely — CLI, `browser.request` gateway method, and agent tool
| OpenClaw uses `browser` for external sites | Remind it that Webcmd handles the open web; for a hard block, set `browser.enabled: false`. |
| Search stopped working | Check whether `web_search` was denied. Webcmd does not replace search — remove it from `tools.deny`. |
| `webcmd` not found in OpenClaw exec | Confirm `webcmd` is on the PATH the Gateway's `exec` tool uses; restart after installing the CLI. |
| Browser sessions stop working after idle | Ask the agent to open a fresh session or re-bind with `tabs` and `bind --page`. |
| Browser Session idles or loses its window | Keep the same Session ID; the next `webcmd --session <session-id> browser ...` command reopens it. Use `webcmd session create -f json`, `webcmd session list`, and `webcmd session close <session-id>` for lifecycle. |

## See also

Expand Down
4 changes: 2 additions & 2 deletions docs/agents/opencode.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ Deny `webfetch` so OpenCode cannot fall back to it while Webcmd is its browser s
| Skills not loading in OpenCode | Run `webcmd skills add` with the `agents` provider, restart OpenCode, and check `/skills`. |
| OpenCode still uses `webfetch` | Confirm `permission.webfetch` is `deny` in the active config, then restart OpenCode. |
| `websearch` is missing entirely | It registers only with the OpenCode provider or `OPENCODE_ENABLE_EXA=1`. Not a Webcmd problem. |
| `webcmd browser` errors | Read `webcmd-usage` and `webcmd-browser` skills; sessions require a `<session>` name after `browser`. |
| Browser sessions stop working after idle | Ask the agent to open a fresh session or re-bind with `tabs` and `bind --page`. |
| `webcmd browser` errors | Read `webcmd-usage` and `webcmd-browser` skills; create a session and pass its ID as root `--session`. |
| Browser Session idles or loses its window | Keep the same Session ID; the next `webcmd --session <session-id> browser ...` command reopens it. Use `webcmd session create -f json`, `webcmd session list`, and `webcmd session close <session-id>` for lifecycle. |

## See also

Expand Down
2 changes: 1 addition & 1 deletion docs/agents/pi.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ To remove one outright, delete its folder — for example `~/.pi/agent/skills/pi
| Pi still uses `browser-tools` or a web-fetch extension | Remove the skill folder or prompt Pi to prefer Webcmd, then restart Pi. |
| Search stopped working after removing an extension | Some extensions bundle search with extraction. Reinstall it and steer Pi with instructions instead — Webcmd does not replace search. |
| `webcmd` not found in Pi's shell | Confirm `webcmd` is on the PATH Pi's `bash` tool uses; restart Pi after installing the CLI. |
| Browser sessions stop working after idle | Ask the agent to open a fresh session or re-bind with `tabs` and `bind --page`. |
| Browser Session idles or loses its window | Keep the same Session ID; the next `webcmd --session <session-id> browser ...` command reopens it. Use `webcmd session create -f json`, `webcmd session list`, and `webcmd session close <session-id>` for lifecycle. |

## See also

Expand Down
13 changes: 10 additions & 3 deletions docs/authentication-and-profiles.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ Use Webcmd with my `work` profile to complete this task on Acme Billing. If the

## Named Profiles

Profiles separate browser identities and their login state. Use a named profile when work and personal accounts, customers, or environments must stay separate.
Profiles are cookie jars and authentication scope. Sessions are browser
windows/workspaces within a profile; separate Sessions let multiple agents use
the same profile in parallel. Use a named profile when work and personal
accounts, customers, or environments must stay separate.

## Hosted Profiles

Expand Down Expand Up @@ -58,14 +61,18 @@ Deletion permanently removes that hosted browser state and its saved sign-in sta

## When You Need to Sign In

When a profile needs interactive sign-in, complete it directly in the browser; never share credentials through chat.
When a profile needs interactive sign-in, complete it directly in the browser;
never share credentials through chat. The handoff belongs to the Session that
started it. After signing in, run the returned verification command verbatim;
it includes the Session selector when applicable. Webcmd blocks `session close`
while that Session has a live handoff.

## Credential Safety

Credentials never belong in prompts or adapter code. Ask the agent to use an authenticated profile and pause for a sign-in handoff instead of sharing passwords, cookies, or API keys.

## Local and Hosted Authentication

In local mode, `webcmd <site> login` opens the foreground Webcmd browser and returns `action_required` immediately. Complete sign-in in that browser, tell the agent when you are done, and let it run `webcmd <site> whoami` before retrying the original task. Never send credentials, OTPs, cookies, or recovery codes through chat.
In local mode, `webcmd <site> login` opens the foreground Webcmd browser and returns `action_required` immediately. Complete sign-in in that browser, tell the agent when you are done, and let it run the returned verification command before retrying the original task. Never send credentials, OTPs, cookies, or recovery codes through chat.

Hosted mode returns a Webcmd-owned live authentication view when interactive sign-in is required. Complete the sign-in there before the agent continues.
29 changes: 21 additions & 8 deletions docs/cli-reference.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,28 @@ The old `web read` command has been renamed to `web fetch-browser`.

## Local Browser Programs

`browser run` executes one Playwright-style JavaScript program against an
existing local CloakBrowser session:
Create an opaque session before raw browser work. Profiles hold cookie/auth
state; sessions are browser workspaces within that profile. Adapter commands
may omit `--session` and use their profile's adapter-default session; pass
`--session <session-id>` only when intentionally routing an adapter into an
explicit session. Raw browser commands must always pass it. The retired
positional session form is invalid:

```bash
webcmd browser work snapshot --snapshot-mode act
webcmd browser work snapshot --snapshot-mode read
webcmd browser work run --stdin --timeout 45
webcmd browser work run --stdin --no-snapshot-diff
webcmd session create -f json
webcmd --session session_abc browser snapshot --snapshot-mode act
webcmd --session session_abc browser snapshot --snapshot-mode read
webcmd --session session_abc browser run --stdin --timeout 45
webcmd --session session_abc browser run --stdin --no-snapshot-diff
webcmd session list
webcmd session close session_abc
```

Agents sharing a profile can work in parallel by creating separate Sessions.
An authentication handoff is scoped to the Session that started it: run the
returned verification command verbatim because it includes `--session` when
needed. `session close` is blocked while that Session has a live handoff.

Use `snapshot` for explicit page inspection. `act` is the default
action-first mode, `tree` preserves fuller page structure, and `read` extracts readable article/content text. Exactly one of `--file
<path>` or `--stdin` is required for `run`. The CLI reads files locally and
Expand All @@ -79,11 +91,12 @@ The program runs in a fresh QuickJS sandbox with `page`, `context`, `browser`,
and `console` globals. `page.snapshotForAI()` is not available. It can use the
supported Page/Frame/Locator methods and passively inspect request and response
events. It cannot access Node.js, the filesystem, environment variables, raw
CDP endpoints, browser launch/connect APIs, or browser-context ownership.
CDP endpoints, browser launch/connect APIs, browser-context ownership, or
`context.newPage()`.
Screenshot bytes are written to a Webcmd-owned cache directory and returned as
a receipt.

The public browser surface is `tabs`, `bind`, `run`, `snapshot`, and `close`.
The public raw-browser surface is `tabs`, `bind`, `run`, and `snapshot`.
Reusable adapters continue to use the existing `IPage` API. Playwright-style
programs are for reconnaissance and ad-hoc multi-step work; they are not pasted
into adapter modules.
Expand Down
6 changes: 4 additions & 2 deletions docs/concepts.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,11 @@ The agent chooses the strategy; the human describes the outcome and constraints.
| `UI` | Drives the live page UI. |
| `LOCAL` | Talks to a local app, service, or CLI. |

## Sessions and State
## Profiles, Sessions, And Tabs

Browser commands can use an `ephemeral` session for an isolated tab or a `persistent` session for a longer workflow. A command can request `freshPage: true` when it needs a clean tab while keeping its session state.
A Profile is the browser identity and storage bucket, such as `default` or `work`. A Session is an opaque browser workspace inside a Profile; raw browser work creates one with `webcmd session create` and selects it at the root with `--session <session-id>`. A tab is one page inside that Session.

Adapter browser commands can use `siteSession: 'ephemeral'` for an isolated tab or `siteSession: 'persistent'` for a longer same-site workflow. Those adapter site-session modes are separate from raw browser Sessions.

## What the Human Needs to Decide

Expand Down
1 change: 1 addition & 0 deletions docs/skills.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ Do not also add the skills with `webcmd skills add` in Codex.
## Other Agents or Plugin-Free Setup

Run `webcmd skills add` to install or refresh the bundled Webcmd skills for your agent. The agent can then start with `webcmd-usage` and load the specialized skill that matches the outcome.
For raw browser work, agents should create a Session with `webcmd session create -f json` and pass it as a root selector: `webcmd --session <session-id> browser ...`.
Loading
Loading