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
22 changes: 22 additions & 0 deletions .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
"name": "openchrome",
"displayName": "OpenChrome",
"version": "1.12.5",
"description": "Harness-engineered browser automation. Control your real Chrome from any AI agent via MCP — parallel lanes, auto-recovery, verifiable contracts.",
"author": {
"name": "OpenChrome contributors",
"url": "https://github.com/shaun0927/openchrome"
},
"homepage": "https://github.com/shaun0927/openchrome",
"repository": "https://github.com/shaun0927/openchrome",
"license": "MIT",
"keywords": ["browser", "automation", "mcp", "chrome", "cdp"],
"mcpServers": {
"openchrome": {
"command": "openchrome",
"args": ["serve", "--auto-launch"]
}
},
"skills": "./skills/"
}
20 changes: 20 additions & 0 deletions .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "openchrome",
"version": "1.12.5",
"description": "Harness-engineered browser automation. Control your real Chrome from any AI agent via MCP — parallel lanes, auto-recovery, verifiable contracts.",
"author": {
"name": "OpenChrome contributors",
"url": "https://github.com/shaun0927/openchrome"
},
"homepage": "https://github.com/shaun0927/openchrome",
"repository": "https://github.com/shaun0927/openchrome",
"license": "MIT",
"keywords": ["browser", "automation", "mcp", "chrome", "cdp"],
"mcpServers": {
"openchrome": {
"command": "openchrome",
"args": ["serve", "--auto-launch"]
}
},
"skills": "./skills/"
}
51 changes: 51 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,57 @@ Transport stability policy: [`docs/transport-lifecycle.md`](docs/transport-lifec

---

## Host plugins

OpenChrome ships plugin manifests for Claude Code and Codex CLI so both hosts
load the MCP server and skill body from the **same shared source** — no
per-host duplication.

### Claude Code

Load from the repo for local development:

```bash
claude --plugin-dir /path/to/openchrome
```

Or install from npm after the package is published to a marketplace:

```bash
/plugin install openchrome # once listed in a marketplace
```

The skill body lives under `skills/openchrome/` and the `/openchrome:connect`
slash command is registered from the top-level `commands/` directory. Run
`/reload-plugins` after updating to pick up new content.

Manifest: `.claude-plugin/plugin.json` — registers the `openchrome` MCP server
(`openchrome serve --auto-launch`). Skills and commands are auto-discovered
from `skills/` and `commands/`.

### Codex CLI

Load from the repo for local development:

```bash
codex --plugin-dir /path/to/openchrome
```

Or follow the Codex plugin installation instructions once the package is listed
in the Codex plugin registry.

Manifest: `.codex-plugin/plugin.json` — identical MCP server entry point and
skill path; the two manifests share the same `skills/openchrome/` body.

### Shared skill body

Both manifests share `skills/openchrome/SKILL.md` as the single source of
truth for skill content, and the slash command stub at `commands/connect.md`
registers `/openchrome:connect`. The `commands/` directory sits at the plugin
root so both hosts auto-discover it.

---

## Documentation

| Topic | Link |
Expand Down
29 changes: 29 additions & 0 deletions commands/connect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
description: >
Connect to OpenChrome and confirm the MCP server is reachable. Runs a quick
health check, reports the Chrome CDP status, and prints the tool surface summary.
---

# /openchrome:connect

Check that OpenChrome is installed, the MCP server is running, and Chrome is
reachable. Then print a one-line summary of the available tool surface.

## Steps

1. Call `oc_connection_health` to verify the CDP connection and server version.
2. If `status` is `"ok"`, respond: "OpenChrome is connected — Chrome is live on
`<cdp_url>`. Server v`<version>` · `<tool_count>` tools available."
3. If `status` is not `"ok"`, report the error message verbatim and suggest
running `openchrome doctor` in a terminal to diagnose.

## Example output

```
OpenChrome is connected — Chrome is live on ws://127.0.0.1:9222.
Server v1.12.5 · 110 tools available.
```

## Arguments

`$ARGUMENTS` — ignored; this command takes no arguments.
61 changes: 61 additions & 0 deletions skills/openchrome/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
---
description: >
OpenChrome browser automation skill. Use when the user asks to navigate, click,
read, screenshot, crawl, or automate anything in a real Chrome browser. Covers
parallel lanes, authenticated scraping, outcome contracts, and skill replay.
---

# OpenChrome

OpenChrome is an MCP server that controls your real, already-logged-in Chrome
through the CDP. It wraps the browser API with a hint engine, circuit breaker,
auto-recovery runtime, and token-efficient page serialization.

<!-- Shared skill body — used by both Claude Code (.claude-plugin) and Codex
(.codex-plugin) manifests. Both manifests point to skills/ at the repo root,
so this file is the single source of truth (SSOT) for skill content. -->

## What you can do

- **Navigate** — `navigate url=<url>` opens a URL in a managed tab.
- **Read** — `read_page mode=dom` returns a compact, ~5–15x token-cheaper
serialization of the page. Use `ref_N` handles in follow-up actions.
- **Interact** — `interact`, `fill_form`, `form_input`, `act` for clicking,
typing, and high-level actions.
- **Screenshot** — `computer` returns a screenshot of the current viewport.
- **Parallel lanes** — open multiple tabs with `oc_lane_create`; work them
concurrently with the same Chrome session and existing cookies.
- **Outcome contracts** — `oc_assert` checks page state against a JSON contract
(url equals, dom_count ≥ N, dom_text contains …) and returns pass / fail /
inconclusive without guessing.
- **Skills** — `oc_skill_record` / `oc_skill_recall` store and replay procedural
memory across sessions.
- **Crawling** — async `crawl_start` / `crawl_status` / `crawl_cancel` with
cursor pagination.

## Setup

```bash
npm install -g openchrome-mcp
openchrome setup # Claude Code
openchrome setup --client codex # Codex CLI
```

Restart your MCP client. Chrome auto-launches on the first tool call.

## Key tools

| Tool | Purpose |
|---|---|
| `navigate` | Open a URL |
| `read_page` | Read page content (dom / markdown / screenshot) |
| `interact` | Click / type on an element |
| `oc_assert` | Verify page state against a contract |
| `oc_lane_create` | Open a parallel tab lane |
| `oc_skill_record` | Store a reusable step sequence |
| `oc_skill_recall` | Retrieve steps for a domain |
| `crawl_start` | Start an async crawl job |
| `oc_evidence_bundle` | Snapshot DOM + screenshot + network + console |
| `oc_diff` | Compare two evidence bundles |

Full catalogue: [`docs/agent/capability-map.md`](../../docs/agent/capability-map.md).
6 changes: 5 additions & 1 deletion tests/benchmark/fixtures/auth-app/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ export async function startAuthApp(): Promise<AuthApp> {
const sid = crypto.randomBytes(16).toString('hex');
sessions.set(sid, username);
res.writeHead(302, {
'set-cookie': `${SESSION_COOKIE}=${sid}; HttpOnly; Path=/`,
'set-cookie': `${SESSION_COOKIE}=${sid}; HttpOnly; Path=/; Max-Age=86400`,
location: '/',
});
res.end();
Expand Down Expand Up @@ -167,6 +167,10 @@ export async function startAuthApp(): Promise<AuthApp> {
close(): Promise<void> {
if (closed) return Promise.resolve();
closed = true;
// Browser drivers keep HTTP/1.1 sockets alive; force-close them so the
// benchmark runner can terminate promptly after each measured run.
server.closeIdleConnections?.();
server.closeAllConnections?.();
return new Promise<void>((resolve) => server.close(() => resolve()));
},
};
Expand Down
Loading