A local capability gateway for AI agents. Plexus is a user-installed, open-source gateway that exposes one AI-native self-describe endpoint, so any AI agent can DISCOVER → UNDERSTAND → be GRANTED → CALL the capabilities of the software on your machine — under a trust model you can see, scope, and revoke.
Open Claude Code (or any coding agent) in this repo and say:
"read START-HERE.md and set up the pomodoro demo for me." It installs, starts
Plexus, configures everything (asking you for a folder and an LLM key), and runs both
acts — while you approve each grant in the Plexus UI. You'll watch a remote agent build
a real app on your Mac with no shell, locked to one folder, every powerful move approved by
you. The onboarding is Plexus's thesis, compiled into your agent's native form.
→ START-HERE.md — the agent-executable runbook (also a fine
copy-paste guide if you'd rather drive by hand).
| You want to… | Go to |
|---|---|
| See what Plexus is and why | you're on the right page — read on |
| Run the demo (hand the repo to your agent) | START-HERE.md |
| Understand the model + build (install, connect an agent, author a source) | docs/README.md — the developer reading path |
This page is the product landing page. It won't repeat the getting-started steps —
follow docs/README.md for those.
MCP answers "what functions do I have?" Plexus answers "how should you use me?" — it wraps the functions in usage knowledge, a legible trust model, and an audit trail, then brokers them to agents over a stable, AI-native protocol.
The point isn't another tool registry. It's the surface no vendor ships a server for: the local macOS software you already use. Plexus turns your Obsidian vault, your Apple Calendar and Reminders, your Things 3 inbox, and your Claude Code orchestration into capabilities an agent can discover and call — without you handing over a blanket key, and without an agent ever self-granting a mutating action.
Transparency is the product. Default-deny, per-capability, scoped, revocable, audited — that trust story is the value, not a tax on it.
Plexus runs on Bun (≥ 1.3.0). Install Bun if you don't have it
(curl -fsSL https://bun.sh/install | bash), then:
# 1. Install dependencies (workspace monorepo)
bun install
# 2. Boot the gateway — loopback only (127.0.0.1:7077). Prints the URL, then stays
# running (Ctrl-C to stop).
bun run start
# Optionally open an Obsidian vault read-only at boot (persists as a managed source):
bun run start --vault ~/Documents/MyVault
# Print the ADMIN connection-key (the management credential — you use it to reach
# /admin; NEVER hand it to an agent). Read from ~/.plexus/, no server needed:
bun run start --print-key
# Prove the whole DISCOVER → GRANT → CALL loop end-to-end (self-contained, no setup):
bun run demoFirst run is automatic: the gateway creates ~/.plexus/ (connection-key, signing
secret, audit log) on first boot — nothing to configure. Open the management UI at
http://127.0.0.1:7077/admin to add sources, approve grants, and read the audit
trail. It's served same-origin from the gateway, so the page's HTML/assets load
key-free — but every /admin/api/* call still needs the connection-key. The SPA
resolves it desktop-IPC inject → cached → one-time paste: the Electron desktop
app injects it over IPC (no paste), while a plain browser uses a cached key or
prompts you to paste it once.
Desktop app (Electron, macOS): a developer-run tray shell supervises the runtime as a sidecar and hosts the same admin UI, with native approval notifications. Signed/notarized distribution and auto-update are deferred (the current build is unsigned). Run it from the desktop package:
bun run --cwd packages/desktop start→ Full walkthrough: docs/README.md — the developer reading
path: install, start, add a source, connect an agent (mint a one-time code + grant a
starting cap-set), and approve a grant with the trust-window picker.
Two credentials, never conflated. This is the whole trust story:
- connection-key (
plx_live_…) — the admin / management credential, and the trust boundary. The owner-as-admin holds it; rotating it revokes everything at once. Agents never see or use it. - per-agent PAT (
plx_agent_…) — each agent's own durable credential. It is redeemed once from a one-time enrollment code, hashed at rest, and revocable per agent. The PAT-authenticated handshake binds the real agentId — an agent can't self-assert someone else's identity.
The flow is admin → agent, not agent-helps-itself:
- The admin connects an agent. In the console's Connect an agent wizard (or
POST /admin/api/agents/connect) you name the agent, grant it a starting cap-set, and Plexus mints a one-time enrollment code (plx_enroll_…, 15-min, single-use). You hand the agent one command — never the connection-key. - The agent installs once. It runs the one-command install
(
curl -fsSL <gateway>/integration/<agentId>/install.sh | …), which redeems the code → stores its PAT (0600) → drops a compiled plugin exposing a per-agent launcherplexus-<agentId>on its PATH. - The agent discovers + calls through its launcher.
plexus-<agentId> listshows what it can call right now (standing-granted) vs what needs approval;plexus-<agentId> <capabilityId>invokes. That launcher is the agent's complete and only interface — it never hand-rolls HTTP and never guesses auth.
What you expose is modeled as Connector → Source → Capability: a managed source
(e.g. an Obsidian vault) registers capabilities (e.g. obsidian.vault.read) that
hot-appear in discovery with no restart. What you trust is a unified model:
per-capability scoped grants, trust-windows (once / 1h / 1d / 7d /
until-revoked), 3-class provenance (first-party / managed / extension), a
sensitivity rating, and the GET /grants ledger where every standing grant is
visible and revocable.
Standing is decided by sensitivity, not origin. A read capability can be
standing (frictionless re-use, 1d/7d) once approved. An execute or otherwise
high-sensitivity capability (e.g. claudecode.run) can never be standing — it is
approved per use with a once ceiling, even under an admin trust-window.
The agent interface is compiled, not bolted on. The per-agent launcher ships inside
a Claude Code plugin that is a projection over the always-present self-describing
floor (.well-known + requestShapes + how-to-use). The floor works for any agent
with no plugin at all; the plugin is a cache/shortcut that makes the same capabilities
feel more native per agent — never a replacement, and never a place a durable secret is
baked in.
→ Deep dive: docs/concepts.md ·
Security model: docs/design/security-model.md ·
Protocol contract: docs/protocol/PLEXUS-PROTOCOL.md
First-party sources (macOS-first; code + hermetic-test verified — live E2E against real macOS TCC apps was not run this round, see KNOWN-LIMITATIONS):
- Obsidian — read-only path-confined filesystem read (
obsidian.vault.read), or read-write via the Obsidian Local REST API plugin (obsidian-rest.vault.{list,read,write}). - Apple Calendar — read-only (
grants:["read"]by construction). - Apple Reminders — read and write.
- Things 3 — AppleScript read + a narrow URL-scheme write ("append a to-do").
- cc-master — Claude Code long-horizon orchestration, launched headless with an
embedded plugin (it never touches your
~/.claude/). - Workspace (
workspace) — one authorized working directory as a path-confined filesystem: read (workspace.{list,read}) and write (workspace.write→ pends). - Claude Code (
claudecode) — headless Claude Code under macOSsandbox-execconfinement (claudecode.run,execute→ pends). - Codex (
codex) — headlesscodex execunder the same sandbox confinement, a mirror ofclaudecode.run(codex.run,execute→ pends).
Each source reports its own health (agent-facing field + the admin dashboard via
GET /admin/api/health), so an agent — and you — can see when a backing app is
unreachable before a call fails.
User extensions — author a manifest, preview the security surface (cli bins, rest hosts, cross-source attaches, per-capability verbs), then install it live:
plexus extension preview ./my-source.json # validate + show the security surface (no commit)
plexus extension add ./my-source.json # install live (you are the human approver)
plexus extension list
plexus extension remove my-sourceOr do all of it from the /admin UI. An authoring guide for coding agents is
served at GET /admin/api/extensions/authoring-guide.
→ Tutorials: connect an agent · create an extension · first-party sources
Overview — the dashboard: what's exposed, what needs you, recent activity.
What I expose — the Connector → Source → Capability surface, with the dynamic config form for adding a source.
Create an extension — author a manifest and preview its security surface before it ever goes live.
- Loopback by default. The gateway binds
127.0.0.1only. Binding to a chosen NIC or0.0.0.0is opt-in (~/.plexus/network.json), and when you do, every/admin/api/*route is connection-key gated — the connection-key becomes the trust boundary for the LAN. - Host/Origin guard on every endpoint before auth (DNS-rebinding defense); a
request without the matching
Hostis rejected (host_forbidden, 403). - Default-deny, scoped invoke. A grant is per-capability and verb-scoped; tokens
are short-lived. Mutating (
write/execute) grants pend for a human — an agent cannot self-grant them. - Re-gating on change. Reconfiguring a source's endpoint/secret purges its grants, so a prior approval can't silently carry over to a new target.
- Secrets are stored under
~/.plexus/secrets/and referenced by name — never written into config files, never echoed back.
→ Full write-up: docs/security.md
Plexus is a Bun + TypeScript + Hono workspace monorepo:
packages/
protocol/ the keystone — the compiler-enforced wire contract (frozen at 0.1.2)
runtime/ the headless loopback gateway (discovery, grants, invoke, audit, sources)
cli/ the `plexus` CLI (discover / manifest / skills / call / source / extension / bundle)
web-admin/ the same-origin React management UI
desktop/ the Electron shell (macOS) — supervisor + tray + native notifications
The OS surface lives behind a single PlatformServices seam: macOS is the shipped,
fully-implemented target; the Windows/Linux implementations are typed stubs behind the
same seam, so cross-platform is a fill-in, not a rewrite.
The protocol is frozen at PLEXUS_PROTOCOL_VERSION = 0.1.2 and evolves
additive-only — new optional fields, never a breaking change to the wire.
Plexus carries two independent version numbers, and the distinction matters:
| What it is | How it moves | Who depends on it | |
|---|---|---|---|
Software version (PLEXUS_VERSION, e.g. 0.7.0-rc.1) |
the product release — the gateway, desktop app, sources, UI | fast — every feature/fix bumps it | nobody on the wire; it's informational (shown in the admin UI as running · v0.7.0-rc.1) |
Protocol version (PLEXUS_PROTOCOL_VERSION, 0.1.2) |
the agent-facing wire contract — the shapes of discover / handshake / grant / invoke | rarely — frozen, additive-only (a new optional field bumps the patch) | agents integrate against this, never the software version |
They are decoupled by design: the product can ship 0.6 → 0.7 → 1.0 … while the
protocol stays 0.1.x, because the wire is stable under a fast-moving app. An agent
that integrated at protocol 0.1.0 keeps working across every software release — it only
needs to care when the protocol version changes (and even then, additively). The admin
UI surfaces both, distinctly: running · v<software> · protocol <protocol>.
Tags/releases track the software version (
v0.7.0-rc.1). The protocol version lives in code (@plexus/protocol) and.well-known/plexus, and bumps on its own schedule.
bash run-tests.sh # the canonical gate: bunx tsc --noEmit (strict) + bun test
bunx tsc --noEmit # typecheck only
bun test # tests onlySee CONTRIBUTING.md for the monorepo layout, the additive-only
protocol rule, and how to author a source module or an extension.
| Doc | What it covers |
|---|---|
| Developer reading path | Start here to understand + build — the spine that orders the docs below. |
| Start here (AI-native onboarding) | Hand the repo to Claude Code: it sets up + runs the pomodoro demo while you approve grants. |
| Getting started (macOS) | Install → start → connect an agent (mint a code + grant a cap-set), end to end. |
| Concepts | The self-describe protocol, the trust model, sources & extensions. |
| Security | Loopback boundary, connection-key, Host/Origin guard, re-gating. |
| Connect an agent | Drive Plexus from a coding agent. |
| Create an extension | Author + preview + install a manifest. |
| First-party sources | Obsidian, Apple Calendar/Reminders, Things 3, cc-master. |
| Pomodoro demo (Plexus × DeepAgents) | A remote agent builds real software on your Mac — no shell, one folder, every powerful move approved. |
| Protocol contract | The frozen wire spec + the ADRs. |
| Known limitations | Honest pre-1.0 state: MCP ingestion, io.input scope, desktop/cross-platform not E2E-verified. |
Contributions welcome — see CONTRIBUTING.md. This project follows
the Contributor Covenant.
MIT © 2026 Plexus contributors.


