Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ node_modules/
dist/
*.tsbuildinfo

# Rust / Tauri build artifacts (packages/vesper-desktop — the native shell, DEV-112).
# Cargo.lock IS committed (this is an application binary — reproducible builds).
target/
/packages/vesper-desktop/src-tauri/gen/
# generated daemon-embed assets + the compiled sidecar binary (DEV-112 Slice 2)
/packages/vesper-cli/src/generated/
/packages/vesper-desktop/src-tauri/binaries/

# Vesper local runtime directory
.vesper/

Expand Down
38 changes: 24 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<p align="center">
<img src="docs/imgs/vesper-world.png" alt="Vesper World — watch your personal agents work" width="100%">
<img src="docs/imgs/vesper-app.png" alt="Vesper — a local-first desktop app for your personal automation agents" width="100%">
</p>

<h1 align="center">Vesper</h1>
Expand All @@ -12,17 +12,18 @@
<img src="https://img.shields.io/badge/LLM-bring%20your%20own%20CLI-ffd479?style=flat-square" alt="Bring your own CLI">
</p>

<p align="center"><b>A local-first runtime for your personal automation agents — that you can actually watch work.</b></p>
<p align="center"><b>A local-first runtime for your personal automation agents — with a native desktop app you actually want to open.</b></p>

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. And instead of a cold dashboard, you watch your agents in a little
pixel-art world: tap one to see, in plain language, what it just did — or to put it to work.
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.

<table>
<tr><td width="34%"><b>Bring your own CLI — no keys</b></td><td>Orchestrates <code>claude</code> / <code>codex</code> / <code>opencode</code> / <code>gemini</code> 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.</td></tr>
<tr><td><b>Watch your agents work</b></td><td>A pixel-art world (<i>Vesper World</i>) where each agent is a character — busier ones grow, the world livens up with use. Click one for a plain-language result + a big <b>Run</b> button. Built for someone who has never opened a terminal.</td></tr>
<tr><td><b>Chat with Vesper &amp; watch it work</b></td><td>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.</td></tr>
<tr><td><b>Local-first &amp; private</b></td><td>SQLite storage + OS-keychain secrets, all on your machine. The UI binds to <code>127.0.0.1</code> only. No accounts, no cloud, no telemetry.</td></tr>
<tr><td><b>Capability-sandboxed pipelines</b></td><td>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.</td></tr>
<tr><td><b>Self-improving skills</b></td><td>The <code>skill-train</code> 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.</td></tr>
Expand All @@ -35,21 +36,30 @@ pixel-art world: tap one to see, in plain language, what it just did — or to p

---

## Vesper World
## The app

```sh
vesper daemon start # hosts the runtime + the UI (background)
vesper ui # opens a browser tab — http://127.0.0.1:4317
vesper ui # open it in your browser — http://127.0.0.1:4317
```

Or run the **native desktop app** — a [Tauri](https://tauri.app) 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.

<p align="center">
<img src="docs/imgs/vesper-runtime.png" alt="Runtime — daemon health, helper-CLI status, storage" width="49%">
<img src="docs/imgs/vesper-diagnostics.png" alt="Diagnostics — CLI probes, recent runs, and the agents running on your machine" width="49%">
</p>
<p align="center">
<img src="docs/imgs/vesper-card.png" alt="Click an agent to see what it just did, in plain language" width="80%">
<img src="docs/imgs/vesper-settings.png" alt="Settings — theme picker and runtime configuration" width="70%">
</p>

Tap an agent → a plain-language card shows what it last did and lets you run it. The world is a live
projection of your real runtime (pipelines, runs, schedules) — nothing is faked. It's deliberately
simple, and built to extend: a planned **Voice** module will let an agent *speak* its result aloud.
See [docs/ui.md](docs/ui.md).
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](docs/ui.md).

## Bring your own CLI

Expand Down Expand Up @@ -82,7 +92,7 @@ vesper init # create ~/.vesper, initialize storage, detect installed CL
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 Vesper World in your browser
vesper ui # open the Vesper app in your browser
```

`vesper hello` is the proof the model works: a fixed prompt to your CLI, reply printed — no
Expand Down Expand Up @@ -152,7 +162,7 @@ this list never drifts. Run `vesper <command> --help` for details; see also [doc
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 Vesper World (the running agents it "echoes"). Vesper ships an
`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
Expand Down
34 changes: 34 additions & 0 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

75 changes: 75 additions & 0 deletions cycle-log.md
Original file line number Diff line number Diff line change
Expand Up @@ -651,3 +651,78 @@ the still-blocked forge sandbox (it executes no LLM-generated code).
- DEFERRED (per spec Out of Scope): applying `fix_proposal`s (software-engineer pipeline); authoring
pipeline CODE (forge, blocked on the sandbox); `NETWORK_FETCH`; a RAG/embedding index over signals;
an elder-surface approval tile; auto-running skill-train on a newly acquired skill.

## Chatbot home + editable pipeline templates (#9 + #4) — SHIPPED

`specs/chatbot-home.md`. The post-onboarding HOME is a simple chatbot; the canvas demotes to a side
activity panel. Built on the SHIPPED orchestration+trace backbone (consumed, not modified). No Linear
issue (issue-capped) -> specs/ + this entry + the commit are the record (Rule 11). Built by a
Backend->Client->Review workflow; the review's 2 real HIGH gaps were then fixed by the lead.

- **Storage (migration `007_chat_home`):** `chat_sessions`, `chat_turns`, `pipeline_templates` + index;
6 synchronous `Store` methods (createSession, appendTurn, listSessions, listTurns, getTemplate,
upsertTemplate) mirroring the existing JSON/assert helpers. `chat_turns.run_id` links an assistant
turn to the run that produced it (transcript bubble == activity-tree root, same data two ways).
- **Router pipeline (`packages/pipelines/router/`):** a chat message is a manual `scheduler.run("router",
{params})` (the EXISTING run path — no new execution). The handler classifies via `ctx.complete` to ONE
label, maps it through a FIXED ALLOWLIST to a registered handler id, and `ctx.spawn`s it; an
unmapped/free-form label -> a clarify turn (NO spawn, no dynamic id — preserves no-eval). caps
[CLI_INVOKE, WRITE_STORAGE, SPAWN_SUBAGENT].
- **Routes + WS:** `POST /api/chat`, `GET /api/chat/sessions`, `GET /api/chat/sessions/:id/turns`,
`GET /api/pipelines`, `GET|PUT /api/pipelines/:id/template`; a `chat:<sessionId>` WS topic next to the
backbone's `agent:<runId>` (one socket, UUID-guarded). Client: transcript home + demoted activity
panel (reuses the runTree render) + a templates screen; reduced-motion + WCAG-AA honored.
- **Security:** a minimal out-of-band approval-token module (`vesper-core/src/approval/`, CSPRNG
single-use) gates `PUT /template`; `POST /api/approval/request` mints a code and prints it to the daemon
TTY (out-of-band — never in the HTTP response, so a local app can mint but not read it). The future
`security-hardening.md` adopts this seam. `POST /api/chat` is isLocalRequest-only (deliberate parity
with the existing run route, so the canvas Run button still works).
- **Lead fixes over the workflow output** (2 real HIGHs the review caught): (1) `mint()` had NO production
caller -> added the `/api/approval/request` mint path + test, so template editing actually works
end-to-end; (2) the router ignored template `default_params` -> it now MERGES the target's editable
default_params UNDER the user message (injected via `registerPipelines({getDefaultParams})` -> daemon
wires `store.getTemplate`), so an edited template configures its runs (#4). + router/server tests.
- 724 tests / 0 fail (+ chatbot suite + the 2 fix tests); Biome clean; no NEW tsc errors (same 16
pre-existing); no provider SDKs.
- NOTED (not blocking): `PUT /template` persists prompt/params only — schedule/caps stay editable via
`vesper schedule` (the spec's Design-Decisions/Acceptance contradict each other; took the conservative
path). Migration `007_chat_home` takes the next free id; the umbrella ledger's planning reservation
(007=rag) shifts to 008/009 for rag/eval (gitignored planning doc, reconciled at their build).
- DEFERRED (per spec Out of Scope): the security-hardening §C token formalization; multi-session history
UX; capability editing from the templates UI; token-level streaming.

---

## Desktop shell redesign — premium dark-glass native companion + Vesper World rebuild — SHIPPED

- Specs: `specs/desktop-app-shell.md` + `specs/vesper-world-rebuild.md` (Omar-authorized 2026-06-02; record
surface = specs + this log; Linear issue cap active). Reference look: OpenClaw Windows Companion.
- **Decisions locked (Omar):** premium dark-glass SUPERSEDES the elder-first *visual* framing (Hard rule 14
amendment pending on a later sync); primary section name = **Pipelines**; presence/echo MOVES to
Diagnostics (not deleted); built shell + rebuilt Chat together as slice 1.
- **What shipped:** the `@vesper/ui` client is now an app shell — custom draggable titlebar (Cmd+E command
search, live status pills off `/api/status`), grouped sidebar, a client-side `SectionRouter`, and a
chrome-only theme system (dark default; light/hearth opt-in) that REPLACES the canvas-coupled `WorldTheme`.
14 sections: Chat + Runtime/CLIs/Permissions/Sandbox/Settings/Diagnostics/About (live) + Pipelines/
Channels/Schedule (thin) + Skills/Memory/Voice (honest stubs naming their specs).
- **Vesper World rebuilt:** the pixel-art canvas + machine-wide presence home are RETIRED (controlled
`git rm`, recoverable). Chat = transcript + a Vesper-ONLY activity rail (follows the conversation's run
tree via the existing `/api/chat` + run-trace APIs; subscribe-before-backfill + de-dupe preserved). No
backend rewrite — reused chat/router/sessions/turns verbatim.
- **Server:** new read-only `/api/status`, `/api/presence`, `/api/runs`; `/api/world` + `snapshot.ts` removed;
presence poll kept (feeds `/api/presence` for Diagnostics).
- **Native:** macOS overlay titlebar (`TitleBarStyle::Overlay` + `hidden_title`, cfg-gated to macOS) so the
custom HTML titlebar shows with the traffic lights inset; tray + single-instance from DEV-112 slice 3.
- **Parallel build:** lead built the backbone + Chat + real sections + server routes; 2 sub-agents built the
6 thin views + the Rust overlay window concurrently (file-disjoint). Net **-890 lines** tracked in vesper-ui.
- **Gotcha (cost a runtime crash Omar caught):** the browser client is bundled by Bun (which does NOT error
on an undefined identifier) and sits OUTSIDE the root tsc program, so a section referenced in the barrel
but never imported (`sandboxSection`) only failed at runtime in the browser — green tests + clean bundle
missed it. FIX + GUARD: `sections/index.test.ts` imports the barrel and asserts ALL_SECTIONS (14, unique
ids, valid shape). Lesson: for the browser client, an import-the-barrel test is the real typecheck.
- Verified: `biome ci` clean (2 cosmetic warnings), vesper-ui 46 / vesper-cli 104 pass, no new tsc errors in
touched files, compiled sidecar serves the new shell end-to-end. No provider SDKs.
- DEFERRED: privileged config writes from Settings (theme is client-side; default-CLI read-only); full
template editing in Pipelines (read-only view); Windows/Linux window chrome (macOS-first per Omar); the
one `!important` (reduced-motion) biome warning; the menu-bar popover app + internal-pipelines auto-skills
feature (next requests).
Binary file added docs/imgs/vesper-app.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/imgs/vesper-diagnostics.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/imgs/vesper-menubar.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/imgs/vesper-runtime.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/imgs/vesper-settings.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@
"vesper": "bun packages/vesper-cli/src/index.ts",
"sync:ai": "bun scripts/sync-ai-docs.ts",
"docs:cli": "bun scripts/gen-cli-docs.ts",
"build:daemon": "bun scripts/build-daemon.ts",
"prepare": "git config core.hooksPath .githooks || true"
},
"engines": {
"bun": ">=1.1.0"
},
"devDependencies": {
"@biomejs/biome": "^2.4.15",
"@types/bun": "^1.3.14"
"@types/bun": "^1.3.14",
"@vesper/ui": "workspace:*"
}
}
Loading
Loading