Lightweight, stable agent runtime. Apache 2.0 licensed.
Zero bloat. Zero lock-in. Just the loop.
RivetOS is a personal AI agent runtime built for reliability. A tiny, stable core routes messages between channels and LLM providers. Everything else is a plugin: providers, channels, tools, memory.
Container-first. The container IS the product. Security via isolation, setup via wizard, updates via source rebuild. One config file drives everything.
- Tiny core, fat plugins: The runtime kernel is a small, stable surface: a loop, a router, a queue, a hook pipeline. Everything else is swappable.
- Streaming-first:
AsyncIterable<StreamEvent>from every provider. Responses stream in real-time. - 8 LLM providers: Anthropic (Claude), xAI (Grok), Google (Gemini), Ollama, vLLM, llama-server (llama.cpp), claude-cli (Claude Code subscription), opencode-cli (OpenCode; default z.ai GLM).
- 1 channel plugin: Agent (HTTP inter-agent / mesh). Human UX is RivetHub via the node gateway. Social bots (Discord, Telegram, Voice) were removed in Phase 5.
- MCP transport plugin: Expose RivetOS tools (memory, web, skills) to external MCP clients over StreamableHTTP.
- 20+ built-in tools: Shell, file I/O, search, web, memory, skills, interaction, MCP client, delegation, sub-agents.
- Multi-agent mesh: Delegate tasks across agents. Local or remote. Transparent routing.
- Hook system: Composable pipeline for safety, auto-actions, session lifecycle.
- Interactive setup:
rivetos initwalks you through everything step by step. - Container deployment: Docker Compose or Proxmox LXC. Images built from source, plugins included.
- Source-based updates:
rivetos updatepulls, rebuilds, restarts. Forks and custom plugins are first-class. - Full control surface:
/stop,/steer,/new,/status,/model,/think,/context. - Interrupt that works:
AbortControllerpropagated to every API call and tool. - Persistent memory: PostgreSQL + pgvector. Hybrid FTS + vector search. Summary DAG. Learning loop.
- rivet-den: harness event contract (
den-protocol) + den-server intake for session linkage and chat indicators. Protocol. - Structured observability: JSON logging, runtime metrics, health endpoints,
rivetos doctor. - Laptop install:
curl -fsSL https://get.rivethub.io/local.sh | bash(stable on rivethub.io / get.rivethub.io). GitHub tags are source pins, not the app update feed. - Apache 2.0: no CLA, no dual-licensing, no surprises. Patent grant included.
One happy path — laptop node + first captured chat. Mesh, Docker, Proxmox, and rivetos init come later.
- Have a supported coding tool on PATH (Claude Code is the reference; Codex, Grok, Kimi, and Hermes also wire in; opencode, pi, and qwen-code are in the source tree but not yet in the installer).
- Install the node:
curl -fsSL https://get.rivethub.io/local.sh | bash- Start a new session in that tool so MCP recall loads (restart the tool, or on Grok run
/mcps reload). Open RivetHub: the Linux AppImage the installer launched, orhttps://localhost:5174. First win is that this new-session turn appears in Hub and amemory_searchfrom the tool returns it. An already-open session will not see the new MCP server.
Desktop / Windows / Android first downloads: rivethub.io. Phone pairing and mesh are day-2 — Getting Started.
Developers (this repo): npm install then npx rivetos local (Node ≥ 22). Do not start with npx rivetos init — that wizard is Node ≥ 24 and targets Docker / mesh / datahub.
┌───────────────────────────────────────────────────────────────┐
│ RivetOS Runtime │
│ │
│ ┌──────────┐ ┌──────────┐ ┌────────────────────────┐ │
│ │ Channels │───> │ Router │───>│ Turn Handler │ │
│ │ (plugin) │ │ (domain) │ │ (application) │ │
│ │ │ │ │ │ │ │
│ │ Agent │ │ message │ │ hooks → media → loop │ │
│ │ (mesh) │ │ → agent │ │ → stream → respond │ │
│ │ │ │ → prov │ │ → memory append │ │
│ │ │ │ │ │ │ │
│ └──────────┘ └──────────┘ └───────────┬────────────┘ │
│ ▲ │ │
│ │ ┌────────────────────────┘ │
│ │ ▼ │
│ ┌──────────┐ ┌──────────┐ ┌──────────────────────┐ │
│ │ Response │<───│Workspace │ │ Memory │ │
│ │ sent to │ │ (domain) │ │ (plugin) │ │
│ │ channel │ │ │ │ │ │
│ │ │ │ AGENT.md │ │ append transcript │ │
│ │ │ │ MEMORY.md│ │ search context │ │
│ │ │ │ │ │ hybrid FTS+vector │ │
│ └──────────┘ └──────────┘ └──────────────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────┐ ┌────────────────────────┐ │
│ │ Observability│ │ Mesh │ │ Boot Layer │ │
│ │ │ │ │ │ │ │
│ │ Metrics │ │ Registry │ │ Config → Registrars │ │
│ │ Health API │ │ Discover │ │ → Lifecycle │ │
│ │ Audit logs │ │ Delegate │ │ │ │
│ └──────────────┘ └──────────┘ └────────────────────────┘ │
└───────────────────────────────────────────────────────────────┘
Dependency rule: Everything points inward. Plugins → Types. Domain → Types. Every plugin is registered the same way, discovery plus manifest.register(). boot additionally lists five workspace packages (provider-claude-cli, memory-postgres, den-server, workflows, harness-kimi-code) as direct dependencies so a default install always has them on disk, and imports specific symbols from them. The pi harness (provider pi-cli, package @rivetos/harness-pi) is discovered the same way as other harness plugins. The qwen-code task executor is a direct @rivetos/boot dependency (@rivetos/harness-qwen-code, imported for executor registration); the qwen-code provider plugin is discovered like every other provider.
rivetOS/
├── packages/
│ ├── types/ # Interfaces & contracts (depends only on den-protocol)
│ ├── core/ # Domain logic, agent loop, runtime, observability
│ ├── boot/ # Composition root, plugin wiring, validation
│ ├── cli/ # CLI commands (rivetos start/stop/init/doctor/...)
│ ├── aisdk/ # AI SDK ↔ RivetOS adapter (messages, stream parts)
│ ├── workflows/ # Workflows v1 engine — document model, step SDK, journal replay
│ ├── wiki-core/ # Memory wiki page model — parse/apply/serialize
│ ├── den-protocol/ # rivet-den event protocol + room-state reducer
│ ├── gateway-client/ # Typed HTTP+WS client for the gateway API
│ ├── mcp/ # MCP primitives shared by the sidecar and clients
│ ├── mcp-v2/ # Era-negotiating MCP surface built on mcp
│ └── nx-plugin/ # @rivetos/nx — generators, executors, dev tooling
├── plugins/
│ ├── channels/ # agent (mesh); social bots removed Phase 5
│ ├── providers/ # API, local, and subscription-backed CLI adapters
│ ├── memory/ # postgres (pgvector + FTS + summary DAG + workers)
│ ├── tools/ # shell, file, search, web-search, interaction, mcp-client
│ └── transports/ # mcp-server (expose RivetOS tools over MCP StreamableHTTP)
├── services/ # den-server, embedding-worker, compaction-worker, mcp-sidecar
├── apps/
│ ├── rivethub-web/ # RivetHub web client (gateway UI)
│ ├── rivethub-electron/ # RivetHub Electron desktop shell (own lockfile; not an npm workspace member)
│ ├── rivethub-android/ # RivetHub Android client (thin gateway client, Apache-2.0)
│ ├── rivet-android/ # On-device RivetOS node (AGPL RikkaHub fork) — not the Hub client
│ ├── rivethub-site/ # rivethub.io marketing / install pages (Nx only; not an npm workspace member)
│ └── site/ # rivetos.dev Astro docs (synced from docs/ via apps/site/scripts/sync-docs.mjs)
├── infra/ # Container Dockerfiles, Compose files, provisioning scripts
└── docs/ # Full documentation (incl. example configs under docs/examples/)
Skills are user-managed and live outside the source tree (default: ~/.rivetos/workspace/skills/). See docs/SKILLS.md.
| Plugin | Description |
|---|---|
provider-codex-cli |
GPT models through Codex CLI using the node's ChatGPT subscription login |
provider-anthropic |
Claude models — streaming, adaptive thinking, prompt caching |
provider-google |
Gemini models via Generative Language API (thought signatures) |
provider-xai |
Grok models with live search and caching |
provider-ollama |
Local Ollama models (native API) |
provider-vllm |
vLLM server — full vLLM surface (sampling extensions, mm/chat_template kwargs, video, reasoning_content) |
provider-llama-server |
llama.cpp llama-server — lean (top_k/min_p + extra_body escape hatch) |
provider-claude-cli |
Drives the local claude binary (Claude Code) using the user's subscription OAuth token |
provider-opencode-cli |
Drives the local opencode binary (harness id opencode); default backend z.ai GLM |
| Plugin | Description |
|---|---|
channel-agent |
HTTP inter-agent messaging and mesh endpoints |
Social channel plugins (channel-telegram, channel-discord, channel-voice-discord) were removed in Phase 5. Human UX is RivetHub via the node gateway. Stale channels.telegram: (etc.) in config is a validation warning only; boot does not crash-loop.
| Plugin | Description |
|---|---|
tool-shell |
Shell execution with safety categorization |
tool-file |
file_read, file_write, file_edit with surgical edits |
tool-search |
search_glob and search_grep |
tool-web-search |
Google CSE + DuckDuckGo fallback, HTML → markdown |
tool-interaction |
ask_user (structured questions) and todo (task list) |
tool-mcp-client |
MCP protocol client (stdio + HTTP transports) |
The memory plugin (@rivetos/memory-postgres) additionally registers memory_search, memory_browse, and memory_stats. Delegation, sub-agents, and skill management add delegate_task, subagent_*, and skill_* tools at runtime.
| Plugin | Description |
|---|---|
transport-mcp (@rivetos/mcp-server) |
Exposes RivetOS tools (memory, web, skills, runtime) to external MCP clients over StreamableHTTP |
runtime:
workspace: ~/.rivetos/workspace
default_agent: opus
agents:
opus:
provider: anthropic
default_thinking: medium
providers:
anthropic:
model: claude-sonnet-4-6
# channels: social bots removed — use RivetHub
# optional agent mesh:
# channels:
# agent:
# port: 3100
# agent_id: opus
memory:
postgres: {}API keys always go in .env, never in config files. See Config Reference for every option.
The loader injects two files into the system prompt (rivetos doctor requires both):
| File | Purpose |
|---|---|
AGENT.md |
Agent identity, operating contract, owner / routed-user gate |
MEMORY.md |
Lightweight context index (query-based) |
Optional: users/<profile>.md (appended as USER.md for a matching profile), HEARTBEAT.md (heartbeat turns only), memory/YYYY-MM-DD.md (daily notes, searched not pinned). Legacy CORE.md / USER.md / WORKSPACE.md at the workspace root are not loaded.
Setup:
rivetos init Interactive setup wizard
rivetos update Pull latest, rebuild, restart
rivetos doctor 12-category health check
rivetos test Smoke test (provider, memory, tools)
Runtime:
rivetos start [--config ...] Start the runtime
rivetos stop Stop the running instance
rivetos status Runtime status with metrics
rivetos logs [options] Tail logs (--follow, --level, --since)
Configuration:
rivetos config show|validate|edit|path|init View, validate, or create config
rivetos agent add|remove|list Manage agents
rivetos model [provider] [mod] Show or switch models
rivetos keys rotate|list Rotate / list mesh SSH keys
Containers & Service:
rivetos build Build container images from source
rivetos service init|start|stop|status|logs Manage the systemd unit
Mesh:
rivetos mesh list|ping|status Mesh management
rivetos mesh enroll <user@host> --name <node> Join a RivetHub mesh
rivetos mesh join --manual <host> Legacy seed-node YAML only
Memory:
rivetos memory backfill-tool-synth Synthesize content for historical tool calls
rivetos memory queue-status Show graphile-worker job queue state
rivetos memory retry-failed Reset dead graphile jobs after a code fix
rivetos db ... Low-level DB inspection helpers
Development:
rivetos plugin init Scaffold a new plugin
rivetos skill init Scaffold a new skill
rivetos skill validate Validate skill frontmatter
rivetos plugins list Show configured plugins
rivetos plugins sync Refresh TUI plugin installs (claude-code/grok/hermes)
rivetos skills list Show discovered skills
npm install # Install + build all packages
npm run ci # Lint + build + test
# (CI additionally runs typecheck, boundary probes, and a secrets scan)
npx nx run core:test # Test a single package
npx nx affected -t test # Test only what you changed
npx nx g @rivetos/nx:plugin # Scaffold a new plugin
npx nx graph # Interactive dependency graphSee CONTRIBUTING.md for the full development guide.
- Getting Started: zero to running in 5 minutes
- Architecture: system design and plugin model
- Config Reference: every config option explained
- Plugins: how to write channels, providers, and tools
- Skills: how to write and share skills
- Deployment: Docker, Proxmox, multi-agent, backup
- Troubleshooting: common issues and fixes
- rivet-den: live agent diorama (quickstart, protocol, pack spec, art pipeline)
- Examples: Ready-to-use config files
The Android client (apps/rivet-android) is vendored source — a RikkaHub
fork licensed AGPL-3.0, a different license than the rest of this
repository (Apache-2.0). Its LICENSE lives in that directory and governs it.
The boundary rules:
- It is Gradle-built, not npm/nx-built: a minimal
package.json(no JS dependencies) registers it in the nx graph for DDD tags and boundary enforcement only. Its real targets areapk/apk-release/check/verify(gradle wrappers), deliberately notbuild/test/lint, so CI's Android-SDK-less nx sweeps skip it. Builds happen where an SDK lives, same posture asapps/rivethub-electron. - Dependency direction is one-way: the Android app may consume this
repo's published artifacts and gateway APIs; no code may be copied FROM
the AGPL-licensed
apps/rivet-android/tree INTO the Apache-2.0 tree. - RivetHub web/desktop reimplement the client UX against the same gateway
contracts (
@rivetos/typesgateway-api): shared design, independent code.