Pick the scheduler
| cron | systemd timer | Claude Code Routines | Uno scheduled task | |
|---|---|---|---|---|
| Where it runs | Your server | Your server | Anthropic's cloud | Your Uno computer |
| Any agent or script | yes | yes | Claude Code only | yes |
| Catches up a missed run | no | yes, with Persistent=true | Runs in the cloud | Not needed: it wakes the computer at the set time |
| Runs on a computer that sleeps when idle | no | no | Not needed | yes, it wakes the computer |
| History of runs | The log you write | journalctl | At claude.ai/code/routines | run now, pause, resume, and the log of every run |
Steps
-
Write the task down
Put the prompt in a file. Say what to check, what counts as done and where the result goes: the agent cannot ask you halfway.
$ mkdir -p ~/prompts ~/logs ~/bin $ cat > ~/prompts/nightly.md <<'EOF' Pull the latest main. Run npm test. If a test fails, fix the code, run the tests again and commit the fix. End with three lines: what failed, what you changed, what is left. EOF
-
Write the script
Use full paths: cron starts with a short
PATHand does not find~/.local/bin.--allowedToolslists what the agent may do without asking; anything else is refused. Claude Code in -p mode exits with 0 on success and a non-zero code when the run fails.#!/bin/bash # ~/bin/nightly.sh set -euo pipefail cd /home/dev/your-project /home/dev/.local/bin/claude -p "$(cat /home/dev/prompts/nightly.md)" \ --allowedTools "Read,Edit,Bash(git pull *),Bash(npm test *),Bash(git commit *)" \ --output-format json > /home/dev/logs/nightly-$(date +%F).json
With Codex, the same line is
codex exec: -C sets the folder, -s the sandbox (read-only, workspace-write), -o writes the last message to a file./home/dev/.local/bin/codex exec -C /home/dev/your-project -s workspace-write \ -o /home/dev/logs/nightly-$(date +%F).txt "$(cat /home/dev/prompts/nightly.md)"
-
Run it once by hand
Make it executable and run it. Fix every error now, while you can see it.
$ chmod +x ~/bin/nightly.sh $ ~/bin/nightly.sh && echo "exit 0" $ jq -r '.result' ~/logs/nightly-$(date +%F).json
-
Schedule it with cron
Open your crontab and add one line. Five fields: minute 0-59, hour 0-23, day of month 1-31, month 1-12, day of week 0-7 (0 and 7 are Sunday). This one runs every day at 07:00 server time.
$ crontab -e # add: 0 7 * * * /home/dev/bin/nightly.sh >> /home/dev/logs/cron.log 2>&1
-
Or schedule it with a systemd timer
A timer catches up after a reboot: Persistent=true runs a missed job right after the machine comes back. A timer starts the service with the same name: agent.timer starts agent.service. Put both files in
/etc/systemd/system/.# nightly-agent.service [Unit] Description=Nightly agent run [Service] Type=oneshot User=dev ExecStart=/home/dev/bin/nightly.sh # nightly-agent.timer [Unit] Description=Run the nightly agent at 07:00 [Timer] OnCalendar=*-*-* 07:00:00 Persistent=true [Install] WantedBy=timers.target
$ sudo systemctl daemon-reload $ sudo systemctl enable --now nightly-agent.timer $ systemctl list-timers nightly-agent.timer
Check that it works
Set the schedule to every minute for a test, wait two minutes, read the log, then set it back. With a timer, start the service once by hand and read its journal.
$ tail -20 ~/logs/cron.log $ sudo systemctl start nightly-agent.service $ journalctl -u nightly-agent.service -n 30
The short way: a scheduled task that wakes the computer
An Uno computer sleeps when idle, and a crontab entry inside a sleeping computer does not run and cannot wake it. Use Uno's scheduled task instead: a scheduled task that comes due wakes a sleeping computer and runs its command. After the run the computer goes back to sleep by default; on_finish keep leaves it on. Set it up in the API: scheduled tasks are set up through the API (POST /api/v1/scheduled-tasks), so your agent can create one for you.
Small: $5 a month
The same job as an Uno scheduled task. The command runs as Uno's own user on the computer, which can use sudo; start your script as your user with sudo -u so the agent finds its sign-in, and a run gets 5 minutes by default and up to 60 minutes with timeout_sec:
$ curl -sS -X POST https://console.uno.place/api/v1/scheduled-tasks \
-H "Authorization: Bearer $UNO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "nightly agent", "box_id": 1234,
"cron_expr": "0 7 * * *", "timezone": "Europe/Berlin",
"command": "sudo -u dev -H /home/dev/bin/nightly.sh",
"timeout_sec": 3,600, "on_finish": "hibernate"}'Every run is written to your access log as a scheduled task, so you can see when the agent ran and why.
A scheduled agent works alone, from a clean address
Your computer runs in the Netherlands. Its traffic can leave through a static address of a regular internet provider in one of 8 countries. Only your account works from that address.
- From a data-center address
- Sites see a server range shared with thousands of strangers. The agent's browser hits more captchas and blocks.
- From your Clean exit IP
- Sites see a regular internet provider's address in the country you picked. Fewer captchas, and less reason for Claude or ChatGPT to flag your account: nobody else works from it.
What a schedule does not do
- It does not answer the agent's questions. A step that needs approval and is not in
--allowedToolsis refused, and the run ends without it. - cron does not run what it missed while the server was off. A timer with
Persistent=truedoes. - It does not stop a run that goes wrong. Give each run a time limit:
timeout 1h /home/dev/bin/nightly.shin cron,TimeoutStartSec=1hin aType=oneshotservice. - On Uno, a scheduled task does not wake a computer whose subscription is suspended or ended.
Pick the computer your scheduled agent lives on
Every plan sleeps when idle and wakes for a scheduled task. Small fits a daily job; take Plus for agents that build and test.
Small
A Telegram bot, a VPN, a small backend
$5/ month
- 1 vCPU · 1 GB
- 15 GB disk
- 25 GB cloud storage
- 5 boosts a month
Plus
Agents that work with your laptop closed
$20/ month
- 4 vCPU · 4 GB
- 40 GB disk
- 100 GB cloud storage
- Uno Work in the cloud
Pro
A product in production, a second MacBook
$70/ month
- 16 vCPU · 16 GB
- 120 GB disk
- 300 GB cloud storage
- Speed of a MacBook Air M4
Max
A team and many agents at once
$200/ month
- 32 vCPU · 48 GB
- 300 GB disk
- 1,024 GB cloud storage
- 5 public IPv4
Add Uno AI to any plan: 40 h of AI work a month on Small, 100 h on Plus, unlimited on Max. Today: GLM-5.3 Flash and MiMo v2.6 Pro. Or sign in with your own Claude or ChatGPT.
Common problems
It works by hand but not from cron
PATH and another working folder. Use full paths to claude, codex, npm and your project, and read ~/logs/cron.log."Not logged in" or a sign-in error in the log
CLAUDE_CODE_OAUTH_TOKEN.The agent stops at the first command
--allowedTools, for example Bash(npm run build *).The timer did not run after a reboot
sudo systemctl enable --now nightly-agent.timer and check systemctl list-timers.