Local-first issue tracking for humans and coding agents.
kata gives agents a structured place to record tasks, decisions, links, comments, and state changes without turning GitHub Issues, markdown plans, or chat transcripts into the source of truth.
The CLI is built for agents and automation: stable commands, JSON output, and predictable failure modes. The TUI is built for people: browse, triage, edit, and supervise agent-written work without reading raw JSON. Both talk to the same local daemon and SQLite database.
Status: early public preview. The CLI, daemon, and TUI are usable, but command contracts and UI details may still change before a stable release.
What you can do:
- Track issues separately per project, with issue numbers that restart per project.
- Create, list, edit, close, reopen, comment, label, assign, and link issues.
- Search, idempotent-create, soft-delete, restore, and irreversibly purge.
- Browse and triage in a TUI (
kata tui) over the same data. - Stream state changes as durable events for polling, live tailing, hooks, and TUI updates.
How it's built:
- Workspace-to-project binding lives in
.kata.toml, falling back to a git remote URL when no binding file exists. - Data lives locally in SQLite under
KATA_HOMEbehind a long-running daemon. - Issues have stable ULID
uidvalues in JSON;#Nremains the project-scoped display label. kata exportandkata importprovide a git-friendly JSONL backup and schema cutover path.- Successful commands emit JSON for reliable parsing by agents and scripts.
Three priorities:
- Agent ergonomics: stable commands, JSON-first workflows, explicit workspace binding, search-before-create, idempotency keys, and predictable exit codes.
- Human oversight: a TUI that helps people browse, triage, edit, and supervise agent activity without reading raw JSON.
- Auditability: append-only comments, event history, actor attribution, and explicit destructive operations.
Longer term, kata is intended to support a shared server mode for teams, CI, and multiple agents. That mode should be a real authenticated deployment, not the local daemon exposed on a public interface.
kata is intentionally small. It is not a project-management suite, a git workflow engine, or an agent worker pool. It is a durable task ledger that humans and agents can both understand.
Beads is a substantial tool in the
same space: a Dolt-powered distributed graph issue tracker for AI agents. Its
default shape is project-local: bd init creates a .beads/ Dolt database
alongside the code, with native Dolt history, branching, merging, push/pull,
and optional server mode for concurrent writers. That does not mean Beads
requires git; it also supports git-free workflows.
kata makes a different architectural bet: the issue ledger should be a local
service adjacent to workspaces, not a database owned by each repository. A
repository that uses kata gets only a small, secret-free .kata.toml binding;
the canonical state lives in KATA_HOME behind a daemon API. That keeps task
state out of code history while still giving agents a structured coordination
layer and giving humans a TUI over the same event stream.
It also has a different complexity budget. Beads is a large, capable system with distributed database semantics, merge behavior, federation, MCP integration, and agent workflow machinery. kata is deliberately smaller: one daemon, one local store, one HTTP API, one TUI, and a narrow issue model that should stay easy to understand, operate, and teach to agents.
git-bug takes the most git-native
approach of the three: it stores issues, comments, and identities as git
objects under custom refs in the repository itself, and distributes them
through ordinary git push / git pull. Every clone carries the full issue
history offline, and bridges sync with GitHub, GitLab, and Jira. kata sits at
the other end of that spectrum — issue state lives outside git entirely, so
the workspace stays clean, non-git workspaces work identically, and issue
history is not interleaved with code history. The trade-off is that kata
cannot piggyback on git remotes for sharing; that is what the future
authenticated server is for.
| Design choice | Beads | kata |
|---|---|---|
| Storage boundary | Project-local .beads/ Dolt database by default |
User-local KATA_HOME SQLite database behind a daemon |
| Repository footprint | Owns issue state near the repo by default; can sync via Dolt remotes | Repo stores only .kata.toml project binding |
| Collaboration model | Dolt push/pull, Dolt server mode, federation, MCP tooling | Local daemon today; future authenticated shared server |
| IDs | Hash-based IDs by default; counter IDs optional | Per-project sequential numbers (#12) |
| Workflow shape | Rich graph tasks, priorities, claiming, messages, dependencies | Deliberately small issue ledger: status, comments, labels, owner, links, events |
| Git relationship | Git integration is optional but first-class; commit conventions and doctor checks can connect code history to issues | Git can help identify workspaces; kata does not infer issue state from commits |
All three approaches are useful. Beads is strongest when you want distributed, database-versioned task memory that can travel with a project and merge across branches or agents. git-bug is strongest when you want issue state to live inside the repository's own git history and ride the same remotes the code does. kata is aimed at a smaller, API-first issue system that can span workspaces and eventually teams without forcing every user and agent to understand the repository, git remote, or distributed database that carries the issue state.
kata is built with Go. To build from source you need Go 1.26 or later and a clone of this repository:
make build
make installmake install places kata in ~/.local/bin. Make sure that directory is on
your PATH.
For development:
make testInitialize kata in a workspace:
kata initkata init creates or resolves the project and writes .kata.toml when
needed. In a git workspace, the default project identity is derived from the
remote URL. For a non-git workspace or an explicit shared identity:
kata init --project github.com/example/product --name productCreate and inspect issues:
kata create "fix login race" --body "Safari can double-submit the callback."
kata list
kata show 1
kata comment 1 --body "Reproduced on macOS."
kata close 1 --reason doneOpen the TUI for human triage:
kata tuiPress ? inside the TUI for keybindings.
Use --workspace <path> when running from outside the project directory:
kata --workspace ~/code/product list --status allSet the actor for a session:
export KATA_AUTHOR=codex-wesm-laptop
kata whoamiActor precedence is --as > KATA_AUTHOR > git config user.name >
anonymous.
Common issue commands:
kata create <title> [--body TEXT | --body-file PATH | --body-stdin]
[--label LABEL] [--owner NAME]
[--parent N] [--blocks N] [--idempotency-key KEY]
kata list [--status open|closed|all] [--limit N]
kata show <issue-ref>
kata edit <number> [--title TEXT] [--body TEXT] [--owner NAME]
kata comment <number> [--body TEXT | --body-file PATH | --body-stdin]
kata close <number> [--reason done|wontfix|duplicate]
kata reopen <number>Labels, ownership, and relationships:
kata label add <number> <label>
kata label rm <number> <label>
kata labels
kata assign <number> <owner>
kata unassign <number>
kata parent <child-ref> <parent-ref> [--replace]
kata unparent <child-ref>
kata block <blocker-ref> <blocked-ref>
kata unblock <blocker-ref> <blocked-ref>
kata relate <a-ref> <b-ref>
kata unrelate <a-ref> <b-ref>
kata link <from-ref> <parent|blocks|related> <to-ref>
kata unlink <from-ref> <parent|blocks|related> <to-ref>For show and relationship commands, an issue ref can be #N, N, a full
UID, or a unique UID prefix of at least 8 characters.
Search, readiness, events, and project inspection:
kata search <query> [--limit N] [--include-deleted]
kata ready [--limit N]
kata events [--after N] [--limit N]
kata events --tail [--last-event-id N]
kata digest --since 24h [--until ...] [--project-id N | --all-projects]
[--actor NAME ...]
kata projects list
kata projects show <project>
kata projects rename <project> <name>
kata projects merge <source> <target> [--rename-target NAME]
kata export [--output PATH]
kata import --input PATH --target PATH [--force]kata digest summarizes activity over a time window. It groups events by
actor and lists per-issue actions (created, commented:N, closed:done,
labeled:bug, unblocks:#7, ...) so you can see at a glance what each agent or
person did overnight. --since accepts a duration (24h, 7d) or an
RFC3339 timestamp; --until defaults to now. The default scope is the
current workspace's project; pass --all-projects for a cross-project
digest, or --project-id N for an explicit one. --actor is repeatable to
limit the report to one or more actors.
Destructive operations are explicit:
kata delete <number> --force --confirm "DELETE #<number>"
kata restore <number>
kata purge <number> --force --confirm "PURGE #<number>"delete is reversible. purge is not.
Daemon, diagnostics, and agent instructions:
kata daemon status
kata daemon stop
kata daemon reload
kata daemon logs --hooks [--tail]
kata health
kata whoami
kata quickstart
kata tuiThis is the short version to give any coding agent, regardless of whether that agent supports skills, memories, or custom instructions. It is also shipped with the CLI:
kata quickstart
kata agent-instructions # aliasSession setup:
- Run from the project workspace, or pass
--workspace <path>. - Set
KATA_AUTHORonce at session start. - Prefer
--jsonfor reads and writes when you need to parse output.
Per-task guidelines:
- Never create a project implicitly. If the workspace is not initialized,
report that
kata initis needed. - Search before creating; pass an idempotency key when you do create.
- Prefer updating existing issues over opening duplicates.
- Close only when the work is actually complete.
- Do not run
deleteorpurgeunless the user explicitly asks for that exact destructive action and issue number.
Use relationships deliberately. The link types mean:
| Type | Meaning |
|---|---|
parent |
This issue is part of a larger issue. |
blocks |
The first issue must be resolved before the second can proceed. |
related |
Useful context, but not ordering. |
Example session:
# Search before creating
kata search "login race" --json
# If no existing issue fits, create with an idempotency key
kata create "fix login race" \
--body "Observed double-submit in Safari callback." \
--idempotency-key "login-race-2026-05-02" \
--json
# Update an existing issue rather than open a duplicate
kata show 12 --json
kata comment 12 --body "Found another reproduction path." --json
kata label add 12 safari --json
kata block 12 18 --json
# Close when done
kata close 12 --reason done --jsonFor long-running agents, poll events and remember the returned cursor; resume
from it on the next call. If a response says reset_required, discard cached
kata state and resume from the reset cursor.
kata events --after 0 --limit 100 --jsonFor live streams, --tail emits newline-delimited JSON:
kata events --tailToday kata is local-first:
- one local daemon;
- one local SQLite database;
- no authentication;
- trusted same-user CLI and TUI clients.
Multiple checkouts or repositories can share one kata project when they use
the same .kata.toml project identity and run kata init in each checkout.
That shares issue numbering, labels, links, and events across those workspaces
in the same local database.
If a repository rename accidentally creates a second project, merge the old source into the surviving target, for example:
kata projects merge old-repo new-repo --rename-target new-repoFuture shared mode should be a distinct deployment:
- a shared kata server reachable over HTTPS, SSH tunnel, or a private network;
- authenticated users and service tokens;
- server-derived actor identity;
- server-side hooks and backups;
- the same project, issue, event, and relationship model.
The local daemon should not be exposed directly to a LAN or public network.
A kata daemon can serve clients on other hosts over a private network (loopback, RFC1918, CGNAT, link-local, ULA — public addresses are rejected):
kata daemon start --listen 100.64.0.5:7777Or set the address persistently in <KATA_HOME>/config.toml:
listen = "100.64.0.5:7777"The CLI flag wins over the config file when both are present. Auto-started
daemons (the on-demand path triggered by kata create, kata list, etc.)
also pick up the config-file value, so on a host where you want every kata
invocation to use the same TCP address you only have to set it once.
Run the daemon under launchd / systemd / nohup on the host that holds the
SQLite database. Clients on other hosts target it by setting KATA_SERVER:
export KATA_SERVER=http://100.64.0.5:7777
kata listOr by writing a per-developer, gitignored .kata.local.toml next to
.kata.toml:
version = 1
[server]
url = "http://100.64.0.5:7777"kata init adds .kata.local.toml to .gitignore automatically.
KATA_SERVER wins over the file when both are set.
There is no authentication in this mode — network ACLs (firewall, VPN,
tailnet) are the access boundary. Default behavior (no flag, no env, no local
file) is unchanged: a local Unix-socket daemon is auto-started on demand. See
docs/superpowers/specs/2026-05-04-kata-remote-client-design.md.
Useful environment variables:
KATA_HOME: data directory. Defaults to~/.kata.KATA_DB: explicit SQLite database path.KATA_AUTHOR: default actor for mutations.KATA_HTTP_TIMEOUT: per-request CLI timeout for non-streaming daemon calls (anytime.ParseDurationstring, e.g.30s,2m). Defaults to5s. Bump this for bulk imports where create requests can exceed the default.KATA_SERVER: opt-in remote daemon URL (e.g.http://100.64.0.5:7777). When set, the client skips local discovery and auto-start entirely. See "Remote daemon" below.XDG_RUNTIME_DIR: runtime socket parent on Unix.
The workspace binding file is intentionally secret-free:
version = 1
[project]
identity = "github.com/example/product"
name = "product"Commit .kata.toml when multiple agents, clones, or worktrees should resolve
to the same kata project.