From b3fec78e1df8aa8885c0c939b661241d3a5e95c8 Mon Sep 17 00:00:00 2001 From: Marcus Vorwaller Date: Thu, 9 Apr 2026 03:15:25 -0700 Subject: [PATCH 1/5] docs: backfill CLI and config docs Nightshift-Task: docs-backfill Nightshift-Ref: https://github.com/marcus/nightshift --- README.md | 67 +++++++++--- website/docs/cli-reference.md | 183 ++++++++++++++++++++++++-------- website/docs/configuration.md | 164 ++++++++++++++++++++++++---- website/docs/installation.md | 40 ++++++- website/docs/integrations.md | 48 ++++++++- website/docs/scheduling.md | 49 +++++++-- website/docs/troubleshooting.md | 25 +++-- 7 files changed, 473 insertions(+), 103 deletions(-) diff --git a/README.md b/README.md index 84f92cd..7384513 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ ![Nightshift logo](logo.png) -Your tokens get reset every week, you might as well use them. Nightshift runs overnight to find dead code, doc drift, test gaps, security issues, and 20+ other things silently accumulating while you ship features. Like a Roomba for your codebase — runs overnight, worst case you close the PR. +Your tokens get reset every week, you might as well use them. Nightshift runs overnight to find dead code, doc drift, test gaps, security issues, and 20+ other things silently accumulating while you ship features. Like a Roomba for your codebase - runs overnight, worst case you close the PR. Everything lands as a branch or PR. It never writes directly to your primary branch. Don't like something? Close it. That's the whole rollback plan. @@ -14,7 +14,7 @@ Everything lands as a branch or PR. It never writes directly to your primary bra - **Budget-aware**: Uses remaining daily allotment, never exceeds configurable max (default 75%) - **Multi-project**: Point it at your repos, it already knows what to look for -- **Zero risk**: Everything is a PR — merge what surprises you, close the rest +- **Zero risk**: Everything is a PR - merge what surprises you, close the rest - **Great DX**: Thoughtful CLI defaults with clear output and reports ## Installation @@ -43,7 +43,9 @@ After installing, run the guided setup: nightshift setup ``` -This walks you through provider configuration, project selection, budget calibration, and daemon setup. Once complete you can preview what nightshift will do: +This walks you through provider configuration, project selection, budget calibration, and daemon setup. It covers Claude, Codex, and Copilot. If you want a manual flow instead, use `nightshift init` for a project config or `nightshift init --global` for `~/.config/nightshift/config.yaml`. + +Once complete you can preview what nightshift will do: ```bash nightshift preview @@ -72,6 +74,12 @@ nightshift preview --write ./nightshift-prompts # Guided global setup nightshift setup +# Bootstrap or inspect config +nightshift init +nightshift init --global +nightshift config +nightshift config validate + # Check environment and config health nightshift doctor @@ -95,6 +103,14 @@ nightshift task show lint-fix --prompt-only nightshift task run lint-fix --provider claude nightshift task run skill-groom --provider codex --dry-run nightshift task run lint-fix --provider codex --dry-run + +# Manage the scheduler and service lifecycle +nightshift daemon start +nightshift daemon start --foreground +nightshift daemon status +nightshift daemon stop +nightshift install +nightshift uninstall ``` If `gum` is available, preview output is shown through the gum pager. Use `--plain` to disable. @@ -115,6 +131,8 @@ daemon, CI) confirmation is auto-skipped. | `--max-tasks` | `1` | Max tasks per project (ignored when `--task` is set) | | `--random-task` | `false` | Pick a random task from eligible tasks instead of the highest-scored one | | `--ignore-budget` | `false` | Bypass budget checks (use with caution) | +| `--branch`, `-b` | _(current branch)_ | Base branch for new feature branches | +| `--timeout` | `30m` | Per-agent execution timeout | | `--yes`, `-y` | `false` | Skip the confirmation prompt | ```bash @@ -138,24 +156,30 @@ nightshift run --ignore-budget # Target a specific project and task directly nightshift run -p ./my-project -t lint-fix + +# Base new branches off develop +nightshift run --branch develop + +# Give agents more time +nightshift run --timeout 45m ``` Other useful flags: - `nightshift status --today` to see today's activity summary - `nightshift daemon start --foreground` for debug -- `--category` — filter tasks by category (pr, analysis, options, safe, map, emergency) -- `--cost` — filter by cost tier (low, medium, high, veryhigh) -- `--prompt-only` — output just the raw prompt text for piping -- `--provider` — required for `task run`, choose claude or codex -- `--dry-run` — preview the prompt without executing -- `--timeout` — execution timeout (default 30m) +- `--category` - filter tasks by category (pr, analysis, options, safe, map, emergency) +- `--cost` - filter by cost tier (low, medium, high, veryhigh) +- `--prompt-only` - output just the raw prompt text for piping +- `--provider` - required for `task run`, choose claude, codex, or copilot +- `--dry-run` - preview the prompt without executing +- `--timeout` - execution timeout (default 30m) -## Authentication (Subscriptions) +## Provider Setup Nightshift supports three AI providers: - **Claude Code** - Anthropic's Claude via local CLI -- **Codex** - OpenAI's GPT via local CLI -- **GitHub Copilot** - GitHub's Copilot via GitHub CLI +- **Codex** - OpenAI's Codex via local CLI +- **GitHub Copilot** - GitHub's Copilot via `gh` or the standalone Copilot CLI ### Claude Code @@ -183,7 +207,7 @@ npm install -g @github/copilot curl -fsSL https://gh.io/copilot-install | bash ``` -Requires GitHub Copilot subscription. See [docs/COPILOT_INTEGRATION.md](docs/COPILOT_INTEGRATION.md) for details. +Nightshift will use the standalone `copilot` binary when it exists, otherwise it falls back to `gh copilot`. `nightshift setup` checks for both. See [docs/COPILOT_INTEGRATION.md](docs/COPILOT_INTEGRATION.md) for details. If you prefer API-based usage, you can authenticate Claude and Codex CLIs with API keys instead. @@ -198,7 +222,7 @@ Nightshift uses YAML config files to define: - Task priorities - Schedule preferences -Run `nightshift setup` to create/update the global config at `~/.config/nightshift/config.yaml`. +Use `nightshift setup` for guided onboarding. Use `nightshift init` to create a project config in the current directory, or `nightshift init --global` to create `~/.config/nightshift/config.yaml`. `nightshift config` shows the merged configuration, and `nightshift config validate` checks both the global and project files. See the [full configuration docs](https://nightshift.haplab.com/docs/configuration) or [SPEC.md](docs/SPEC.md) for detailed options. @@ -207,6 +231,8 @@ Minimal example: ```yaml schedule: cron: "0 2 * * *" + max_projects: 1 + max_tasks: 1 budget: mode: daily @@ -220,6 +246,7 @@ providers: preference: - claude - codex + - copilot claude: enabled: true data_path: "~/.claude" @@ -228,12 +255,18 @@ providers: enabled: true data_path: "~/.codex" dangerously_bypass_approvals_and_sandbox: true + copilot: + enabled: true + data_path: "~/.copilot" + dangerously_skip_permissions: false projects: - path: ~/code/sidecar - path: ~/code/td ``` +Default provider order is `claude -> codex -> copilot`. Nightshift uses whichever provider has budget remaining, unless you override the provider or disable one in config. + Task selection: ```yaml @@ -267,9 +300,9 @@ make install-hooks ``` This symlinks `scripts/pre-commit.sh` into `.git/hooks/pre-commit`. The hook runs: -- **gofmt** — flags any staged `.go` files that need formatting -- **go vet** — catches common correctness issues -- **go build** — ensures the project compiles +- **gofmt** - flags any staged `.go` files that need formatting +- **go vet** - catches common correctness issues +- **go build** - ensures the project compiles To bypass in a pinch: `git commit --no-verify` diff --git a/website/docs/cli-reference.md b/website/docs/cli-reference.md index d5a2cd4..1e4e41f 100644 --- a/website/docs/cli-reference.md +++ b/website/docs/cli-reference.md @@ -5,12 +5,14 @@ title: CLI Reference # CLI Reference -## Core Commands +## Top-Level Commands | Command | Description | |---------|-------------| -| `nightshift setup` | Guided global configuration | -| `nightshift run` | Execute scheduled tasks | +| `nightshift setup` | Guided end-to-end onboarding | +| `nightshift init` | Create a global or project config | +| `nightshift config` | Show, edit, or validate config | +| `nightshift run` | Execute configured tasks now | | `nightshift preview` | Show upcoming runs | | `nightshift budget` | Check token budget status | | `nightshift task` | Browse and run tasks | @@ -18,75 +20,172 @@ title: CLI Reference | `nightshift status` | View run history | | `nightshift logs` | Stream or export logs | | `nightshift stats` | Token usage statistics | -| `nightshift daemon` | Background scheduler | +| `nightshift report` | Read run reports | +| `nightshift snapshot` | Capture usage snapshots | +| `nightshift busfactor` | Analyze ownership concentration | +| `nightshift daemon` | Manage the background scheduler | +| `nightshift install` | Install a system service | +| `nightshift uninstall` | Remove an installed service | + +## Bootstrap and Config + +`nightshift setup` walks through provider setup, project selection, budget calibration, and daemon installation. + +```bash +nightshift setup +``` + +`nightshift init` creates `nightshift.yaml` in the current directory by default. Use `--global` to create `~/.config/nightshift/config.yaml`, and `--force` to overwrite an existing file without prompting. + +```bash +nightshift init +nightshift init --global +nightshift init --force +``` + +`nightshift config` shows the merged configuration from global and project files, plus environment overrides. + +```bash +nightshift config +nightshift config get budget.max_percent +nightshift config set budget.max_percent 15 +nightshift config set --global logging.level debug +nightshift config validate +``` + +| Subcommand | Description | +|------------|-------------| +| `config` | Show merged config and source paths | +| `config get KEY` | Read a nested value by key path | +| `config set KEY VALUE` | Update a value; use `--global` to force global config | +| `config validate` | Validate global, project, and merged config | ## Run Options -`nightshift run` shows a preflight summary before executing, then prompts for confirmation in interactive terminals. +`nightshift run` shows a preflight summary, then prompts for confirmation in interactive terminals. Non-TTY contexts skip the prompt automatically. ```bash -nightshift run # Preflight + confirm + execute (1 project, 1 task) -nightshift run --yes # Skip confirmation -nightshift run --dry-run # Show preflight, don't execute -nightshift run --max-projects 3 # Process up to 3 projects -nightshift run --max-tasks 2 # Run up to 2 tasks per project -nightshift run --random-task # Pick a random eligible task -nightshift run --ignore-budget # Bypass budget limits (use with caution) -nightshift run --project ~/code/myapp # Target specific project (ignores --max-projects) -nightshift run --task lint-fix # Run specific task (ignores --max-tasks) +nightshift run # Preflight + confirm + execute +nightshift run --yes # Skip confirmation +nightshift run --dry-run # Show preflight summary and exit +nightshift run --project ~/code/myapp # Target a single project +nightshift run --task lint-fix # Run a specific task +nightshift run --max-projects 3 # Process up to 3 projects +nightshift run --max-tasks 2 # Run up to 2 tasks per project +nightshift run --random-task # Pick a random eligible task +nightshift run --ignore-budget # Bypass budget checks +nightshift run --branch develop # Base new feature branches on develop +nightshift run --timeout 45m # Increase per-agent timeout +nightshift run --no-color # Disable ANSI colors ``` | Flag | Default | Description | |------|---------|-------------| -| `--dry-run` | `false` | Show preflight summary and exit without executing | -| `--yes`, `-y` | `false` | Skip confirmation prompt | -| `--max-projects` | `1` | Max projects to process (ignored when `--project` is set) | -| `--max-tasks` | `1` | Max tasks per project (ignored when `--task` is set) | -| `--random-task` | `false` | Pick a random task from eligible tasks instead of the highest-scored one | +| `--dry-run` | `false` | Show the preflight summary and exit without executing | +| `--yes`, `-y` | `false` | Skip the confirmation prompt | +| `--project`, `-p` | _(all configured)_ | Target a single project directory | +| `--task`, `-t` | _(auto-select)_ | Run a specific task by name | +| `--max-projects` | `1` | Max projects to process when `--project` is not set | +| `--max-tasks` | `1` | Max tasks per project when `--task` is not set | +| `--random-task` | `false` | Pick one random eligible task instead of the highest-scored task | | `--ignore-budget` | `false` | Bypass budget checks with a warning | -| `--project`, `-p` | | Target a specific project directory | -| `--task`, `-t` | | Run a specific task by name | +| `--branch`, `-b` | _(current branch)_ | Base branch for new feature branches | +| `--timeout` | `30m` | Per-agent execution timeout | +| `--no-color` | `false` | Disable colored output | + +`--random-task` and `--task` are mutually exclusive. When `--max-projects` or `--max-tasks` is omitted, Nightshift falls back to the values in `schedule.max_projects` and `schedule.max_tasks`. + +## Daemon and Services + +`nightshift daemon` manages the scheduler loop. + +```bash +nightshift daemon start +nightshift daemon start --foreground +nightshift daemon start --timeout 45m +nightshift daemon status +nightshift daemon stop +``` -Non-interactive contexts (daemon, cron, piped output) skip the confirmation prompt automatically. +| Subcommand | Description | +|------------|-------------| +| `daemon start` | Start the scheduler in the background by default | +| `daemon start --foreground` | Run the scheduler in the current terminal | +| `daemon status` | Show whether the daemon is running | +| `daemon stop` | Stop the running daemon | -## Preview Options +`nightshift install` installs the scheduler as a system service. If you do not pass an init system, Nightshift auto-detects one from the current platform. + +```bash +nightshift install +nightshift install launchd +nightshift install systemd +nightshift install cron +nightshift uninstall +``` + +## Preview ```bash nightshift preview # Default view nightshift preview -n 3 # Next 3 runs -nightshift preview --long # Detailed view -nightshift preview --explain # With prompt previews -nightshift preview --plain # No pager +nightshift preview --long # Detailed prompts +nightshift preview --explain # Budget and cooldown explanations +nightshift preview --plain # Disable pager output nightshift preview --json # JSON output -nightshift preview --write ./dir # Write prompts to files +nightshift preview --write ./dir # Write prompts to files +``` + +## Budget + +Budget commands accept `--provider` values of `claude`, `codex`, or `copilot`. + +```bash +nightshift budget +nightshift budget --provider claude +nightshift budget --provider copilot +nightshift budget snapshot --local-only +nightshift budget snapshot --provider codex +nightshift budget history -n 10 +nightshift budget calibrate ``` -## Task Commands +| Command | Notes | +|---------|-------| +| `budget` | Show current budget status | +| `budget snapshot` | Capture a usage snapshot for calibration | +| `budget history` | Show recent snapshots | +| `budget calibrate` | Show inferred calibration status | + +## Tasks + +Task commands also accept `--provider` values of `claude`, `codex`, or `copilot` when running tasks. ```bash -nightshift task list # All tasks +nightshift task list nightshift task list --category pr nightshift task list --cost low --json nightshift task show lint-fix nightshift task show lint-fix --prompt-only nightshift task run lint-fix --provider claude -nightshift task run lint-fix --provider codex --dry-run +nightshift task run lint-fix --provider copilot --dry-run ``` -## Budget Commands +## Reports and Diagnostics ```bash -nightshift budget # Current status -nightshift budget --provider claude -nightshift budget snapshot --local-only -nightshift budget history -n 10 -nightshift budget calibrate +nightshift status --today +nightshift logs --follow +nightshift stats +nightshift report --period last-night +nightshift snapshot --provider claude +nightshift busfactor . +nightshift doctor ``` -## Global Flags +## Shared Flags + +| Flag | Scope | Description | +|------|-------|-------------| +| `--verbose` | Root command | Verbose output | -| Flag | Description | -|------|-------------| -| `--verbose` | Verbose output | -| `--provider` | Select provider (claude, codex) | -| `--timeout` | Execution timeout (default 30m) | diff --git a/website/docs/configuration.md b/website/docs/configuration.md index 4a7ee3d..4656a52 100644 --- a/website/docs/configuration.md +++ b/website/docs/configuration.md @@ -5,18 +5,52 @@ title: Configuration # Configuration -Nightshift uses YAML config files. Run `nightshift setup` for an interactive setup, or edit directly. +Nightshift uses YAML config files. Use `nightshift setup` for a guided bootstrap, `nightshift init` to create a config file, or edit the files directly. -## Config Location +## Config Sources -- **Global:** `~/.config/nightshift/config.yaml` -- **Per-project:** `nightshift.yaml` or `.nightshift.yaml` in the repo root +Nightshift reads config in this order: + +1. Global config: `~/.config/nightshift/config.yaml` +2. Project config: `nightshift.yaml` in the current project directory +3. Environment overrides such as `NIGHTSHIFT_BUDGET_MAX_PERCENT` + +Project config values override global config values, and environment variables override both. + +## Config Workflow + +```bash +nightshift init +nightshift init --global +nightshift config +nightshift config get budget.max_percent +nightshift config set budget.max_percent 15 +nightshift config set --global logging.level debug +nightshift config validate +``` + +- `nightshift init` creates `nightshift.yaml` in the current directory. +- `nightshift init --global` creates `~/.config/nightshift/config.yaml`. +- `nightshift config` shows the merged config and the source paths. +- `nightshift config set` writes to the project config when one exists, otherwise to the global config. Use `--global` to force the global file. +- `nightshift config validate` checks the global file, project file, and merged config. + +`nightshift config set` accepts booleans, integers, floats, and strings. For example, `true`, `15`, `12.5`, and `debug` are all parsed correctly. + +## Config Locations + +| Type | Location | +|------|----------| +| Global | `~/.config/nightshift/config.yaml` | +| Project | `nightshift.yaml` | ## Minimal Config ```yaml schedule: cron: "0 2 * * *" + max_projects: 1 + max_tasks: 1 budget: mode: daily @@ -30,6 +64,7 @@ providers: preference: - claude - codex + - copilot claude: enabled: true data_path: "~/.claude" @@ -38,6 +73,10 @@ providers: enabled: true data_path: "~/.codex" dangerously_bypass_approvals_and_sandbox: true + copilot: + enabled: true + data_path: "~/.copilot" + dangerously_skip_permissions: false projects: - path: ~/code/sidecar @@ -46,17 +85,33 @@ projects: ## Schedule -Use cron syntax or interval-based scheduling: +Use either cron or interval scheduling. Nightshift rejects configs that set both. ```yaml schedule: cron: "0 2 * * *" # Every night at 2am # interval: "8h" # Or run every 8 hours + window: + start: "22:00" + end: "06:00" + timezone: "America/Denver" + max_projects: 1 + max_tasks: 1 ``` +| Field | Default | Description | +|-------|---------|-------------| +| `cron` | - | Cron expression for scheduled runs | +| `interval` | - | Duration string for repeated runs | +| `window.start` | `22:00` | Start of the allowed execution window | +| `window.end` | `06:00` | End of the allowed execution window | +| `window.timezone` | local time | Time zone for the window | +| `max_projects` | `1` | Default max projects per run | +| `max_tasks` | `1` | Default max tasks per project | + ## Budget -Control how much of your token budget Nightshift uses: +Control how much of your token budget Nightshift uses. | Field | Default | Description | |-------|---------|-------------| @@ -64,11 +119,50 @@ Control how much of your token budget Nightshift uses: | `max_percent` | `75` | Max budget % to use per run | | `reserve_percent` | `5` | Always keep this % available | | `billing_mode` | `subscription` | `subscription` or `api` | -| `calibrate_enabled` | `true` | Auto-calibrate from local CLI data | +| `calibrate_enabled` | `true` | Enable subscription calibration via snapshots | +| `snapshot_interval` | `30m` | Automatic snapshot cadence | +| `snapshot_retention_days` | `90` | Snapshot retention window | +| `weekly_tokens` | `700000` | Fallback weekly budget | +| `per_provider` | - | Provider-specific weekly budgets | +| `week_start_day` | `monday` | Week boundary for calibration | +| `db_path` | `~/.local/share/nightshift/nightshift.db` | Override database path | +| `aggressive_end_of_week` | `false` | Spend more near the end of the week | + +If `billing_mode: api`, Nightshift uses the explicit token budgets in `weekly_tokens` and `per_provider` instead of calibration. + +## Providers + +Nightshift supports Claude Code, Codex, and GitHub Copilot. It uses the providers listed in `providers.preference` order. + +```yaml +providers: + preference: + - claude + - codex + - copilot + copilot: + enabled: true + data_path: "~/.copilot" +``` + +| Field | Default | Description | +|-------|---------|-------------| +| `providers.preference` | `["claude", "codex", "copilot"]` | Provider priority order | +| `providers.claude.enabled` | `true` | Enable Claude provider | +| `providers.claude.data_path` | `~/.claude` | Claude Code data directory | +| `providers.claude.dangerously_skip_permissions` | `false` | Skip Claude permission prompts | +| `providers.codex.enabled` | `true` | Enable Codex provider | +| `providers.codex.data_path` | `~/.codex` | Codex data directory | +| `providers.codex.dangerously_bypass_approvals_and_sandbox` | `false` | Bypass Codex approvals and sandboxing | +| `providers.copilot.enabled` | `true` | Enable Copilot provider | +| `providers.copilot.data_path` | `~/.copilot` | Copilot request-tracking directory | +| `providers.copilot.dangerously_skip_permissions` | `false` | Allow Copilot to run with broader tool access | + +Copilot tracks request counts, not token usage. Its budget view is an estimate based on monthly request limits. ## Task Selection -Enable/disable tasks and set priorities: +Enable and prioritize built-in tasks, disable specific tasks, or define custom tasks. ```yaml tasks: @@ -82,9 +176,40 @@ tasks: intervals: lint-fix: "24h" docs-backfill: "168h" + custom: + - type: pr-review + name: "PR Review Session" + description: | + Review open PRs and check for regressions. + Create follow-up tasks for anything that needs attention. + category: pr + cost_tier: high + risk_level: medium + interval: "72h" +``` + +- `tasks.enabled` restricts the built-in tasks Nightshift may run. +- `tasks.disabled` explicitly blocks a task even if it is enabled elsewhere. +- `tasks.intervals` overrides cooldowns per task. +- `tasks.custom` defines user-authored tasks. `type`, `name`, and `description` are required. + +## Integrations + +```yaml +integrations: + claude_md: true + agents_md: true + task_sources: + - td: + enabled: true + teach_agent: true ``` -Each task has a default cooldown interval to prevent the same task from running too frequently on a project. +| Field | Default | Description | +|-------|---------|-------------| +| `integrations.claude_md` | `true` | Read `CLAUDE.md` or `claude.md` for context | +| `integrations.agents_md` | `true` | Read `AGENTS.md` for context | +| `integrations.task_sources` | - | External task sources like `td` or GitHub issues | ## Multi-Project Setup @@ -93,25 +218,27 @@ projects: - path: ~/code/project1 priority: 1 # Higher priority = processed first tasks: - - lint - - docs + - lint-fix + - docs-backfill - path: ~/code/project2 priority: 2 - - # Or use glob patterns - pattern: ~/code/oss/* exclude: - ~/code/oss/archived ``` +Each project can point at a path or a glob pattern. Use `exclude` to skip directories that match the pattern. + ## Safe Defaults | Feature | Default | Override | |---------|---------|----------| -| Read-only first run | Yes | `--enable-writes` | -| Max budget per run | 75% | `budget.max_percent` | -| Auto-push to remote | No | Manual only | -| Reserve budget | 5% | `budget.reserve_percent` | +| Confirmation prompt in TTY | Yes | `--yes` | +| Confirmation prompt in non-TTY | Auto-skip | `--yes` or interactive terminal | +| Max projects per run | `1` | `--max-projects` or `schedule.max_projects` | +| Max tasks per project | `1` | `--max-tasks` or `schedule.max_tasks` | +| Max budget per run | `75%` | `budget.max_percent` | +| Reserve budget | `5%` | `budget.reserve_percent` | ## File Locations @@ -125,6 +252,3 @@ projects: If `state/state.json` exists from older versions, Nightshift migrates it to the SQLite database and renames the file to `state.json.migrated`. -## Providers - -Nightshift supports Claude Code and Codex as execution providers. It will use whichever has budget remaining, in the order specified by `preference`. diff --git a/website/docs/installation.md b/website/docs/installation.md index e2b37d2..4457030 100644 --- a/website/docs/installation.md +++ b/website/docs/installation.md @@ -39,16 +39,46 @@ nightshift --version nightshift --help ``` -## Prerequisites +## Provider Prerequisites -- **Claude Code CLI** (`claude`) and/or **Codex CLI** (`codex`) installed -- Authenticated via subscription login or API keys: +Nightshift can use Claude Code, Codex, and GitHub Copilot. Install and authenticate the providers you want to use: + +### Claude Code ```bash -# Claude Code claude /login +``` + +### Codex -# Codex +```bash codex --login ``` + +### GitHub Copilot + +Install either the standalone `copilot` binary or the GitHub CLI: + +```bash +npm install -g @github/copilot +# or +curl -fsSL https://gh.io/copilot-install | bash +``` + +Nightshift prefers the standalone `copilot` binary when it is available and falls back to `gh copilot`. Sign in with your GitHub account before running tasks. + +## Next Step + +Use the guided setup for the fastest path: + +```bash +nightshift setup +``` + +If you prefer to bootstrap manually, create a config first: + +```bash +nightshift init +nightshift init --global +``` diff --git a/website/docs/integrations.md b/website/docs/integrations.md index 96d5e3f..c26ed90 100644 --- a/website/docs/integrations.md +++ b/website/docs/integrations.md @@ -7,7 +7,19 @@ title: Integrations Nightshift integrates with your existing development workflow. -## Claude Code +## AI Providers + +Nightshift supports three execution providers. It uses the first enabled provider in `providers.preference`, which defaults to `claude -> codex -> copilot`. + +```yaml +providers: + preference: + - claude + - codex + - copilot +``` + +### Claude Code Nightshift uses the Claude Code CLI to execute tasks. Authenticate via subscription or API key: @@ -16,7 +28,13 @@ claude /login ``` -## Codex +Relevant config keys: + +- `providers.claude.enabled` +- `providers.claude.data_path` +- `providers.claude.dangerously_skip_permissions` + +### Codex Nightshift supports OpenAI's Codex CLI as an alternative provider: @@ -24,13 +42,37 @@ Nightshift supports OpenAI's Codex CLI as an alternative provider: codex --login ``` +Relevant config keys: + +- `providers.codex.enabled` +- `providers.codex.data_path` +- `providers.codex.dangerously_bypass_approvals_and_sandbox` + +### GitHub Copilot + +Nightshift supports GitHub Copilot through either the standalone `copilot` binary or `gh copilot`. + +```bash +npm install -g @github/copilot +# or +curl -fsSL https://gh.io/copilot-install | bash +``` + +Copilot usage is tracked by request count instead of token usage. Nightshift stores that tracking data under `providers.copilot.data_path` (default: `~/.copilot`). + +Relevant config keys: + +- `providers.copilot.enabled` +- `providers.copilot.data_path` +- `providers.copilot.dangerously_skip_permissions` + ## GitHub All output is PR-based. Nightshift creates branches and pull requests for its findings. ## td (Task Management) -Nightshift can source tasks from [td](https://td.haplab.com) — task management for AI-assisted development. Tasks tagged with `nightshift` in td will be picked up automatically. +Nightshift can source tasks from [td](https://td.haplab.com) - task management for AI-assisted development. Tasks tagged with `nightshift` in td will be picked up automatically. ```yaml integrations: diff --git a/website/docs/scheduling.md b/website/docs/scheduling.md index b552a79..dfaa8b0 100644 --- a/website/docs/scheduling.md +++ b/website/docs/scheduling.md @@ -5,30 +5,53 @@ title: Scheduling # Scheduling -Nightshift can run automatically on a schedule. +Nightshift can run automatically on a schedule or be triggered manually when you want immediate execution. -## Cron-Based +## Schedule Configuration + +Use cron or interval scheduling. Nightshift rejects configs that set both. ```yaml schedule: cron: "0 2 * * *" # Every night at 2am + # interval: "8h" # Or run every 8 hours + window: + start: "22:00" + end: "06:00" + timezone: "America/Denver" + max_projects: 1 + max_tasks: 1 ``` +- `cron` schedules a specific time. +- `interval` repeats runs after a fixed duration. +- `window` restricts execution to a local time range. +- `max_projects` and `max_tasks` provide defaults for scheduled and manual runs when CLI flags are omitted. + +If you want to bootstrap a schedule from scratch, run `nightshift init` or `nightshift setup`, then validate with `nightshift config validate`. + ## Daemon Mode -Run as a persistent background process: +Run Nightshift as a persistent background process: ```bash nightshift daemon start nightshift daemon start --foreground # For debugging +nightshift daemon start --timeout 45m +nightshift daemon status nightshift daemon stop ``` -## System Service +The daemon requires a configured schedule. It writes its PID file to `~/.local/share/nightshift/nightshift.pid` and uses the scheduler loop to launch runs on schedule. -Install as a system service for automatic startup: +## Service Lifecycle + +Install Nightshift as a system service for automatic startup: ```bash +# Auto-detect the init system +nightshift install + # macOS (launchd) nightshift install launchd @@ -37,20 +60,32 @@ nightshift install systemd # Universal (cron) nightshift install cron + +# Remove the installed service +nightshift uninstall ``` +- `nightshift install` auto-detects the platform when you do not pass an init system. +- `nightshift uninstall` removes the matching launchd, systemd, or cron entry if one is installed. + ## Manual Runs Skip the scheduler and run immediately: ```bash nightshift run # Preflight summary + confirm + execute -nightshift run --dry-run # Show preflight summary, don't execute +nightshift run --dry-run # Show preflight summary and exit nightshift run --yes # Skip confirmation prompt nightshift run --project ~/code/myproject nightshift run --task lint-fix nightshift run --max-projects 3 --max-tasks 2 # Process more projects/tasks +nightshift run --random-task # Pick a random eligible task nightshift run --ignore-budget # Bypass budget limits +nightshift run --branch develop # Base new branches on develop +nightshift run --timeout 45m # Increase per-agent timeout ``` -In interactive terminals, `nightshift run` shows a preflight summary and asks for confirmation before executing. Use `--yes` to skip the prompt (e.g., in scripts). Non-TTY contexts auto-skip confirmation. +`nightshift run` shows a preflight summary before executing. In interactive terminals you get a confirmation prompt; `--yes` skips it. Non-TTY contexts such as cron, daemons, and CI skip confirmation automatically. + +`--random-task` is mutually exclusive with `--task`. When `--max-projects` or `--max-tasks` is omitted, Nightshift falls back to the values in the config file. + diff --git a/website/docs/troubleshooting.md b/website/docs/troubleshooting.md index e998551..5d43db4 100644 --- a/website/docs/troubleshooting.md +++ b/website/docs/troubleshooting.md @@ -8,33 +8,39 @@ title: Troubleshooting ## Common Issues **"Something feels off"** -- Run `nightshift doctor` to check config, schedule, and provider health +- Run `nightshift doctor` to check config, schedule, provider, and budget health **"No config file found"** ```bash -nightshift init # Create project config -nightshift init --global # Create global config +nightshift init # Create nightshift.yaml in the current directory +nightshift init --global # Create ~/.config/nightshift/config.yaml +nightshift config validate ``` +**"No schedule configured"** +- Set either `schedule.cron` or `schedule.interval` in config +- Use `nightshift setup` if you want the guided bootstrap flow + **"Insufficient budget"** - Check current budget: `nightshift budget` -- Increase `max_percent` in config -- Wait for budget reset (check reset time in output) +- Increase `budget.max_percent` in config +- Wait for budget reset (check the reset time in the output) **"Calibration confidence is low"** - Run `nightshift budget snapshot` a few times to collect samples -- Ensure tmux is installed so usage percentages are available +- Ensure `tmux` is installed so usage percentages are available - Keep snapshots running for at least a few days **"tmux not found"** -- Install tmux or set `budget.billing_mode: api` if you pay per token +- Install `tmux` or set `budget.billing_mode: api` if you pay per token **"Week boundary looks wrong"** - Set `budget.week_start_day` to `monday` or `sunday` **"Provider not available"** -- Ensure Claude/Codex CLI is installed and in PATH -- Check API key environment variables are set +- Ensure Claude Code, Codex, or Copilot is installed and in `PATH` +- For Copilot, install either `gh` or the standalone `copilot` binary +- Check API key or subscription login state for the provider you are using ## Debug Mode @@ -59,3 +65,4 @@ nightshift --help ``` Report issues: https://github.com/marcus/nightshift/issues + From af621a78cb054e973d2e47749effc4653c6db464 Mon Sep 17 00:00:00 2001 From: Marcus Vorwaller Date: Thu, 9 Apr 2026 03:21:23 -0700 Subject: [PATCH 2/5] docs: backfill Nightshift CLI docs Nightshift-Task: docs-backfill Nightshift-Ref: https://github.com/marcus/nightshift --- README.md | 22 ++++++++++++++++------ website/docs/cli-reference.md | 26 +++++++++++++++++--------- website/docs/configuration.md | 30 ++++++++++++++++-------------- website/docs/installation.md | 14 ++++++++++---- website/docs/integrations.md | 24 ++++++++++++++++++------ website/docs/scheduling.md | 9 +++++---- website/docs/troubleshooting.md | 7 ++++--- 7 files changed, 86 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index 7384513..b7c2b5d 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ After installing, run the guided setup: nightshift setup ``` -This walks you through provider configuration, project selection, budget calibration, and daemon setup. It covers Claude, Codex, and Copilot. If you want a manual flow instead, use `nightshift init` for a project config or `nightshift init --global` for `~/.config/nightshift/config.yaml`. +This walks you through provider configuration, project selection, budget calibration, and daemon setup. It covers Claude, Codex, and Copilot, and checks for the provider CLIs on `PATH`. If you want a manual flow instead, use `nightshift init` for a project config, `nightshift init --global` for `~/.config/nightshift/config.yaml`, and `nightshift config validate` to verify the result. Once complete you can preview what nightshift will do: @@ -78,6 +78,8 @@ nightshift setup nightshift init nightshift init --global nightshift config +nightshift config get budget.max_percent +nightshift config set budget.max_percent 15 nightshift config validate # Check environment and config health @@ -107,9 +109,13 @@ nightshift task run lint-fix --provider codex --dry-run # Manage the scheduler and service lifecycle nightshift daemon start nightshift daemon start --foreground +nightshift daemon start --timeout 45m nightshift daemon status nightshift daemon stop nightshift install +nightshift install launchd +nightshift install systemd +nightshift install cron nightshift uninstall ``` @@ -179,7 +185,7 @@ Other useful flags: Nightshift supports three AI providers: - **Claude Code** - Anthropic's Claude via local CLI - **Codex** - OpenAI's Codex via local CLI -- **GitHub Copilot** - GitHub's Copilot via `gh` or the standalone Copilot CLI +- **GitHub Copilot** - GitHub's Copilot via the standalone `copilot` binary or `gh copilot` ### Claude Code @@ -201,13 +207,17 @@ Supports signing in with ChatGPT or an API key. ### GitHub Copilot ```bash -# Install Copilot CLI +# Standalone binary npm install -g @github/copilot # or curl -fsSL https://gh.io/copilot-install | bash +# GitHub CLI extension +gh extension install github/gh-copilot ``` -Nightshift will use the standalone `copilot` binary when it exists, otherwise it falls back to `gh copilot`. `nightshift setup` checks for both. See [docs/COPILOT_INTEGRATION.md](docs/COPILOT_INTEGRATION.md) for details. +Nightshift prefers the standalone `copilot` binary when it exists, otherwise it falls back to `gh copilot`. `nightshift setup` checks for both and uses whichever is on `PATH`. + +If you use `gh copilot`, authenticate with `gh auth login` first. If you prefer API-based usage, you can authenticate Claude and Codex CLIs with API keys instead. @@ -222,9 +232,9 @@ Nightshift uses YAML config files to define: - Task priorities - Schedule preferences -Use `nightshift setup` for guided onboarding. Use `nightshift init` to create a project config in the current directory, or `nightshift init --global` to create `~/.config/nightshift/config.yaml`. `nightshift config` shows the merged configuration, and `nightshift config validate` checks both the global and project files. +Use `nightshift setup` for guided onboarding. Use `nightshift init` to create a project config in the current directory, or `nightshift init --global` to create `~/.config/nightshift/config.yaml`. `nightshift config` shows the merged configuration, `nightshift config get KEY` reads a value, `nightshift config set KEY VALUE` writes a value, and `nightshift config validate` checks both the global and project files. -See the [full configuration docs](https://nightshift.haplab.com/docs/configuration) or [SPEC.md](docs/SPEC.md) for detailed options. +See the [full configuration docs](https://nightshift.haplab.com/docs/configuration) for detailed options. Minimal example: diff --git a/website/docs/cli-reference.md b/website/docs/cli-reference.md index 1e4e41f..370b79b 100644 --- a/website/docs/cli-reference.md +++ b/website/docs/cli-reference.md @@ -10,8 +10,8 @@ title: CLI Reference | Command | Description | |---------|-------------| | `nightshift setup` | Guided end-to-end onboarding | -| `nightshift init` | Create a global or project config | -| `nightshift config` | Show, edit, or validate config | +| `nightshift init` | Create a global or project config file | +| `nightshift config` | Show, edit, or validate config files | | `nightshift run` | Execute configured tasks now | | `nightshift preview` | Show upcoming runs | | `nightshift budget` | Check token budget status | @@ -23,13 +23,13 @@ title: CLI Reference | `nightshift report` | Read run reports | | `nightshift snapshot` | Capture usage snapshots | | `nightshift busfactor` | Analyze ownership concentration | -| `nightshift daemon` | Manage the background scheduler | -| `nightshift install` | Install a system service | -| `nightshift uninstall` | Remove an installed service | +| `nightshift daemon` | Manage the background daemon lifecycle | +| `nightshift install` | Install a launchd/systemd/cron service | +| `nightshift uninstall` | Remove the installed service | ## Bootstrap and Config -`nightshift setup` walks through provider setup, project selection, budget calibration, and daemon installation. +`nightshift setup` walks through provider setup, project selection, budget calibration, PATH setup, and daemon installation. ```bash nightshift setup @@ -43,7 +43,7 @@ nightshift init --global nightshift init --force ``` -`nightshift config` shows the merged configuration from global and project files, plus environment overrides. +`nightshift config` shows the merged configuration from global and project files, plus environment overrides. `nightshift config set` writes to the project config when one exists, otherwise to the global config. Use `--global` to force the global file. ```bash nightshift config @@ -60,6 +60,8 @@ nightshift config validate | `config set KEY VALUE` | Update a value; use `--global` to force global config | | `config validate` | Validate global, project, and merged config | +`nightshift config set` accepts booleans, integers, floats, and strings. + ## Run Options `nightshift run` shows a preflight summary, then prompts for confirmation in interactive terminals. Non-TTY contexts skip the prompt automatically. @@ -97,7 +99,7 @@ nightshift run --no-color # Disable ANSI colors ## Daemon and Services -`nightshift daemon` manages the scheduler loop. +`nightshift daemon` manages the scheduler loop. `daemon start` backgrounds the process by default, `--foreground` keeps it in the current terminal, and `--timeout` defaults to 30m. ```bash nightshift daemon start @@ -111,6 +113,7 @@ nightshift daemon stop |------------|-------------| | `daemon start` | Start the scheduler in the background by default | | `daemon start --foreground` | Run the scheduler in the current terminal | +| `daemon start --timeout 45m` | Set the per-agent execution timeout | | `daemon status` | Show whether the daemon is running | | `daemon stop` | Stop the running daemon | @@ -124,6 +127,8 @@ nightshift install cron nightshift uninstall ``` +`launchd` targets macOS, `systemd` targets Linux, and `cron` works everywhere. `nightshift uninstall` removes the matching service entry if one is installed. + ## Preview ```bash @@ -169,8 +174,12 @@ nightshift task show lint-fix nightshift task show lint-fix --prompt-only nightshift task run lint-fix --provider claude nightshift task run lint-fix --provider copilot --dry-run +nightshift task run lint-fix --provider codex --timeout 45m +nightshift task run lint-fix --provider claude -p ~/code/myapp --branch develop ``` +`nightshift task run` requires `--provider`. It accepts `--project`, `--dry-run`, `--timeout` (default 30m), and `--branch` for new feature branches. + ## Reports and Diagnostics ```bash @@ -188,4 +197,3 @@ nightshift doctor | Flag | Scope | Description | |------|-------|-------------| | `--verbose` | Root command | Verbose output | - diff --git a/website/docs/configuration.md b/website/docs/configuration.md index 4656a52..f85697e 100644 --- a/website/docs/configuration.md +++ b/website/docs/configuration.md @@ -5,21 +5,12 @@ title: Configuration # Configuration -Nightshift uses YAML config files. Use `nightshift setup` for a guided bootstrap, `nightshift init` to create a config file, or edit the files directly. +Nightshift uses YAML config files. Use `nightshift setup` for guided bootstrap, `nightshift init` or `nightshift init --global` to create a config file, and `nightshift config` to inspect or edit the merged view. -## Config Sources - -Nightshift reads config in this order: - -1. Global config: `~/.config/nightshift/config.yaml` -2. Project config: `nightshift.yaml` in the current project directory -3. Environment overrides such as `NIGHTSHIFT_BUDGET_MAX_PERCENT` - -Project config values override global config values, and environment variables override both. - -## Config Workflow +## Bootstrap Workflow ```bash +nightshift setup nightshift init nightshift init --global nightshift config @@ -29,14 +20,26 @@ nightshift config set --global logging.level debug nightshift config validate ``` +- `nightshift setup` walks through provider setup, projects, budget, schedule, PATH, and daemon installation. - `nightshift init` creates `nightshift.yaml` in the current directory. - `nightshift init --global` creates `~/.config/nightshift/config.yaml`. -- `nightshift config` shows the merged config and the source paths. +- `nightshift config` shows the merged config plus the source paths. +- `nightshift config get` reads a nested value by key path. - `nightshift config set` writes to the project config when one exists, otherwise to the global config. Use `--global` to force the global file. - `nightshift config validate` checks the global file, project file, and merged config. `nightshift config set` accepts booleans, integers, floats, and strings. For example, `true`, `15`, `12.5`, and `debug` are all parsed correctly. +## Config Sources + +Nightshift reads config in this order: + +1. Global config: `~/.config/nightshift/config.yaml` +2. Project config: `nightshift.yaml` in the current project directory +3. Environment overrides such as `NIGHTSHIFT_BUDGET_MAX_PERCENT` + +Project config values override global config values, and environment variables override both. `nightshift config` reflects that same merge order when it prints the current configuration. + ## Config Locations | Type | Location | @@ -251,4 +254,3 @@ Each project can point at a path or a glob pattern. Use `exclude` to skip direct | PID file | `~/.local/share/nightshift/nightshift.pid` | If `state/state.json` exists from older versions, Nightshift migrates it to the SQLite database and renames the file to `state.json.migrated`. - diff --git a/website/docs/installation.md b/website/docs/installation.md index 4457030..2b41ca3 100644 --- a/website/docs/installation.md +++ b/website/docs/installation.md @@ -41,7 +41,7 @@ nightshift --help ## Provider Prerequisites -Nightshift can use Claude Code, Codex, and GitHub Copilot. Install and authenticate the providers you want to use: +Nightshift can use Claude Code, Codex, and GitHub Copilot. Install and authenticate the providers you want to use before running `nightshift setup` or `nightshift run`: ### Claude Code @@ -58,15 +58,20 @@ codex --login ### GitHub Copilot -Install either the standalone `copilot` binary or the GitHub CLI: +Install either the standalone `copilot` binary or GitHub CLI with the Copilot extension: ```bash +# Standalone binary npm install -g @github/copilot # or curl -fsSL https://gh.io/copilot-install | bash +# GitHub CLI extension +gh extension install github/gh-copilot ``` -Nightshift prefers the standalone `copilot` binary when it is available and falls back to `gh copilot`. Sign in with your GitHub account before running tasks. +Nightshift prefers the standalone `copilot` binary when it is available and falls back to `gh copilot`. `nightshift setup` checks for both. + +If you use `gh copilot`, authenticate with `gh auth login` first. ## Next Step @@ -76,9 +81,10 @@ Use the guided setup for the fastest path: nightshift setup ``` -If you prefer to bootstrap manually, create a config first: +If you prefer to bootstrap manually, create a config first and validate it: ```bash nightshift init nightshift init --global +nightshift config validate ``` diff --git a/website/docs/integrations.md b/website/docs/integrations.md index c26ed90..4cba437 100644 --- a/website/docs/integrations.md +++ b/website/docs/integrations.md @@ -28,6 +28,8 @@ claude /login ``` +Nightshift looks for the `claude` binary on `PATH`. + Relevant config keys: - `providers.claude.enabled` @@ -42,6 +44,8 @@ Nightshift supports OpenAI's Codex CLI as an alternative provider: codex --login ``` +Nightshift looks for the `codex` binary on `PATH`. + Relevant config keys: - `providers.codex.enabled` @@ -53,12 +57,17 @@ Relevant config keys: Nightshift supports GitHub Copilot through either the standalone `copilot` binary or `gh copilot`. ```bash +# Standalone binary npm install -g @github/copilot # or curl -fsSL https://gh.io/copilot-install | bash +# GitHub CLI extension +gh extension install github/gh-copilot ``` -Copilot usage is tracked by request count instead of token usage. Nightshift stores that tracking data under `providers.copilot.data_path` (default: `~/.copilot`). +Nightshift prefers the standalone `copilot` binary when it is available and falls back to `gh copilot`. Copilot usage is tracked by request count instead of token usage. Nightshift stores that tracking data under `providers.copilot.data_path` (default: `~/.copilot`). + +If you use `gh copilot`, authenticate with `gh auth login` first. Relevant config keys: @@ -72,7 +81,7 @@ All output is PR-based. Nightshift creates branches and pull requests for its fi ## td (Task Management) -Nightshift can source tasks from [td](https://td.haplab.com) - task management for AI-assisted development. Tasks tagged with `nightshift` in td will be picked up automatically. +Nightshift can source tasks from [td](https://td.haplab.com) - task management for AI-assisted development. The td reader imports every task from `td list --format json`; there is no tag filter. ```yaml integrations: @@ -82,17 +91,20 @@ integrations: teach_agent: true # Include td usage + core workflow in prompts ``` +When `teach_agent` is enabled, Nightshift adds td workflow notes to the agent prompt. + ## CLAUDE.md / AGENTS.md Nightshift reads project-level instruction files to understand context when executing tasks. Place a `CLAUDE.md` or `AGENTS.md` in your repo root to give Nightshift project-specific guidance. Tasks mentioned in these files get a priority bonus (+2). ## GitHub Issues -Source tasks from GitHub issues labeled with `nightshift`: +Source tasks from GitHub issues by enabling the GitHub task source: ```yaml integrations: - github_issues: - enabled: true - label: "nightshift" + task_sources: + - github_issues: true ``` + +Nightshift reads open issues with the hard-coded `nightshift` label via `gh issue list --label nightshift --state open`. The label is not configurable in Nightshift's current schema. diff --git a/website/docs/scheduling.md b/website/docs/scheduling.md index dfaa8b0..f16249c 100644 --- a/website/docs/scheduling.md +++ b/website/docs/scheduling.md @@ -28,7 +28,7 @@ schedule: - `window` restricts execution to a local time range. - `max_projects` and `max_tasks` provide defaults for scheduled and manual runs when CLI flags are omitted. -If you want to bootstrap a schedule from scratch, run `nightshift init` or `nightshift setup`, then validate with `nightshift config validate`. +If you want to bootstrap a schedule from scratch, run `nightshift setup` for the guided path, or `nightshift init` / `nightshift init --global` for a manual path. After editing the schedule, run `nightshift config validate`. ## Daemon Mode @@ -42,7 +42,7 @@ nightshift daemon status nightshift daemon stop ``` -The daemon requires a configured schedule. It writes its PID file to `~/.local/share/nightshift/nightshift.pid` and uses the scheduler loop to launch runs on schedule. +`nightshift daemon start` backgrounds the scheduler by default. `--foreground` keeps it in the current terminal, and `--timeout` defaults to 30m if you do not override it. The daemon requires a configured schedule. It writes its PID file to `~/.local/share/nightshift/nightshift.pid` and uses the scheduler loop to launch runs on schedule. ## Service Lifecycle @@ -66,6 +66,7 @@ nightshift uninstall ``` - `nightshift install` auto-detects the platform when you do not pass an init system. +- `launchd` targets macOS, `systemd` targets Linux, and `cron` works everywhere. - `nightshift uninstall` removes the matching launchd, systemd, or cron entry if one is installed. ## Manual Runs @@ -83,9 +84,9 @@ nightshift run --random-task # Pick a random eligible task nightshift run --ignore-budget # Bypass budget limits nightshift run --branch develop # Base new branches on develop nightshift run --timeout 45m # Increase per-agent timeout +nightshift run --no-color # Disable ANSI colors ``` `nightshift run` shows a preflight summary before executing. In interactive terminals you get a confirmation prompt; `--yes` skips it. Non-TTY contexts such as cron, daemons, and CI skip confirmation automatically. -`--random-task` is mutually exclusive with `--task`. When `--max-projects` or `--max-tasks` is omitted, Nightshift falls back to the values in the config file. - +`--random-task` is mutually exclusive with `--task`. When `--max-projects` or `--max-tasks` is omitted, Nightshift falls back to the values in `schedule.max_projects` and `schedule.max_tasks`. `--branch` defaults to the current branch, and `--timeout` defaults to 30m. diff --git a/website/docs/troubleshooting.md b/website/docs/troubleshooting.md index 5d43db4..7614707 100644 --- a/website/docs/troubleshooting.md +++ b/website/docs/troubleshooting.md @@ -12,6 +12,7 @@ title: Troubleshooting **"No config file found"** ```bash +nightshift setup # Guided bootstrap with provider and daemon checks nightshift init # Create nightshift.yaml in the current directory nightshift init --global # Create ~/.config/nightshift/config.yaml nightshift config validate @@ -19,7 +20,8 @@ nightshift config validate **"No schedule configured"** - Set either `schedule.cron` or `schedule.interval` in config -- Use `nightshift setup` if you want the guided bootstrap flow +- Use `nightshift setup` or `nightshift init` if you want the bootstrap flow +- Re-run `nightshift config validate` after editing the schedule **"Insufficient budget"** - Check current budget: `nightshift budget` @@ -39,7 +41,7 @@ nightshift config validate **"Provider not available"** - Ensure Claude Code, Codex, or Copilot is installed and in `PATH` -- For Copilot, install either `gh` or the standalone `copilot` binary +- For Copilot, install either `gh` or the standalone `copilot` binary, then run `gh auth login` if you use `gh copilot` - Check API key or subscription login state for the provider you are using ## Debug Mode @@ -65,4 +67,3 @@ nightshift --help ``` Report issues: https://github.com/marcus/nightshift/issues - From 722ba4de301692dedcc5f00edc92a0f44176640d Mon Sep 17 00:00:00 2001 From: Greg Gardner Date: Sun, 12 Jul 2026 02:07:30 -0700 Subject: [PATCH 3/5] docs: complete budget and scheduling guides Nightshift-Task: docs-backfill Nightshift-Ref: https://github.com/marcus/nightshift --- website/docs/budget.md | 119 ++++++++++++++++++++----------------- website/docs/scheduling.md | 112 +++++++++++++++++----------------- 2 files changed, 122 insertions(+), 109 deletions(-) diff --git a/website/docs/budget.md b/website/docs/budget.md index e965cea..072f053 100644 --- a/website/docs/budget.md +++ b/website/docs/budget.md @@ -3,11 +3,11 @@ sidebar_position: 6 title: Budget --- -# Budget Management +# Budget management -Nightshift is designed to use tokens you'd otherwise waste. It tracks your remaining budget and never exceeds your configured limits. +Nightshift calculates an allowance for each enabled provider before it selects work. The allowance is based on local usage data, the configured or calibrated weekly budget, and the limits in `budget`. -## Check Budget +Use the status command to inspect the resolved budget, usage, reserve, allowance, and any reset times captured in a snapshot: ```bash nightshift budget @@ -15,58 +15,82 @@ nightshift budget --provider claude nightshift budget --provider codex ``` -## Configuration Options +The provider must be enabled in [Configuration](/docs/configuration). If a provider has no remaining allowance, Nightshift skips it and tries the next provider in `providers.preference`. -| Option | Type | Default | Description | -|--------|------|---------|-------------| -| `budget.mode` | string | `daily` | `daily` or `weekly` usage model | -| `budget.max_percent` | int | `75` | Max % of budget per run | -| `budget.reserve_percent` | int | `5` | Always keep this % in reserve | -| `budget.billing_mode` | string | `subscription` | `subscription` or `api` | -| `budget.calibrate_enabled` | bool | `true` | Enable subscription calibration via snapshots | -| `budget.snapshot_interval` | duration | `30m` | Automatic snapshot cadence | -| `budget.snapshot_retention_days` | int | `90` | Snapshot retention window | -| `budget.week_start_day` | string | `monday` | Week boundary for calibration | -| `budget.db_path` | string | `~/.local/share/nightshift/nightshift.db` | Override DB path | +## Configuration -## Budget Modes +These settings belong under the top-level `budget` key. -### Daily Mode (recommended) +| Field | Default | Purpose | +| --- | --- | --- | +| `mode` | `daily` | Allowance model: `daily` or `weekly`. | +| `max_percent` | `75` | Percentage of the available budget that one Nightshift run may use. Valid values are 1–100. | +| `reserve_percent` | `5` | Percentage held back after the allowance calculation. Valid values are 0–100. | +| `aggressive_end_of_week` | `false` | In weekly mode, increases the allowance when two or fewer days remain. | +| `weekly_tokens` | `700000` | Default weekly token budget when there is no provider-specific value or usable calibration. | +| `per_provider` | unset | Weekly token overrides keyed by `claude`, `codex`, or `copilot`. | +| `billing_mode` | `subscription` | `subscription` enables optional calibration; `api` uses configured token limits. | +| `calibrate_enabled` | `true` | Enables subscription-budget inference from snapshots. It is disabled automatically for API billing. | +| `snapshot_interval` | `30m` | How often the daemon collects snapshots. This must be a positive Go duration, such as `30m` or `1h`. | +| `snapshot_retention_days` | `90` | Number of days to retain snapshots. Set `0` to keep them indefinitely. | +| `week_start_day` | `monday` | `monday` or `sunday`; determines how snapshots are grouped for calibration. | +| `db_path` | `~/.local/share/nightshift/nightshift.db` | SQLite database location. | -Each night uses up to `max_percent` of your daily budget (weekly / 7). Consistent, predictable usage. +For example: -### Weekly Mode +```yaml +budget: + mode: weekly + max_percent: 60 + reserve_percent: 10 + aggressive_end_of_week: true + billing_mode: subscription + calibrate_enabled: true + snapshot_interval: 30m + snapshot_retention_days: 90 + week_start_day: monday + weekly_tokens: 700000 + per_provider: + claude: 700000 + codex: 500000 +``` -Uses `max_percent` of *remaining* weekly budget. With `aggressive_end_of_week: true`, spends more near week's end to avoid waste. +## Allowance modes -## Calibration +`daily` is the default. Nightshift divides the resolved weekly budget by seven, calculates the unused part of that daily budget, applies `max_percent`, then subtracts the configured reserve and any predicted daytime usage. -Nightshift infers subscription budgets by correlating local token counts with provider usage percentages. +`weekly` spreads the unused weekly budget over the days remaining until the provider's reset, then applies `max_percent`, the reserve, and any predicted daytime usage. With `aggressive_end_of_week: true`, the weekly calculation uses a 1× multiplier with two days remaining and a 2× multiplier with one day remaining. -Formula: `inferred_budget = local_tokens / (scraped_pct / 100)` +The status output shows the values it used, including the budget source and confidence when calibration is available. `--ignore-budget` on `nightshift run` bypasses these checks; use it deliberately because it can select an otherwise exhausted provider. -Confidence levels: -- **low**: 1–2 samples or high variance -- **medium**: stable signal across several snapshots -- **high**: consistent signal across a week or more +## Subscription calibration and snapshots -```bash -nightshift budget calibrate +For subscription accounts, Nightshift can infer a provider's weekly budget from snapshots. A snapshot records local token totals and, when tmux scraping is available, the provider's reported usage percentage. The inference is: + +```text +weekly budget = local weekly tokens / (reported percentage / 100) ``` -Enable auto-calibration in config: +Snapshots with a reported percentage between 10% and 95% and nonzero local tokens are used for the current configured week. Nightshift uses the median after filtering outliers and falls back to the previous week or configured budget when it has no usable current samples. -```yaml -budget: - calibrate_enabled: true - snapshot_interval: 30m +Capture and inspect snapshots with the `nightshift budget` subcommands: + +```bash +nightshift budget snapshot +nightshift budget snapshot --provider claude +nightshift budget snapshot --local-only +nightshift budget history -n 10 +nightshift budget history --provider codex --n 20 +nightshift budget calibrate ``` -> Calibration uses tmux to scrape usage percentages. If tmux is unavailable, snapshots are local-only and budgets fall back to config values. +`snapshot` reads local usage data for enabled providers. For Claude and Codex, it can also use tmux to run the provider usage command and capture its percentage and reset information. `--local-only`, `calibrate_enabled: false`, and `billing_mode: api` disable that scraping. Copilot snapshots are local-only. -## API Billing +When the daemon is running, it takes a snapshot immediately and then at `snapshot_interval`. It also prunes old rows once every 24 hours. The status and history commands display captured session and weekly reset times when the provider supplied them; a missing reset line simply means no reset time was captured. -For API-billed accounts, set explicit token limits: +## API billing + +Use explicit limits for API accounts. API mode turns calibration off and uses `per_provider` where set, otherwise `weekly_tokens`. ```yaml budget: @@ -77,23 +101,6 @@ budget: codex: 500000 ``` -`weekly_tokens` and `per_provider` are authoritative for `billing_mode: api`. For subscription users, they act as a fallback until calibration has enough snapshots. - -## Budget History - -View past budget snapshots: - -```bash -nightshift budget history -n 10 -nightshift budget snapshot --local-only -``` - -## Morning Summary - -After each run, Nightshift generates a summary at `~/.local/share/nightshift/summaries/nightshift-YYYY-MM-DD.md` covering budget usage, tasks completed, and suggested next steps. - -## Safety +## Troubleshooting -- `max_percent` (default 75%) caps how much budget a single run can use -- `reserve_percent` (default 5%) always keeps some budget available for your daytime work -- If budget is exhausted, Nightshift skips remaining tasks gracefully +If a budget result has little confidence or falls back to configuration, run `nightshift budget snapshot --provider ` and inspect the output. It identifies missing local data, disabled calibration, unavailable tmux, and provider data-path problems. [Doctor](/docs/cli-reference) also checks recent snapshot health. diff --git a/website/docs/scheduling.md b/website/docs/scheduling.md index f16249c..e94457b 100644 --- a/website/docs/scheduling.md +++ b/website/docs/scheduling.md @@ -5,88 +5,94 @@ title: Scheduling # Scheduling -Nightshift can run automatically on a schedule or be triggered manually when you want immediate execution. +Configure exactly one schedule, then run the daemon to execute Nightshift automatically. A schedule uses either a five-field cron expression or a Go duration interval; setting both is invalid. -## Schedule Configuration +## Cron or interval -Use cron or interval scheduling. Nightshift rejects configs that set both. +Use cron when work should start at a calendar time. Nightshift accepts five fields: minute, hour, day of month, month, and day of week. ```yaml schedule: - cron: "0 2 * * *" # Every night at 2am - # interval: "8h" # Or run every 8 hours + cron: "0 2 * * *" # Every day at 2:00 AM +``` + +Use an interval when work should recur relative to the last scheduled run: + +```yaml +schedule: + interval: "8h" +``` + +Intervals use Go duration syntax, for example `30m`, `1h`, or `24h`, and must be positive. The interval scheduler's first run is one interval after it starts; neither scheduling mode runs immediately on daemon startup. + +## Execution windows + +An optional window restricts jobs to a time range. The start is inclusive and the end is exclusive. Windows may cross midnight. + +```yaml +schedule: + cron: "0 * * * *" window: start: "22:00" end: "06:00" - timezone: "America/Denver" - max_projects: 1 - max_tasks: 1 + timezone: "America/Los_Angeles" ``` -- `cron` schedules a specific time. -- `interval` repeats runs after a fixed duration. -- `window` restricts execution to a local time range. -- `max_projects` and `max_tasks` provide defaults for scheduled and manual runs when CLI flags are omitted. +In this example, Nightshift runs hourly from 22:00 through 05:00 in the specified timezone. If `timezone` is omitted, the daemon's local timezone is used. `start` and `end` must be `HH:MM` values with hours from 0–23 and minutes from 0–59. -If you want to bootstrap a schedule from scratch, run `nightshift setup` for the guided path, or `nightshift init` / `nightshift init --global` for a manual path. After editing the schedule, run `nightshift config validate`. +For cron schedules, an occurrence outside the window is skipped; the next cron occurrence is evaluated normally. For interval schedules, the next interval that falls outside the window is moved to the next window start. -## Daemon Mode +## Per-run limits -Run Nightshift as a persistent background process: +The `schedule` section also supplies defaults for manual `nightshift run` invocations when its matching flag was not explicitly passed: + +```yaml +schedule: + cron: "0 2 * * *" + max_projects: 3 + max_tasks: 2 +``` + +- `max_projects` limits eligible projects per `nightshift run`; `0` leaves the command's default of one project in effect. +- `max_tasks` limits selected tasks per project; `0` leaves the command's default of one task in effect. +- An explicit `nightshift run --max-projects` or `--max-tasks` flag overrides the corresponding configuration value. `--project` ignores the project limit and `--task` ignores the task limit. + +The current daemon loop does not read these two limits: it processes configured projects and selects up to five tasks for each eligible project. Use `nightshift run` when you need these particular limits enforced. + +## Daemon lifecycle + +The daemon requires either `schedule.cron` or `schedule.interval`. ```bash nightshift daemon start -nightshift daemon start --foreground # For debugging -nightshift daemon start --timeout 45m nightshift daemon status nightshift daemon stop ``` -`nightshift daemon start` backgrounds the scheduler by default. `--foreground` keeps it in the current terminal, and `--timeout` defaults to 30m if you do not override it. The daemon requires a configured schedule. It writes its PID file to `~/.local/share/nightshift/nightshift.pid` and uses the scheduler loop to launch runs on schedule. - -## Service Lifecycle - -Install Nightshift as a system service for automatic startup: +`nightshift daemon start` detaches into the background. Use `--foreground` to keep it attached for debugging, or `--timeout 45m` to set the per-agent execution timeout: ```bash -# Auto-detect the init system -nightshift install +nightshift daemon start --foreground --timeout 45m +``` -# macOS (launchd) -nightshift install launchd +The daemon writes its PID to `~/.local/share/nightshift/nightshift.pid`. `status` reports the process, configured schedule, and window. `stop` sends `SIGTERM` and waits up to ten seconds before force-stopping a process that has not exited. The daemon also handles `SIGINT` and `SIGTERM` for graceful scheduler shutdown. -# Linux (systemd) -nightshift install systemd +## Preview and manual runs -# Universal (cron) -nightshift install cron +Preview upcoming work without starting a daemon: -# Remove the installed service -nightshift uninstall +```bash +nightshift preview +nightshift preview -n 3 +nightshift preview --explain ``` -- `nightshift install` auto-detects the platform when you do not pass an init system. -- `launchd` targets macOS, `systemd` targets Linux, and `cron` works everywhere. -- `nightshift uninstall` removes the matching launchd, systemd, or cron entry if one is installed. - -## Manual Runs - -Skip the scheduler and run immediately: +To run once without waiting for the schedule: ```bash -nightshift run # Preflight summary + confirm + execute -nightshift run --dry-run # Show preflight summary and exit -nightshift run --yes # Skip confirmation prompt -nightshift run --project ~/code/myproject -nightshift run --task lint-fix -nightshift run --max-projects 3 --max-tasks 2 # Process more projects/tasks -nightshift run --random-task # Pick a random eligible task -nightshift run --ignore-budget # Bypass budget limits -nightshift run --branch develop # Base new branches on develop -nightshift run --timeout 45m # Increase per-agent timeout -nightshift run --no-color # Disable ANSI colors +nightshift run --dry-run +nightshift run --yes +nightshift run --max-projects 3 --max-tasks 2 ``` -`nightshift run` shows a preflight summary before executing. In interactive terminals you get a confirmation prompt; `--yes` skips it. Non-TTY contexts such as cron, daemons, and CI skip confirmation automatically. - -`--random-task` is mutually exclusive with `--task`. When `--max-projects` or `--max-tasks` is omitted, Nightshift falls back to the values in `schedule.max_projects` and `schedule.max_tasks`. `--branch` defaults to the current branch, and `--timeout` defaults to 30m. +In an interactive terminal, `nightshift run` shows a preflight summary and asks for confirmation. Non-interactive runs, including daemon runs, skip that prompt automatically. See [Configuration](/docs/configuration) for the complete YAML layout and [CLI Reference](/docs/cli-reference) for command options. From 11ab9d66d87bbd8e2e91a8a12a42a11e4db596bb Mon Sep 17 00:00:00 2001 From: Greg Gardner Date: Sun, 12 Jul 2026 02:14:50 -0700 Subject: [PATCH 4/5] docs: correct end-of-week budget multiplier Nightshift-Task: docs-backfill Nightshift-Ref: https://github.com/marcus/nightshift --- website/docs/budget.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/budget.md b/website/docs/budget.md index 072f053..b1b97e4 100644 --- a/website/docs/budget.md +++ b/website/docs/budget.md @@ -26,7 +26,7 @@ These settings belong under the top-level `budget` key. | `mode` | `daily` | Allowance model: `daily` or `weekly`. | | `max_percent` | `75` | Percentage of the available budget that one Nightshift run may use. Valid values are 1–100. | | `reserve_percent` | `5` | Percentage held back after the allowance calculation. Valid values are 0–100. | -| `aggressive_end_of_week` | `false` | In weekly mode, increases the allowance when two or fewer days remain. | +| `aggressive_end_of_week` | `false` | In weekly mode, doubles the allowance with one day remaining before reset. | | `weekly_tokens` | `700000` | Default weekly token budget when there is no provider-specific value or usable calibration. | | `per_provider` | unset | Weekly token overrides keyed by `claude`, `codex`, or `copilot`. | | `billing_mode` | `subscription` | `subscription` enables optional calibration; `api` uses configured token limits. | From 3dd7d4c9148ee40d707999df154739157e482ad5 Mon Sep 17 00:00:00 2001 From: Greg Gardner Date: Tue, 18 Aug 2026 02:05:00 -0700 Subject: [PATCH 5/5] docs: document dev build/test workflow and provider-calibration Add a Building and testing subsection to the README Development section covering the Makefile targets, and a package doc comment for cmd/provider-calibration, the only package in the repo without one. Nightshift-Task: docs-backfill Nightshift-Ref: https://github.com/marcus/nightshift --- README.md | 32 ++++++++++++++++++++++++++++++++ cmd/provider-calibration/main.go | 12 ++++++++++++ 2 files changed, 44 insertions(+) diff --git a/README.md b/README.md index b7c2b5d..d7da7cd 100644 --- a/README.md +++ b/README.md @@ -301,6 +301,38 @@ Each task has a default cooldown interval to prevent the same task from running ## Development +Nightshift is a Go module. Clone the repo and pull dependencies: + +```bash +git clone https://github.com/marcus/nightshift.git +cd nightshift +make deps +``` + +### Building and testing + +Common targets in the `Makefile` (run `make help` for the full list): + +```bash +make build # build ./cmd/nightshift into ./nightshift +make test # go test ./... +make test-race # go test -race ./... +make coverage # test with a coverage profile, printed per function +make lint # golangci-lint run (requires golangci-lint on PATH) +make check # test + lint +make clean # remove the binary and coverage artifacts +``` + +`make install` installs the binary into your Go bin directory. `make coverage-html` writes `coverage.html` from the coverage profile. + +To compare local Claude and Codex session token usage for budget calibration: + +```bash +make calibrate-providers +``` + +This runs `cmd/provider-calibration` against the current repo. See [Provider Calibration Guide](docs/guides/provider-calibration.md) for the flags and how to read the output. + ### Pre-commit hooks Install the git pre-commit hook to catch formatting and vet issues before pushing: diff --git a/cmd/provider-calibration/main.go b/cmd/provider-calibration/main.go index ee573b2..ddc1c7e 100644 --- a/cmd/provider-calibration/main.go +++ b/cmd/provider-calibration/main.go @@ -1,3 +1,15 @@ +// Package main is the CLI entry point for provider-calibration, a helper that +// compares locally recorded Claude and Codex session usage so token-cost +// assumptions can be re-checked. +// +// It reads Codex session files (--codex-sessions) and Claude project files +// (--claude-projects), optionally filtered by repo path (--repo), Codex +// originator (--codex-originator), and a minimum user-turn count +// (--min-user-turns). It reports per-session and per-user-turn token +// distributions for each provider, the cross-provider ratios, and a suggested +// multiplier, either as a human-readable report or as JSON (--json). +// +// See docs/guides/provider-calibration.md for the full workflow. package main import (