Skip to content

feat: one-shot delayed triggers — /at command and run_once cron flag #288

@nathanschram

Description

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions