╔══════════════════════════════════════════════════════════════╗
║ ║
║ T R I A G E ║
║ ║
║ meta-scheduler that watches its own queue ║
║ ║
╚══════════════════════════════════════════════════════════════╝
A self-aware priority queue. Signals push facts about the world; rules turn facts into priority deltas; the queue reorders itself on every tick. You set the goals — Triage decides the order, and tells you exactly why.
Mirrored on both GitHub and Codeberg. Issues filed on either forge are welcome; commits land on both.
╔════════════════════════════════════════════════════════╗
║ T R I A G E v0.4.0 ║
╚════════════════════════════════════════════════════════╝
ID PRI BAR SUBJECT
════════════ ══════ ═════ ════════════════════════════════════════
7cfa440bc639 [ 101] █████ Fix the linter ← blocker auto-bumped
f35d7cea6b7d [ 100] █████ Add feature X ← blocked-by linter
19c80b807ddd [ 35] █▒░░░ Rotate cert ← deadline pressure
abc123456789 [ 2] ░░░░░ Routine cleanup
In a real terminal the banner is bright magenta, the priorities are
color-banded (high = yellow, mid = green, low = dim cyan), and the
priority bars fill in proportionally. The default bbs theme is
unapologetically 1990s.
┌─────────────────────┐
signals ─────► │ Signal sources │ (cron-window, github-ci, ...)
└──────────┬──────────┘
▼
┌─────────────────────┐
│ ~/.triage/state/ │ (append-only JSONL per source)
└──────────┬──────────┘
▼
tick ─────► ┌─────────────────────┐ ─────► reordered queue
│ Triage scheduler │ + per-task audit log
└──────────┬──────────┘
▼
┌─────────────────────┐
tasks ─────► │ triage CLI │
└─────────────────────┘
- Signal sources push facts (
cron-window,github-ci, futurerunpod-cost,github-pr...). - Rules turn facts into priority deltas
(
base_score,deadline_decay,cron_window_active,ci_failing,blocker_transitive). - The queue reorders on every
triage tick. - Every reorder is explainable —
triage why <id>shows exactly which rules contributed which deltas, so the order is never a black box.
See DESIGN.md for the full architecture, the rule
catalog, and the roadmap.
git clone https://github.com/CryptoJones/Triage # or codeberg.org/CryptoJones/Triage
cd Triage
pip install -e .Pure Python stdlib. No runtime dependencies. Tested on 3.10 / 3.11 / 3.12.
triage add "Fix the auth bug" --base-score 10
triage add "Rotate the staging cert" --deadline 2026-05-20T00:00:00Z
triage add "Weekday-only chore" --cron-window "* 9-17 * * 1-5"
triage add "Watch CI" --tag "gh-ci:CryptoJones/Triage@main"
triage add "Wait on linter" --blocked-by <linter-task-id>
triage list # current priority order
triage show <id> # the raw task record (JSON)
triage why <id> # which rules contributed which deltas
triage rm <id> # removetriage tick # recompute priorities; print new order
triage poll github-ci # invoke a network-bound signal sourcetick is cheap, local, and idempotent — call it from cron, a shell
loop, or Claude Code's ScheduleWakeup. poll is for signal sources
that hit the network (you pay for those explicitly).
Every CLI invocation appends a single JSON line to a log file so an
external agent can tail -f and parse Triage's behavior:
tail -f /var/log/triage.log | jq . # if the file is owned by your userSample entries:
{"ts":"2026-05-16T06:16:18+00:00","event":"add","task_id":"9e8040d267d9","subject":"Investigate slow query","base_score":10,"tags":[],"deadline":null,"blocked_by":[]}
{"ts":"2026-05-16T06:16:18+00:00","event":"tick","ranked_count":2,"emitted_cron_signals":0,"top":[{"id":"ad2006db3c12","priority":35,"subject":"Rotate cert"},...],"warnings":[]}
{"ts":"2026-05-16T06:16:19+00:00","event":"poll","source":"github-ci","emitted":1,"warnings":[]}
{"ts":"2026-05-16T06:16:20+00:00","event":"rm","task_id":"9e8040d267d9"}Configuration:
| Mechanism | What it does |
|---|---|
--log-file PATH flag |
Per-invocation log path. |
TRIAGE_LOG_FILE=PATH env |
Per-shell log path. |
| Default | /var/log/triage.log. Falls back to ~/.triage/triage.log if /var/log isn't writable (warns once on stderr). |
--no-log flag |
Disable logging for this invocation. |
TRIAGE_NO_LOG=1 env |
Disable logging globally for the shell. |
To use the standard /var/log path without sudo on every call:
sudo touch /var/log/triage.log
sudo chown $(id -un):$(id -gn) /var/log/triage.logLogging is a strict one-way side channel — errors during write are swallowed so the CLI's primary behavior is never disrupted.
triage theme # list available themes
triage theme --name bbs # render sample rows
triage --theme modern list # one-shot theme override
TRIAGE_THEME=mono triage list # per-shell theme| Theme | Aesthetic |
|---|---|
bbs |
Default. 1990s BBS: bright magenta, double-line box (╔═╗), block bars. |
modern |
Subtle palette, single-line boxes (┌─┐), dot-fill bars (█▒·). |
mono |
No color, ASCII-only (+-+, #=.) — safe for pipes / dumb terminals. |
Color follows the standards:
- Auto-disabled when stdout isn't a TTY.
NO_COLOR=1disables color (per no-color.org).FORCE_COLOR=1enables color on non-TTY.--no-colorflag = explicit per-invocation kill switch.
claude_skill-Triage
is the Claude Code skills repository for this project. It currently
ships TaskPriorityReorder — the manual override for when a human
just wants to bump a task to the top of Claude Code's task list — and
will host the triage skill (the automatic, signal-driven counterpart)
at Triage v0.7.
The two skills share Triage's stable-id-plus-recomputable-priority primitive.
| Version | Feature | Status |
|---|---|---|
| v0.1 | scaffold, three rules, cron-window signal, CLI | shipped |
| v0.2 | blocker_transitive propagation + cycle detection |
shipped |
| v0.3 | github-ci signal source + ci_failing rule + triage poll |
shipped |
| v0.4 | BBS-style ANSI theme system + triage theme subcommand |
shipped |
| v0.5 | runpod-cost signal source + cost_pressure rule |
shipped |
| v0.6 | JSONL event log writer for external agents | shipped |
| v0.7 | github-pr stale-PR signal source |
planned |
| v0.8 | Claude Code triage skill (in claude_skill-Triage repo) |
planned |
| v0.9 | triage watch long-running mode + systemd unit |
planned |
Apache 2.0. See LICENSE.
Proudly Made in Nebraska. Go Big Red! 🌽 https://xkcd.com/2347/