kata

module
v0.0.0-...-7143b1a Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 12, 2026 License: MIT

README

kata カタ

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.

Quick Start

go install github.com/wesm/kata/cmd/kata@latest   # or see Install for other options

cd your-repo
kata init                                         # bind this workspace to a kata project
kata create "fix login race"                      # returns the issue's short_id, e.g. abc4
kata list                                         # list open issues
kata show abc4                                    # inspect by short_id
kata close abc4 --done --message "Fixed; tests green." --commit <sha>
kata tui                                          # browse and triage interactively

See Install for go install, build-from-source, and Windows instructions; see Working with kata for a longer walkthrough.

What kata does today

What you can do:

  • Track issues separately per project, with short IDs derived from each issue's ULID (kata#abc4).
  • 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_HOME behind a long-running daemon.
  • Issues have stable ULID uid values; short_id (the lowercased last 4+ chars of the ULID) is the display label, qualified as kata#abc4 across projects.
  • kata export and kata import provide a git-friendly JSONL backup and schema cutover path.
  • Successful commands emit JSON for reliable parsing by agents and scripts.

Goals

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.

Why kata, and how is it different from Beads or git-bug?

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 Short IDs derived from each issue's ULID (kata#abc4)
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.

Install

kata is a single Go binary with no runtime dependencies and builds on macOS, Linux, and Windows. Pre-built release binaries are not published yet; install from source using one of the options below. All paths require Go 1.26 or later (https://go.dev/dl/).

go install (any platform)
go install github.com/wesm/kata/cmd/kata@latest

Go places kata in $(go env GOBIN), falling back to $(go env GOPATH)/bin (typically ~/go/bin on Unix, %USERPROFILE%\go\bin on Windows). Add that directory to your PATH.

Build from a clone (macOS / Linux)
make install                            # installs to ~/.local/bin
make install GOBIN=/usr/local/bin       # or set GOBIN to install elsewhere

Add the install directory to your PATH if it isn't already. GOBIN from the environment is also honored (export GOBIN=/opt/bin && make install).

Build from a clone (Windows)

PowerShell or cmd.exe:

go build -o kata.exe ./cmd/kata
# Move kata.exe to a directory on your PATH, e.g. %USERPROFILE%\.local\bin

The go install command above also works on Windows and is usually simpler.

Development
make test          # run the test suite
make lint          # run golangci-lint

Working with kata

Initialize kata in a workspace:

kata init

kata init creates or resolves the project and writes .kata.toml when needed. In a git workspace, the default project name is derived from the remote URL. For a non-git workspace or an explicit shared project name:

kata init --project product

Create and inspect issues:

kata create "fix login race" --body "Safari can double-submit the callback."
kata list
# Each issue prints its short_id (e.g. abc4); use it for follow-up commands.
kata show abc4
kata comment abc4 --body "Reproduced on macOS."
kata close abc4 --done --message "Fixed; verified tests pass." --commit <sha>

Open the TUI for human triage:

kata tui

Press ? inside the TUI for keybindings.

Use --workspace <path> when running from outside the project directory:

kata --workspace ~/code/product list --status all

Set the actor for a session:

export KATA_AUTHOR=codex-wesm-laptop
kata whoami

Actor precedence is --as > KATA_AUTHOR > git config user.name > anonymous.

Core Commands

Common issue commands:

kata create <title> [--body TEXT | --body-file PATH | --body-stdin]
                  [--label LABEL] [--owner NAME] [--priority 0..4]
                  [--parent <ref>] [--blocks <ref>] [--blocked-by <ref>]
                  [--related <ref>] [--idempotency-key KEY] [--force-new]
kata list [--status open|closed|all] [--limit N]
kata show <issue-ref>
kata edit <issue-ref> [--title TEXT] [--body TEXT] [--owner NAME]
                  [--priority 0..4 | --priority -]
                  [--parent <ref>] [--blocks <ref>] [--blocked-by <ref>] [--related <ref>]
                  [--remove-parent <ref>] [--remove-blocks <ref>]
                  [--remove-blocked-by <ref>] [--remove-related <ref>]
                  [--comment TEXT]
kata comment <ref> [--body TEXT | --body-file PATH | --body-stdin]
kata close <ref> --done --message <text> [--commit|--pr|--test|--reviewed|--evidence] [--comment TEXT]
kata close <ref> [--wontfix|--duplicate-of <ref>|--superseded-by <ref>|--audit-no-change] [--comment TEXT]
kata reopen <ref> [--comment TEXT]

--comment TEXT is available on close, reopen, edit, assign, unassign, and label add/rm. The mutation lands first; the comment is appended in a follow-up call. If the comment call fails, the error names the issue so you can retry with kata comment <ref> --body ....

Refs accept a bare short_id (abc4), a qualified short_id (kata#abc4), or a full 26-char ULID. The relationship flags on create/edit are documented in detail in "Relationships ride on kata create and kata edit" below.

Closing issues:

kata close abc4 --done --message "<what changed and how it was verified>" \
                --commit <sha>
kata close abc4 --duplicate-of d4ex  --message "<short pointer>"
kata close abc4 --superseded-by d4ex --message "<short pointer>"
kata close abc4 --wontfix --message "<>=60 chars of rationale>"
kata close abc4 --audit-no-change \
                --message "<scope + verification of no-change conclusion>" \
                --evidence "no-change-audit:<short rationale>" \
                --reviewed <path/to/file>

Closing an issue asserts that the work is complete. Close each issue as soon as its work is verified — not at the end of a batch. Use the needs-review label and a comment when the work is incomplete instead. The daemon refuses these structurally dangerous patterns:

  • closing a parent while its children remain open
  • closing >3 siblings under the same parent within 5 minutes
  • closing two siblings of the same parent with the same close message (within 30 minutes, for done/audit-no-change)

The sibling-burst and repeated-message throttles can be disabled daemon-wide via [close.throttle] enabled = false in <KATA_HOME>/config.toml; the parent-completeness refusal and the substance/evidence checks on --message/--evidence always run.

The TUI close path (x in kata tui) bypasses the substance and evidence checks — interactive humans close with a single keystroke. Structural guards still apply.

kata audit closes lists close events with filters; specific lazy closes can be undone individually with kata reopen <ref>.

Labels, ownership, and relationships:

kata label add <ref> <label> [--comment TEXT]
kata label rm <ref> <label> [--comment TEXT]
kata labels
kata assign <ref> <owner> [--comment TEXT]
kata unassign <ref> [--comment TEXT]

Relationships ride on kata create and kata edit as repeatable flags, all framed from the operating issue's POV:

# Add (work on create + edit)
kata create "..." --parent <ref> --blocks <ref> --blocked-by <ref> --related <ref>
kata edit   <ref> --parent <ref> --blocks <ref> --blocked-by <ref> --related <ref>

# Remove (edit only)
kata edit <ref> --remove-parent <ref>        # strict: must equal current parent
kata edit <ref> --remove-blocks <ref>        # idempotent
kata edit <ref> --remove-blocked-by <ref>    # idempotent
kata edit <ref> --remove-related <ref>       # idempotent

--parent is at-most-one and replaces any existing parent on edit. The other flags are repeatable. --remove-parent <ref> is strict: it fails loudly if the current parent is unset or different from <ref> (an optimistic-concurrency check against agents acting on stale state). All mutations in a single edit call apply atomically.

Every <ref> above accepts a bare short_id (abc4), a qualified short_id (kata#abc4), or a 26-char ULID. Legacy numeric #N refs no longer resolve.

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 [--project NAME] [--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:abc4, ...) 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 <ref> --force --confirm "DELETE <qualified-id>"
kata restore <ref>
kata purge <ref> --force --confirm "PURGE <qualified-id>"

The confirmation string is the issue's qualified short_id, e.g. DELETE kata#abc4. 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 tui

Agent Quickstart

This 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   # alias

Session setup:

  • Run from the project workspace, or pass --workspace <path>.
  • Set KATA_AUTHOR once at session start.
  • Prefer --json for 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 init is 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 delete or purge unless the user explicitly asks for that exact destructive action and issue ref.

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 (using abc4 as a placeholder for the issue's actual short_id, which kata create --json and kata search --json both return):

# 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 abc4 --json
kata comment abc4 --body "Found another reproduction path." --json
kata label add abc4 safari --json
kata edit abc4 --blocks d4ex --json

# Close when done
kata close abc4 --done --message "Fixed; verified tests pass." --commit <sha> --json

For 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 --json

For live streams, --tail emits newline-delimited JSON:

kata events --tail

Sharing and multi-user workflows

Today 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 name and run kata init in each checkout. That shares the issue ledger — short_ids, 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-repo

Future 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.

Remote daemon (opt-in, no auth)

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:7777

Or 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 list

Or 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.

Backup and restore

kata export writes the local database as JSONL; kata import rebuilds a database from that file. Together they cover backups, machine moves, and migrations between schema versions.

Back up the local database:

kata daemon stop
kata export --output backups/kata-$(date -u +%Y%m%d).jsonl
kata daemon start

Without --output, kata export writes a timestamped file (kata-export-YYYYMMDDTHHMMSSZ.jsonl) in the current directory. Export refuses to run while a daemon holds the database open; pass --allow-running-daemon to take a best-effort snapshot on a host where you cannot stop the daemon.

Restore into a fresh database file:

kata import --input backups/kata-20260512.jsonl --target ~/.kata/restored.db

kata import always creates a brand-new database. The target must not exist; --force deletes it first. There is no merge mode today — see "Exporting a single project" below for what that means in practice. To activate a restored database, point KATA_DB at it (or move it into KATA_HOME as kata.db) and restart the daemon.

JSONL is plain text and diffs cleanly, so a simple versioned-backup setup is to keep snapshots in a git repository:

mkdir -p ~/kata-backups && cd ~/kata-backups
git init -q
kata daemon stop
kata export --output snapshot.jsonl
kata daemon start
git add snapshot.jsonl
git commit -q -m "snapshot $(date -u +%FT%TZ)"

Run that on a schedule (cron, launchd, systemd timer) and you have point-in-time recovery without operating a backup service. Push the repo to a private remote if you want off-host storage.

Exporting a single project

Use the global --project NAME flag to scope an export to one project:

kata daemon stop
kata --project myproj export --output backups/myproj.jsonl
kata daemon start

--project-id N works too if you prefer the numeric id from kata projects list --json.

A single-project export round-trips into a fresh database that contains only that project:

kata import --input backups/myproj.jsonl --target /tmp/myproj-only.db

This is useful for archiving one project before deleting it, handing a project's full history to a collaborator who'll set up a fresh kata install, or moving a project to a different host.

What does not work today:

  • Importing a per-project snapshot into an existing populated database. kata import always wipes the target first; there is no merge or "add this project" mode. So you cannot use per-project files as building blocks to stitch a multi-project database together.
  • Re-importing a snapshot on top of itself to refresh it incrementally.

For multi-project backups, take the full-database snapshot shown above instead of one file per project. A per-project merge import (apply one project's snapshot to an existing database without disturbing other projects) is planned — tracked in wesm/kata#42.

Configuration

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 (any time.ParseDuration string, e.g. 30s, 2m). Defaults to 5s. 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]
name = "product"

Commit .kata.toml when multiple agents, clones, or worktrees should resolve to the same kata project.

Directories

Path Synopsis
cmd
kata command
Package main is the kata CLI entry point.
Package main is the kata CLI entry point.
internal
api
Package api types for Plan 4 events endpoints.
Package api types for Plan 4 events endpoints.
config
Package config resolves the kata data directory, database path, and per-database runtime namespace from environment variables.
Package config resolves the kata data directory, database path, and per-database runtime namespace from environment variables.
daemon
Package daemon contains the in-process kata daemon: namespace resolution, runtime file lifecycle, listening endpoint, and HTTP server wiring.
Package daemon contains the in-process kata daemon: namespace resolution, runtime file lifecycle, listening endpoint, and HTTP server wiring.
daemonclient
Package daemonclient resolves a running kata daemon and builds matching *http.Clients for both unix-socket and tcp endpoints.
Package daemonclient resolves a running kata daemon and builds matching *http.Clients for both unix-socket and tcp endpoints.
db
Package db opens the kata SQLite database and bootstraps it from the canonical schema.sql.
Package db opens the kata SQLite database and bootstraps it from the canonical schema.sql.
hooks
Package hooks implements the daemon's post-commit hook dispatcher.
Package hooks implements the daemon's post-commit hook dispatcher.
hooks/hookprobe command
Command hookprobe is a deterministic test helper used by the hooks package.
Command hookprobe is a deterministic test helper used by the hooks package.
jsonl
Package jsonl exports and imports kata database state as ordered NDJSON.
Package jsonl exports and imports kata database state as ordered NDJSON.
shortid
Package shortid derives, validates, and parses kata's short_id display references.
Package shortid derives, validates, and parses kata's short_id display references.
similarity
Package similarity provides text-normalization primitives used by both the idempotency fingerprint (Canonical only) and the look-alike soft-block pipeline (full Tokenize → Jaccard → Score).
Package similarity provides text-normalization primitives used by both the idempotency fingerprint (Canonical only) and the look-alike soft-block pipeline (full Tokenize → Jaccard → Score).
testenv
Package testenv provides a per-test harness that boots a real daemon over TCP loopback, suitable for integration tests.
Package testenv provides a per-test harness that boots a real daemon over TCP loopback, suitable for integration tests.
testfix
Package testfix collects small filesystem and git fixtures shared across test packages: writing a stock .kata.toml, faking a .git directory, and running real git for tests that need a working repository.
Package testfix collects small filesystem and git fixtures shared across test packages: writing a stock .kata.toml, faking a .git directory, and running real git for tests that need a working repository.
textsafe
Package textsafe sanitizes user-authored text before it is rendered to a terminal.
Package textsafe sanitizes user-authored text before it is rendered to a terminal.
tui
Package tui implements the kata terminal UI built on Bubble Tea.
Package tui implements the kata terminal UI built on Bubble Tea.
uid
Package uid wraps ULID generation and validation for kata stable IDs.
Package uid wraps ULID generation and validation for kata stable IDs.
version
Package version exposes the kata build's version string, derived from runtime/debug.BuildInfo so a stripped binary still reports a stable identifier.
Package version exposes the kata build's version string, derived from runtime/debug.BuildInfo so a stripped binary still reports a stable identifier.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL