Skip to content

Getty/karr

Repository files navigation

App::karr

Git-native kanban for shared helper agents, human operators, and downstream repos that want a board without checking a board directory into the work tree.

karr keeps canonical state in refs/karr/*, not in commits, branches, or a persistent karr/ folder. Tasks, config, logs, snapshots, and helper refs move through normal Git transport, which makes the tool fit naturally into AI-heavy and multi-machine workflows.

Why it exists

Most task tools assume a central web service or a checked-in file tree. karr takes a different route:

  • board state lives in Git refs
  • mutating commands pull, materialize, write back, and push
  • tasks stay separate from branches and commits
  • downstream projects can vendor the CLI through Docker and keep the exact same UX

That gives you a shared board with far fewer file-level collisions and without having to bolt on another ticket system just to coordinate agents.

Quick start

Inside an existing Git repository:

karr init --name "My Project"
karr create "Fix login bug" --priority high
karr list
karr board

Claim and progress work:

NAME=$(karr agentname)
karr pick --claim "$NAME" --status todo --move in-progress
karr handoff 1 --claim "$NAME" --note "Ready for review" --timestamp

Protect yourself before destructive operations:

karr backup > karr-backup.yml
karr restore --yes < karr-backup.yml
karr destroy --yes

Installation

Perl

cpanm App::karr

Docker

The published images are:

  • raudssus/karr:latest
  • raudssus/karr:user

latest is the ergonomic default. It starts as root only long enough to inspect /work, then drops to the owner of the mounted workspace before running karr. That keeps host files from becoming root-owned.

user is the fixed-user image. It defaults to 1000:1000 and is the better base when you want a deterministic downstream derivative.

Minimal smoke test:

docker run --rm -it -w /work -v "$(pwd):/work" raudssus/karr:latest --help

Recommended alias for real use:

alias karr='docker run --rm -it \
  -w /work \
  -e HOME=/home/karr \
  -v "$(pwd):/work" \
  -v "$HOME/.gitconfig:/home/karr/.gitconfig:ro" \
  -v "$HOME/.claude:/home/karr/.claude" \
  -v "$HOME/.codex:/home/karr/.codex" \
  -v "$HOME/.cursor:/home/karr/.cursor" \
  raudssus/karr:latest'

With that alias, all normal commands stay identical:

karr init --name "HandyIntelligence Prototype" --claude-skill
karr skill install --agent codex --global --force
karr create "Document release workflow"

If you want a custom fixed-user image in CI or a downstream repo:

docker build --target runtime-user \
  --build-arg KARR_UID=1010 \
  --build-arg KARR_GID=1010 \
  -t raudssus/karr:user1010 .

How it works

The write path:

pull refs -> change task/config -> push refs

Commands work directly against refs via C. A materialized F view is generated on demand (see C) and is never committed — it is always in F<.gitignore>.

Important refs:

  • C<refs/karr/config> holds sparse YAML config overrides
  • C<refs/karr/meta/next-id> holds the next numeric task id
  • C<refs/karr/tasks/EidE/data> holds task Markdown plus frontmatter
  • C<refs/karr/log/EagentE> holds append-style JSON log lines

Command map

Board lifecycle

Command Use it for
karr init create the board in refs/karr/*
karr config inspect and change merged board settings
karr backup export the whole board as YAML
karr restore --yes replace the board from a YAML snapshot
karr destroy --yes remove the board completely
karr sync explicitly pull/push board refs

Task lifecycle

Command Use it for
karr create create a task
karr list filter and search tasks
karr show inspect one task in full
karr edit update body, metadata, claim, or blocked state
karr move change status explicitly or with --next / --prev
karr archive soft-delete into archived
karr delete permanently remove the task ref

Flow and coordination

Command Use it for
karr board grouped board view
karr pick atomic next-task selection with claim
karr handoff move into review and append a note
karr context generate agent-facing board summary
karr log inspect per-agent or per-task activity
karr agentname generate short claim names

Skills and helper refs

Command Use it for
karr skill install install bundled skills for Claude Code, Codex, or Cursor
karr skill check detect outdated installed skills
karr skill update refresh installed skills
karr set-refs store shared non-task payloads in allowed refs
karr get-refs fetch helper payloads back out

Multi-agent workflow

NAME=$(karr agentname)

# pick the best available task
karr pick --claim "$NAME" --status todo --move in-progress

# inspect board state
karr board
karr list --claimed-by "$NAME"

# hand off to review
karr handoff 1 --claim "$NAME" --note "Implementation complete" --timestamp

# inspect activity trail
karr log --agent "$NAME"

pick respects blocked state, claim timeout, and class-of-service ordering:

  • expedite
  • fixed-date
  • standard
  • intangible

Automated execution: karr-foundation

karr-foundation is a single-shot, idempotent companion binary that drives agents across one or more boards. Point cron (or a systemd timer, or a tight loop) at it and it scans configured repos, decides whether there is work, and drains each board — running the configured agent command repeatedly until no actionable task remains.

# every 5 minutes
*/5 * * * * karr-foundation

karr-foundation --force            # run regardless of board state
karr-foundation --dry-run --verbose

It reads ~/.config/karr-foundation/config.yml (or --config):

dirs:
  - /path/to/repo1          # explicit board repos
scan:
  - /path/to/parent-dir     # auto-discover direct subdirs that have a .karr

Each repo carries a .karr file describing how to run its agent:

command: claude -p "Use karr-coordinator agent, pick next task"
on_idle: skip               # 'skip' (default) | 'always-run'
max_runtime: 1800           # per-command SIGKILL + total drain budget (seconds)
drain: true                 # loop until drained (default) | false: single run
max_attempts: 2             # stalls on one task before auto-block
max_iterations: 50          # hard cap on drain iterations
cooldown_base: 1            # cooldown minutes at level 0
cooldown_max: 64            # cooldown ceiling in minutes
error_patterns:             # extra case-insensitive substrings → common-error
  - my custom api error

After every agent run, foundation classifies the outcome from what it can observe — exit code, board ref movement, and the run's captured output:

  • progress — the board changed; keep draining.
  • stall — a task the agent claimed or left in-progress did not move. Its attempt counter is bumped, and at max_attempts it is auto-blocked (a blocked: reason is written so it drops out of the actionable set and the drain can finish). The agent may always set a better reason itself with karr edit --block; the auto-block is only a fallback so the loop always terminates.
  • common-error — a non-zero/timeout exit, or output matching a known pattern (rate limit, auth, network, 5xx, plus your error_patterns). No task is penalized; the repo enters an exponential cooldown (cooldown_base × 2^level minutes, capped at cooldown_max, reset on the next clean run) and is skipped until it expires.
  • idle — the agent did nothing and grabbed nothing; stop.

Concurrent invocations are safe: a PID lock per repo means a cron tick that fires while an agent is still running simply skips that repo. All per-repo state is gitignored: .karr.state (board hash, per-task attempts, cooldown, last error), .karr.lock, and .karr.log.

Helper refs

Not all shared workflow state belongs in tasks. karr also supports arbitrary non-protected refs outside refs/karr/*.

karr set-refs superpowers/spec/1234.md draft ready
karr get-refs superpowers/spec/1234.md

Use this for:

  • planning blobs
  • generated specs
  • agent scratch state
  • workflow metadata you want synced through Git but not modeled as cards

Protected namespaces such as branches, tags, remotes, stash, and refs/karr/* are blocked.

Skills

The distribution ships a bundled karr skill that can be installed locally in a repo or globally in the current home directory.

karr skill install
karr skill install --agent claude-code
karr skill install --agent codex --global --force
karr skill check --global
karr skill update

Supported targets:

  • claude-code
  • codex
  • cursor

Project-local Claude installation during board setup:

karr init --name "My Project" --claude-skill

Board snapshots and destructive operations

Backups are full YAML snapshots of refs/karr/*:

karr backup > karr-backup.yml

Restore is intentionally destructive:

karr restore --yes < karr-backup.yml

It deletes current refs/karr/* refs first and then replays the snapshot.

Full board removal is explicit too:

karr destroy --yes

If a remote exists, restore and destroy also prune the remote board state to match.

Stored task shape

Tasks live in refs/karr/tasks/*/data, but the payload itself is ordinary Markdown with YAML frontmatter:

---
id: 1
title: Fix login bug
status: in-progress
priority: high
class: standard
claimed_by: agent-fox
created: 2026-03-12T10:00:00Z
updated: 2026-03-12T10:00:00Z
---

Task description here.

That makes the format easy to inspect, script, and reuse from Perl code.

Programmatic usage

karr is primarily a CLI, but the lower-level modules are usable from Perl:

use App::karr::Git;
use App::karr::BoardStore;

my $git   = App::karr::Git->new(dir => '.');
my $store = App::karr::BoardStore->new(git => $git);

my $config = $store->effective_config;
my @tasks  = $store->load_tasks;

Or create a task directly:

use App::karr::Task;

my $task = App::karr::Task->new(
  id       => $store->allocate_next_id,
  title    => 'Write release notes',
  status   => 'backlog',
  priority => 'high',
);

$store->save_task($task);
$git->push;

Why Docker matters here

Perl installation is the normal local path, but Docker is equally valid when a downstream repo wants to vendor karr instead of adding a direct Perl tool dependency. That keeps the command surface identical across:

  • local Perl installs
  • Codex/Claude/Cursor-heavy repos
  • CI or ops environments that prefer containerized tooling

License

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.

About

Kanban Assignment & Responsibility Registry — Git-native, file-based kanban board for multi-agent workflows (Perl)

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages