Queue a message for your Claude Code session — it gets delivered the moment your usage limits reset, or at a time you choose.
You hit your Claude usage limit at 11 PM. The limits reset at 2 AM — while you sleep. Without this tool your next 5-hour limit window starts only when you type your next message in the morning. With it, your queued message fires at 2 AM, the session keeps working, and by the time you're back the next reset is already hours closer.
English · Русская версия
Developed with the support of infilarite.
npm install -g claude-delayed-message
cdm installcdm install registers a lightweight background check (Windows Task Scheduler / macOS launchd / Linux systemd timer or cron — every 10 minutes) and installs the /delay skill into ~/.claude/skills/. It also resolves the absolute path to your claude binary so the scheduled task can find it even without your shell's PATH.
/delay Continue the refactoring we discussed: extract the parser into its own module
Queued [a1b2c3d4] — will be sent to this session as soon as your usage limits reset.
/delay at "tomorrow 9:00" Run the test suite and summarize failures
/delay list
/delay edit a1b2c3d4 Continue the refactoring, but start with tests
/delay cancel a1b2c3d4
Or straight from the terminal:
echo "Continue where we left off" | cdm add --project C:\work\my-app
cdm list
cdm log
cdm status/delay ──► queue (~/.claude-delayed-message/queue/*.json)
▲
OS scheduler (every 10 min) ──► cdm run-once
├─ queue empty → exit (no probe, zero cost)
├─ "at" items due → deliver now
└─ "limits-reset" items:
probe (tiny haiku request)
├─ limit error → free; remember expected reset time, wait
└─ success → limits are back: deliver everything FIFO
via claude --resume <session> -p (stdin)
- Queueing itself runs in a local hook (
UserPromptExpansion) —/delayworks even when your limits are fully exhausted, because no model turn is needed to enqueue. - The probe is free while you're limited (rejected requests don't consume anything) and costs a fraction of a cent when limits are back — at which point your real message is sent immediately anyway.
- Early resets (Anthropic occasionally resets everyone's limits ahead of schedule) are caught within one tick.
- Delivery resumes the same session ID, so open the chat and continue where it left off.
| Command | What it does |
|---|---|
cdm add -m "<text>" [--at "<time>"] [--session auto] [--project <dir>] |
Queue a message (text also accepted via --message-file or stdin) |
cdm list |
Show the queue |
cdm edit <id> [-m "<text>"] [--at "<time>"] [--on-reset] |
Edit a pending item |
cdm cancel <id> |
Cancel a pending item |
cdm log |
Delivery history |
cdm status |
Scheduler state, resolved claude path, CLI token expiry, last tick, queue size |
cdm lang [code] |
Show or set the output language (en, ru, uk); English by default |
cdm install / cdm uninstall |
Register/remove the scheduler, the /delay skill and hook |
Time formats for --at: 09:00, tomorrow 9am, tomorrow 12:30pm, ISO like 2026-07-08T09:00. A bare HH:MM that already passed today rolls to tomorrow.
Output is English by default. Run cdm lang ru (Russian) or cdm lang uk (Ukrainian) to switch all messages, hook replies and notifications; cdm lang en switches back.
A delayed message is delivered by a headless claude --resume, which does not inherit the permission mode you had selected in the chat — so by default it can't edit files (writes are auto-denied). To let a queued run act autonomously, the permission mode is captured from your chat at queue time (via the /delay hook) and passed to delivery. You can also set it explicitly:
- Per message:
cdm add … --permission-mode bypassPermissions(choices:default,acceptEdits,bypassPermissions,auto,dontAsk,plan). - As a default for every delivery: add
"deliveryPermissionMode": "bypassPermissions"to~/.claude-delayed-message/config.json.
cdm list shows the mode as [perm: <mode>] when set, so an elevated run is never a surprise. With nothing set, no permission flag is added and your project's Claude Code settings apply. bypassPermissions lets the run do anything without prompting — use it only for work you'd run unattended yourself.
Does the probe waste my limits? While limited — no, rejected requests are free. When limits are available the probe is one tiny haiku request, and it only happens when something is queued.
What permissions does the delivered run get? Exactly what that project's Claude Code settings allow. The tool never adds permission flags (no --dangerously-skip-permissions, ever).
Which session does --session auto pick? The most recently active Claude Code session for that project directory. If you run several sessions against the same project at once, pass an explicit --session <uuid> (the UUID is visible in the claude --resume picker) so the message lands in the right chat.
Where is my data? Plain JSON in ~/.claude-delayed-message/. Your message texts are stored there in clear text — treat the folder accordingly.
The app was closed when the message fired — did I lose the answer? No. The session file is shared; open the chat in Claude Code and the new turn is there.
Nothing is being delivered — how do I find out why? Run cdm status. If it shows a probe error mentioning 401 / Failed to authenticate, your standalone CLI login has expired (the desktop app refreshes its own token, the CLI does not): run claude auth login in any terminal — the queue resumes automatically on the next tick. You also get a desktop notification when this happens.
How do I uninstall? cdm uninstall removes the scheduler entry and the skill; your data folder stays.
Probing and delivery run through the standalone claude CLI in headless mode. Its access token is separate from the Claude Code desktop app:
- The desktop app refreshes its token automatically — you can work normally for weeks while the CLI token is long expired.
- Headless mode (
claude -p) does not refresh an expired token — it fails with401 Invalid authentication credentials. claude auth statusmay still printloggedIn: truewith an expired access token — don't rely on it alone.
Refresh: run claude auth login in any terminal and complete the browser sign-in. The queue resumes automatically on the next tick — nothing else to do.
Monitoring: nothing manual is required. On the first failed tick you get a desktop notification, and cdm status shows the probe error marked [AUTH] (with a reminder roughly every 6 hours while the problem persists). cdm status also prints the token expiry date, so you can spot it going stale before anything breaks.
PolyForm Noncommercial 1.0.0 — free for personal and other noncommercial use.
Commercial licensing: to use this in a commercial context, contact gladluter@gmail.com for a commercial license.