Skip to main content

Local-first session bridge that lets AI agents borrow your authenticated browser sessions per-site, per-action, fully audited.

Project description

Coral — sudo for browser agents

License: Apache 2.0 Python 3.11+ Status: alpha CI

Alpha — pre-audit. Coral has not yet undergone an external security review. The design (THREAT_MODEL.md) is transparent about what's defended and what isn't, but until a v1.0 release ships with a third-party review, treat Coral as experimental. Don't use it to broker sessions for accounts you can't afford to have compromised.

Coral is a local-first session bridge that lets AI agents borrow your already-authenticated browser sessions on a per-site, per-action, fully audited basis. You log in once in your real Chrome — passing 2FA, captchas, whatever — and Coral persists the resulting authenticated state in a passphrase-encrypted vault. When an agent needs to act on that site, Coral spins up a fresh isolated Chromium with your session restored and hands the agent a CDP URL it can drive. The agent never sees your password.

How it fits together

  • Python daemon + CLI (this repo) — vault, HTTP API, MCP server, Playwright session manager, policy engine.
  • Chrome extension (extension/) — captures sessions from your normal browsing. Submitted to the Chrome Web Store; while the listing is under review, load it unpacked as shown below.
  • MCP — any MCP-speaking agent (Claude Desktop, Cursor, Claude Code, browser-use, Stagehand, …) drives Coral over stdio or local HTTP.

What it looks like in your code

The dominant use case is embedding Coral as a session manager inside your own agent code. You log in to a site once in your real Chrome, Coral persists the session in an encrypted vault, and your application hands the agent of your choice an authenticated, isolated browser via CDP. The agent never sees a password.

Here's the whole pattern with browser-use:

from mcp import ClientSession
from mcp.client.stdio import StdioServerParameters, stdio_client
from browser_use import Agent, Browser
from langchain_openai import ChatOpenAI


async def run_against_my_session(task: str, origin: str) -> str:
    """Drive an authenticated browser via an LLM, without ever handling
    the user's password. Coral owns the session; browser-use drives it."""
    server = StdioServerParameters(command="coral", args=["mcp-stdio"])

    async with stdio_client(server) as (r, w), ClientSession(r, w) as coral:
        await coral.initialize()

        listing = await coral.call_tool("coral_list_sessions", {})
        sessions = listing.structuredContent["sessions"]
        chosen = next(
            s for s in sessions if s["origin"] == origin and s["state"] == "active"
        )

        opened = await coral.call_tool(
            "coral_open_session",
            {"session_id": chosen["session_id"], "purpose": task},
        )
        cdp_url = opened.structuredContent["cdp_url"]
        handle  = opened.structuredContent["session_handle"]

        try:
            agent = Agent(
                task=task,
                llm=ChatOpenAI(model="gpt-4o"),
                browser=Browser(cdp_url=cdp_url),   # Coral's isolated Chromium
            )
            return str(await agent.run())
        finally:
            await coral.call_tool("coral_close_session", {"session_handle": handle})

That snippet drops into any Python codebase — a CLI subcommand, a FastAPI handler, a worker, a notebook cell. Coral provides the authenticated, policy-checked browser; browser-use provides the LLM-driven action loop. They meet at the CDP URL. Every navigation the agent makes still flows through Coral's policy engine; denied paths abort before the network call.

The same pattern works with Stagehand in TypeScript, or with the raw mcp SDK + Playwright if you're building your own action loop — see examples/ for both.

Requirements

  • Python 3.11+ (pip or uv).
  • macOS or Linux. Windows isn't supported yet.
  • SQLCipher native library — install before pip install coralbridge, because sqlcipher3 builds against it:
    • macOS — brew install sqlcipher
    • Debian / Ubuntu — sudo apt install libsqlcipher-dev
    • Fedora / RHEL — sudo dnf install sqlcipher-devel
    • Arch — sudo pacman -S sqlcipher
  • Node 20+ — only required if you want to build the Chrome extension from source. Otherwise grab the pre-built zip from the latest GitHub release.

Install

pip install coralbridge
playwright install chromium

That's it. coral is now on your PATH ready to run.

Working from a checkout instead (recommended for contributors):

git clone https://github.com/noelschwarz/coral
cd coral
uv sync --all-extras
uv run playwright install chromium

After uv sync, use uv run coral … everywhere — or run uv tool install . to get the coral script on your PATH without prepending uv run.

Quickstart

Three terminal commands and three Chrome clicks. End-to-end under a minute.

1. Start the daemon

coral up

coral up initializes the encrypted vault on first run (asks for a passphrase), starts the daemon in the background, and copies a pairing challenge to your clipboard.

2. Load the extension

Pre-built bundle (recommended) — no Node.js required. Grab coral-extension.zip from the latest release, unzip it into any directory, and load that directory in Chrome (step 3 below).

mkdir -p ~/coral-extension && cd ~/coral-extension
curl -L -o coral-extension.zip \
  https://github.com/noelschwarz/coral/releases/latest/download/coral-extension.zip
unzip -o coral-extension.zip

Build from source — only if you want unreleased extension changes:

cd extension
npm ci
npm run build
# load extension/dist/ in Chrome

In Chrome:

  1. Open chrome://extensions.
  2. Toggle Developer mode (top-right).
  3. Click Load unpacked and select the directory from the step above (~/coral-extension/ for the pre-built bundle, or extension/dist/ when building from source).
  4. Pin the Coral icon to your toolbar.
  5. Click the icon — the popup auto-detects the clipboard challenge — and press Pair.

3. Capture a session

  1. Navigate to any site you're already logged into.
  2. Click the Coral icon → Capture session.

Verify from the terminal:

coral status      # daemon state, active sessions, connected agents
coral list        # captured sessions

That's it — an MCP agent can now open this session via coral_open_session.

Make it permanent

So you don't have to keep a terminal open or re-run coral up after every reboot:

coral install-service

That writes a launchd LaunchAgent (macOS) or systemd --user unit (Linux) and stores the vault passphrase in your OS keychain (ADR-017). The daemon now starts automatically on login.

To undo:

coral uninstall-service

Wire Coral into your MCP client

If you'd rather have your IDE-resident agent (Claude Desktop, Cursor, Claude Code) call Coral on its own — instead of embedding the snippet above in your own code — one command writes the config:

coral mcp install --client claude-desktop   # or: cursor, claude-code

That writes a coral MCP-server entry into the client's config file (no JSON editing). Restart the client and it'll spawn coral mcp-stdio on demand. The LLM in your IDE can then call coral_list_sessions / coral_open_session / coral_close_session itself as part of any chat task. coral mcp status --client <name> shows the current entry; coral mcp uninstall --client <name> removes it.

For embedding Coral inside your own application code, see the snippet above and the examples/ directory:

Per-session Chromium isolation (ADR-010) keeps every session in its own sandboxed profile no matter which client drives it.

Copy, modify, and discard.

Daily commands

coral status                          # daemon state, sessions, agents
coral list                            # captured sessions
coral revoke https://example.com      # revoke session(s) for an origin
coral audit --since 0 --limit 50      # tail the audit log
coral panic --yes                     # revoke everything + stop daemon
coral diagnose                        # install + security self-check
coral keychain status                 # is the vault passphrase stashed?

Policy & review

Each origin has a YAML policy declaring allowed_paths, denied_paths, rate limits, and review thresholds. Six bundled behavior packs (GitHub, Gmail, Linear, LinkedIn, Notion, Slack) seed at first run with default_action: deny plus explicit allow-lists.

coral policy get https://github.com               # print the active YAML
coral policy put https://github.com -f my.yaml    # upload a new one
coral reviews list                                # pending operator reviews
coral approve <review_id>
coral deny    <review_id>

Schema in docs/policy-language.md; rationale in ADR-011.

Environment variables

  • CORAL_HOME — data directory (default ~/.coral).
  • CORAL_PASSPHRASE — non-interactive passphrase for init / start (CI and scripts only — prefer the OS keychain for daily use).
  • CORAL_HTTP_PORT, CORAL_MCP_HTTP_PORT — port overrides. The host is always 127.0.0.1 (ADR-008).
  • CORAL_DIAG_LEVEL — structured stderr log filter (debug|info|warn|error, default info).

Docs

Contributing

See CONTRIBUTING.md for the dev workflow, quality gates, and DCO sign-off requirements. The project follows the Contributor Covenant 2.1.

Community

License

Licensed under the Apache License, Version 2.0. Contributions are accepted under the same terms.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

coralbridge-0.6.0.tar.gz (111.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

coralbridge-0.6.0-py3-none-any.whl (85.5 kB view details)

Uploaded Python 3

File details

Details for the file coralbridge-0.6.0.tar.gz.

File metadata

  • Download URL: coralbridge-0.6.0.tar.gz
  • Upload date:
  • Size: 111.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for coralbridge-0.6.0.tar.gz
Algorithm Hash digest
SHA256 09bb71547f1fd8025e4082b26d57accaf75c4bcaecaf9e42b12c4c3781307880
MD5 1fa531e05ea5269a86f9e3f6f5cc05de
BLAKE2b-256 938ca2127e8c17fc34d95f29bb17cf7dbfe2b40546e697a68325b5fceace8061

See more details on using hashes here.

Provenance

The following attestation bundles were made for coralbridge-0.6.0.tar.gz:

Publisher: release.yml on noelschwarz/coral

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file coralbridge-0.6.0-py3-none-any.whl.

File metadata

  • Download URL: coralbridge-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 85.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for coralbridge-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 cb6b5380bcd9e2e11e6bc0805d68f796c8a6eb0b8129463b26941e7e1dd60281
MD5 cbb9ee85ccd026c280db846898369dd7
BLAKE2b-256 86bdf47276d3d65b827b8aa062505cfdfe6a0299ba78b0d308676af64884eba2

See more details on using hashes here.

Provenance

The following attestation bundles were made for coralbridge-0.6.0-py3-none-any.whl:

Publisher: release.yml on noelschwarz/coral

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page