Cadences reference
A cadence is a recurring job himmel can arm on your machine: a crontab entry (Linux, macOS) or a scheduled task (Windows) that fires a runner on a schedule. Every cadence is off until you arm it: the install wizard only offers the ones whose precondition holds, and nothing arms itself.
The wizard menu is not a hand-written list. It reads
scripts/himmelctl/lib/cadence-registry.json, one row per cadence, and a
staleness lint asserts each row’s script still exists and still exposes
arm, status and disarm. This page is derived from that file; when the two
disagree, the JSON wins.
The common interface
Every cadence script takes the same three verbs:
bash <script> arm [--time HH:MM] [--force] [--dry-run]bash <script> statusbash <script> disarm [--dry-run]arminstalls the schedule. It refuses to double-arm (already armed);--forcereplaces the existing entry.--dry-runprints what it would register and registers nothing.statusreports whether the job is armed, its schedule and its last run.disarmremoves exactly whatarmadded.- Some cadences (
doctor, the reconcile, failure-review and qmd-quality scripts) also acceptrun, one pass, the verb the scheduler calls, so you can test the job by hand.
Per-script flags beyond that are in the table. Several cadences also register
themselves with the observability registry so /himmel-doctor can warn when a
task silently vanishes.
Registry cadences (offered by the install wizard)
| Id | Script | Offered when | What it does |
|---|---|---|---|
pipeline | scripts/luna/pipeline-cadence.sh | a vault exists | Daily fetch-health, harvest and synthesize, plus weekly health runs against the vault. The one wizard-recommended cadence. arm --vault <path> |
qmd | scripts/luna/qmd-cadence.sh | a vault exists | Daily qmd update, embed and completeness assert over every configured collection, so the index never goes silently stale |
graphmap | scripts/luna/graphmap-cadence.sh | a vault exists | Hourly free structural (AST) refresh, weekly semantic refresh of the vault and himmel graphify graphs, plus a 6-hourly refresh, publish and auto-merge PR for himmel’s own graph. Arming it commits to the hourly job. arm --vault <path> |
vault-stall | scripts/luna/vault-stall-cadence.sh | a vault exists | Every 15 minutes: detect a stalled vault auto-commit, remediate only the known-benign pre-commit refusals, alert on everything else without echoing the secret. arm --vault <path> |
drift-fix | scripts/upstreams/drift-fix-cadence.sh | always | Nightly /drift-fix (bump auto-bumpable pins, open an ordinary PR) and /fork-resync (rebase carried forks, audit only). Stops at the PR or audit; never merges. Extra flag --resync-time |
upstream-watch | scripts/upstreams/upstream-watch-cadence.sh | always | Daily scan of himmel’s open upstream PRs and issues for a delta. No Claude session; Telegram-notified only when something changed |
doctor | scripts/doctor-cadence.sh | always | Daily himmel-doctor run from the primary checkout. A FAIL or a new WARN goes to Telegram and the statusline shows the counts. Report only, fixes nothing. Cron only (Linux, macOS) |
pull-cadence | scripts/luna-vitals/connectors/pull-cadence.sh | GOOGLE_HEALTH_REFRESH_TOKEN is set | Daily Google Health connector pull to a review artifact. No Claude session. Setup: luna/google-health-connector-setup.md |
Cadences armed by hand (not in the wizard)
These have no wizard row; arm them directly with the same three verbs.
| Script | What it does | Notes |
|---|---|---|
scripts/handover/reconcile-cadence.sh | Periodic seat-liveness check: runs reconcile-workers.sh --report and orphans only seats whose pid is confirmed dead past the grace window | arm [--interval-min N] (default 10; N must divide 60). One crontab entry tagged HIMMEL-ReconcileCadence |
scripts/eval/worker-digest/failure-review-cadence.sh | Daily failure review: runs the failure router over recorded worker failures and shows what failed. No model is run | Dry-run by default: a scheduled run files nothing and calls no Jira. arm --live opts in to live routing. arm [--vault PATH] [--live] |
scripts/cleanup/steering-cull-cadence.sh | Weekly read-only steering-file cull: runs /writing-for-agents (headless claude -p, plan mode, Read only, behind bank-preflight.sh) over himmel CLAUDE.md, ~/.claude/CLAUDE.md, RTK.md and the memory index. Writes a dated proposal doc and appends one line naming it to the live chief’s bridge inbox: the newest held *-chief queue lock (queue-lock.sh status --sweep), resolved at run time, so a chief handover never strands it. No live chief, or no inbox for it, raises the shared cadence-alert.sh alert instead. Never edits a file | arm --proposal-dir <dir> [--chief <chief>] [--day 0-6] [--time HH:MM] [--backend claude-cli|claude-api --api-account A|B|auto] (default Monday 07:00). --chief is an override that pins one session; omit it normally. --backend claude-api runs the call through the API lane (API credit, no subscription draw, no bank-preflight) and never falls back to the subscription; the default stays claude-cli. Medium cuts and any live-file cut are counted as escalated; low repo cuts are listed in the doc, not auto-opened as a PR |
scripts/security/snyk-scan-cadence.sh | Weekly station run of snyk-scan.sh: Snyk Open Source (snyk test --all-projects) and Snyk Code over the primary checkout, JSON plus a short summary written to the state repo under specs/security/snyk/. A High or Critical finding, or a failed scan (snyk missing, not authenticated, monthly quota reached), raises the shared cadence-alert.sh alert; a clean run clears it. On the station a monthly test-count ledger refuses a run that would pass the cap; the GitHub workflow starts every run with an empty ledger, so it is bounded only by its cadence times its count. snyk-scan.sh --forks (on demand, and on the first Monday of the month in the snyk-weekly GitHub workflow with --no-upstream, and on any dispatch; not in this station cadence) scans the forks himmel pins (qmd, graphify, claude-hud, obsidian-second-brain, claude-obsidian) at their pinned refs, one report section per fork under specs/security/snyk/<date>.forks.*. A station run also scans each tracking fork’”’“‘s upstream HEAD and marks each finding fixed upstream or not, but skips any third-party tree (a pinned fork or an upstream HEAD) that holds a gradlew, mvnw, build.gradle*, pom.xml, build.sbt, Package.swift or mix.exs (snyk would run that build tool) and reports the skip. The workflow costs about 16 Open Source tests every Monday for the main scan plus about 48 for the forks on the first Monday, so 112 to 128 of the free 400 in a month; Snyk cannot read uv.lock, so those are exported with uv export and looked up on osv.dev. Never runs per PR | arm [--day 0-6] [--time HH:MM] [--force] [--dry-run] (default Monday 06:30), status, disarm. Cron only (Linux) |
scripts/eval/cache-health-cadence.sh | Hourly scripted prompt-cache health check (no model, no claude -p): cache-health.py computes per-role hit rate, write share and compactions from session transcripts, writes ~/.himmel/state/cache-health/metrics.json (schema), and sends ONE Telegram DM plus one line to the live chief’s bridge inbox only when a threshold is crossed (role hit rate more than 3 points under its 7-day baseline, a 1M-token session under 90 %, workers averaging over 4 compactions). One alert per crossing, one recovery message, no repeats. The chief is resolved at run time like the steering cull; a failed run raises the shared cadence-alert.sh alert | `arm [—minute 0-59] [—every-hours 1 |
scripts/eval/stability-scorecard.sh | Daily stability scorecard row (no model): measures the last 24 h from ci-metrics.sh (CI queue wait p50/p90, failed-job rate, cancelled runner-minute share), failed CI runs on main, classifier denials, tickets created on the current version (residuals) and deferred-escape tickets (labelled by scripts/cr/mark-deferred-escape.sh; the note cell splits them per class-<id> and priority), and appends one row per UTC day to specs/research/stability-scorecard.tsv in the state repo. A date already recorded is skipped, a failed source reads unknown and the run exits 1. stuck_playbook_hits is n/a (no ledger) | arm [--hour 0-23] [--minute 0-59] (default 06:20 daily). One crontab entry tagged HIMMEL-StabilityScorecard; the runner exports HANDOVER_DIR from the arming shell |
scripts/eval/judge-accuracy/judge-accuracy-cadence.sh | Weekly judge-accuracy run (no model call, no budget draw): reads PR and main-run state with gh from the primary checkout, runs judge_accuracy.py (one eval-runs row; new adjudication candidates are queued for a judge-ro call to rule), appends the five-question answer row with decision-158-answers.py, and renders the reviewer page with review-page.py to ~/.himmel/state/review-page/review-page.md (REVIEW_PAGE_FILE overrides), which the config-ui serves at GET /api/reviewers. A failed run raises the shared cadence-alert.sh alert; a clean run clears it | arm --verdicts <dir> [--day 0-6] [--time HH:MM] [--force] [--dry-run] (default Monday 07:30), status, disarm. One crontab entry tagged HIMMEL-JudgeAccuracy |
scripts/eval/qmd-quality/qmd-quality-cadence.sh | Weekly qmd retrieval-quality eval; appends metrics and alerts when MRR drops | arm --golden <file> [--index <file>] [--day 0-6]. The index snapshot is deleted after every run |
scripts/cleanup/reap-mcp-orphans.sh | Finds MCP and LSP children (context7-mcp, graphify-mcp, tsserver and similar) whose ancestor chain holds no live owner and logs them to ~/.cache/himmel/reap-mcp-orphans.log. Report-only by default; --kill arms it | Manual and report-only until the SessionEnd hook and the daily sweep are wired after a one-week soak (deferred slices of HIMMEL-1620). Run bash scripts/cleanup/reap-mcp-orphans.sh by hand; add --kill only after the soak |
Choosing
- Start with
doctorandupstream-watch: report-only, no Claude session, no writes outside the state directory. - Add the vault trio (
pipeline,qmd,vault-stall) only if you run a companion vault. graphmapanddrift-fixrun Claude sessions or open PRs; read their headers before arming.
See also: setup/updating.md (what ensure re-arms),
configuration.md (off-switches), and /pipeline-cadence
in commands-catalog.md.