A local-first runtime for your personal automation agents — with a native desktop app you actually want to open.
Vesper runs on your machine and hosts small automation pipelines (your "agents") under one host
process. It drives the AI CLI you already pay for — claude, codex, opencode, or gemini —
so it holds no API keys and ships no provider SDKs. Nothing leaves your machine except the
calls your own CLI makes. You talk to it in a premium dark-glass desktop app: chat with Vesper, watch
exactly what it's doing as it works, and manage every pipeline, channel, schedule, and permission from
one window — with a macOS menu-bar popover for a quick glance.
| Bring your own CLI — no keys | Orchestrates claude / codex / opencode / gemini over a subprocess. You pay once for your CLI; Vesper adds no per-call billing and stores no LLM credentials. Pick the model per request. |
| Chat with Vesper & watch it work | A native dark-glass desktop app: chat with Vesper and it picks the right pipeline, runs it, and streams every step in a live activity rail. A sectioned sidebar manages pipelines, channels, schedules, runtime, permissions, and more — plus a macOS menu-bar popover. |
| Local-first & private | SQLite storage + OS-keychain secrets, all on your machine. The UI binds to 127.0.0.1 only. No accounts, no cloud, no telemetry. |
| Capability-sandboxed pipelines | Every agent declares what it may touch — invoke a CLI, read/write storage, touch files — and the host enforces it (deny-by-default) before any side effect. |
| Self-improving skills | The skill-train engine optimizes a skill's playbook against its own test set (SkillOpt-style: epochs, held-out validation, greedy accept) — using your CLI, never a provider key. |
| A real scheduler | Cron, event, and manual triggers with run-count caps, backoff, and a dead-letter queue. Your agents can run on their own, unattended. |
vesper daemon start # hosts the runtime + the UI (background)
vesper ui # open it in your browser — http://127.0.0.1:4317Or run the native desktop app — a Tauri shell over the same daemon — from
packages/vesper-desktop (bun run dev): a frameless window with a macOS menu-bar (tray) popover, no
browser involved.
Chat with Vesper and it routes your message to the right pipeline and streams the run live in a Vesper activity rail. Every section reads your real runtime — nothing is faked: Runtime (daemon + helper-CLI health), Diagnostics (CLI probes, recent runs, and the agents running on your machine), Channels, Schedule, Pipelines, Permissions, Settings (theme + config), and more. Dark glass is the default; a light and a warm theme ship too. See docs/ui.md.
Vesper does not ship or call any LLM provider SDK, and it never holds an API key. It orchestrates the AI CLI you already have authenticated:
claude(Claude Code) ·opencode·codex·gemini
It shells out to whichever you have installed (via Bun.spawn) and composes on top. The only secrets
Vesper keeps are pipeline-side (e.g. a GitHub token) in your OS keychain — never LLM auth.
- Bun ≥ 1.1
- macOS (the vault uses the system Keychain via the
securityCLI) - At least one installed, authenticated CLI from the list above (
vesper cli install <name>can set one up)
One-liner (fetches a release, installs deps with Bun, links vesper onto your PATH):
curl -fsSL https://raw.githubusercontent.com/ogarciarevett/vesper/main/install.sh | shIt never runs as root, never auto-creates ~/.vesper (you run vesper init), and is re-runnable to
upgrade. Pin a version with --version <tag>; include the opt-in WhatsApp-Web channel with
--with-whatsapp. Piping a script to a shell runs code you have not read — if you prefer, download
it, read it, then run it:
curl -fsSL https://raw.githubusercontent.com/ogarciarevett/vesper/main/install.sh -o install.sh
less install.sh && sh install.shFrom npm (no clone; needs Bun on your PATH — the CLI runs under Bun):
bunx @ogarciarevett/vesper status # run once, no install
bun install -g @ogarciarevett/vesper # or install the `vesper` command globallyFrom source (for development):
git clone https://github.com/ogarciarevett/vesper.git
cd vesper && bun install
cd packages/vesper-cli && bun link # make `vesper` global (or run from the repo)vesper init # create ~/.vesper, initialize storage, detect installed CLIs
vesper cli list # show each CLI + probe status (ok / not-authenticated / not-installed)
vesper hello # ask your configured CLI to reply — proves orchestration works
vesper daemon start # start the runtime + UI (background)
vesper ui # open the Vesper app in your browservesper hello is the proof the model works: a fixed prompt to your CLI, reply printed — no
Vesper-held key, captured over a subprocess pipe.
Generated from the command registry by bun run docs:cli and kept in sync by a pre-commit hook, so
this list never drifts. Run vesper <command> --help for details; see also docs/CLI.md.
| Command | Description |
|---|---|
vesper init |
Create the ~/.vesper runtime, initialize storage, and detect installed CLIs. |
vesper hello |
Ask the configured CLI to reply — proves orchestration works (no Vesper API key). |
vesper vault set <key> # value via stdin |
Store a secret for a pipeline (value read from stdin, never the command line). |
vesper vault get <key> |
Print a stored secret value. |
vesper vault list |
List stored secret keys (never their values). |
vesper cli list |
List supported CLIs with version, working status, and remediation hints. |
vesper cli select <name> |
Set the default CLI adapter (must be installed). |
vesper cli install <name> |
Install a supported LLM CLI (claude/codex/opencode/gemini/cursor). |
vesper connections list |
List messaging channels with availability, credential, and enabled status. |
vesper connections set <id> [key=value ...] # token via stdin |
Store a channel credential (stdin) + any key=value params, and enable it. |
vesper connections pair <id> |
Scan a QR to connect a channel (auto-captures your chat). Daemon must be running. |
vesper connections setup <id> # Telegram/Discord; daemon must be running |
Auto-connect a token channel — Vesper drives your CLI's browser to create the bot. |
vesper connections test <id> |
Authenticate a channel's stored credential (e.g. Telegram getMe). |
vesper connections send <id> <chatId> # message via stdin |
Send a one-off message to a channel recipient (message via stdin). |
vesper connections enable <id> |
Enable a channel (the daemon starts it on next launch). |
vesper connections disable <id> |
Disable a channel (deregisters it; the stored token is kept). |
vesper status |
Show versions and the health of every subsystem. |
vesper daemon run |
Run the daemon in the foreground (IPC + scheduler + UI). Ctrl-C to stop. |
vesper daemon start |
Start the daemon in the background (detached). |
vesper daemon stop |
Stop the running daemon. |
vesper daemon restart |
Restart the daemon (stop, then start). |
vesper daemon status |
Show the daemon's lifecycle status (PID, uptime, socket). |
vesper daemon install |
Install the daemon as a macOS LaunchAgent (starts at login, stays alive). |
vesper daemon uninstall |
Remove the macOS LaunchAgent and stop the daemon. |
vesper ui [--no-open] [--theme <id>] |
Open Vesper World — a visual, living view of your agents (requires the daemon). |
vesper schedule list |
List all scheduled tasks in an aligned table. |
vesper schedule show <id> |
Print full details for a single task. |
vesper schedule run <id> [--cli <name>] [--param key=value] [--quiet] |
Manually run a task by id, invoking the resolved CLI and recording a run. |
vesper schedule enable <id> |
Enable a scheduled task by id. |
vesper schedule disable <id> |
Disable a scheduled task by id. |
vesper runs list [--pipeline <name>] [--status <status>] [--limit <n>] |
List recorded pipeline runs (oldest first). |
vesper skill train <name> [--cli <a>] [--optimizer-cli <a>] [--judge-cli <a>] [--epochs N] [--batchsize M] [--val-fraction F] [--dry-run] [--yes] |
Train a skill against its tasks.json via the skill-train pipeline. |
vesper skill list [--skills-dir <dir>] |
List trainable skills (those with a tasks.json validation harness). |
vesper skill diff <name> [--skills-dir <dir>] |
Diff the committed SKILL.md against the trained best candidate. |
vesper skill accept <name> [--skills-dir <dir>] [--yes] |
Adopt the trained best candidate into the committed SKILL.md (checkpointed; revertible). |
vesper skill revert <name> [--skills-dir <dir>] |
Restore the committed SKILL.md from the latest accept checkpoint. |
vesper evolve list |
Show the latest auto-evolve report and open skill/fix proposals. |
vesper voice say "<text>" |
Speak text aloud with the local system voice (macOS say). |
vesper voice ask "<question>" [--cli <name>] [--silent] |
Ask Vesper (your CLI is the brain); print the reply and speak it aloud. |
vesper voice chat [--cli <name>] [--silent] |
Hold a back-and-forth conversation — one line per turn, until EOF. |
vesper voice setup |
Prepare the local voice runtime (model directory + guidance). |
vesper voice mic-test |
Check the voice output path (mic capture ships with the native shell). |
~/.vesper/config.json:
{
"cli": {
"default": "claude",
"adapters": { "claude": { "command": "claude", "args": ["-p"] } }
},
"storage": { "redactRunSummaries": false },
"presence": {
"pollMs": 3000,
"matchers": [
{ "id": "mytool", "label": "My Tool", "kind": "cli", "pattern": "(?:^|/)mytool(?:\\s|$)" }
]
}
}cli.default selects which CLI pipelines use; per-adapter command/args override the headless
invocation if a tool changes its flags. storage.redactRunSummaries (opt-in) stores run summaries as
size-only metadata instead of raw CLI output.
presence tunes the live agent view in the Diagnostics section (the running agents it "echoes"). Vesper ships an
allowlist for claude, codex, opencode, gemini, and zeroclaw; presence.matchers adds
your own without touching code. Each matcher is { id, label, kind: "cli" | "app", pattern, exclude? },
where pattern/exclude are regexes matched (case-insensitively) against a process's full command
line — match the tool's binary, not its install path, to avoid false positives. presence.pollMs sets
the re-scan interval (default 3000). Malformed matchers (bad kind, uncompilable regex) are ignored.
A vesper-core host (vault · SQLite storage · CLI adapters · capabilities · scheduler · IPC) runs
your pipelines; vesper-cli is the developer surface; vesper-ui is the consumer surface. Every LLM
call is a shell-out to your CLI — there is no provider SDK anywhere in the dependency tree.
Talk to Vesper (local-first voice). vesper voice ask "..." holds a spoken conversation where your
CLI is the brain and your machine does the speech: the reply is read aloud sentence-by-sentence through
the system voice (macOS say), nothing leaves the machine, and each turn is audited without storing the
words. Hands-free microphone capture, on-device Whisper transcription, and a global push-to-talk hotkey
arrive with the native voice shell; premium ElevenLabs voices are an opt-in. Today: vesper voice say|ask|chat|setup|mic-test.
bun test # run the suite
bun run lint # Biome lint + format check
bun run docs:cli # regenerate docs/CLI.md + this README's command table (enforced pre-commit)The only dependency is @biomejs/biome (+ Bun's types) — no LLM provider SDKs.
MIT.




