Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 34 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ This repo holds the runner and its config — nothing else. No dependencies, no
## Requirements

- [Claude Code](https://docs.claude.com/en/docs/claude-code) CLI, logged in.
- [pnpm](https://pnpm.io) — used only as a task runner here (`pnpm plan`, `pnpm overnight`), no actual dependencies to install.
- [pnpm](https://pnpm.io) — used only as a task runner here (`pnpm nightlight`, `pnpm plan`, `pnpm overnight`), no actual dependencies to install.
- Git, GitHub CLI (`gh`) authenticated for the target repo.
- [`jq`](https://jqlang.org) — formats the live session output (see Usage below). Install instructions for every platform: [jqlang.org/download](https://jqlang.org/download).
- A target repo with a `TASKS.md` at its root (see format below) and a `CLAUDE.md` with your test command and conventions.
Expand All @@ -41,7 +41,32 @@ This `.env` only ever holds `PROJECT_REPOS_DIR` — a path, not a secret — and
3. Edit `CLAUDE.md` here if you want to change the workflow rules (branching scheme, quality gates, how research tasks work, etc.) — the defaults are a reasonable starting point.
4. Edit `.claude/settings.json` to match your actual test/lint/build commands (defaults assume npm/pnpm).
5. In each target repo, add a `TASKS.md` with your work queue and confirm `CLAUDE.md` has a test command and conventions documented. That's the only setup required in the target repo itself.
6. `chmod +x overnight.sh plan.sh discover.sh stats.sh`. No `pnpm install` needed — `package.json` has no dependencies, it's just script aliases.
6. `chmod +x overnight.sh plan.sh discover.sh nightlight.sh stats.sh`. No `pnpm install` needed — `package.json` has no dependencies, it's just script aliases.

## nightlight.sh

The whole pipeline in one command — chains `discover.sh` → `plan.sh` → `overnight.sh`:

```bash
./nightlight.sh some-repo # single repo, start to finish
./nightlight.sh # every repo under PROJECT_REPOS_DIR, start to finish
```

It's a thin orchestrator, not a fourth workflow: each phase is the exact same script described below, run in sequence, with no new approval logic of its own — discover's and plan's own interactive approval gates still apply exactly as if you'd run them by hand. The one thing `nightlight.sh` adds is a pause between planning and execution:

```
Discover and plan are done. Start the overnight run now? [y/N]
```

Discover and plan never write or merge anything without your approval inside those sessions, so chaining them costs nothing extra. `overnight.sh` is different — unattended, potentially hours, real cost — so this is the one point where a chained command should make you deliberately opt in rather than sliding straight into an unattended run. Answering no exits cleanly with a reminder of the equivalent `./overnight.sh` command; nothing is lost, you can run it whenever you're ready.

Every flag is supported and routed to whichever phase actually understands it — `--scan` goes to `discover.sh` only, and `overnight.sh`'s own flags (`--stop-after`, `--limit`, `--stack`, `--extra-instructions`, `--override-prompt`, see `### Limiting a run` below) are forwarded to the `overnight.sh` call verbatim, unvalidated by `nightlight.sh` itself — `overnight.sh` is the one source of truth for what each flag means and requires (e.g. its own single-repo rule for everything but `--limit`):

```bash
./nightlight.sh some-repo --scan --stop-after 27
```

Or via `package.json`: `pnpm nightlight [repo] [--scan] [overnight flags]`.

## discover.sh

Expand Down Expand Up @@ -100,10 +125,11 @@ Skills live in a named folder with a `SKILL.md` inside (not a flat `.md` file di
## Scripts

```bash
pnpm discover [repo] [--scan] # ./discover.sh [repo] [--scan]
pnpm plan [repo] # ./plan.sh [repo]
pnpm overnight some-repo # ./overnight.sh some-repo
pnpm stats [some-repo] # ./stats.sh [some-repo]
pnpm nightlight [repo] [--scan] [overnight flags] # ./nightlight.sh [repo] [--scan] [overnight flags]
pnpm discover [repo] [--scan] # ./discover.sh [repo] [--scan]
pnpm plan [repo] # ./plan.sh [repo]
pnpm overnight some-repo # ./overnight.sh some-repo
pnpm stats [some-repo] # ./stats.sh [some-repo]
```

Thin `package.json` wrappers around the shell scripts — no dependencies, nothing to `pnpm install`. Args pass straight through to the script (pnpm doesn't need a `--` separator the way npm does), so `pnpm plan some-repo` and `./plan.sh some-repo` are identical. Use whichever reads better; the rest of this README uses the raw `./script.sh` form since it's unambiguous about what's actually running.
Expand All @@ -123,6 +149,8 @@ Thin `package.json` wrappers around the shell scripts — no dependencies, nothi

`discover.sh`/`plan.sh` with no repo run across every repo under `PROJECT_REPOS_DIR` (see `## discover.sh` / `## plan.sh` above) — but they're still two separate commands, run whenever you want; discover doesn't automatically feed into plan. Since discover's Finalize now merges its own PR (see Safety model below), running `plan` any time after `discover` already sees whatever discover found, with no manual merge step in between.

`./nightlight.sh some-repo` (see `## nightlight.sh` above) is the equivalent of the three commands above, chained into one, with a confirmation pause before the `overnight.sh` step.

`overnight.sh` resolves a bare name against `$PROJECT_REPOS_DIR` (from `.env`) or accepts a full path. Run it inside `tmux` or a terminal window you can leave open — closing the window kills the process. Disable sleep/hibernate for the duration.

Only run one repo at a time per machine (shared usage pool). Chain sequentially if you need more than one: `./overnight.sh repo-a && ./overnight.sh repo-b`.
Expand Down
47 changes: 47 additions & 0 deletions nightlight.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/bin/bash
# usage: pnpm nightlight [repo] [--scan] [overnight flags]
# with repo: chains discover -> plan -> overnight for that one repo
# without: chains discover -> plan -> overnight, each in its own
# no-arg multi-repo mode across PROJECT_REPOS_DIR
#
# --scan is forwarded to discover only.
# --stop-after/--limit/--stack/--extra-instructions/--override-prompt are
# forwarded to overnight only, exactly as overnight.sh itself defines them
# (including its own single-repo requirement for all but --limit) -- see
# overnight.sh's own usage comment for what each does.
set -e
cd "$(dirname "$0")"

REPO=""
SCAN_FLAG=""
OVERNIGHT_FLAGS=()
while [[ $# -gt 0 ]]; do
case "$1" in
--scan) SCAN_FLAG="--scan"; shift ;;
--stop-after|--limit|--stack|--extra-instructions|--override-prompt)
OVERNIGHT_FLAGS+=("$1" "$2"); shift 2 ;;
--*) echo "unknown flag: $1"; exit 1 ;;
*) REPO="$1"; shift ;;
esac
done

REPO_ARGS=(); [[ -n "$REPO" ]] && REPO_ARGS+=("$REPO")
DISCOVER_ARGS=("${REPO_ARGS[@]}"); [[ -n "$SCAN_FLAG" ]] && DISCOVER_ARGS+=("--scan")

echo "=== discover ==="
./discover.sh "${DISCOVER_ARGS[@]}"

echo
echo "=== plan ==="
./plan.sh "${REPO_ARGS[@]}"

echo
read -p "Discover and plan are done. Start the overnight run now? [y/N] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "Skipping the overnight run -- run ./overnight.sh${REPO:+ $REPO} whenever you're ready."
exit 0
fi

echo "=== overnight ==="
./overnight.sh "${REPO_ARGS[@]}" "${OVERNIGHT_FLAGS[@]}"
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"private": true,
"description": "Leave a light on while you sleep. Unattended Claude Code sessions that turn TASKS.md queues into reviewable PRs, with explicit permission allowlists and no unreviewed merges.",
"scripts": {
"nightlight": "bash nightlight.sh",
"plan": "bash plan.sh",
"discover": "bash discover.sh",
"overnight": " bash overnight.sh",
Expand Down