Architecture
Architecture
New to the code? Read Architecture overview first (ten minutes), then The Vyre map: a 30-minute tour of the kernel, modules, the Gate, the Vault, Records and Flows, the apps and where data lives. This page is the short version.
Vyre is one small daemon, vyred, on each machine you own, plus a Claude Code plugin. Everything else is a module the daemon loads. This page is the map. The specification is the source of truth for every detail, and the decision records say why each hard choice went the way it did.
One process per machine
vyred runs every service on its machine (Section 2 of the spec, principle 3). It is the same code on the box and on the Mac, with different modules enabled, chosen by role in ~/.vyre/config.json (box or local). Most Core modules run on both; a few run only on the box (names, onboarding, agents' computers, Glass streaming), and the Local modules run only on the Mac. The exact split is in The box and the Mac. The vyre CLI is a thin client: every command is a call to vyred, over its unix socket (~/.vyre/vyred.sock) on the same machine or its HTTP API from elsewhere.
Everything is a module, including the core services, and every module uses the same contract: a module.json manifest and an entry file that registers tools and emits events. See Modules and The module contract. The loaded set on this branch is listed in the module reference.
The three layers
| Layer | Where it runs | What it is | Code |
|---|---|---|---|
| Core | the box (and the Mac, for the parts a Mac needs) | The services inside vyred: config, the store (SQLite through node:sqlite), the event log, the module loader, projects and threads, recall, memory, the vault, watchers, the Gate, the Switchboard (headless sessions), agents, computers, names and certificates, pairing, files, presence, learning, push. | core/ |
| Harness | inside every Claude Code session Vyre starts, and any session with the plugin installed | A Claude Code plugin. Vyre's own sessions load it with --plugin-dir, so your global Claude Code setup is never changed; you can also install it in your own Claude Code from the vyre-ai/vyre marketplace (ADR 0020). Hooks (Brief at session start, Enrich on each prompt, Rules before each tool call, Learn after file changes and commands, Stop at the end of each turn), the vyre MCP server that exposes module tools to Claude, three skills and the /vyre command. Every hook starts at harness/hooks/run.js, which runs the Vyre package's harness/hooks/hook.js, which calls vyred; with no Vyre on the machine it says how to install it once and does nothing else. If vyred is not running, Rules still runs in-process, so the floor holds. | harness/ |
| Local | the Mac only | Lumen (the Control-twice command bar) and hands-mac (computer use through the macOS accessibility tree). | local/ |
Optional first-party modules live in modules/: hands-desktop and hands-chrome (module name chrome) for agents' computers. modules/vault-extension is not a vyred module: it is the browser extension for vault autofill.
The box and the Mac are paired into one system by core/link: the Mac can call the box's tools, the box's events reach the Mac, and the box reads the Mac's sessions through a request the Mac holds open, so the Mac opens no port (ADR 0021). See The box and the Mac.
The floor's rules run twice: in Claude Code's PreToolUse hook, and in vyred for every tool call that does not come from you at your own surface. See the security floor.
Surfaces
Every surface talks to vyred's API. None reads the store directly (Section 9 of the spec).
| Surface | What it is | Built from |
|---|---|---|
| CLI | vyre: home, projects, threads, agents, vault, up, status, and vyre call for any tool. | core/cli |
| Lumen | The command bar on the Mac: press Control twice, talk to the assistant, an agent or a session. | local/capsule |
| Vyre app | One Expo app that runs as a web app at your address (/app/), on iPhone and on Android: Now, Projects, Memory, Agents, Chat, Vault, Settings. | apps/app |
| Chat | Projects, then every Claude Code session on the machine, each shown as a readable conversation that follows the terminal live. Sending from Chat drives the same session. | apps/app/src/chat |
| Glass | An agent's screen, live, with take-over. | apps/app/screens/glass and core/computers |
| Phone | The same Vyre app on iPhone and Android, or the web build added to the Home Screen. | apps/app |
| Status line | Vyre's line under every Claude Code session in your terminal, such as vyre · 2 need you · box ok · juno idle. vyre statusline install adds it. | core/statusline, harness/statusline |
A thread is one thing wherever it is viewed, and one screen types into it at a time (floor rules 3 and 4). Every session is a real Claude Code session, in a terminal or headless under the Switchboard; Vyre never imitates Claude Code.
Repository layout
The full tree is Section 3 of the spec. In short:
bin/vyre the CLI entry (thin: checks the Node version, calls core/cli)
core/ services that run inside vyred, one folder each
harness/ the Claude Code plugin: hooks, MCP server, skills, commands
local/ Mac-only modules: capsule, hands-mac
apps/app/ the Vyre app (Expo); vyred serves its web build at /app/
modules/ first-party optional modules
box/ the Docker stack for a server: Dockerfile, compose.yml, the host wrapper
site/ vyre.run: the landing page (build-site.sh adds the installer)
scripts/ install, release, perf-check, and the docs tooling
docs/ these pages, the spec, the ADRs
test/ cross-module tests; unit tests sit beside their code
Runtime data never lives in the repository. It lives in ~/.vyre/ (override with VYRE_HOME): config.json, the store vyre.db, the sealed vault/, installed modules/, watchers/, certs/, models/ and embedder/ (the search model, fetched on first use), logs/ and the socket. On a Docker box that folder is inside the vyre_vyre-home volume. See Looking after the box.
Principles that shape the code
The nine principles are in Section 2 of the spec. The ones you meet first when reading the code:
- Public Claude Code surfaces only. Plugins, hooks, MCP and documented CLI flags. Reading transcript files is the one exception, kept in a single adapter,
core/transcripts. - Local first. Nothing leaves your machines except through the Gate.
- Boring, readable code. Node 22.5 or newer, ES modules, plain JavaScript with JSDoc types and
// @ts-check, no build step for the core,node:sqlite,node:test. A dependency needs a reason in the changelog. - Light by default. Idle budgets for
vyred, Lumen and the Vyre app.scripts/perf-checkholdsvyredto its budget in CI; Lumen and the app are measured by hand. See Performance. - The security floor cannot be configured away. See the floor and Security.
Decision records
Architecture decision records live in docs/adr/. Each states the problem, the decision and its consequences.
| ADR | Decision |
|---|---|
| 0001 | How the vault seals, releases and shares credentials |
| 0002 | Network and identity: how a caller is identified at the server's door |
| 0003 | How Glass streams an agent's screen, and who may type into it |
| 0004 | Presence: proving a person is there before a human-only action |
| 0005 | Glass: a remote computer you can watch, take over, sign in on and browse |
| 0006 | The vault, next: a key hierarchy and presence on every value (proposed) |
| 0007 | The memory graph and the learning loop |
| 0008 | The install journey (proposed) |
| 0009 | Hardening an agent's container |
| 0010 | Vault autofill |
| 0011 | Web Push for the moments you are needed |
| 0012 | Chrome's debugging port never leaves the container unauthenticated |
| 0016 | Connectors, the MCP hub and native accounts (proposed) |
| 0019 | This docs site: one source in docs/, checked and built without a framework |
| 0020 | Vyre as an installable Claude Code plugin |
| 0021 | The box reads the paired Mac through the link |
Where to go next
- Specification, the whole design.
- Performance, the budgets and how they are measured.
- Security, the model in one page.
- Contributing, if you want to change any of this.