Scheduled tasks
Continue a session later, keep it working toward a goal, or watch a command for changes.
Controller can continue an existing session without starting a new conversation.
Each follow-up runs after the current turn ends and keeps the session's full
history. Use self from inside a running agent session; it resolves to that
session's ID.
Continue after a delay
Use wake when you know when to check again:
controller sessions wake self "Check the CI status again" --delay 30sThe follow-up waits until the delay passes, then Controller starts it on a
scheduler tick. Messages sent to the same session while it waits can run
first; the pending follow-up does not hold up the message queue. Durations
include 30s, 5m, 1h, and 2d. You can use --run-at <iso> for a
specific time instead. The message is a positional
argument, so put it in quotes when it contains spaces.
List pending follow-ups or cancel one by the ID printed by wake:
controller sessions queue list self
controller sessions queue list self --json
controller sessions queue remove self <messageId>The queue includes messages from the user, wakes, goals, sends, and monitors.
list shows each ID, origin, run time, and message text; --json emits the
full queue as a JSON array. remove succeeds only while the message is still
queued. It does not interrupt a running session. Clearing a goal or stopping
a monitor stops future messages from that source, but any messages already
queued remain until they run or you remove them.
Keep working toward a goal
Use goal when the session should continue until a condition is met:
controller sessions goal set self \
--condition "all required CI checks on PR #123 are SUCCESS" \
--max-turns 5After each turn, Controller evaluates the condition. If it is met, the goal
clears. Otherwise, Controller queues another turn when the session's queue is
empty. --max-turns limits the evaluations; --expires-at <iso> sets an
absolute deadline. Use controller sessions goal show self to inspect the
goal or controller sessions goal clear self to stop it.
Watch a command
Use monitor to run a command in the background while the agent continues:
controller sessions monitor start self \
--description "CI checks" \
--command "gh pr checks 123 --watch" \
--timeout-ms 600000Each stdout line is added to the session event log. The default timeout is
five minutes, with a maximum of one hour. Add --persistent to keep the
monitor running for the session's lifetime instead of using a timeout. A
monitor can also use --on-line <regex> to queue a follow-up when a matching
line appears. Inspect active monitors with controller sessions monitor list self and stop one with controller sessions monitor stop <monitorId>.
Before ending a turn with work still pending, confirm that a Controller
follow-up was registered. A watch or background task inside Codex or Claude
Code can return results during the current turn, but does not resume a
Controller session after that turn ends. Monitor output alone is only logged;
use --on-line to queue a new turn when a matching line arrives.
Example: stay with a PR until CI passes
After opening a PR, attach a goal and queue the first check:
gh pr create --fill
controller sessions goal set self \
--condition "all required CI checks on PR #123 are SUCCESS" \
--max-turns 5
controller sessions wake self \
"Check gh pr checks 123. If all checks pass, finish. If one fails, read its log, fix it, and push again." \
--delay 30sWhen the delayed turn runs, the agent checks CI and handles any failure. At
the end of each turn, Controller evaluates the goal. It clears the goal when
the checks pass, or queues another turn while the goal remains active, up to
the turn limit. For a command that announces a final status, a monitor with
--on-line can queue the follow-up as soon as that line appears.
Where to inspect state
On macOS, Controller's default state directory is
~/Library/Application Support/Controller (or CONTROLLER_HOME if set):
- Delayed wakes live in
queues/<sessionId>.jsonwith arunAttime. - Goals live in
goals/<sessionId>.json. - Monitor output lives in the session event log. Active monitor processes are held in memory and do not survive a server restart.
There are no wakes.json, goals.json, or monitors.json files in the current
implementation. The agent's in-session explanation of these commands lives in
server/lib/agent-preamble.ts.