Skip to content

Repository files navigation

Plexus

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.

License: MIT Protocol 0.1.3 Runtime: Bun + TypeScript Platform: macOS-first

Watch it govern — five agents reaching real capabilities through the Plexus wall: reads flow standing, a write pends for approval, execute is per-call, off-subset bounces, revoke cuts it off

Five agents, one wall — reads flow, writes pend, execute is per-call, off-subset bounces, revoke is surgical. Watch it live on the site →


▶︎ Try it in 5 minutes — hand it to your AI

Open Claude Code (or any coding agent) in this repo and say: "read docs/getting-started.md and set Plexus up for me." It installs, starts Plexus, configures everything (asking you for the folder to expose), connects itself as an agent, and demonstrates one read and one write — while you approve each grant in the Plexus UI. You'll watch an agent reach your Mac's capabilities with no shell, locked to what you exposed, every powerful move approved by you.

docs/getting-started.md — the end-to-end runbook (also a fine copy-paste guide if you'd rather drive by hand).

Where to start

You want to… Go to
See what Plexus is and why you're on the right page — read on
Run it (hand the repo to your agent) docs/getting-started.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.


Why Plexus

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, Reminders, Notes, Mail, Contacts and Photos, your browser, your Shortcuts, 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.


Quick start (macOS)

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 demo

First 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.


Concepts (the 60-second model)

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:

  1. 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.
  2. 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 launcher plexus-<agentId> on its PATH.
  3. The agent discovers + calls through its launcher. plexus-<agentId> list shows 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) live with no restart — they appear immediately in the admin surface, and an agent discovers them once the owner adds them to that agent's authorized subset. 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 lands standing (frictionless re-use, 1d/7d) at connect. A side-effecting capability (write / execute, e.g. claudecode.run) is approved per use by default — a posture the agent can never lift itself. Only the owner can lift it, per agent + per capability: the standing opt-in at connect (default off, double-confirmed — the only path for execute), or, for a write, approving its pending request with a real trust window or granting it directly; once lifted, it rides a real trust-window / until-revoked.

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


What's exposed

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.
  • Apple Notes — read + a create-only write (apple-notes.notes.create; no update/delete exists).
  • Apple Mail — strictly read-only (mailboxes, bounded search, read one message; no draft/send exists).
  • Apple Contacts — read-only search + full-card read.
  • Apple Photos — read posture: albums, metadata-only search, and a jailed export (~/.plexus/exports/photos/).
  • Shortcuts — list (read) + run (execute → pends; record-mode by default, real launch is owner opt-in).
  • Browser — read-only Safari/Chrome tabs, bookmarks, history (per-browser graceful degradation).
  • Browser control (browser-control) — drive a real Chrome over the DevTools Protocol, no Puppeteer/Playwright dependency. The owner's decision is which browser: a fresh empty profile (launch, the default — no cookies, no sessions) or the browser they are logged into (attach, opt-in). The page surface is fully open, arbitrary JavaScript included, because inside an authorized page click+type already equal full user agency; what is withheld is the browser-global half of CDP (Target, Browser, Storage, the cookie jar), which is what keeps a domain allowlist meaningful. File upload is jailed to an owner-named directory.
  • 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 macOS sandbox-exec confinement (claudecode.run, execute → pends).
  • Codex (codex) — headless codex exec under the same sandbox confinement, a mirror of claudecode.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-source

Or 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


Screenshots

Overview — the dashboard: what's exposed, what needs you, recent activity.

Plexus overview

What I expose — the Connector → Source → Capability surface, with the dynamic config form for adding a source.

What I expose

Create an extension — author a manifest and preview its security surface before it ever goes live.

Create an extension


Security posture

  • Loopback by default. The gateway binds 127.0.0.1 only. Binding to a chosen NIC or 0.0.0.0 is 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 Host is 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


macOS-first, with a real cross-platform seam

Plexus is a Bun + TypeScript + Hono workspace monorepo:

packages/
  protocol/    the keystone — the compiler-enforced wire contract (frozen at 0.1.3)
  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, and Linux is implemented and end-to-end verified — the headless portable gateway runs on a real Linux kernel in Docker (Ubuntu + Bun; see docs/deploy-linux.md), auto-gating first-party sources to the portable {workspace, sysinfo} set. Windows is implemented behind the same seam but not yet validated on a real Windows host — so cross-platform is a fill-in, not a rewrite.

The protocol is frozen at PLEXUS_PROTOCOL_VERSION = 0.1.3 and evolves additive-only — new optional fields, never a breaking change to the wire.


Versioning — two numbers, two clocks

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.9.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.9.1)
Protocol version (PLEXUS_PROTOCOL_VERSION, 0.1.3) 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.9.1). The protocol version lives in code (@plexus/protocol) and .well-known/plexus, and bumps on its own schedule.


Build, test, typecheck

bash run-tests.sh    # the canonical gate: bunx tsc --noEmit (strict) + bun test
bunx tsc --noEmit    # typecheck only
bun test             # tests only

See CONTRIBUTING.md for the monorepo layout, the additive-only protocol rule, and how to author a source module or an extension.


Docs

Doc What it covers
Developer reading path Start here to understand + build — the spine that orders the docs below.
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/Notes/Mail/Contacts/Photos, Shortcuts, browser, Claude Code.
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.

Contributing & conduct

Contributions welcome — see CONTRIBUTING.md. This project follows the Contributor Covenant.

License

MIT © 2026 Plexus contributors.

About

A local, open-source capability gateway for AI agents — one AI-native self-describe endpoint so any agent can discover, understand, be granted, and call the software on your machine, under a trust model you can see, scope, and revoke.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

15 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages