run-ledger
Skill0 starsChanged 24 days agoMITView on GitHub
Instrument an unattended job with START/END lines and read the run ledger it leaves. Use when the user wants to know whether a scheduled claude -p, cron, launchd, systemd or CI job really ran, asks to add a heartbeat, start/end logging or run history to a job, or asks which runs hung, failed or were skipped. Detects a START without END, gaps between starts, a schedule that stopped, and failed statuses.
2 other projects use a version of this.
Adopted by
Most recently taken up by
- aditya-deokar/software-factorytheir own version, first seen Sep 29, 2026
- kvantatech/RedLinetheir own version, first seen Aug 6, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- kvantatech/RedLine★ 1same name
- aditya-deokar/software-factory★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repositoryOne other file it gives its agents.
- agent-chain-doctorSkill
The file
We split this skill into the rules it gives an agent
3 rules. About 0 are common, 2 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 25
Default file: $LEDGER, else ./.heartbeat/beats.tsv.
- Distinctive: line 65
When editing a user's job, show the diff and keep their existing redirections and timeouts.
- Distinctive: line 66
Never put the ledger in a directory the job deletes or resets (git clean, a temp dir).
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Run ledger: START/END for every unattended run
Running the scripts. One Bash call = one script call, by the absolute path shown (
${CLAUDE_SKILL_DIR}/scripts/<script>), with nobashprefix, no variable assignment, and nothing chained after it (;,&&,|,echo $?): the exit code is reported anyway. Only that exact form is pre-approved by this skill'sallowed-tools; indontAskmode or a headlessclaude -prun, anything else is refused. Use the Read tool, notcatortail, for logs.
A scheduler's own status says little. A run that hangs writes no error; a fire that never
happens writes nothing at all. What they never write is the proof that they started and
finished. The ledger is that proof: one START line before the work, one END line after it,
in a plain tab-separated file.
START 20261012T030001Z-4242 2026-10-12T03:00:01Z
END 20261012T030001Z-4242 2026-10-12T03:04:10Z okDefault file: $LEDGER, else ./.heartbeat/beats.tsv. The format is the one used by the
launcher of the Unattended Claude Code Field Kit, so both can share a file.
Script: ${CLAUDE_SKILL_DIR}/scripts/ledger.sh. To instrument a job, copy it into the job's
repository (e.g. tools/ledger.sh); to read a ledger, run it from the skill folder.
A. Instrument a job (pick one)
1. Wrap the command (simplest, cron/launchd/systemd/CI). Copy ledger.sh next to the job
(e.g. tools/ledger.sh in the repository) and put wrap in front of the command:
cd /path/to/repo && tools/ledger.sh wrap -- timeout -k 60 45m /full/path/to/claude -p "$(cat prompt.md)" --output-format stream-json --verbose >> logs/agent.log 2>&1wrap writes START, runs the command (stdin from /dev/null, as a background job), writes
END ok or END exit-N, writes END killed if the wrapper itself gets TERM/INT/HUP, and exits
with the command's status. Keep timeout (on macOS: gtimeout from coreutils): the ledger
records a hang, it does not stop one.
2. Explicit calls, when the job script has several steps or its own statuses:
id=$(tools/ledger.sh start)
# ... work ...
tools/ledger.sh end "$id" ok # or skip-nothing-new, exit-3, timeout, no-work ...Statuses are one word (letters, digits, ., _, :, -). ok and anything starting with
skip count as healthy; everything else is reported as FAILED.
3. Inside a cloud routine or Desktop scheduled task (no wrapper of yours runs there): make the first and last steps of the prompt write the lines, and commit the file so another clock can read it:
First step: run `tools/ledger.sh start` and keep the id it prints. Commit and push .heartbeat/beats.tsv.
Last step, whatever happened: run `tools/ledger.sh end <id> <status>` and commit and push again.When editing a user's job, show the diff and keep their existing redirections and timeouts.
Never put the ledger in a directory the job deletes or resets (git clean, a temp dir).
B. Read the ledger
"${CLAUDE_SKILL_DIR}/scripts/ledger.sh" report -f .heartbeat/beats.tsv -n 20 # one line per run: start, end, duration, status
"${CLAUDE_SKILL_DIR}/scripts/ledger.sh" check -f .heartbeat/beats.tsv -e 3600 -m 2700-e = expected interval between starts (seconds), -m = longest healthy run (seconds).
check prints one finding per line and exits 0 (OK), 1 (findings) or 2 (no ledger):
| Finding | Meaning | Next step |
OPEN <id> ... | START without END after -m | hung, killed or crashed: the run's log; chain-diagnose link 4 |
GAP a -> b (... slots missed) | starts further apart than 1.5 x -e | scheduler did not fire: chain-diagnose link 1 |
LATE last START ... | nothing started for 1.5 x -e up to now | the schedule stopped: chain-diagnose link 1 |
FAILED <id> <status> | the run ended badly | classify its log: chain-diagnose |
BAD-LINE <n> | line n is not a record | two writers interleaved, or a hand edit |
--now 2026-10-12T02:30:00Z (or epoch seconds) pins the clock, e.g. to replay "what would the
check have said at 3 a.m.".
C. Turn the check into an alarm
The check is useful only if something other than the job runs it, on another clock:
35 * * * * cd /path/to/repo && tools/ledger.sh check -e 3600 -m 2700 >/dev/null || echo "agent: ledger check failed"(cron mails the output line if mail is set up.) Or run it in a GitHub Actions schedule on a
repository where the job pushes the ledger: a failed step sends the owner an email. If the user
has the Field Kit, its missed-run-check workflow does exactly this; use this skill to read and
explain the ledger, and that workflow for the hourly alarm.
Report
Give the user: the command(s) you added or the findings, the last 3 runs from report, and the
exact check line they can schedule. Do not claim a job is healthy from one OK: say over which
period the ledger covers it.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

