A scheduled task repeats a prompt on a schedule or by an automation trigger, and this is no longer a one-off run but a production workflow with its own requirements. Three of them are key: the task must be idempotent, limited in rights and leave evidence understandable after your absence. Idempotency - so a repeated run does not break what is already done; narrow rights - so an automatic action does not go beyond the frame; understandable evidence - so you make sense of the result without watching the run live.
The evidence requirement distinguishes a scheduled task from an interactive one most of all. In interactive work you see the course of the work and can intervene; a scheduled task runs without witnesses. So it must leave behind a clear trace - a report, a log, an artifact - from which you reconstruct what happened and whether all is well. A task that "did something" and left no understandable evidence is useless in production: you can neither trust it nor analyze its failure.
Frequent scheduled tasks create an operational load easy to forget. They can spawn many worktrees, and without cleanup this accumulates. So completed runs are archived, and only those that must really keep working state are pinned. This is the same discipline as with sessions: not to grow endlessly but to consciously decide what to keep and what to remove. Automation without cleaning up after itself turns into a dump of worktrees hard to make sense of later.
Recurring mutation is the riskiest class of scheduled tasks, and it is approached in stages. A task that "fixes the code itself" every night requires far stricter isolation and review than a one-off interactive turn: it has no human nearby, and the consequences accumulate every night. The sensible path is to first automate a read-only report, make sure it is useful and reliable, and only then, separately and consciously, move to automatic mutation. Trusting a nightly code edit at once means risking blindly.
Remote control is an experimental command for a local app-server daemon and short-lived pairing. It helps to see its commands once: start, pair with JSON output and stop. The experimental status here matters as much as with App Server: you do not build a critical process on the command without checking its current behavior. Remote control is handy for quick pairing, but it is not the foundation on which to build a production integration.
Remote control has a hard security rule around pairing. The pairing code must not get into logs or persistent chat: it is the key to pairing, and its leak opens access. It is treated as a secret - short-lived, but a secret nonetheless. And a separate boundary of responsibility: remote control does not replace app-server --listen as the supported protocol for your own client. If you build your own client, its foundation is App Server with its transport authentication, not experimental pairing.
The point of this chapter is that automation and remote control require stricter discipline than interactive work, not less. The absence of a human nearby does not simplify the task but raises the requirements: idempotency, narrow rights, understandable evidence, a staged move to mutation, protection of the pairing code. A scheduled task and remote control are production, and in production the cost of a mistake is higher and repeats, so the boundaries are set stricter, not more relaxed, than in a one-off run at the terminal.
The typical failures around this topic are predictable. Making a scheduled task non-idempotent and breaking the done on a repeated run. Not leaving understandable evidence and being unable to analyze the result after absence. Rolling out nightly automatic mutation at once, skipping the read-only report stage. Leaking the pairing code into logs. And building a production client on experimental remote control instead of app-server --listen. Make tasks idempotent, leave evidence, move to mutation in stages, guard the pairing code and build the client on App Server.
# Remote control - experimental (local app-server daemon, short-lived pairing)
codex remote-control start
codex remote-control pair --json
codex remote-control stop
# the pairing code NOT in logs/persistent chat; does not replace app-server --listen for your client
# recurring mutation: a read-only report first, then separately and consciously - auto-edit