Skip to content

Cobrust-lang/cobrust-studio

Cobrust Studio

A desktop-first control plane for managing AI coding agents under engineering discipline.

Open the desktop app or run the headless server, point it at a git repo, and it gives you a typed REST + SSE API + a 5-page SvelteKit UI to run bounded agent turns and one-shot LLM dispatches, capture the resulting decisions as Architecture Decision Records (markdown), capture the surprises as findings (markdown), and ledger every token through a JSONL audit trail. All git-native — your docs/ tree stays plain markdown editable by vim.

License Release Stage ADSD


What it actually is (30-second version)

If your team is using Cursor / Claude Code / OpenHands / similar for serious work — not toy demos — you eventually want answers to:

  1. What did the agents decide? → ADRs (one markdown file per decision)
  2. What went wrong? → findings (one markdown file per failure / dead end / benchmark surprise)
  3. Where did the tokens go? → ledger (one JSONL line per LLM dispatch — provider, model, cost, latency)
  4. Can Chinese-native teams use the UI directly? → built-in [ EN | 中 ] toggle across the core pages
  5. Are we drifting from the plan? → live /api/events SSE stream as ADRs and findings get added
  6. Is the methodology actually being followed? → a 5-gate CI script that fails the merge if it isn't

Cobrust Studio is moving to a desktop-first Tauri shell around the same SvelteKit UI and Rust/Axum backend. The v0.3.x distribution is still a 9 MiB single Rust binary that gives you all five as a web UI + REST API against any git repo you point at; ADR-0013 makes the desktop app the primary v0.4.x product path while preserving cobrust-studio serve for headless/server use. Markdown is source of truth; SQLite is just a materialized index for fast queries. There's no SaaS, no vendor lock-in, no per-seat pricing — you self-host, your data stays on your laptop or server.

Methodology vocabulary

The web UI surfaces these terms. Skim the table once and the rest of the project makes sense:

Term What it is Where it lives
ADR (Architecture Decision Record) One file per design decision: context + options considered + decision + consequences. Frontmatter has adr_id, title, status, date. docs/agent/adr/NNNN-*.md
Finding One file per negative result, bug postmortem, benchmark surprise. Frontmatter has finding_id, severity, status. docs/agent/findings/*.md
Wave A batch of related commits, like an agile sprint. Named A1, A2, etc. Tx tags reference the wave. Commit message scope tags
Tx tag Conventional-commit scope plus a wave coordinate (feat(server): A4.7 wire dispatch SSE). git log
5 gates cargo fmt --check + cargo clippy -D warnings + cargo build --locked + cargo test --locked + bash scripts/doc-coverage.sh. Required green before any merge. scripts/doc-coverage.sh
守闸 (CTO gate-check) Post-merge audit by the CTO role: trust-but-verify cold rebuild + 5-gate + read the diff. Done in Chinese to honor the methodology's origin, not to gatekeep — every gate name is also annotated in English. Wave merge commit messages

The methodology itself (ADSD — Agent-Driven Software Development) is a separate open project distilled from a 9-week run building the Cobrust language project: https://github.com/Cobrust-lang/agent-driven-development.

Studio dogfoods ADSD — meaning the same discipline that builds the tool is the discipline the tool surfaces. You can read all the methodology in the ADSD repo above without ever installing Studio.


Try it (5 minutes, pre-built tarball)

v0.3.x release tags ship 5 server/headless builds — linux x86_64 + aarch64, macOS x86_64 + arm64, windows x86_64. Grab one from the latest releases page and you have a working binary in under 60 seconds. No Rust toolchain, no Node, no pnpm — Studio is a single binary with the SvelteKit frontend baked in via rust-embed.

v0.4.x is resequenced by ADR-0013: desktop app bundles become the primary packaging path via Tauri, while the cobrust-studio serve binary remains supported for CI, dogfood automation, and remote/server deployments.

# Example for macOS arm64; pick the tarball matching your platform:
curl -sL https://github.com/Cobrust-lang/cobrust-studio/releases/latest/download/cobrust-studio-v0.3.0-aarch64-apple-darwin.tar.gz | tar xz
cd cobrust-studio-v0.3.0-aarch64-apple-darwin

# Dogfood mode: point Studio at THIS extracted directory (or any other git repo)
./cobrust-studio serve --project . --port 7878
open http://localhost:7878

You should see Studio's 5 pages. Use the top-right [ EN | 中 ] toggle to switch the UI between English and Chinese; the choice persists across reloads.

  • /login — paste your LLM endpoint + API key (custom endpoint or OpenAI-compatible)
  • /adr — list/detail/create the 6+ ADRs that live in this repo (docs/agent/adr/)
  • /agent — run a bounded agent turn, watch the timeline of iterations + tool calls + tool results + final answer
  • /finding — list the failures + bug postmortems captured during development
  • /ledger — every LLM dispatch with provider, model, tokens, latency, cost

Build from source (alternative)

If you'd rather build it yourself, you need rustup (Rust 1.94+), pnpm (Node 20+ for SvelteKit), and a git repository to point Studio at.

git clone https://github.com/Cobrust-lang/cobrust-studio && cd cobrust-studio
bash scripts/build-release.sh
# → target/release/cobrust-studio (~9 MiB self-contained binary)
./target/release/cobrust-studio serve --project . --port 7878

Desktop shell from source (v0.4.x / ADR-0013)

The Tauri shell lives in src-tauri/ and reuses the same SvelteKit build and Axum REST/SSE backend. It starts an embedded Studio server on 127.0.0.1:0, then opens the WebView at the resolved loopback URL so existing relative /api/* calls keep working.

# Optional: pick the repo Studio should manage. Defaults to current dir.
export COBRUST_STUDIO_PROJECT=$PWD

pnpm --dir web install
pnpm --dir web tauri:dev

Desktop defaults to COBRUST_PERSIST_SESSION=keychain so relaunches can auto-unlock after the first /login. Override with COBRUST_PERSIST_SESSION=none|file and COBRUST_PERSIST_SESSION_FILE when testing server-style persistence modes.


Configuration

Primary flow — /login

Use the /login page to configure your LLM endpoint. Fill in:

  • Endpoint URL (e.g. https://api.anthropic.com)
  • API key
  • Model — fetched from your provider via the login model-discovery action, then stored in the sealed session
  • Passphrase — used to encrypt the key before disk storage (never stored itself)

Studio derives an AES-256 key from your passphrase via Argon2id (intentionally slow to resist brute force) and seals your credentials with AES-256-GCM. The encrypted blob stays in SQLite; the derived key lives only in server memory. On process restart, re-entering the passphrase re-derives the key — your API key stays encrypted at rest.

Measured Argon2id wall-clock (release-mode build, m=64 MiB / t=3 / p=1):

  • Apple M4 (2024 MacBook): ~70 ms (N=5, median)
  • GitHub Actions Linux runner (2 vCPU shared, x86_64): ~300-400 ms estimated
  • Old laptop (2018-era Intel i5): ~500-800 ms estimated

Hard ceiling is 2 s (secret::tests::bench_argon2id_derive enforces). If your hardware exceeds that, file a finding — the m_cost parameter may need tuning. Re-run the bench yourself with:

cargo test --release -p studio-server --lib -- --ignored --nocapture bench_argon2id_derive

Rotating your passphrase: delete the SQLite session_kv row and re-login. Today there's no POST /api/change-passphrase route — that's an ADR-pending v0.3.x enhancement. Procedure for now:

# while the server is stopped:
sqlite3 .cobrust-studio/studio.db "DELETE FROM session_kv WHERE key = 'endpoint';"
# then start the server and visit /login with the new passphrase

See docs/human/en/secret-storage.md for the full security model.

Headless / CI escape hatch — --dev-api-key

For CI pipelines, Playwright fixtures, or scripted usage:

cobrust-studio serve \
  --project /path/to/project \
  --dev-api-key sk-ant-xxx \
  --dev-endpoint https://api.anthropic.com \
  --dev-model claude-opus-4-7

This bypasses /login and injects credentials at boot. Also available via env vars COBRUST_DEV_API_KEY, COBRUST_DEV_ENDPOINT, COBRUST_DEV_MODEL.

The studio.toml api_key_env field (e.g. ANTHROPIC_API_KEY) also remains supported for backward compatibility and for the studio.toml router path.

Persistent session (long-lived deployments) — --persist-session

For systemd units / Docker containers / headless servers that restart for deploys or host reboots and shouldn't require a human to re-enter the passphrase every time, M8 (v0.4.0, ADR-0009) ships an opt-in --persist-session flag. Two backends:

# Backend A — OS keychain (macOS Keychain / freedesktop secret-service / Windows DPAPI)
cobrust-studio serve \
  --project /path/to/project \
  --persist-session=keychain

# Backend B — 0600 plaintext file (sysadmin-friendly fallback for Docker / no D-Bus)
cobrust-studio serve \
  --project /path/to/project \
  --persist-session=file \
  --persist-session-file=/etc/cobrust-studio/passphrase

Default is --persist-session=none (v0.3.0 baseline; re-enter passphrase on every restart). Env var equivalents: COBRUST_PERSIST_SESSION, COBRUST_PERSIST_SESSION_FILE.

On the next /api/login, the passphrase is mirrored into the chosen backend. On the next binary boot, the server reads it back, re-derives the in-memory session key (verifying via AES-GCM open() before stashing), and you're authenticated without visiting /login. POST /api/logout?purge=true clears the backend entry for the "I want to fully forget this credential" case.

Security trade-off summary (full table in docs/human/en/secret- storage.md §"Persistent session backends"):

Mode Cold disk theft Sysadmin-equivalent attacker Best for
none (default) Protected (passphrase needed) Out of scope (same trust as server) Dev laptops; interactive use
keychain Protected (passphrase not on disk) Out of scope Single-user servers; dev laptops with passphrase fatigue
file Weakened (file IS on disk) Out of scope Docker; D-Bus-less Linux; sysadmin-managed deployments

The keychain mode keeps the cold-disk-theft posture intact (the passphrase lives in a user-scoped keychain, not on the disk image). The file mode trades some at-rest security for sysadmin friendliness — it's the right choice for Docker / NixOS / Kubernetes deployments where a keychain isn't viable.

Three credential paths — security hierarchy

Studio supports three ways to provide a credential, in descending order of at- rest security:

Path At-rest encryption Recommended for
/login (POST /api/login from browser or curl) ✅ AES-256-GCM + Argon2id Default. Production / pilot use.
--dev-api-key CLI flag + COBRUST_DEV_* env ❌ plaintext in process memory + shell history CI fixtures, Playwright, hermetic e2e
studio.toml api_key_env = "ANTHROPIC_API_KEY" + env var ❌ plaintext on disk in studio.toml (the var name) + plaintext in env Legacy / pre-M6 deployments (deprecated; v0.3.x will require migration)

The first two work today and are documented. The third fires a tracing::warn! at startup when detected — it's kept for backward compat but slated for removal. Pick /login unless you have a specific reason not to.


Why this and not Linear + git?

Linear / GitHub Projects A handcrafted ADR repo Cobrust Studio
Source of truth SaaS DB Git markdown Git markdown
Vendor lock-in High None None
Live dispatch + token ledger No No Yes (SSE)
Per-decision audit trail Free text in PR Manual ADR with frontmatter + schema check
Negative-results discipline None Manual findings/ convention First-class finding type + CI gate
CI gate forcing the discipline None Whatever you write doc-coverage.sh 6-step gate
5-min self-host No (SaaS only) N/A Yes (9 MiB single binary)
Bounded agent-turn timeline No No Yes (/api/agent-turn with built-in tools)
Cost Per-seat-per-month Free + your time Free + your time

If your engineering culture already does "ADR + plain markdown + git" and you just want a fast web view + an LLM dispatch surface on top, Studio is the shortest path.

If your team would benefit from being forced into the discipline by a CI gate, Studio's scripts/doc-coverage.sh is the lever — it fails the merge if ADRs are missing frontmatter, if any last_verified_commit is a HEAD placeholder (vs a real git SHA), or if cargo test has any FAILED groups.


Architecture

┌──────────────────────────────────────────────────────┐
│  SvelteKit 5 web (5 pages, baked into binary)        │
└─────────────────────┬────────────────────────────────┘
                      │ REST + SSE (axum 0.7)
┌─────────────────────▼────────────────────────────────┐
│  studio-server     /api/health      /api/version     │
│                    /api/login       /api/project     │
│  (Axum + tokio)    /api/adr         /api/finding     │
│                    /api/ledger      /api/dispatch    │
│                    /api/agent-turn  /api/models/*    │
│                    /api/events      404 JSON fallback│
└──────┬────────────────────────────────┬──────────────┘
       │ Store                          │ Router
       │                                │
┌──────▼─────────┐               ┌──────▼─────────────┐
│ studio-store   │               │ studio-router      │
│ markdown CRUD  │  JSONL ledger │ LlmProvider trait  │
│ + SQLite index │ ◄───────────► │ Anthropic provider │
│ + filesystem   │ (canonical)   │ OpenAI-compat      │
│   watcher      │               │ + BLAKE3 cache     │
└────────────────┘               └────────────────────┘

Three crates total (~3000 LOC of Rust + 1500 LOC of SvelteKit). The studio-router crate is a stripped fork of cobrust-llm-router per ADR-0005 — consensus mode + per-task routing tables dropped; LlmProvider trait + Anthropic/OpenAI providers + BLAKE3 content-addressed cache + JSONL ledger kept. Same upstream copyright headers on every lifted file.

See docs/agent/adr/ for design decisions and docs/agent/modules/ for per-crate agent-facing module specs.


What's in this repo right now (v0.3.0)

  • ✅ 3 crates compile clean, ~200 tests pass (33 ok groups, 0 FAILED)
  • ✅ 14 Playwright e2e specs (13 active + 1 STUDIO_E2E_ROUTER-gated; all pass)
    • 2 dedicated /login e2e specs (login.spec.ts drives the SvelteKit form; login-aead.spec.ts hits the API surface)
  • ✅ 2 Playwright dogfood specs (Studio managing its own ADRs — both pass)
  • ✅ Real-LLM e2e against an OpenAI-compatible endpoint — PASS
  • scripts/build-release.sh produces a ~9 MiB self-contained binary
  • scripts/smoke-dogfood.sh end-to-end 5-step smoke (incl. M6 /api/login round-trip)
  • ✅ doc-coverage CI gate enforces 7 invariants (crate agent-docs / zh-en parity / ADR frontmatter / ADR id monotonic / last_verified_commit is a real git SHA / cargo fmt --check / cargo test exit 0 AND 0 FAILED groups)
  • ✅ 5 findings filed (3 closed + 2 closed by the post-tag M4 audit)
  • 5-platform tarballs ship first-time green on v0.2.1 + v0.3.0 (two consecutive tags): linux x86_64 + aarch64, macOS x86_64 + arm64, windows x86_64. macOS x86_64 cross-compiles from macos-14 (Apple Silicon) using --target=x86_64-apple-darwin, eliminating the macos-13 runner- queue dependency. Sarah v2 pilot-gate #3 closed.
  • ✅ M6: AEAD round-trip on /login shipped — AES-256-GCM + Argon2id (m=64MiB / t=3 / p=1). Server-side derive; in-memory SessionKey; re-derive round-trip exercised by seal_then_re_derive_then_open regression test. --dev-api-key escape hatch for CI/headless use. Sarah v2 pilot-gate #2 closed.
  • ⚠️ Single-user / single-project by design — no RBAC, no multi-tenancy in v0.2.x
  • ⚠️ Bus factor 1 (looking for design partners — see below)

Looking for 3-5 design partners

If your team already runs AI-driven development at multi-agent fidelity — 3+ parallel agent workflows, ADR/finding discipline, you'd benefit from an honest token ledger and a forced doc-coverage gate — open an issue with the design-partner template describing your setup. Studio in concert with ADSD is a hard adoption (you import a vocabulary + a CI gate, not just a UI), but a real one if you're already 80% of the way there.

Top friction items design partners would file against me, in priority order:

  1. AEAD round-trip on /login — kill the env-var workaround ✅ shipped in M6 (v0.2.0)
  2. 5-platform tarballs first-time green ✅ shipped in v0.2.1 (cross-compile patch)
  3. Multi-provider /login ✅ shipped in M7 (v0.3.0) — LoginRequest + EndpointSecret gain provider_kind (Anthropic / OpenAI-compat); the SvelteKit form adds a Provider dropdown with URL-based auto-suggest. vLLM / DeepSeek / Together / OpenRouter / Groq / Ollama now work end-to-end via the session path. ADR-0008 Phase 2 merged.
  4. Persistent session across binary restart ✅ shipped in M8 (v0.4.0) — --persist-session=keychain|file wraps the user passphrase in OS keychain (macOS Keychain / freedesktop secret-service / Windows DPAPI) OR a 0600 plaintext file (Docker / D-Bus-less Linux fallback). Boot auto-unlock re-derives the SessionKey without a /login round-trip. POST /api/logout?purge=true for hard-forget. ADR-0009 Phase 2 merged.
  5. A --multi-user mode with proper RBAC + audit log (post-MVP, M7+)
  6. task_tag dispatch metadata ✅ shipping in M9 (v0.4.0) — studio_router::DispatchContext + Router::dispatch_ctx; /api/dispatch.task_tag now records into the JSONL ledger for cost-by-task analysis without polluting CompletionRequest. ADR-0010 closes ADR-0006 §F-03.
  7. Persona simulation in CI — already-run human-in-the-loop (Mei / Aleksandr / Sarah v1-v3 audits all landed), not yet automated

I'm hakureirm on GitHub. File issues with the design-partner label.


Contributing

Reads-first, code-second: read CLAUDE.md (the project's constitution) before opening a PR. Every PR needs to keep all 6 doc-coverage.sh gates green. Conventional commits + Tx tags (feat(scope): A4.7 ...) are enforced socially, not by hook (yet).

ADRs land for any cross-file decision. Findings land for any failure / bug postmortem / benchmark surprise. Negative results are first-class deliverables — see ADSD §"Honest fail acceptance".


License

Dual-licensed under Apache-2.0 and MIT at your option. Same as Rust itself and ADSD itself.

Studio's studio-router crate is a derivative work of cobrust-llm-router (also Apache-2.0 OR MIT, same author lineage) per ADR-0005 §"License attribution"; upstream copyright headers are preserved on every lifted file.


Honest status

This started as a 5-day MVP (built 2026-05-11 → 2026-05-12, single contributor) and has been continuously hardened since. The early honest mistakes:

Each was caught by the audit pattern (hermetic Playwright + clean- shell probe + persona-driven re-test) and named in the CHANGELOG by file:line.

v0.3.0 is the current stable tag. v0.2.1 was the first to ship all 5 platform tarballs first-time green; v0.3.0 is the second consecutive 5/5 (Sarah v2 pilot-gate #3 closed; release.yml cross-compile path proven durable). The CHANGELOG names every regression that came before it and the gate that missed each one. If you'd prefer a year-old tag where you don't see the patch dance, this isn't your project.

The methodology discipline runs throughout the repo — see docs/agent/findings/cto-shougate-test-gate-grep-leak.md for the kind of self-incrimination postmortem the project writes about itself.

About

Methodology-as-a-service: web console packaging the Cobrust ADR + finding + bilingual + wave + 5-gate + ADSD discipline for AI-driven dev teams. Rust + Axum + SvelteKit. v0.1.2 — early; looking for 3-5 design partners.

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors