Context
Untether's trigger system currently only supports recurring crons. There's no way to schedule a one-shot delayed run — e.g. "run this prompt in 30 minutes, once." This is a common need when dogfooding from mobile (e.g. "remind me to check the build in 20 minutes").
Claude Code has a ScheduleWakeup tool that lets the agent schedule itself to wake up after a delay (60-3600s), but this only works in Claude Code's local /loop mode — it doesn't work through Untether.
Proposal
Two complementary features:
1. /at command — on-demand delayed runs (~4-6 hours)
Interactive Telegram command for scheduling a one-shot delayed agent run:
/at 30m Check the build status
/at 2h Review the PR comments
/at 90s Run the test suite
Implementation:
- Parse delay from command arguments (supports
Ns, Nm, Nh suffixes)
- Create an
anyio task with anyio.sleep(delay) then run_job()
- Store pending timers in memory (lost on restart — acceptable for one-shot delays)
- Optional: persist to a state file for restart survival
- Show confirmation: "⏳ Scheduled: will run in 30 minutes"
- On fire: send notification then start the run, same as cron dispatch
- Clean up after firing
Delay range: 60s to 24h (matching ScheduleWakeup's 60s minimum, extending the max for practical use)
2. run_once cron flag — config-driven one-shot (~2-3 hours)
Add run_once: bool = False to CronConfig for crons that should fire once then disable:
[[triggers.crons]]
id = "deploy-check"
schedule = "0 15 * * *"
prompt = "Check today's deployment status"
run_once = true
Implementation:
- Add
run_once field to CronConfig in triggers/settings.py
- After firing,
TriggerManager removes the cron from the active list
- Log the removal:
triggers.cron.run_once_completed
- The cron stays in the TOML (not auto-deleted) but is skipped in-memory after firing
- On config reload (hot-reload or restart), the cron resets and can fire again
Use case: "Fire this at 3pm today, then never again until I re-enable it" — useful for scheduled one-off tasks.
Effort
| Item |
Estimate |
/at command (parsing, timer, dispatch, cleanup) |
~4-6 hours |
run_once cron flag (settings, manager, scheduler) |
~2-3 hours |
| Tests for both |
~2-3 hours |
| Total |
~8-12 hours |
Related
Context
Untether's trigger system currently only supports recurring crons. There's no way to schedule a one-shot delayed run — e.g. "run this prompt in 30 minutes, once." This is a common need when dogfooding from mobile (e.g. "remind me to check the build in 20 minutes").
Claude Code has a
ScheduleWakeuptool that lets the agent schedule itself to wake up after a delay (60-3600s), but this only works in Claude Code's local/loopmode — it doesn't work through Untether.Proposal
Two complementary features:
1.
/atcommand — on-demand delayed runs (~4-6 hours)Interactive Telegram command for scheduling a one-shot delayed agent run:
Implementation:
Ns,Nm,Nhsuffixes)anyiotask withanyio.sleep(delay)thenrun_job()Delay range: 60s to 24h (matching ScheduleWakeup's 60s minimum, extending the max for practical use)
2.
run_oncecron flag — config-driven one-shot (~2-3 hours)Add
run_once: bool = FalsetoCronConfigfor crons that should fire once then disable:Implementation:
run_oncefield toCronConfigintriggers/settings.pyTriggerManagerremoves the cron from the active listtriggers.cron.run_once_completedUse case: "Fire this at 3pm today, then never again until I re-enable it" — useful for scheduled one-off tasks.
Effort
/atcommand (parsing, timer, dispatch, cleanup)run_oncecron flag (settings, manager, scheduler)Related
/loopsupport (agent self-pacing, v0.36.0)ScheduleWakeuptool — one-shot delayed wakeup for/loopmode