Two skills that turn Claude Code from an interactive tool into an autonomous worker. Validated, secured, ready for overnight runs.
This is what it looks like when you use Claude Code for larger tasks. Four problems everyone encounters who has tried it.
40 clicks per hour on "Approve". After 20 minutes, you stop reading what you're approving.
After /compact, Claude forgets the plan, the stack, the completed steps. Without correction, it loops.
rm -rf ~/ has documented cases of deleting entire home directories. --dangerously-skip-permissions alone is not a safety concept.
No overnight runs. No parallel work. Leave the terminal, Claude stops.
Nightshift for planned project work. 24x7 for a continuous task queue. Both generate a complete, ready-to-run setup.
One task. One project. One validated plan. Claude works all night and commits the result in the morning.
Endless runner. Drop tasks as folders. Claude processes them sequentially and delivers results.
Each skill generates a complete setup. Install, copy into your project, start.
Nightshift detects the task type and fills the runbook with the matching phases, risk checks, and autonomy zones.
| Property | Nightshift | 24x7 |
|---|---|---|
| Mode | Single run, then exit | Endless loop |
| Task type | Planned project work | Continuous task queue |
| Workspace | Directly in the project repo | Isolated workspace |
| Runbook | Validated, genre-based | Freeform via task.md |
| Compact recovery | Hook re-injects plan | Not needed (fresh session) |
| Output | Git commit in project | Files in outbox/output/ |
| Parallel projects | Start multiple nightshifts | One queue, sequential |
| Idle behavior | — | Configurable |
| Loop detection | Stall warning after 3 checks without progress | Not needed (fresh session per task) |
| Cross-run memory | decisions.md in project root | decisions.md in workspace root |
--dangerously-skip-permissions alone is not a safety concept. Both skills build four lines of defense.
Two barriers. One reads the command text and blocks rm against dangerous targets, sudo, mkfs, dd to a device, chmod 777, curl|bash, eval. No pattern for fork bombs. The other reads the target path of Write, Edit and NotebookEdit and blocks every write outside the project.
Kernel-level isolation. Claude can only write to the project folder and /tmp.
git checkout . reverts everything. Always commit before starting.
Heartbeat monitor detects when Claude stalls, and can terminate or restart the run instead of only reporting it.
Both skills combine four mechanisms. None of them work well alone. Together, they make autonomous runs reliable.
A markdown file with checkboxes that Claude reads before each step. When context compression happens (and it will, on any run longer than 20 minutes), Claude loses its internal memory of the plan. The runbook survives because it's a file on disk, not in Claude's context window. After every compression, a hook tells Claude: "Read runbook.md again. Find the next unchecked item. Continue there."
The runbook also contains autonomy zones that tell Claude what it may do freely, what to log, and what is forbidden. Plus an error budget defining how many test failures are acceptable before Claude should stop.
Claude Code hooks are scripts that fire on specific events. They run even with --dangerously-skip-permissions. A PreToolUse hook returning exit code 2 blocks the tool call unconditionally — Claude cannot override it.
Nightshift generates a Dockerfile and a docker-compose.yml. The container mounts the project as /project and nothing else from the host: no home directory, no ~/.claude, no neighbouring projects. Outbound traffic runs through a proxy that allows api.anthropic.com and answers everything else with 403. nightshift-run.sh refuses to start when it finds neither container nor sandbox profile and ends with exit code 3; NIGHTSHIFT_ALLOW_UNSANDBOXED=1 is the deliberate way out. It measures the state rather than asking for it: the container by /.dockerenv, /run/.containerenv, /proc/1/cgroup or an overlay root, the profile by a probe that fails under it, since the runner can list the project but not /Users. 24x7 has the same container and the same check, with ./24x7-docker.sh, the workspace at /workspace and CLAUDE_24X7_ALLOW_UNSANDBOXED=1 as the opt-out.
The sandbox-exec profile remains the macOS option. It restricts Claude's filesystem writes at the kernel level: Claude can only write to the project directory and /tmp, and rm -rf ~/ fails without the hook having to catch it.
What the profile does not restrict: reads outside the home directory, and network traffic. It denies /Users and /home but re-grants $HOME/.claude and $HOME/.config, and it allows outbound TCP on port 443 to any host. Your other projects' transcripts sit in the first directory, CLI tokens commonly in the second. Anything the run can read, it can also send. Call it a write boundary, not a security boundary. The security policy has the threat model.
The open read access is a concession. A profile listing only the few paths this one used to allow no longer starts any program on current macOS: measured on Darwin 27, sandbox-exec -f nightshift-sandbox.sb /bin/echo hi ends with SIGABRT, because the dyld cache lives outside that list. A profile under which nothing runs protects nobody.
Important: the seatbelt profile is a file, not a state. It only applies when you start with sandbox-exec -f nightshift-sandbox.sb ./nightshift-run.sh, and the runner checks that for itself. NIGHTSHIFT_SANDBOXED is a cross-check, not a switch — a value that disagrees with the measurement ends the run with exit code 3. Setting it grants nothing; a while ago any word in it did. The container path (./nightshift-docker.sh) needs no such discipline and is the same route on Linux and macOS.
A separate script that checks the heartbeat log. If Claude hasn't written a heartbeat in N minutes (default: 10), it acts. Three actions: melden reports and is the default, beenden sends TERM to the run and KILL after a grace period, neustart does that and starts the run again, up to a restart budget. A run that ended on its own is never restarted: the watchdog only restarts what it just terminated itself, and a budget stop looks exactly like a run that ended. What stays uncovered is a busy loop, because a Claude retrying the same failing test keeps writing heartbeats, and a run inside the container, whose heartbeat lands in its own tmpfs.
The watchdog catches crashes (no heartbeat). But what about loops? Claude retries the same failing test 50 times — the heartbeat looks healthy, but no progress is made. The Stop hook now tracks completed steps between checks. If 3 consecutive checks show no new checkmarks in the runbook, a STALL WARNING is injected into Claude's context.
The warning tells Claude to check its error budget and skip the step if allowed. This catches the most expensive failure mode in autonomous runs: burning hours of API credits on a loop that a human would have interrupted after 5 minutes.
Autonomous runs are ephemeral — Claude starts fresh each time. But architecture decisions made in one run should inform the next. If Tuesday's run chose PostgreSQL over SQLite, Wednesday's run should know that.
Both skills now maintain a decisions.md file. Claude reads it at the start of every run and appends relevant decisions at the end. Format: date, decision, reasoning. Append-only, never overwrite. It's not learning — it's structured remembering.
Nightshift: decisions.md in the project root, persists across overnight runs. 24x7: decisions.md in the workspace root, shared across all tasks.
Everything you need to do, in order. Takes about 5 minutes to set up, then Claude runs for hours.
Download nightshift.skill from the latest release and unpack it into Claude's skill directory: unzip nightshift.skill -d ~/.claude/skills/. The file is a ZIP archive and unpacks to ~/.claude/skills/nightshift/. This makes the skill available in Claude Code and Claude.ai. You only do this once.
Open Claude and say something like: "Set up a nightshift run for /my/project — refactor auth module to use JWT tokens". Claude detects the genre (refactoring), asks you to confirm, generates a runbook with concrete steps, validates it against 15 checks, and produces all setup files.
Claude generates a setup package. Copy the files into your project: runbook.md, .claude/settings.json, the shell scripts, and the sandbox profile. Append CLAUDE-nightshift.md to your existing CLAUDE.md.
This is your safety net. Run git add -A && git commit -m "Checkpoint before Nightshift". If anything goes wrong during the run, git checkout . brings you back to exactly this state. Never skip this step.
The default: ./nightshift-docker.sh with an ANTHROPIC_API_KEY in the environment. For background operation on the host (terminal can be closed): ./nightshift-run-bg.sh. The PID lock prevents accidental double starts. The run is measured and stops at 25 USD, adjustable with NIGHTSHIFT_BUDGET_USD.
Look at the git log: git log --oneline -5. Check what changed: git diff HEAD~1. Open runbook.md to see which steps were completed [x]. If something went wrong, git checkout . undoes everything.
Set it up once, then drop tasks as folders whenever you need something done.
Install the skill from the latest release: unzip 24x7.skill -d ~/.claude/skills/. Then tell Claude: "Set up a 24x7 runner at /my/workspace with idle behavior cleanup". Claude generates the workspace structure with runner, watchdog, hooks, container files, and sandbox profile.
Copy the generated files to your workspace, make scripts executable, and start: ./runner-bg.sh. The runner now polls the inbox every 30 seconds. Start the watchdog in a second terminal: ./watchdog.sh
Create a folder in inbox/ with a task.md describing the assignment and optionally a materials/ folder with input files. The runner detects it automatically, moves it to working/, spawns a fresh Claude session, and routes the result to outbox/ or failed/.
Check outbox/your-task/output/ for the deliverables. Read outbox/your-task/log.md for what Claude did. Failed tasks land in failed/ with error information in their log.md.
A single Claude session running for hours suffers from "context rot" — Claude becomes increasingly unreliable as context accumulates and gets compressed. The 24x7 runner avoids this entirely: the bash loop is the daemon (runs forever), Claude is the worker (fresh session per task, exits cleanly). Every task gets Claude at full quality.
Autonomous Claude Code is powerful but not magic. Here's what you need to know before you start.
Both skills run Claude Code in headless mode. Every tool call, every file read, every response consumes API credits. Nightshift counts them: the tokens from the stream-json stream are summed, the dollars estimated from a dated price table, and at the budget Claude's whole process group is stopped with exit code 9. Measured against a real run, the estimate came to 0.25860 USD where Claude reported 0.25863 USD. A model the table does not know costs twice the most expensive known row, and a stream without any usage events yields unbekannt, not a zero. The figure in the receipt is an estimate, the invoice is at console.anthropic.com. 24x7 has the same counter now. Its budget covers the whole daemon run rather than a single task: the counter is handed what is left before each call, so the limit holds across tasks instead of restarting at zero every time. Idle counts against it too, and that is the point, because idle calls Claude rather than sleeping and an empty inbox cost nearly as much as a full one. At the limit the running task moves to failed/ with the reason and the daemon exits 9.
The generated sandbox profile is just a file. You must explicitly start with sandbox-exec -f sandbox.sb ./run.sh. Without it, Claude has full access to your entire user account. The PreToolUse hooks catch two things: a dangerous command text, and a write target outside the project. What passes either way is a write that a Bash command performs, and every read. With the profile active, writes outside the project are blocked; reads and outbound traffic are not. Details in the security policy. On Linux there is no sandbox-exec, see the note below.
Vague steps produce vague results. "Implement auth" can mean anything — Claude will guess, and in headless mode, nobody corrects the guess. Good steps include file paths, function names, or shell commands. The 15-point validation catches the worst offenders, but you should review the runbook before starting. If a runbook needs more than 20 steps, split it into multiple runs.
Without a clean git state, you have no rollback. The runner warns you about uncommitted changes (non-blocking), but it's your responsibility to commit first. git checkout . is your emergency brake — it only works if you committed before the run.
sandbox-exec is macOS-only and deprecated by Apple, which is why Nightshift no longer builds on it. ./nightshift-docker.sh runs the same way on Linux and macOS and is the sharper boundary, because reads and outbound traffic are fenced as well. A dedicated user account remains the weaker fallback without Docker, and it needs NIGHTSHIFT_PROJEKT so the run works in the copy rather than in the original directory, plus NIGHTSHIFT_ALLOW_UNSANDBOXED=1, because permission scoping is not isolation. The README has the steps. 24x7 works the same way, with ./24x7-docker.sh.
Nightshift handles compression with two mechanisms: the SessionStart hook re-injects the plan after /compact, and the Stop hook repeats constraints every 5 steps. This works well for 10–20 step runbooks. For very long tasks (30+ steps), quality degrades even with these mechanisms. Split into multiple runs instead. The 24x7 skill avoids this entirely with fresh sessions per task.
The claude command must be installed and authenticated. These skills generate setups that use claude -p (headless mode).
The runner scripts are bash. The build script is Python and needs version 3.9 or newer. Hooks use jq to parse JSON. All three must be in your PATH. The 24x7 runner additionally needs timeout or gtimeout — macOS ships neither, brew install coreutils provides gtimeout.
For the default Nightshift run, the same on Linux and macOS. The container needs an ANTHROPIC_API_KEY, because it has its own home and does not see an OAuth login on the host. Without Docker: the macOS sandbox-exec option, or the explicit opt-out.
Nightshift commits results to your repo. Without git, there's no rollback. For 24x7, any directory works.