agentleFS
elfovoelfovo/agent-chain-doctor/skills/run-ledger/SKILL.md

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

  • Other versions2 projects use a version of this.

    Word for word · 0

    None found.

    Edited · 0

    None found.

    Wrote their own version · 2

    1. kvantatech/RedLine★ 1same name
    2. 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.

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
  1. Very specific:

    Default file: $LEDGER, else ./.heartbeat/beats.tsv.

    line 25
  2. Distinctive:

    When editing a user's job, show the diff and keep their existing redirections and timeouts.

    line 65
  3. Distinctive:

    Never put the ledger in a directory the job deletes or resets (git clean, a temp dir).

    line 66

≈ “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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

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 no bash prefix, 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's allowed-tools; in dontAsk mode or a headless claude -p run, anything else is refused. Use the Read tool, not cat or tail, 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  ok

Default 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>&1

wrap 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):

FindingMeaningNext step
OPEN <id> ...START without END after -mhung, killed or crashed: the run's log; chain-diagnose link 4
GAP a -> b (... slots missed)starts further apart than 1.5 x -escheduler did not fire: chain-diagnose link 1
LATE last START ...nothing started for 1.5 x -e up to nowthe schedule stopped: chain-diagnose link 1
FAILED <id> <status>the run ended badlyclassify its log: chain-diagnose
BAD-LINE <n>line n is not a recordtwo 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.

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.