name: janitor-pause description: Suppresses ai-maestro-janitor heartbeat output without removing the cron. Use when starting a large refactor, doing focused exploration, or any block of work where drift nudges would be noise. Trigger with /janitor-pause, "pause the janitor", "silence the janitor for 2h", or "quiet the heartbeat for the rest of today".
Janitor pause
Overview
Writes a sentinel file .janitor/state/paused that dispatch.py checks at the top of every heartbeat. While the file exists (and its expiry has not passed), all heartbeat fires exit silently with a single log entry — detectors do not run, drift lines are not emitted, the rate-limit resume cue is suppressed.
The cron itself stays armed. No CronDelete happens. When the pause expires (or /janitor-unpause runs), the next heartbeat fires normally.
This is the lighter alternative to /janitor-disarm: pause when you want a quiet block of work; disarm when you're moving away from the project.
Prerequisites
$CLAUDE_PROJECT_DIRset (used to locate.janitor/state/).- The janitor heartbeat is armed (otherwise pausing is a no-op).
Instructions
Determine the pause duration from the user's request:
- "pause indefinitely" / no duration →
EXPIRY=0 - "pause for 2h" / "for 30m" / "until 18:00" → compute
EXPIRYas epoch seconds - Recognize
m(minutes),h(hours),d(days) suffixes
- "pause indefinitely" / no duration →
Write the sentinel file atomically:
STATE_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}/.janitor/state" mkdir -p "$STATE_DIR" printf '%s' "$EXPIRY" > "$STATE_DIR/paused.tmp.$$" mv -f "$STATE_DIR/paused.tmp.$$" "$STATE_DIR/paused"Report the outcome in one line. If
EXPIRY=0:Janitor paused (no expiry — run /janitor-unpause to lift).Otherwise:Janitor paused until <local-time-with-offset> (~<N>h<M>m from now).
Output
One line confirming the pause and its expiry. The next heartbeat will emit nothing until the expiry passes or /janitor-unpause runs.
Error Handling
$CLAUDE_PROJECT_DIRunset → fall back to$(pwd). The sentinel still works becausedispatch.pyresolves the same path.- Cannot create
$STATE_DIR(permission denied) → abort with the error verbatim. ReportJanitor pause failed: <error>. - User asks for a past-time expiry → refuse, report
Janitor pause refused: expiry <ts> is in the past. - User asks to pause an already-paused janitor → overwrite the sentinel with the new expiry and report the new value.
- Heartbeat not armed (no
$STATE_DIR/heartbeat-armed-at.ts) → still write the sentinel, but append to the report:Note: heartbeat is not armed; the pause will only take effect after /janitor-arm.This way the sentinel survives a future/janitor-armrather than silently doing nothing now.
Examples
User: /janitor-pause
User: pause the janitor
User: silence the janitor for 2h
User: pause until 18:00
User: quiet the heartbeat for the rest of today
Scope
This skill ONLY writes the paused sentinel. It does not affect the cron, touch detector seen-files, modify state, or prune logs. To re-enable normal heartbeat behaviour, run /janitor-unpause (or wait for the expiry to pass — dispatch.py auto-cleans the sentinel on the first heartbeat after expiry).
Resources
${CLAUDE_PLUGIN_ROOT}/scripts/dispatch.py— checks forpausedsentinel and exits early when present and not expired.$CLAUDE_PROJECT_DIR/.janitor/state/paused— the sentinel file itself; first line is the expiry epoch (or0for indefinite).
Checklist
Copy this checklist and track your progress:
- Parse the user's duration request (or default to indefinite)
- Compute
EXPIRYas epoch seconds (or0) - Atomically write the sentinel via tmp+rename
- Report the pause outcome in one line, including the local-time expiry if set