Kanbus

Git-backed project management for people and AI agents.

Kanbus Configuration (Python + Rust)

Kanbus uses a single configuration file to define project identity, hierarchy, workflows, and priorities. The same schema and behaviors apply to both implementations.

Location

.kanbus.yml

The file must exist; there is no fallback path. A missing file is a hard error with a clear message.

Event history storage

Loading semantics (dotyaml parity)

  1. Load .env (unless disabled), setting variables only when they are not already defined.
  2. Parse .kanbus.yml, interpolating {{ VAR|default }} expressions from the environment.
  3. Flatten the resulting config into environment variables with the KANBUS_ prefix (nested keys joined by underscores, lists as comma-separated strings, booleans as true/false, null as empty string).
  4. Never override an environment variable that is already set unless override=true is explicitly requested.

These rules mirror the Python dotyaml package and must be matched in the Rust crate.

Field reference

Every key accepted at the top level of .kanbus.yml. Unknown keys are errors. This table is generated from the configuration model by tools/generate_configuration_reference.py and checked in CI.

<!-- BEGIN GENERATED: project-configuration-fields --> <!-- Generated by tools/generate_configuration_reference.py; do not edit by hand. -->

Key Type Default Description
project_directory str required Relative path to the primary project directory.
virtual_projects Dict[str, VirtualProjectConfig] {} Map of label to virtual project configuration.
new_issue_project Optional[str] None Project label for new issue creation routing.
ignore_paths List[str] [] Paths to exclude from project discovery.
console_port Optional[int] None Optional port for the web console server.
project_key str required Issue ID project key (prefix).
project_id Optional[str] None Stable UUID identifying the project across clones and worktrees; scopes realtime topics.
name Optional[str] None Optional human-readable board title.
project_management_template Optional[str] None Optional template path for CONTRIBUTING_AGENT.md.
methodologies Optional[List[Union[str, ProjectMethodologyBundleReference]]] None Methodology names assembled into CONTRIBUTING_AGENT.md.
hierarchy List[str] required Hierarchy ordering.
types List[str] required Non-hierarchical types.
workflows Dict[str, Dict[str, List[str]]] required Workflow definitions.
transition_labels Dict[str, Dict[str, Dict[str, str]]] {} Display label for every workflow transition, keyed by workflow, from-status, then to-status.
initial_status str required Initial status for new issues.
priorities Dict[int, PriorityDefinition] required Priority map.
default_priority int required Default priority.
assignee Optional[str] None Default assignee identifier.
time_zone Optional[str] None Preferred display time zone.
statuses List[StatusDefinition] [] Status definitions with display names, categories, and colors.
categories List[CategoryDefinition] [] Status category definitions with display names and colors.
sort_order Dict[str, Any] {} Optional status/category sort rules for console columns.
type_colors Dict[str, str] {} Optional map of issue type to color name.
beads_compatibility bool False Default Beads compatibility mode.
events bool True Whether Kanbus generates events under project/events and commits them with kbs commit.
wiki_directory Optional[str] None Optional directory containing wiki pages.
ai Optional[AiConfiguration] None Optional AI provider and model configuration.
right_now RightNowConfiguration see section Right-now summary configuration.
standup StandupConfiguration see section Standup report configuration.
jira Optional[JiraConfiguration] None Optional Jira synchronization configuration.
snyk Optional[SnykConfiguration] None Optional Snyk vulnerability synchronization configuration.
realtime RealtimeConfig see section Realtime gossip configuration.
coordination CoordinationConfiguration see section Multi-agent coordination configuration.
router Optional[IssueRouterConfiguration] None Optional issue router configuration.
overlay OverlayConfig see section Overlay cache configuration.
hooks HooksConfiguration see section Lifecycle hook configuration.
github_security Optional[GithubSecurityConfiguration] None Optional GitHub security synchronization configuration.
<!-- END GENERATED: project-configuration-fields -->

Minimal configuration

project_directory: project
project_key: kbs
hierarchy: [initiative, epic, task, sub-task]
types: [bug, story, chore]
workflows:
  default:
    open: [in_progress, closed]
    in_progress: [open, closed]
    closed: [open]
initial_status: open
priorities:
  0: {name: critical}
  1: {name: high}
  2: {name: medium}
  3: {name: low}
default_priority: 2
transition_labels:
  default:
    open: {in_progress: Start work, closed: Drop}
    in_progress: {open: Pause, closed: Finish}
    closed: {open: Reopen}
categories:
  - {name: To do}
  - {name: Done}
statuses:
  - {key: open, name: Open, category: To do}
  - {key: in_progress, name: In Progress, category: To do}
  - {key: closed, name: Closed, category: Done}

kbs init writes a complete starting configuration; edit that rather than starting from scratch.

Validation rules

Beyond the schema, loading fails when:

Environment integration

Realtime gossip + overlay

realtime:
  transport: auto            # auto | uds | mqtt
  broker: auto               # auto | off | mqtt://... | mqtts://...
  autostart: false           # autostart mosquitto if unreachable (the gossip bridge always autostarts)
  keepalive: false           # keep autostarted broker running
  uds_socket_path: null      # override UDS socket path
  mqtt_custom_authorizer_name: null  # optional AWS IoT custom authorizer name
  mqtt_api_token: null       # optional API token for custom authorizer auth
  topics:
    project_events: "projects/{project}/events"

overlay:
  enabled: true
  ttl_s: 86400

coordination:
  providers: [git]             # git | [mqtt, git] | [mutex_api, mqtt, git]
  contention_window: 5s        # Competing claims use this window for tie-break
  default_lease_ttl: 300s      # Initial claim lifetime and default renewal step
  mutex_api:
    endpoint: null              # e.g. https://mutex.example.test
    bearer_token: null          # sent as Authorization: Bearer <token>

Coordination durations are positive integer values followed by s, m, or h (for example 5s, 2m, or 1h). The provider lists are ordered strongest first: [git], [mqtt, git], or [mutex_api, mqtt, git]. Git records remain the durable coordination history. Git-only claims are soft; MQTT adds shared visibility; the Mutex API adds hard exclusion for live leases. The Mutex API client uses POST, PUT, DELETE, and GET on {endpoint}/api/coordination/leases/{resource} with bearer authentication. When its endpoint or token is missing, or the service is unavailable, Kanbus falls back through configured MQTT and Git providers. A live-lease conflict and owner mismatch remain errors. For a hard claim, Kanbus appends the Git claim event only after the API accepts the acquire; if that append fails it tries to release the lease and reports the durable-write failure.

Claims, renewals, and releases are immutable records in project/events/, keyed by the resource in the event's issue_id subject field. These events do not change issue assignees or statuses. Git coordination is soft: workers can record competing claims, and the winner is selected from claims in the initial contention window by (claim_id, owner, event_id). Later claims do not replace an active winner; expiry or release makes the resource eligible again.

Notes:

Examples

Default software project

project_key: "KAN"
issue_types: [bug, story, chore]
workflow_bindings:
  bug: default
  story: default
  chore: default
initial_status: open
priorities: [critical, high, medium, low, trivial]
default_priority: medium
priority_import_aliases:
  P0: critical
  P1: high
  P2: medium
  P3: low
priority_accept_unmapped: true

Beads import mapping

project_key: "BDX"
issue_types: [bug, task]
workflow_bindings:
  bug: default
  task: default
priorities: [urgent, high, normal, low]
default_priority: normal
priority_import_aliases:
  P0: urgent
  P1: high
  P2: normal
  P3: low
priority_accept_unmapped: false

Methodologies

methodologies selects the process guidance assembled into the generated CONTRIBUTING_AGENT.md, in the listed order. Entries are built-in names (bdd, git-flow) or { path: <folder> } for a bundle in the repository. When the key is absent the default is [bdd, git-flow]; methodologies: [] produces core guidance only.

methodologies:
  - bdd
  - git-flow
  - path: methodologies/crap

See Methodologies for the bundle format, tools, and the kbs methodology commands.

AI and right-now defaults

Kanbus routes LLM calls through LiteLLM (ai.provider: litellm). The product default model is gpt-5.6-luna (OpenAI via OPENAI_API_KEY).

ai:
  provider: litellm
  model: gpt-5.6-luna

right_now:
  enabled: true
  default_tree_expanded: false
  max_length: 120
  model: gpt-5.6-luna

Right-now summaries are generated only when they are displayed: kbs now and the console Now panel generate a summary that is missing or older than the issue or one of its direct children. Board-mutating commands (create, update, comment, dep, delete) never call an LLM. Each generation is logged to project/events/llm_usage.jsonl; a call whose model has no known price is logged with "cost": null, and kbs cost reports it under Unpriced Calls instead of counting it as $0.

Credentials

Run kbs setup ai (or kanbus setup ai) once per user to store an LLM API key. It prompts for the key (hidden input) and writes it to ~/.kanbus.env (mode 600), so every project on the machine picks it up without a per-project .env.

Lookup order: shell environment, then ~/.kanbus.env, then the project .env file.

kbs setup ai                         # interactive prompt
pbpaste | kbs setup ai --from-stdin  # read from stdin, e.g. a clipboard or secrets manager
kbs setup ai --variable ANTHROPIC_API_KEY   # store a different provider's variable
kbs setup ai --status                # show which source (if any) provides the key

Check kbs setup ai --status or kbs doctor to confirm a key is configured. Never store API keys in .kanbus.yml.

For a LiteLLM proxy instead of a direct provider key, set LITELLM_API_KEY alongside LITELLM_API_BASE or LITELLM_PROXY_URL (the Rust kbs now/standup path also accepts OPENAI_API_BASE); these follow the same shell-environment / ~/.kanbus.env / project-.env lookup order.

Machine-wide settings

Any KANBUS_* environment override can also live in ~/.kanbus.env, so every clone and worktree on the machine shares it, using the same kbs setup env NAME --value ... (or --from-stdin) command used for credentials. Environment overrides always beat .kanbus.yml. This is useful for settings that should be consistent machine-wide rather than per project, such as the realtime transport/broker/autostart/keepalive variables, KANBUS_REALTIME_MQTT_API_TOKEN, KANBUS_REALTIME_MQTT_CUSTOM_AUTHORIZER_NAME, and the coordination mutex endpoint/token (KANBUS_COORDINATION_MUTEX_API_ENDPOINT, KANBUS_COORDINATION_MUTEX_API_BEARER_TOKEN).

kbs setup env KANBUS_REALTIME_BROKER --value mqtt://127.0.0.1:1883
pbpaste | kbs setup env KANBUS_REALTIME_MQTT_API_TOKEN --from-stdin

Standup windows

Standup reports resolve completed vs active buckets from shared window settings. Field names are locked for config, CLI, and console API:

standup:
  window: rolling        # rolling | calendar
  lookback: 24h          # rolling duration; hours required (1d = 24h sugar)
  skip_weekends: false   # calendar only; ignored when window is rolling
  timezone: America/New_York  # optional IANA zone; unset uses system local

Defaults:

standup.lookback_hours is not accepted (extra=forbid). Migrate to standup.lookback with a duration string such as 24h or 1d.

CLI overrides (same names as config/API): --window, --lookback, --skip-weekends / --no-skip-weekends.

Optional sync sections

github_security:
  repo: owner/repo
  dependabot:
    min_severity: low
    state: open
    parent_epic: kanbus-abc123