Skip to content
Workflow · AI agents

Overnight agent runs with budgets and a morning report

Queue coding tasks to run unattended, each with a finish-line check, its own worktree and branch, a dollar cap inside a nightly total, and safe retry settings.

Verified install Not agent-tested v1.0.0 MIT updated pythongitbash
Equips
  • 1 1 Rules
  • 1 1 Skills
  • – 0 MCP

Leaving agents running overnight is now common, and so are the two ways it goes wrong. One stuck task burns the whole budget. Or a rate or usage limit leaves a request waiting until morning with nothing done. Claude Code now has the controls for both. --max-budget-usd and --max-turns cap a print-mode run. CLAUDE_CODE_RETRY_WATCHDOG keeps retrying capacity errors, and since 2.1.295 and 2.1.301 it can be told to give up after a set wait or when a usage limit resets too far away.

This loadout turns those controls into a routine. Every task needs a finish line (a command that exits 0), and each runs in its own git worktree and branch. A standard-library runner gives each task the smaller of its budget and what is left of the night's total, sets the retry variables, runs the finish-line check after the agent, and writes a ledger and a morning report with result, cost, turns and commits per branch. It refuses --dangerously-skip-permissions outside a sandbox and never pushes or merges. The verifier drives it with a stub agent that prints Claude Code's documented JSON result.

What's in it

  • One finish-line command per task; no check, no unattended run
  • Worktree and branch per task; nothing pushed, merged or deleted
  • Per-task --max-budget-usd inside a nightly total; queue stops when it runs out
  • Retry watchdog with MAX_WAIT_MS and MAX_USAGE_LIMIT_WAIT_MS, so limits end runs instead of hanging them
  • Morning report per branch with result, cost, turns and commits

You'll need

  • Tools: python3, git, claude
Level 1 · automated

Verification

Verified install

Checked at commit 42646ff · 9 passed, 0 failed, 1 not applicable

CheckResultWhat we found
Listinglisting.yaml matches the schema and declares every file in the folder. Pass
Schema valid; 6 files declared, none missing or extra
  • tested.status: untested (agent tests are separate from Level 1)
Files parseJSON parses; SKILL.md and .mdc front matter is valid YAML with the fields each agent needs; code fences are closed. Pass All 6 files parse; front matter valid
AdaptersCLAUDE.md imports @AGENTS.md, GEMINI.md imports @./AGENTS.md, and both match the generator. Pass
CLAUDE.md and GEMINI.md import AGENTS.md and are up to date
  • CLAUDE.md: matches the generator
  • GEMINI.md: matches the generator
Install pathsEvery file lands where each agent documents it, with no collisions, and the laid-out project is re-discovered correctly. Pass
Correct paths for all 6 agents; layouts re-discovered
  • Claude Code: 5 files, 1 skill in .claude/skills/
  • Codex CLI: 4 files, 1 skill in .agents/skills/
  • Cursor: 4 files, 1 skill in .agents/skills/
  • Gemini CLI: 5 files, 1 skill in .agents/skills/
  • Antigravity CLI: 4 files, 1 skill in .agents/skills/
  • GitHub Copilot: 4 files, 1 skill in .agents/skills/
MCP configmcp.json is structurally valid, converts to each agent's format, declares no literal secrets, and referenced packages exist on npm/PyPI. Not applicable No MCP servers in this loadout
Safety scanThe intake scanner finds no credentials, risky shell, hidden Unicode, instructions hidden in HTML comments or after long blank padding, or prompt-injection and covert wording (such as telling the agent to keep something from you), and the listing's network flag is honest. Pass
Clean: no credentials, risky shell, hidden text or covert instructions
  • Scanner intake-precheck/2: verdict clean; network no (listing says yes)
ReferencesLinks and file paths between the loadout's files resolve, including for each agent's installed layout. Pass 2 references between files resolve for every agent
Size limitsFile count and sizes are within the submission limits; SKILL.md bodies stay under 500 lines. Pass
6 files, 15.1 KB total; largest skills/night-shift/scripts/night_shift.py 8.6 KB
  • Limits: 30 files, 32 KB per file, 128 KB total, 500 lines per skill or rule
LicenceA recognised SPDX licence, with the licence text available. Pass MIT, by SetupBay; text in the repository LICENSE
Starter buildA minimal fixture project with the loadout applied installs and builds or type-checks, and the loadout's own code examples compile. Pass
The night-shift runner drives a stub Claude Code that prints the documented JSON result: one task fixes a bug on its own branch and passes its finish line, one hits its budget and is reported as not reached, and the third is refused because the night's total is spent. Each run got its own worktree,
  • Applied 9 loadout files at every agent's paths
  • ✓ set up a repo: bash -c cp -r project repo && cd repo && git init -q -b main && git config user.email fixture@example.com && git config user.name fixture && git add -A && git commit -qm base && echo ready
  • ✓ refuses a plan that bypasses permission checks: bash -c cd repo && sed 's/"acceptEdits"/"bypassPermissions"/' night-shift.json > /tmp/bad-plan.json && python3 ../.agents/skills/night-shift/scripts/night_shift.py run --plan /tmp/bad-plan.json; echo "exit=$?"
  • ✓ run the queue: bash -c cd repo && export STUB_LOG=$PWD/../stub.log PATH="$PWD/../bin:$PATH" && python3 ../.agents/skills/night-shift/scripts/night_shift.py run; echo "exit=$?"
  • ✓ each run got its budget, the watchdog settings and its own branch: bash -c cat stub.log
  • ✓ morning report and a clean main tree: bash -c cd repo && cat .night-shift/report.md && git status --porcelain | wc -l && git log --oneline main | wc -l && git log --oneline main..night/$(date +%F)-fix-week-start && git remote | wc -l
  • Covers: Per-task --max-budget-usd capped by what is left of the nightly total; the queue stops before a task that can't get $0.50
  • Covers: CLAUDE_CODE_RETRY_WATCHDOG, _MAX_WAIT_MS and _MAX_USAGE_LIMIT_WAIT_MS set for every run
  • Covers: Worktree and night/<date>-<task> branch per task; the main tree stays clean and nothing is pushed
  • Covers: Claude Code's JSON result (subtype, num_turns, total_cost_usd) read into the ledger and report
  • Covers: Not covered: a real Claude Code session (the stub prints the documented output shape)

What this means: a script checked the files themselves: they parse, they install where each agent looks, any MCP config is sound, the safety scan is clean, references between files resolve, and, where a free and repeatable fixture exists, a small starter project builds with the loadout applied. No AI agent was run. Per-agent results from agent runs are separate and stay untested until an agent actually runs.

Install

Choose your agent. Run the commands from your project root, or download a zip already laid out in the right folders.

Claude Code reads CLAUDE.md (imports AGENTS.md with @AGENTS.md) and skills from .claude/skills/.

Download zip
curl -fsSL --create-dirs -o AGENTS.md https://setupbay.com/raw/overnight-agent-runs/1.0.0/AGENTS.md
curl -fsSL --create-dirs -o CLAUDE.md https://setupbay.com/raw/overnight-agent-runs/1.0.0/CLAUDE.md
curl -fsSL --create-dirs -o .claude/skills/night-shift/SKILL.md https://setupbay.com/raw/overnight-agent-runs/1.0.0/skills/night-shift/SKILL.md
curl -fsSL --create-dirs -o .claude/skills/night-shift/scripts/night_shift.py https://setupbay.com/raw/overnight-agent-runs/1.0.0/skills/night-shift/scripts/night_shift.py
curl -fsSL --create-dirs -o .claude/skills/night-shift/references/night-shift.example.json https://setupbay.com/raw/overnight-agent-runs/1.0.0/skills/night-shift/references/night-shift.example.json
FileGoes to
AGENTS.mdAGENTS.md
CLAUDE.mdCLAUDE.md
skills/night-shift/SKILL.md.claude/skills/night-shift/SKILL.md
skills/night-shift/scripts/night_shift.py.claude/skills/night-shift/scripts/night_shift.py
skills/night-shift/references/night-shift.example.json.claude/skills/night-shift/references/night-shift.example.json

Already have an AGENTS.md or CLAUDE.md? The commands above overwrite it — download the file instead and merge the sections you want.

Files

Rules AGENTS.md Rules for any unattended agent task. 22 lines
Download Raw
# AGENTS.md: unattended overnight agent runs

Agents in this repo may run unattended (headless, overnight, in CI). Unattended work follows these rules, because
nobody is there to stop a loop or answer a question.

## Every unattended task
- Has a **finish line**: one command that exits 0 when the task is done. Run it yourself before you stop.
- Runs in its **own git worktree on its own branch** (`night/<date>-<task>`), never in the main working tree.
- Has a **dollar cap** (`--max-budget-usd`) and a **turn cap** (`--max-turns`), inside a total for the night.
- Commits its work to its branch, then ends with one line: done, or what is blocking.

## Never, when unattended
- Push, merge, open or close pull requests, delete branches, or touch other worktrees.
- Edit, skip or delete tests to reach a finish line.
- Change budgets, permissions, CI config or settings files.
- Use secrets, production systems or paid services the task did not name.
- Wait for a human: if a decision is needed, commit what you have and say what the decision is.

## Running a batch
Use the `night-shift` skill: it creates the worktrees, sets the budgets and Claude Code's unattended retry settings,
runs each task, checks its finish line, and writes `.night-shift/report.md`. A human reviews every branch before merging.
Adapter CLAUDE.md Imports AGENTS.md for Claude Code. 11 lines
Download Raw
# CLAUDE.md

@AGENTS.md

## Claude Code notes

- Skills from this loadout live in `.claude/skills/`: `night-shift`. Use them when their description matches the task.
- Follow AGENTS.md above; where this file and AGENTS.md disagree, AGENTS.md wins.

<!-- From SetupBay "Overnight agent runs with budgets and a morning report" v1.0.0 — https://setupbay.com/loadouts/overnight-agent-runs/ -->
Adapter GEMINI.md Imports AGENTS.md for Gemini CLI. 11 lines
Download Raw
# GEMINI.md

@./AGENTS.md

## Gemini CLI notes

- Skills from this loadout live in `.agents/skills/`: `night-shift`. Use them when their description matches the task.
- Follow AGENTS.md above; where this file and AGENTS.md disagree, AGENTS.md wins.

<!-- From SetupBay "Overnight agent runs with budgets and a morning report" v1.0.0 — https://setupbay.com/loadouts/overnight-agent-runs/ -->
Skill skills/night-shift/SKILL.md Plan, run and review an overnight batch. 55 lines
Download Raw
---
name: night-shift
description: Queue coding tasks to run unattended overnight, each in its own git worktree with a dollar cap and a finish-line check, then read the morning report. Use when the user wants agents to work while they sleep, run a batch of tasks unattended, or asks what the overnight run did.
---

# Night shift

Unattended runs fail in two expensive ways: one stuck task eats the whole budget, or a usage limit leaves a request
hanging until morning with nothing to show. This skill gives every task a **finish line** (a command that exits 0
when it is done), its own worktree and branch, its own dollar cap inside a total for the night, and Claude Code's
unattended retry settings. Nothing is pushed or merged; the human reviews branches in the morning.

## 1. Write the plan with the human
Copy `references/night-shift.example.json` to `night-shift.json` at the repo root and fill it in together:
- **One task = one finish line.** "Make `pytest -q tests/test_dates.py` pass" is a task. "Improve the codebase" is not.
  If you cannot name the check command, the task is not ready for an unattended run.
- `budget_usd` per task and `budget_usd_total` for the night. The script never lets a task start with less than
  $0.50 left and passes Claude Code the smaller of the task budget and what is left as `--max-budget-usd`.
- Permissions: headless runs cannot answer prompts, so anything not allowed is refused. Allow only what the tasks
  need (`--allowedTools "Bash(pytest *)"`, `--permission-mode acceptEdits`). Never bypass permission checks
  (bypassPermissions mode or the "dangerously" flag) outside a container or VM; the script refuses both unless
  `NIGHT_SHIFT_SANDBOXED=1`.
- Keep `--max-turns` (it ends a run that loops) and `--output-format json` (the script reads the cost from it).

## 2. Start it
```bash
python3 .agents/skills/night-shift/scripts/night_shift.py run
```
(Claude Code installs the skill under `.claude/skills/`.) The main working tree must be committed first: each task
branches from `HEAD`. The script sets these unless they are already set:

| Variable | Value | Why |
|---|---|---|
| `CLAUDE_CODE_RETRY_WATCHDOG` | `1` | keep retrying 429 and 529 errors instead of failing the task |
| `CLAUDE_CODE_RETRY_WATCHDOG_MAX_WAIT_MS` | `1800000` | but end one request after 30 minutes of waiting (v2.1.295+) |
| `CLAUDE_CODE_RETRY_WATCHDOG_MAX_USAGE_LIMIT_WAIT_MS` | `3600000` | end a request whose usage limit resets more than an hour away (v2.1.301+) |

The watchdog already fails at once on spend-limit and out-of-credits errors (v2.1.239+), so a hard limit stops the run.
For Codex, use `codex exec --json` as the agent and keep the budget in the spend-cap guard from the
`agent-spend-cap` loadout; Codex has no budget flag.

## 3. Read the morning report
`.night-shift/report.md` has one row per task: finish line, result, cost, turns, commits, branch, and the agent's last
line. `python3 .../night_shift.py report` rewrites it from `.night-shift/ledger.jsonl`. Then:
- For a passed task: review the diff (`git log -p main..night/<date>-<task>`), run the full suite, and only then merge.
  A passed finish line is not a review.
- For a task that did not reach the finish line: read its last note and the commits. Make the task smaller or the
  check clearer before queueing it again. Do not just raise the budget.
- Remove finished worktrees: `git worktree remove .night-shift/worktrees/<task>`.

## Never
- Push, merge, open PRs or delete branches from an unattended run.
- Queue tasks that need secrets, production access, or a human decision halfway through.
- Edit the plan's budget upwards during the night.
Skill file skills/night-shift/scripts/night_shift.py Worktree-per-task runner with budgets, checks and a report. 183 lines
Download Raw
#!/usr/bin/env python3
"""Run a queue of agent tasks unattended: one git worktree and branch per task, a per-task and total
dollar budget, Claude Code's unattended retry settings, a finish-line check, and a morning report.

Usage:
  python3 night_shift.py run [--plan night-shift.json]   run every task in the plan, in order
  python3 night_shift.py report                           rewrite .night-shift/report.md from the ledger

Plan (night-shift.json):
  {
    "budget_usd_total": 6.00,
    "agent": ["claude", "-p", "--output-format", "json", "--max-turns", "40", "--permission-mode", "acceptEdits"],
    "tasks": [ {"id": "fix-flaky-date-test", "goal": "...", "check": "pytest -q tests/test_dates.py", "budget_usd": 2.00} ]
  }
The script appends --max-budget-usd (the smaller of the task budget and what is left) and the prompt.
Results go to .night-shift/ledger.jsonl and .night-shift/report.md. Branches are named night/<date>-<id>.
It never pushes, merges or deletes a branch. Exit 0 when every task ran, 3 when the budget stopped the queue.
Standard library only.
"""
import datetime
import json
import os
import subprocess
import sys

STATE = ".night-shift"
WATCHDOG_DEFAULTS = {
    "CLAUDE_CODE_RETRY_WATCHDOG": "1",                            # keep retrying 429/529 instead of failing at 3 a.m.
    "CLAUDE_CODE_RETRY_WATCHDOG_MAX_WAIT_MS": "1800000",          # but give up on one request after 30 minutes of waits
    "CLAUDE_CODE_RETRY_WATCHDOG_MAX_USAGE_LIMIT_WAIT_MS": "3600000",  # and end it if the usage limit resets more than 1 h away
}
MIN_TASK_USD = 0.50


def sh(cmd, cwd=None, timeout=None, env=None):
    return subprocess.run(cmd, cwd=cwd, capture_output=True, text=True, timeout=timeout, env=env)


def die(msg, code=1):
    print(f"night-shift: {msg}", file=sys.stderr)
    sys.exit(code)


def load_plan(path):
    try:
        plan = json.load(open(path))
    except (OSError, ValueError) as e:
        die(f"cannot read {path}: {e}")
    agent = plan.get("agent") or []
    if not agent:
        die("plan has no agent command")
    bypass = any(a.startswith("--dangerously") for a in agent) or "bypassPermissions" in agent
    if bypass and os.environ.get("NIGHT_SHIFT_SANDBOXED") != "1":
        die("refusing to run with permission checks bypassed outside a sandbox (set NIGHT_SHIFT_SANDBOXED=1 only inside a container or VM)")
    if "--max-budget-usd" in agent:
        die("leave --max-budget-usd out of the agent command; the script sets it per task from the budget")
    ids = [t.get("id", "") for t in plan.get("tasks", [])]
    if not ids or any(not i or not i.replace("-", "").isalnum() for i in ids) or len(set(ids)) != len(ids):
        die("every task needs a unique id made of letters, digits and hyphens")
    for t in plan["tasks"]:
        if not t.get("goal") or not t.get("check"):
            die(f"task {t['id']} needs a goal and a check command (the finish line)")
    return plan


def spent_tonight(ledger, night):
    return sum(r.get("cost_usd", 0) for r in ledger if r.get("night") == night)


def read_ledger():
    p = os.path.join(STATE, "ledger.jsonl")
    return [json.loads(l) for l in open(p)] if os.path.exists(p) else []


def prompt_for(task, branch):
    return (
        f"{task['goal']}\n\n"
        f"Finish line: `{task['check']}` exits 0 in this worktree. Run it yourself before you stop.\n"
        f"You are on branch {branch} in your own worktree. Commit your work to this branch with a clear message.\n"
        "Do not push, open pull requests, merge, or change files outside this worktree. Do not edit or skip tests to reach the finish line.\n"
        "If you cannot reach the finish line, commit what you have, then end with a short note: what is blocking, what you tried."
    )


def run(plan_path):
    plan = load_plan(plan_path)
    if sh(["git", "rev-parse", "--is-inside-work-tree"]).returncode != 0:
        die("run this from the root of a git repository")
    os.makedirs(os.path.join(STATE, "worktrees"), exist_ok=True)
    exclude = sh(["git", "rev-parse", "--git-path", "info/exclude"]).stdout.strip()
    if exclude and f"/{STATE}/" not in (open(exclude).read() if os.path.exists(exclude) else ""):
        os.makedirs(os.path.dirname(exclude), exist_ok=True)
        with open(exclude, "a") as fh:
            fh.write(f"\n/{STATE}/\n")  # keep worktrees and the ledger out of git status
    night = datetime.date.today().isoformat()
    total = float(plan.get("budget_usd_total", 0))
    ledger_path = os.path.join(STATE, "ledger.jsonl")
    stopped = False
    env = dict(os.environ)
    for k, v in WATCHDOG_DEFAULTS.items():
        env.setdefault(k, v)
    for task in plan["tasks"]:
        left = round(total - spent_tonight(read_ledger(), night), 4)
        budget = round(min(float(task.get("budget_usd", left)), left), 2)
        if budget < MIN_TASK_USD:
            print(f"STOP before {task['id']}: ${left:.2f} left of ${total:.2f} tonight")
            stopped = True
            break
        branch = f"night/{night}-{task['id']}"
        wt = os.path.join(STATE, "worktrees", task["id"])
        if os.path.exists(wt):
            die(f"{wt} already exists; review and remove it (git worktree remove) before re-running {task['id']}")
        r = sh(["git", "worktree", "add", "-q", "-b", branch, wt])
        if r.returncode != 0:
            die(f"git worktree add failed for {task['id']}: {r.stderr.strip()}")
        cmd = [*plan["agent"], "--max-budget-usd", f"{budget:.2f}", prompt_for(task, branch)]
        print(f"run {task['id']}: budget ${budget:.2f} (left ${left:.2f}), branch {branch}")
        started = datetime.datetime.now()
        try:
            a = sh(cmd, cwd=wt, timeout=int(task.get("timeout_min", 90)) * 60, env=env)
            out, code = a.stdout, a.returncode
        except subprocess.TimeoutExpired:
            out, code = "", "timeout"
        try:
            res = json.loads(out.strip().splitlines()[-1]) if out.strip() else {}
        except ValueError:
            res = {}
        cost = float(res.get("total_cost_usd") or 0)
        chk = sh(["bash", "-c", task["check"]], cwd=wt, timeout=1800)
        ahead = sh(["git", "rev-list", "--count", f"HEAD..{branch}"]).stdout.strip() or "0"
        row = {
            "night": night, "task": task["id"], "branch": branch, "agent_exit": code,
            "subtype": res.get("subtype", "no-json"), "turns": res.get("num_turns"), "cost_usd": round(cost, 4),
            "check": task["check"], "check_ok": chk.returncode == 0, "commits": int(ahead),
            "minutes": round((datetime.datetime.now() - started).total_seconds() / 60, 1),
            "note": (res.get("result") or "").strip().splitlines()[-1][:200] if res.get("result") else "",
        }
        with open(ledger_path, "a") as fh:
            fh.write(json.dumps(row) + "\n")
        print(f"  {task['id']}: {'PASS' if row['check_ok'] else 'FAIL'} check, {row['subtype']}, ${cost:.4f}, {row['commits']} commit(s)")
    write_report()
    return 3 if stopped else 0


def write_report():
    ledger = read_ledger()
    if not ledger:
        die("no runs in the ledger yet")
    night = ledger[-1]["night"]
    rows = [r for r in ledger if r["night"] == night]
    lines = [f"# Night shift {night}", "", "| Task | Finish line | Result | Cost | Turns | Commits | Branch |", "|---|---|---|---|---|---|---|"]
    for r in rows:
        result = "passed" if r["check_ok"] else "not reached"
        if r["subtype"] not in ("success",):
            result += f" ({r['subtype']})"
        lines.append(f"| {r['task']} | `{r['check']}` | {result} | ${r['cost_usd']:.2f} | {r['turns'] if r['turns'] is not None else '-'} | {r['commits']} | `{r['branch']}` |")
    spent = sum(r["cost_usd"] for r in rows)
    passed = sum(1 for r in rows if r["check_ok"])
    lines += ["", f"Spent ${spent:.2f} on {len(rows)} task(s); {passed} reached the finish line.", ""]
    for r in rows:
        if r["note"]:
            lines.append(f"- {r['task']}: {r['note']}")
    lines += ["", "Review each branch (`git log -p main..<branch>`) before merging. Nothing was pushed.",
              "Remove a worktree when done with it: `git worktree remove .night-shift/worktrees/<task>`."]
    with open(os.path.join(STATE, "report.md"), "w") as fh:
        fh.write("\n".join(lines) + "\n")
    print("\n".join(lines[:4 + len(rows) + 2]))


def main(argv):
    if not argv or argv[0] not in ("run", "report"):
        print(__doc__.strip(), file=sys.stderr)
        return 2
    if argv[0] == "report":
        write_report()
        return 0
    plan = argv[argv.index("--plan") + 1] if "--plan" in argv else "night-shift.json"
    return run(plan)


if __name__ == "__main__":
    sys.exit(main(sys.argv[1:]))
Skill file skills/night-shift/references/night-shift.example.json Example plan with three tasks. 26 lines
Download Raw
{
  "budget_usd_total": 6.00,
  "agent": ["claude", "-p", "--output-format", "json", "--max-turns", "40", "--permission-mode", "acceptEdits", "--allowedTools", "Bash(pytest *)", "Bash(git add *)", "Bash(git commit *)"],
  "tasks": [
    {
      "id": "fix-flaky-date-test",
      "goal": "tests/test_dates.py::test_week_start fails on Sundays. Find the cause in src/dates.py and fix it.",
      "check": "pytest -q tests/test_dates.py",
      "budget_usd": 2.00,
      "timeout_min": 60
    },
    {
      "id": "csv-export-header",
      "goal": "The CSV export in src/export.py has no header row. Add one, matching the column names in docs/export.md.",
      "check": "pytest -q tests/test_export.py",
      "budget_usd": 1.50
    },
    {
      "id": "type-errors-billing",
      "goal": "Make mypy pass for src/billing/ without adding type: ignore comments.",
      "check": "mypy src/billing",
      "budget_usd": 2.50
    }
  ]
}

All files: source zip · Licence MIT · By SetupBay · First listed

Installing and checks

How do I install Overnight agent runs with budgets and a morning report in Claude Code?

From your project root, put AGENTS.md, CLAUDE.md, skills/night-shift/SKILL.md at .claude/skills/night-shift/SKILL.md, skills/night-shift/scripts/night_shift.py at .claude/skills/night-shift/scripts/night_shift.py, skills/night-shift/references/night-shift.example.json at .claude/skills/night-shift/references/night-shift.example.json. The "Claude Code" tab on this page has the curl commands, or download https://setupbay.com/download/overnight-agent-runs/claude-code.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.

How do I install Overnight agent runs with budgets and a morning report in Codex CLI?

From your project root, put AGENTS.md, skills/night-shift/SKILL.md at .agents/skills/night-shift/SKILL.md, skills/night-shift/scripts/night_shift.py at .agents/skills/night-shift/scripts/night_shift.py, skills/night-shift/references/night-shift.example.json at .agents/skills/night-shift/references/night-shift.example.json. The "Codex CLI" tab on this page has the curl commands, or download https://setupbay.com/download/overnight-agent-runs/codex.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.

How do I install Overnight agent runs with budgets and a morning report in Cursor?

From your project root, put AGENTS.md, skills/night-shift/SKILL.md at .agents/skills/night-shift/SKILL.md, skills/night-shift/scripts/night_shift.py at .agents/skills/night-shift/scripts/night_shift.py, skills/night-shift/references/night-shift.example.json at .agents/skills/night-shift/references/night-shift.example.json. The "Cursor" tab on this page has the curl commands, or download https://setupbay.com/download/overnight-agent-runs/cursor.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.

How do I install Overnight agent runs with budgets and a morning report in Gemini CLI?

From your project root, put AGENTS.md, GEMINI.md, skills/night-shift/SKILL.md at .agents/skills/night-shift/SKILL.md, skills/night-shift/scripts/night_shift.py at .agents/skills/night-shift/scripts/night_shift.py, skills/night-shift/references/night-shift.example.json at .agents/skills/night-shift/references/night-shift.example.json. The "Gemini CLI" tab on this page has the curl commands, or download https://setupbay.com/download/overnight-agent-runs/gemini-cli.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.

How do I install Overnight agent runs with budgets and a morning report in Antigravity CLI?

From your project root, put AGENTS.md, skills/night-shift/SKILL.md at .agents/skills/night-shift/SKILL.md, skills/night-shift/scripts/night_shift.py at .agents/skills/night-shift/scripts/night_shift.py, skills/night-shift/references/night-shift.example.json at .agents/skills/night-shift/references/night-shift.example.json. The "Antigravity CLI" tab on this page has the curl commands, or download https://setupbay.com/download/overnight-agent-runs/antigravity-cli.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.

How do I install Overnight agent runs with budgets and a morning report in GitHub Copilot?

From your project root, put AGENTS.md, skills/night-shift/SKILL.md at .agents/skills/night-shift/SKILL.md, skills/night-shift/scripts/night_shift.py at .agents/skills/night-shift/scripts/night_shift.py, skills/night-shift/references/night-shift.example.json at .agents/skills/night-shift/references/night-shift.example.json. The "GitHub Copilot" tab on this page has the curl commands, or download https://setupbay.com/download/overnight-agent-runs/copilot.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.

What has been checked in Overnight agent runs with budgets and a morning report?

It passed the Level 1 automated install checks on 2026-10-24: the files parse, install to each agent's documented paths, and pass the safety scan. No AI agent has run it yet, so no agent pass or fail is claimed.

More for Claude Code, Codex, Cursor, Gemini CLI, Antigravity CLI and GitHub Copilot.