Kanbus

Git-backed project management for people and AI agents.

Architecture Overview

Kanbus is intentionally simple: a git-backed issue store with dual Python and Rust implementations that share a single specification. The architecture keeps storage, execution, and user experience aligned so both runtimes behave identically.

Language Duality

Kanbus ships two first-class CLIs—Python and Rust—that execute the same Gherkin-defined behaviors. The Python path is optimized for rapid iteration and rich ecosystem tooling; the Rust path is optimized for binary distribution and tight resource use. Both consume the same project layout, data model, and validation rules to preserve behavioral parity.

File Organization Model

Kanbus stores each issue as its own JSON file under project/issues/, eliminating merge-heavy monoliths and removing any secondary database. Hierarchical types and workflows live in .kanbus.yml, keeping schema alongside data. There is exactly one storage path: the JSON files in the repository. No fallbacks, no mirrored SQLite caches, and no daemon-owned state are required to read or list issues.

Subsystems

Both runtimes keep the same module boundaries. Names below are shared between rust/src/ and python/src/kanbus/ unless noted.

Subsystem Modules Responsibility
Storage issue_files, file_io, ids, event_history, overlay Read and write one JSON file per issue, allocate identifiers, append event history.
Configuration config, config_loader, project, workflows, hierarchy, status_semantics Load .kanbus.yml, validate it, and resolve workflows, hierarchy and status meaning.
Issue operations issue_creation, issue_update, issue_close, issue_delete, issue_comment, issue_transfer, issue_mutation, dependencies The mutating commands behind the CLI.
Queries and display issue_listing, issue_lookup, queries, issue_display, issue_line, dependency_tree, right_now, standup* Listing, search, formatting, and the now and standup views.
Methodologies and policy methodology_bundles, methodologies, policy_*, hooks, doctor Pluggable process rules, Gherkin policy checks, lifecycle hooks and health checks.
Daemon and realtime daemon_*, gossip, coordination*, notification_events Optional index daemon, realtime gossip and coordination. The CLI works without any of it.
Issue router router*, agent_assignment, agent_metadata Leases, assignment and agent conversation for the issue router.
Wiki wiki*, console_wiki (Rust) Jinja plus Markus page rendering.
Integrations beads_write, migration, jira_sync, snyk_sync, github_security_sync Beads interop and external trackers.
AI ai_credentials, summarize, litellm_completion, llm_cost Optional summaries; never required for core commands.
Console (Rust only) console_backend, console_snapshot*, console_ui_state, bin/console_local, bin/console_lambda The HTTP and SSE server behind the web console, plus the Lambda adapter.

Event History

Kanbus records an append-only event log under project/events/ (and project-local/events/ for local issues). Each discrete issue action writes a single JSON file named with an RFC3339 timestamp plus a UUID suffix (e.g., 2026-02-21T06:09:40.180Z__<event_id>.json). The event payload captures issue identifiers, actor, timestamps, and action-specific fields (state transitions, comment IDs, dependency changes, and field updates). There is no indexing layer; consumers scan and filter the files when event history is requested. Events are generated by default and committed with the issues by kbs commit; setting events: false in .kanbus.yml turns generation off entirely.

Performance Benchmark

We benchmarked end-to-end “list all beads” latency using the Beads project itself as real-world data:

The results show that fast listing does not require a SQLite sidecar. Kanbus streams directly from JSON files while matching or beating the SQLite-backed Beads path, removing an entire class of synchronization failures and simplifying the mental model for operators and contributors.

Beads CLI Listing Response Time (warm)

Warm-start median response times (ms): Go 5277.6; Python — Beads JSONL 538.7; Rust — Beads JSONL 9.9; Python — Project JSON 653.5; Rust — Project JSON 54.6.

Beads CLI Cold vs Warm Response Time

Cold/Warm medians (stacked bars, cold over warm): Go 197.6/5277.6; Python — Beads 566.1/538.7; Rust — Beads 11.9/9.9; Python — JSON 648.3/653.5; Rust — JSON 92.4/54.6. Warm runs keep the Kanbus daemon resident; cold runs disable it and clear caches. Go/Beads warm mode jumps because its SQLite daemon import dominates the second pass.

Takeaway: direct JSON reads keep response time low in steady state without a secondary database. The SQLite sidecar adds variance and operational complexity while providing little benefit for the listing path.

ID Generation Strategy

Kanbus uses flat hash-based IDs (e.g., kanbus-a1b2c3) with explicit parent pointers, rather than hierarchical IDs encoded in the identifier itself (e.g., kanbus-0lb.1, kanbus-0lb.2).

Why Hierarchical IDs Cause Collisions

Beads-style hierarchical IDs embed parent-child relationships directly in the ID format:

This approach breaks down when multiple agents create children concurrently:

  1. Agent A reads parent tskl-0lb, sees it has 2 children, creates tskl-0lb.3
  2. Agent B reads parent tskl-0lb (same state), sees it has 2 children, creates tskl-0lb.3
  3. Both agents commit their changes
  4. Git merge succeeds (different files), but both issues have ID tskl-0lb.3

The collision occurs because the ID generation depends on reading the current count of children, which becomes stale in concurrent workflows.

The Kanbus Approach

Kanbus generates IDs using SHA256 hashes of the title plus a random nonce, producing globally unique identifiers without coordination:

Multiple agents can create children of the same parent simultaneously without collision risk. The hierarchy is maintained through explicit parent pointers in the issue data, not encoded in the ID format.

This design principle applies throughout Kanbus: hierarchy should be rendered from the graph structure, not encoded in identifiers. IDs are opaque handles; relationships are first-class data.