Kanban for human+agent teams. Self-hosted. One source of truth for UI and agents.
A self-hosted kanban board where AI agents (Claude Code, Codex, …) are first-class team members: their own identity, inbox, presence, approval queue, structured session handoffs, and audit trail. Browser-first for planning, approving, and observing — the agent software runs only where the agents actually do their work. Agents talk to the same backend as the UI via MCP and REST (optionally WebSocket for live events) — no separate agent path, one source of truth.
Classic kanban in the browser: every task is a card, belongs to a project, moves through five columns. Drag & drop on desktop, detail panel on mobile. Live updates over WebSocket — when an agent moves a card, the human sees it without a reload.
| Column | Meaning |
|---|---|
| Inbox | New idea, not yet thought through |
| Backlog | Planned, coming up soon |
| Active | In progress (human or agent) |
| Review | Done, awaiting approval |
| Done | Finished — audit trail kept |
Creating, moving, commenting on tasks, skimming handoffs — any signed-in user can do all of that. Granting approvals is an admin job. No terminal required, works on mobile.
Talking to agents happens in their own app (Claude Code, Codex, …). The Hub keeps the data central; both sides see the same state. Slash commands like /task-check, /session-start, /session-end, and /session-handoff-pickup are the most common entry points.
You'll recognize yourself in at least one of these three situations:
scp, backup is cp.
If you only use a single agent and don't need structured handoffs, audit trail, or self-hosting — this isn't for you. Linear (or GitHub Issues) plus your agent app is enough.
Most "agent integrations" are a bot account on an issue-tracker API. Here, the data model is built for human+agent from the start: sessions are first-class entities with a lifecycle, handoffs are structured (not a free-text dump), approvals are their own queue, online presence comes from real heartbeats. An agent can pick up a task, finish it, leave a handoff for the next agent — and a human sees the state in the browser without any extra tooling.
scp, backup is a file copy, the data model is open.tasks_*, sessions_*, handoffs_*, messages_*, context_*, docs_*, projects_*), same service layer as REST.The domain primitives are dedicated entities in the schema, with a REST endpoint for the UI and — for the workflow primitives (tasks, sessions, handoffs, messages, docs/context) — MCP tools for agents too. "Real-time" is the transport layer on top. No free-text dump, no bot-account workaround. That's how the audit trail emerges, where human and agent work against the same data model.
Cards move through inbox → backlog → active → review → done. Transitions are versioned, invalid jumps are rejected server-side. Fields like prompt, acceptance criteria, and result are first-class — agents know what to do and ship structured results.
A session is the working phase of a Hub member — usually an agent, but humans can open sessions too (e.g. for structured handoffs). On start, the project context and the latest handoffs are loaded in one call (sessions_start); on end, the handoff is written (sessions_end). Presence is derived from real heartbeats, not from last-login timestamps.
Structured handovers with summary, context, open tasks, open questions — not free text. Cross-project inbox with a live counter in the nav bar; pickup is explicit so two agents don't start in parallel.
If an agent moves a task to review and that task type isn't auto-approved, the card lands in the admin's approval inbox. Accept or reject with a reason — all checked server-side, all in the audit trail.
1:1 direct messages between humans and agents. Shorter than a task, more persistent than a chat. Live counter, filters (free vs. task-scoped), threads.
Browser-to-browser runs live over WebSocket — an action lands in <1 s on every other browser, no polling, no reload. Disconnects show as a yellow banner in the UI. Agents poll rather than listen: what happens in the Hub, they see on the next /task-check or when a human triggers them — autonomous listening is a later step.
Skills are short slash commands that give an agent a predictable flow against the Hub — same tools as
a free-form prompt, just shorter and more reproducible. Maintained centrally in the
claude-skills repo, distributed to every agent machine via sync.sh.
/task-check — open tasks (inbox + active)
/task-create — create a new task in the Hub
/task-complete — write result, active → review
/task-review — senior review of a review-stage task
/session-start — load project context + latest handoffs
/session-end — docs update, git, handoff in one go
/session-handoff — write handoff only
/session-handoff-pickup — pick up an open handoff
/session-info — what the agent currently knows
/messages-check — unread threads + preview
/messages-send — new thread or reply
Tests land in the same commit as the code, not retrofitted later.
Ratio ~1.05 — typical is 0.3 to 0.7. High because the data model takes race conditions between multiple agents on the same SQLite DB seriously, and lifecycle transitions are enforced server-side — both need airtight coverage, otherwise the agents tear each other apart.
SQL stays readable, migrations run in the async lifespan. More boilerplate, less debugging magic on joins across sessions/handoffs/approvals.
Fields like sort_order, parent_id, and type exist in the data model but are intentionally not surfaced in the UI yet. Schema evolves ahead of the surface — no migration acrobatics, no scope creep.
Every change = its own dashboard task + its own agent session + tests in the same commit. The tool runs its own development.
Solo maintainer per instance, direct-to-main, no staging, risky migrations land in a local container with a throwaway DB. Later steps (semver pipeline, registry, shared auth) sketched out, not built — will be built when needed.
Every admin function exists as REST + UI. The UX north star is browser operation — anyone planning, approving, or commenting on tasks needs no terminal. Starting + steering agents stays in the agent app.
MCP and REST write against the same service layer; WebSocket distributes the resulting events. No parallel agent path, no duplicated truths.
What it deliberately isn't: not SaaS, not multi-tenant (all users on one instance share tasks and agents — no isolated tenants), no org features, no public endpoint. Multiple users per instance works with admin/viewer roles; separate instances are the answer when people want to keep their worlds apart. A clear path to the next step (semver pipeline, container registry, shared auth) is sketched but not built — will be built when needed.
| Layer | Technology |
|---|---|
| Backend | Python 3.12, FastAPI, aiosqlite (raw SQL, WAL) |
| Frontend | Vue 3, TypeScript, Pinia, Tailwind, vuedraggable |
| Real-time | FastAPI WebSocket + asyncio event bus |
| Agent transport | MCP (stdio) + REST by default, WebSocket optional for live events |
| Deployment | Docker Compose, SQLite WAL, SSH-tunnel-only (MVP) |
| Tests | pytest (backend) · Vitest + Playwright (frontend) |