defer — run a prompt after a timer
Session-scoped deferred execution. Parses /defer <duration>: <prompt>, launches a background polling timer that emits TIMER DONE, then runs <prompt> exactly as if the user just typed it.
NOT cross-session — the timer dies with the Claude Code process. Point users at /schedule for anything longer-lived.
Subcommands
| Form |
Action |
/defer <duration>: <prompt> |
Arm a new timer. |
/defer list |
Show pending defers. |
/defer cancel <id> |
Cancel one defer. |
/defer cancel all |
Cancel every pending defer. |
<id> = the background-bash shell id returned at arm time. Cancellation uses TaskStop with task_id=<id>.
Argument format
/defer <duration>: <deferred prompt>
- Duration: integer + unit, case-insensitive. Units:
s|sec|secs|second|seconds, m|min|mins|minute|minutes, h|hr|hrs|hour|hours. Whitespace optional.
- Separator: the first
: after the duration. Everything after, trimmed, is the prompt. The prompt may contain :, /<cmd>, @file.
- Reject with one short error line if: duration ≤ 0, duration > 21600 (6h), non-integer (
1.5h → suggest 90m), empty prompt, or shape mismatch. Do not guess.
Informal regex: ^\s*(\d+)\s*([A-Za-z]+)\s*:\s*(\S.*?)\s*$, unit lower-cased before matching.
Workflow — arm
Parse → duration_seconds, deferred_prompt. Apply rejection rules.
Launch Bash with run_in_background: true, using the polling-timer script in references/timer-script.md. Capture the returned <sid>. Do not interpolate the prompt into the script.
Persist /tmp/claude-defer-<sid>.txt:
END_TS=<unix_end_time>
<deferred_prompt verbatim>
Confirm with one line: Deferring for <human_duration> (id <sid>). Will run: <≤80-char prompt summary>
End the turn. Do not poll, sleep, or Monitor — the harness re-invokes on completion.
Workflow — wakeup
The completion notification's <task-id> IS the shell id <sid>. Use it directly.
- Read the bash output (path is in the notification). Last non-empty line must be
TIMER DONE AND exit code 0 → proceed. Otherwise → interrupted (see references/edge-cases.md).
- Read
/tmp/claude-defer-<sid>.txt, strip the leading END_TS=…\n. If missing/malformed, report and stop.
- Announce:
Timer elapsed. Executing: <summary>.
- Execute the prompt body exactly as if the user just typed it (leading
/<name> → Skill; otherwise → normal request).
- Clean up:
rip /tmp/claude-defer-<sid>.txt (env hook blocks rm).
Workflow — list
Glob /tmp/claude-defer-*.txt. For each, parse END_TS from line 1, summarize the prompt, render a compact table. Format details in references/examples.md.
Workflow — cancel
- TaskStop with
task_id=<sid>. On error (unknown id), report and stop.
rip /tmp/claude-defer-<sid>.txt.
- Print
Cancelled defer <sid>. End turn. The completion notification will fire and the wakeup handler's interrupted branch will recognise the cancel.
cancel all → enumerate sids from the temp-file glob, do the above for each.
References
- references/timer-script.md — the polling-timer bash script (verbatim, do not modify).
- references/examples.md — concrete examples for arm / list / cancel / invalid input.
- references/edge-cases.md — interrupted branch, stale files, concurrency, environmental gotchas.
1---2name: defer3description: Defer execution of a slash-command or prompt until a timer elapses. Starts a background polling timer that prints "TIMER DONE" on stdout, then executes the deferred prompt.4---56# defer — run a prompt after a timer78Session-scoped deferred execution. Parses `/defer <duration>: <prompt>`, launches a background polling timer that emits `TIMER DONE`, then runs `<prompt>` exactly as if the user just typed it.910NOT cross-session — the timer dies with the Claude Code process. Point users at `/schedule` for anything longer-lived.1112## Subcommands1314| Form | Action |15| ----------------------------- | --------------------------- |16| `/defer <duration>: <prompt>` | Arm a new timer. |17| `/defer list` | Show pending defers. |18| `/defer cancel <id>` | Cancel one defer. |19| `/defer cancel all` | Cancel every pending defer. |2021`<id>` = the background-bash shell id returned at arm time. Cancellation uses **TaskStop** with `task_id=<id>`.2223## Argument format2425```26/defer <duration>: <deferred prompt>27```2829- **Duration**: integer + unit, case-insensitive. Units: `s|sec|secs|second|seconds`, `m|min|mins|minute|minutes`, `h|hr|hrs|hour|hours`. Whitespace optional.30- **Separator**: the first `:` after the duration. Everything after, trimmed, is the prompt. The prompt may contain `:`, `/<cmd>`, `@file`.31- **Reject** with one short error line if: duration ≤ 0, duration > 21600 (6h), non-integer (`1.5h` → suggest `90m`), empty prompt, or shape mismatch. Do not guess.3233Informal regex: `^\s*(\d+)\s*([A-Za-z]+)\s*:\s*(\S.*?)\s*$`, unit lower-cased before matching.3435## Workflow — arm36371. **Parse** → `duration_seconds`, `deferred_prompt`. Apply rejection rules.382. **Launch** Bash with `run_in_background: true`, using the polling-timer script in [references/timer-script.md](references/timer-script.md). Capture the returned `<sid>`. Do **not** interpolate the prompt into the script.393. **Persist** `/tmp/claude-defer-<sid>.txt`:4041 ```42 END_TS=<unix_end_time>43 <deferred_prompt verbatim>44 ```45464. **Confirm** with one line: `Deferring for <human_duration> (id <sid>). Will run: <≤80-char prompt summary>`475. **End the turn.** Do not poll, sleep, or Monitor — the harness re-invokes on completion.4849## Workflow — wakeup5051The completion notification's `<task-id>` IS the shell id `<sid>`. Use it directly.52531. **Read the bash output** (path is in the notification). Last non-empty line must be `TIMER DONE` AND exit code `0` → proceed. Otherwise → **interrupted** (see [references/edge-cases.md](references/edge-cases.md)).542. **Read** `/tmp/claude-defer-<sid>.txt`, strip the leading `END_TS=…\n`. If missing/malformed, report and stop.553. **Announce**: `Timer elapsed. Executing: <summary>`.564. **Execute** the prompt body exactly as if the user just typed it (leading `/<name>` → Skill; otherwise → normal request).575. **Clean up**: `rip /tmp/claude-defer-<sid>.txt` (env hook blocks `rm`).5859## Workflow — list6061Glob `/tmp/claude-defer-*.txt`. For each, parse `END_TS` from line 1, summarize the prompt, render a compact table. Format details in [references/examples.md](references/examples.md#list).6263## Workflow — cancel64651. **TaskStop** with `task_id=<sid>`. On error (unknown id), report and stop.662. `rip /tmp/claude-defer-<sid>.txt`.673. Print `Cancelled defer <sid>.` End turn. The completion notification will fire and the wakeup handler's interrupted branch will recognise the cancel.6869`cancel all` → enumerate sids from the temp-file glob, do the above for each.7071## References7273- [references/timer-script.md](references/timer-script.md) — the polling-timer bash script (verbatim, do not modify).74- [references/examples.md](references/examples.md) — concrete examples for arm / list / cancel / invalid input.75- [references/edge-cases.md](references/edge-cases.md) — interrupted branch, stale files, concurrency, environmental gotchas.