NAME
App::karr::Foundation - Single-shot foundation daemon — periodic agent execution across karr boards
VERSION
version 0.301
SYNOPSIS
# Typical cron entry — run every 5 minutes
*/5 * * * * /path/to/karr-foundation
# Force a run regardless of board state
karr-foundation --force
# Preview what would run
karr-foundation --dry-run --verbose
# Read-only overview of every board (no agent runs)
karr-foundation --status
DESCRIPTION
karr-foundation is a single-shot, idempotent CLI meant to be invoked periodically (cron, systemd-timer, while-loop). It scans configured karr boards, detects changes or open work, and drains each board by invoking the configured agent command repeatedly until no actionable task remains.
Config file: ~/.config/karr-foundation/config.yml (or --config).
dirs:
- /path/to/repo1
- /path/to/repo2
scan:
- /path/to/parent-dir # finds all direct subdirs that have a .karr file
Per-repo .karr file:
claude: true # synthesize the canonical claude command (opt-in)
claude_bin: claude # binary for claude: true (default: claude)
claude_max_turns: 30 # --max-turns for claude: true (default: 30)
claude_permission_mode: bypassPermissions # (default: bypassPermissions)
prompt: >- # agent instruction, exposed as $PROMPT
Use the karr-coordinator skill: pick the next actionable task and move it.
command: claude -p "$PROMPT" # explicit command; wins over claude: true
on_idle: skip # 'skip' (default) | 'always-run'
max_runtime: 1800 # seconds: per-command SIGKILL (0 = no limit)
drain: true # loop until drained (default) | false for single run
max_attempts: 2 # stalls on one task before auto-block (default: 2)
max_iterations: 50 # hard cap on drain iterations (default: 50)
cooldown_base: 1 # cooldown minutes at level 0 (default: 1)
cooldown_max: 64 # cooldown ceiling in minutes (default: 64)
error_patterns: # extra case-insensitive substrings → common-error
- my custom api error
claude, claude_bin, claude_max_turns, claude_permission_mode, command and prompt/default_prompt may also be set globally in the config file; the per-repo .karr value wins.
Coordinator and overview. Agent execution is opt-in — a board runs an agent only via command or claude: true. When no board has an agent configured, the default action is a read-only overview of every board (status counts, in-progress/blocked tasks, lock and cooldown state); a human can use foundation purely to coordinate their own work. --status forces the overview regardless of configuration.
Live output. When run interactively (TTY) or with --verbose, the agent's output is streamed to the terminal in real time as foundation reads it; it is always appended to .karr.log regardless of TTY. To shape what is shown, the command may emit stream-json and filter it, e.g.:
command: >-
claude -p "$PROMPT"
--output-format stream-json --verbose --include-partial-messages
--permission-mode bypassPermissions --max-turns 10
2>&1 | jq -r 'select(.type == "stream_event") | .event.delta.text // empty'
Set max_runtime: 0 in .karr to disable the per-run timeout entirely (agent runs until completion with no SIGKILL).
Drain semantics. Each iteration runs command once, then classifies the result from what foundation 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 / left
in-progressdid not move. That task's attempt counter is bumped; atmax_attemptsit is auto-blocked (blocked: auto-block: no progress after N attempts (foundation)) so it drops out of the actionable set and the drain can finish. The agent may always set a better reason itself withkarr edit --block; the auto-block is a fallback.common-error — a non-zero/timeout exit or a
error_patternsmatch (rate limit, auth, network, 5xx, …). No task is penalized; the repo enters an exponential cooldown (cooldown_base× 2^level minutes, capped atcooldown_max, reset on the next clean run) and is skipped until it expires.idle — the agent did nothing and grabbed nothing; stop.
All state files are gitignored: .karr.state (board hash, per-task attempts, cooldown, last error), .karr.lock, .karr.log.
SUPPORT
Issues
Please report bugs and feature requests on GitHub at https://github.com/Getty/karr/issues.
IRC
Join #langertha on irc.perl.org or message Getty directly.
CONTRIBUTING
Contributions are welcome! Please fork the repository and submit a pull request.
AUTHOR
Torsten Raudssus <getty@cpan.org>
COPYRIGHT AND LICENSE
This software is copyright (c) 2026 by Torsten Raudssus <torsten@raudssus.de> https://raudssus.de/.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.