{"id":51007550,"url":"https://github.com/noelschwarz/coral","last_synced_at":"2026-06-20T22:01:49.041Z","repository":{"id":359895150,"uuid":"1229418777","full_name":"noelschwarz/coral","owner":"noelschwarz","description":"Coral is an open-source, local-first session bridge that lets AI agents borrow a user's already-authenticated browser sessions on a per-site, per-action, fully audited basis.","archived":false,"fork":false,"pushed_at":"2026-06-02T03:59:47.000Z","size":44450,"stargazers_count":1,"open_issues_count":11,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-02T05:23:47.021Z","etag":null,"topics":["agents","ai","ai-agents","browser-automation","chrome-extension","local-first","mcp","model-context","playwright","python","security","session-management"],"latest_commit_sha":null,"homepage":"https://basematter.dev","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/noelschwarz.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":"THREAT_MODEL.md","audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-05T02:54:09.000Z","updated_at":"2026-05-25T22:48:56.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/noelschwarz/coral","commit_stats":null,"previous_names":["noelschwarz/coral"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/noelschwarz/coral","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noelschwarz%2Fcoral","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noelschwarz%2Fcoral/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noelschwarz%2Fcoral/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noelschwarz%2Fcoral/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/noelschwarz","download_url":"https://codeload.github.com/noelschwarz/coral/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noelschwarz%2Fcoral/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34586666,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-20T02:00:06.407Z","response_time":98,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agents","ai","ai-agents","browser-automation","chrome-extension","local-first","mcp","model-context","playwright","python","security","session-management"],"created_at":"2026-06-20T22:01:43.296Z","updated_at":"2026-06-20T22:01:49.035Z","avatar_url":"https://github.com/noelschwarz.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Coral — `sudo` for browser agents\n\n[![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)\n[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)\n[![Status: alpha](https://img.shields.io/badge/status-alpha-orange.svg)](THREAT_MODEL.md)\n[![CI](https://github.com/noelschwarz/coral/actions/workflows/ci.yml/badge.svg)](https://github.com/noelschwarz/coral/actions)\n\n\u003e **Alpha — pre-audit.** Coral has not yet undergone an external security\n\u003e review. The design ([THREAT_MODEL.md](THREAT_MODEL.md)) is transparent about\n\u003e what's defended and what isn't, but until a v1.0 release ships with a\n\u003e third-party review, treat Coral as experimental. Don't use it to broker\n\u003e sessions for accounts you can't afford to have compromised.\n\nCoral is a **local-first session bridge** that lets AI agents borrow your\nalready-authenticated browser sessions on a per-site, per-action, fully\naudited basis. You log in once in your real Chrome — passing 2FA, captchas,\nwhatever — and Coral persists the resulting authenticated state in a\npassphrase-encrypted vault. When an agent needs to act on that site, Coral\nspins up a fresh isolated Chromium with your session restored and hands the\nagent a CDP URL it can drive. **The agent never sees your password.**\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/img/demo.gif\"\n       alt=\"Coral demo: terminal opens a captured GitHub session; a fresh authenticated Chromium pops up, prints the page title, writes refreshed cookies back to the encrypted vault, and closes — without the agent ever seeing the password.\"\n       width=\"780\"\u003e\n\u003c/p\u003e\n\n## How it fits together\n\n- **Python daemon + CLI** (this repo) — vault, HTTP API, MCP server,\n  Playwright session manager, policy engine.\n- **Chrome extension** (`extension/`) — captures sessions from your normal\n  browsing. Submitted to the Chrome Web Store; while the listing is under\n  review, load it unpacked as shown below.\n- **MCP** — any MCP-speaking agent (Claude Desktop, Cursor, Claude Code,\n  browser-use, Stagehand, …) drives Coral over stdio or local HTTP.\n\n## What it looks like in your code\n\nThe dominant use case is **embedding Coral as a session manager inside\nyour own agent code**. You log in to a site once in your real Chrome,\nCoral persists the session in an encrypted vault, and your application\nhands the agent of your choice an authenticated, isolated browser via\nCDP. The agent never sees a password.\n\nHere's the whole pattern with [`browser-use`](https://github.com/browser-use/browser-use):\n\n```python\nfrom mcp import ClientSession\nfrom mcp.client.stdio import StdioServerParameters, stdio_client\nfrom browser_use import Agent, Browser\nfrom langchain_openai import ChatOpenAI\n\n\nasync def run_against_my_session(task: str, origin: str) -\u003e str:\n    \"\"\"Drive an authenticated browser via an LLM, without ever handling\n    the user's password. Coral owns the session; browser-use drives it.\"\"\"\n    server = StdioServerParameters(command=\"coral\", args=[\"mcp-stdio\"])\n\n    async with stdio_client(server) as (r, w), ClientSession(r, w) as coral:\n        await coral.initialize()\n\n        listing = await coral.call_tool(\"coral_list_sessions\", {})\n        sessions = listing.structuredContent[\"sessions\"]\n        chosen = next(\n            s for s in sessions if s[\"origin\"] == origin and s[\"state\"] == \"active\"\n        )\n\n        opened = await coral.call_tool(\n            \"coral_open_session\",\n            {\"session_id\": chosen[\"session_id\"], \"purpose\": task},\n        )\n        cdp_url = opened.structuredContent[\"cdp_url\"]\n        handle  = opened.structuredContent[\"session_handle\"]\n\n        try:\n            agent = Agent(\n                task=task,\n                llm=ChatOpenAI(model=\"gpt-4o\"),\n                browser=Browser(cdp_url=cdp_url),   # Coral's isolated Chromium\n            )\n            return str(await agent.run())\n        finally:\n            await coral.call_tool(\"coral_close_session\", {\"session_handle\": handle})\n```\n\nThat snippet drops into any Python codebase — a CLI subcommand, a\nFastAPI handler, a worker, a notebook cell. **Coral provides the\nauthenticated, policy-checked browser; `browser-use` provides the\nLLM-driven action loop. They meet at the CDP URL.** Every navigation\nthe agent makes still flows through Coral's policy engine; denied\npaths abort before the network call.\n\nThe same pattern works with [Stagehand](https://github.com/browserbase/stagehand)\nin TypeScript, or with the raw `mcp` SDK + Playwright if you're\nbuilding your own action loop —\nsee [`examples/`](examples/) for both.\n\n## Requirements\n\n- **Python 3.11+** (`pip` or `uv`).\n- **macOS** or **Linux**. Windows isn't supported yet.\n- **SQLCipher native library** — install *before* `pip install coralbridge`,\n  because `sqlcipher3` builds against it:\n  - macOS — `brew install sqlcipher`\n  - Debian / Ubuntu — `sudo apt install libsqlcipher-dev`\n  - Fedora / RHEL — `sudo dnf install sqlcipher-devel`\n  - Arch — `sudo pacman -S sqlcipher`\n- **Node 20+** — only required if you want to build the Chrome extension\n  from source. Otherwise grab the pre-built zip from the [latest GitHub\n  release](https://github.com/noelschwarz/coral/releases/latest).\n\n## Install\n\n```sh\npip install coralbridge\nplaywright install chromium\n```\n\nThat's it. `coral` is now on your `PATH` ready to run.\n\nWorking from a checkout instead (recommended for contributors):\n\n```sh\ngit clone https://github.com/noelschwarz/coral\ncd coral\nuv sync --all-extras\nuv run playwright install chromium\n```\n\nAfter `uv sync`, use `uv run coral …` everywhere — or run `uv tool install .`\nto get the `coral` script on your `PATH` without prepending `uv run`.\n\n## Quickstart\n\nThree terminal commands and three Chrome clicks. End-to-end under a minute.\n\n### 1. Start the daemon\n\n```sh\ncoral up\n```\n\n`coral up` initializes the encrypted vault on first run (asks for a\npassphrase), starts the daemon in the background, and **copies a pairing\nchallenge to your clipboard**.\n\n### 2. Load the extension\n\n**Pre-built bundle (recommended)** — no Node.js required. Grab\n`coral-extension.zip` from the [latest release](https://github.com/noelschwarz/coral/releases/latest),\nunzip it into any directory, and load that directory in Chrome (step 3\nbelow).\n\n```sh\nmkdir -p ~/coral-extension \u0026\u0026 cd ~/coral-extension\ncurl -L -o coral-extension.zip \\\n  https://github.com/noelschwarz/coral/releases/latest/download/coral-extension.zip\nunzip -o coral-extension.zip\n```\n\n**Build from source** — only if you want unreleased extension changes:\n\n```sh\ncd extension\nnpm ci\nnpm run build\n# load extension/dist/ in Chrome\n```\n\nIn Chrome:\n\n1. Open `chrome://extensions`.\n2. Toggle **Developer mode** (top-right).\n3. Click **Load unpacked** and select the directory from the step above\n   (`~/coral-extension/` for the pre-built bundle, or `extension/dist/`\n   when building from source).\n4. Pin the Coral icon to your toolbar.\n5. Click the icon — the popup auto-detects the clipboard challenge — and\n   press **Pair**.\n\n### 3. Capture a session\n\n1. Navigate to any site you're already logged into.\n2. Click the Coral icon → **Capture session**.\n\nVerify from the terminal:\n\n```sh\ncoral status      # daemon state, active sessions, connected agents\ncoral list        # captured sessions\n```\n\nThat's it — an MCP agent can now open this session via `coral_open_session`.\n\n### Make it permanent\n\nSo you don't have to keep a terminal open or re-run `coral up` after every\nreboot:\n\n```sh\ncoral install-service\n```\n\nThat writes a launchd LaunchAgent (macOS) or systemd `--user` unit (Linux)\nand stores the vault passphrase in your OS keychain\n([ADR-017](docs/ADR-017-keychain-integration.md)). The daemon now starts\nautomatically on login.\n\nTo undo:\n\n```sh\ncoral uninstall-service\n```\n\n## Wire Coral into your MCP client\n\nIf you'd rather have your IDE-resident agent (Claude Desktop, Cursor,\nClaude Code) call Coral on its own — instead of embedding the snippet\nabove in your own code — one command writes the config:\n\n```sh\ncoral mcp install --client claude-desktop   # or: cursor, claude-code\n```\n\nThat writes a `coral` MCP-server entry into the client's config file\n(no JSON editing). Restart the client and it'll spawn `coral mcp-stdio`\non demand. The LLM in your IDE can then call `coral_list_sessions` /\n`coral_open_session` / `coral_close_session` itself as part of any chat\ntask. `coral mcp status --client \u003cname\u003e` shows the current entry;\n`coral mcp uninstall --client \u003cname\u003e` removes it.\n\nFor embedding Coral inside your own application code, see the\n[snippet above](#what-it-looks-like-in-your-code) and the\n[`examples/`](examples/) directory:\n\n- [`examples/browser_use/`](examples/browser_use/) — Python +\n  [browser-use](https://github.com/browser-use/browser-use) LLM agent.\n- [`examples/stagehand/`](examples/stagehand/) — TypeScript +\n  [Stagehand](https://github.com/browserbase/stagehand).\n- [`examples/python_mcp/`](examples/python_mcp/) — raw `mcp` SDK +\n  Playwright for custom action loops.\n\nPer-session Chromium isolation ([ADR-010](docs/ADR-010-per-session-chromium.md))\nkeeps every session in its own sandboxed profile no matter which\nclient drives it.\n\nCopy, modify, and discard.\n\n## Daily commands\n\n```sh\ncoral status                          # daemon state, sessions, agents\ncoral list                            # captured sessions\ncoral revoke https://example.com      # revoke session(s) for an origin\ncoral audit --since 0 --limit 50      # tail the audit log\ncoral panic --yes                     # revoke everything + stop daemon\ncoral diagnose                        # install + security self-check\ncoral keychain status                 # is the vault passphrase stashed?\n```\n\n## Policy \u0026 review\n\nEach origin has a YAML policy declaring `allowed_paths`, `denied_paths`,\nrate limits, and review thresholds. Six bundled behavior packs (GitHub,\nGmail, Linear, LinkedIn, Notion, Slack) seed at first run with\n`default_action: deny` plus explicit allow-lists.\n\n```sh\ncoral policy get https://github.com               # print the active YAML\ncoral policy put https://github.com -f my.yaml    # upload a new one\ncoral reviews list                                # pending operator reviews\ncoral approve \u003creview_id\u003e\ncoral deny    \u003creview_id\u003e\n```\n\nSchema in [`docs/policy-language.md`](docs/policy-language.md); rationale\nin [ADR-011](docs/ADR-011-policy-engine.md).\n\n## Environment variables\n\n- `CORAL_HOME` — data directory (default `~/.coral`).\n- `CORAL_PASSPHRASE` — non-interactive passphrase for `init` / `start`\n  (CI and scripts only — prefer the OS keychain for daily use).\n- `CORAL_HTTP_PORT`, `CORAL_MCP_HTTP_PORT` — port overrides. The host is\n  always `127.0.0.1` ([ADR-008](docs/ADR-008-http-api-and-mcp.md)).\n- `CORAL_DIAG_LEVEL` — structured stderr log filter\n  (`debug|info|warn|error`, default `info`).\n\n## Docs\n\n- [`coral-engineering-spec.md`](coral-engineering-spec.md) — source of truth.\n- [`docs/architecture.md`](docs/architecture.md) — current module map.\n- [`THREAT_MODEL.md`](THREAT_MODEL.md) — what Coral defends against (and what it doesn't).\n- [`docs/policy-language.md`](docs/policy-language.md) — YAML policy schema.\n- [`SECURITY.md`](SECURITY.md) — vulnerability reporting policy.\n- [`CHANGELOG.md`](CHANGELOG.md) — release history.\n- [`docs/release-process.md`](docs/release-process.md) — tagging,\n  building, attaching the extension zip, publishing to PyPI.\n- `docs/ADR-006` … `docs/ADR-018` — individual architectural decisions.\n\n## Contributing\n\nSee [`CONTRIBUTING.md`](CONTRIBUTING.md) for the dev workflow, quality\ngates, and DCO sign-off requirements. The project follows the\n[Contributor Covenant 2.1](CODE_OF_CONDUCT.md).\n\n## Community\n\n- **Questions, design discussions, show-and-tell:** [GitHub Discussions](https://github.com/noelschwarz/coral/discussions).\n- **Bugs and feature requests:** [GitHub Issues](https://github.com/noelschwarz/coral/issues).\n- **Security reports:** use [private vulnerability reporting](https://github.com/noelschwarz/coral/security/advisories/new),\n  not a public issue. Details in [`SECURITY.md`](SECURITY.md).\n\n## License\n\nLicensed under the [Apache License, Version 2.0](LICENSE). Contributions\nare accepted under the same terms.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnoelschwarz%2Fcoral","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnoelschwarz%2Fcoral","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnoelschwarz%2Fcoral/lists"}