A self-hosted web platform that turns your existing CLI coding agents (Claude Code, GitHub Copilot CLI, Codex) into a unified, session-managed, browser-accessible workbench — powered by the agentic
.mdrepository you already have.
Give engineers a single web interface to run, observe, and manage their locally installed CLI coding agents — without replacing, wrapping-away, or re-authenticating anything. The agents, configs, and .md-based agentic repository you already trust stay exactly where they are; the platform simply makes them operable from anywhere.
Evolve from "a web UI on top of CLI agents" into an agent operations platform: a place where interactive sessions, scheduled automations, and fully autonomous runs coexist — with the same guardrails (approval modes), the same audit trail (session history), and the same portability (Linux, self-hosted, single binary/compose stack). Long-term, the platform is engine-agnostic: any CLI agent that speaks stdin/stdout or exposes a headless mode can be plugged in as a backend.
- Mount, don't manage — reuse existing local configs (
~/.claude/,~/.copilot/,~/.codex/), API keys, MCP servers, and the agentic.mdrepo as-is. Zero duplicate auth or config drift. - The CLI is the engine, the web is the cockpit — the platform never re-implements agent logic; it orchestrates real CLI processes (headless/non-interactive modes, e.g.
claude -p --output-format stream-json). - Safety is a dial, not a switch — approval-gated by default, full-auto by explicit opt-in, per session.
- Lean single-tenant first — one user, one host, no auth complexity beyond a login gate; multi-tenancy is a future concern, not an architectural debt.
- Everything is a session — interactive chats, scheduled jobs, and auto-runs share one session model, one history store, one UI.
- Linux host (bare metal, VM, or container) — local workstation or server.
- Engine adapters for Claude Code, GitHub Copilot CLI, Codex CLI, using each tool's headless/programmatic mode and its locally installed binary + config.
- Web UI: chat interface with streaming output, structured tool-call progression (tool started → args → result), diffs, and file references.
- Session lifecycle: create, resume, fork, archive, search; persistent history (à la Claude Code web).
- Approval modes: per-session policy ranging from approve-every-tool-call → approve-writes-only → full auto (YOLO).
- Working-directory / repo targeting per session (point a session at any local checkout).
- Later phases: scheduling & automation (cron-style and event-triggered runs), run queues, notifications.
- Multi-tenant auth, RBAC, orgs/teams (future).
- Managing or storing provider API keys — engines bring their own auth.
- Re-implementing agent capabilities (planning, tool use, MCP) — delegated to the engines.
- Windows/macOS hosting (WSL users can host on the Linux side).
- Model routing / LLM gateway features.
┌──────────────┐ WebSocket/SSE ┌────────────────────┐
│ Web UI │ ◄───────────────► │ Platform Server │
│ (chat, tool │ │ - session manager │
│ timeline, │ REST │ - engine adapters │
│ history) │ ◄───────────────► │ - approval broker │
└──────────────┘ │ - scheduler (v2) │
└─────────┬──────────┘
│ spawn / PTY / stream-json
┌────────────────────┼────────────────────┐
▼ ▼ ▼
claude (CLI) copilot (CLI) codex (CLI)
~/.claude/* ~/.copilot/* ~/.codex/*
└──────── shared: repos + agentic .md repo ────────┘
Key mechanism: each engine adapter normalizes the engine's native event stream (e.g. Claude Code's stream-json) into one internal event schema — message, tool_call, tool_result, approval_request, done — which drives both the UI and the history store (SQLite is sufficient for single-tenant).
Goal: replace terminal-only usage for day-to-day interactive work with at least one engine, end-to-end, on a Linux host.
| # | Requirement | Notes |
|---|---|---|
| 1 | Linux deployment | Single service (systemd unit or docker compose) |
| 2 | Engine: Claude Code first, adapter interface designed for Copilot CLI & Codex | Claude Code has the most mature headless mode; others follow in fast-follow releases |
| 3 | Web chat UI | Streaming responses, markdown rendering, visible tool-call progression with collapsible detail |
| 4 | Session management | List / resume / rename / delete; history persisted across restarts; resume maps to engine-native resume where available |
| 5 | Permission control | Per-session --permission-mode (ask / accept-edits / plan / bypass), inherited from ~/.claude when unset; the engine decides what to surface and the UI prompts for it |
| 6 | Config mounting | Detect and use existing engine binaries + user configs; no keys stored by the platform |
| 7 | Repo targeting | Choose working directory per session; agentic .md repo picked up natively by the engine |
- One engine live (Claude Code); adapter contract proven with a stub for a second engine.
- No scheduling, no automation triggers, no notifications.
- Single user behind a simple login/token; HTTPS via reverse proxy is the operator's choice.
- No fancy diff viewer beyond rendered patches in the tool timeline.
- A full coding task (plan → edit → test) completed entirely via the web UI, with correct approval prompts.
- Session survives a server restart and can be resumed with context intact.
- Zero engine configuration was duplicated into the platform.
- v1.1 — Multi-engine: Copilot CLI + Codex adapters; per-session engine picker; side-by-side engine comparison on the same prompt (stretch).
- v1.2 — Automation: cron-style scheduled sessions, run templates ("run nightly dependency audit with full-auto in repo X"), run queue + concurrency limits.
- v1.3 — Triggers & notifications: webhook-triggered runs (CI, Git events), completion notifications (webhook/email), run reports.
- v2 — Hardening for sharing: authn/authz, per-user config isolation, audit log — the on-ramp to multi-tenant.
- Engine CLIs change their headless interfaces → isolate all engine specifics in adapters; pin tested versions; contract tests per adapter.
- Full-auto sessions doing damage → full-auto requires explicit per-session opt-in, is visually distinct in the UI, and is constrained to the session's working directory; recommend running the service as a dedicated user.
- Approval flows differ per engine (some only support allow-lists, not interactive gating) → permission policy is delegated to the engine (Claude via
--permission-mode); the hub relays whatever the engine surfaces to the user. Engines without interactive gating apply their mode themselves or degrade to pre-run permission profiles. - Scope creep toward "yet another agent framework" → principle #2 is the tie-breaker: if a feature re-implements engine behavior, it's out.
- Linux host, Node.js ≥ 20, pnpm ≥ 10
- At least one engine CLI installed and authenticated as the user that runs the server (e.g.
claude login). Theechostub engine needs nothing and is enabled by default for trying the platform out.
pnpm install
pnpm build # builds shared, server, web
pnpm --filter @hub/shared build && pnpm dev # server :3000 + Vite :5173 (proxied)Open http://localhost:5173 and sign in with the token printed in the server log (or set AUTH_TOKEN). Tests (no API key needed — the echo engine covers the full flow):
pnpm test # unit + adapter contract + keyless e2e
CLAUDE_LIVE=1 pnpm --filter @hub/server test # live claude CLI integration (costs cents)
pnpm --filter @hub/server spike # protocol probe: run when qualifying a new CLI versioncd deploy
cp .env.example .env # set AUTH_TOKEN at minimum
docker compose up -d --buildThe compose file mounts ~/.claude + ~/.claude.json (your existing engine auth — the platform stores no keys) and $HOME/code as /workspace (override with WORKSPACES=...). Keep the workspace mount path stable: the engine keys its transcript store by project path, so moving it breaks session resume.
See the install steps in deploy/agentic-cli-hub.service. Run the service as a dedicated user: a full auto session can do anything that user can do, so give it exactly the workspaces it should reach (WORKSPACE_ROOTS). Bind to 127.0.0.1 and let your reverse proxy terminate HTTPS.
| Env var | Default | Purpose |
|---|---|---|
AUTH_TOKEN |
generated per boot (logged) | Single access token for UI/API/WebSocket |
HOST / PORT |
127.0.0.1 / 3000 |
Bind address |
DATA_DIR |
./data |
SQLite session history |
WORKSPACE_ROOTS |
$HOME |
Colon-separated dirs sessions may target as cwd |
WORKTREE_ROOT |
$DATA_DIR/worktrees |
Where isolated per-session git worktrees are created |
ENGINES |
claude-code,echo |
Engine adapters to enable |
CLAUDE_BIN |
claude on PATH |
Engine binary override |
ENGINE_IDLE_TIMEOUT_MS |
1800000 |
Kill idle engine processes (sessions resume seamlessly) |
APPROVAL_TIMEOUT_MS |
0 (wait forever) |
Auto-deny pending approvals after this long |
LOG_LEVEL |
info |
Fastify/pino log level |
shared/ @hub/shared — normalized event schema, WS protocol, API DTOs
server/ @hub/server — Fastify + WebSocket hub, SQLite event log,
engine adapters (claude-code, echo), permission-mode policy
web/ @hub/web — Svelte 5 chat UI (tool timeline, approvals, sessions)
deploy/ Dockerfile, docker-compose.yml, systemd unit, .env.example
Status: v0.1 — single-tenant, Linux-first, engine-mounted. The .md agentic repository remains the brain; this platform is the body.