NAME

App::karr::Foundation - Single-shot foundation daemon — periodic agent execution across karr boards

VERSION

version 0.300

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

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:

command: claude -p "Use karr-coordinator agent, pick next task"
on_idle: skip             # 'skip' (default) | 'always-run'
max_runtime: 1800         # seconds: per-command SIGKILL + total drain budget
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

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-progress did not move. That task's attempt counter is bumped; at max_attempts it 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 with karr edit --block; the auto-block is a fallback.

  • common-error — a non-zero/timeout exit or a error_patterns match (rate limit, auth, network, 5xx, …). 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.

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.