diff --git a/README.md b/README.md index 84f92cd..b7c2b5d 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, 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: ```bash nightshift preview @@ -72,6 +74,14 @@ nightshift preview --write ./nightshift-prompts # Guided global setup nightshift setup +# Bootstrap or inspect config +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 nightshift doctor @@ -95,6 +105,18 @@ 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 start --timeout 45m +nightshift daemon status +nightshift daemon stop +nightshift install +nightshift install launchd +nightshift install systemd +nightshift install cron +nightshift uninstall ``` If `gum` is available, preview output is shown through the gum pager. Use `--plain` to disable. @@ -115,6 +137,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 +162,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 the standalone `copilot` binary or `gh copilot` ### Claude Code @@ -177,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 ``` -Requires GitHub Copilot subscription. 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. @@ -198,15 +232,17 @@ 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, `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: ```yaml schedule: cron: "0 2 * * *" + max_projects: 1 + max_tasks: 1 budget: mode: daily @@ -220,6 +256,7 @@ providers: preference: - claude - codex + - copilot claude: enabled: true data_path: "~/.claude" @@ -228,12 +265,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 +310,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..06158c4 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 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 | | `nightshift task` | Browse and run tasks | @@ -18,75 +20,333 @@ 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 busfactor` | Analyze ownership concentration | +| `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, PATH setup, 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. `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 +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 | + +`nightshift config set` accepts booleans, integers, floats, and strings. ## 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. `daemon start` backgrounds the process by default, `--foreground` keeps it in the current terminal, and `--timeout` defaults to 30m. + +```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 start --timeout 45m` | Set the per-agent execution timeout | +| `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 +``` + +`launchd` targets macOS, `systemd` targets Linux, and `cron` works everywhere. `nightshift uninstall` removes the matching service entry if one is installed. + +## 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 +nightshift task run lint-fix --provider codex --timeout 45m +nightshift task run lint-fix --provider claude -p ~/code/myapp --branch develop ``` -## Budget Commands +`nightshift task run` requires `--provider`. It accepts `--project`, `--dry-run`, `--timeout` (default 30m), and `--branch` for new feature branches. + +## Observability and Diagnostics + +### Run Status + +`nightshift status` reads run history from the Nightshift database. It shows the +five most recent runs by default, or an aggregate for the current day. ```bash -nightshift budget # Current status -nightshift budget --provider claude -nightshift budget snapshot --local-only -nightshift budget history -n 10 -nightshift budget calibrate +nightshift status +nightshift status --last 10 +nightshift status --today +``` + +| Flag | Default | Description | +|------|---------|-------------| +| `--last`, `-n` | `5` | Show the last N runs | +| `--today` | `false` | Show today's activity summary instead of individual runs | + +If both flags are present, `--today` takes precedence. + +### Logs + +`nightshift logs` reads structured log files from the configured log directory. +It can filter, summarize, follow, or export matching entries. + +```bash +nightshift logs +nightshift logs --tail 100 --level warn +nightshift logs --since today --component scheduler +nightshift logs --since "2025-02-10 22:00" --until "2025-02-11 06:00" +nightshift logs --summary --match timeout +nightshift logs --follow --raw +nightshift logs --export ./nightshift-logs.txt +``` + +| Flag | Default | Description | +|------|---------|-------------| +| `--tail`, `-n` | `50` | Limit output to the last N matching log lines | +| `--follow`, `-f` | `false` | Continue streaming new log entries | +| `--export`, `-e` | _(unset)_ | Export matching logs to a file | +| `--since` | _(unset)_ | Include entries at or after this time | +| `--until` | _(unset)_ | Include entries at or before this time | +| `--level` | _(unset)_ | Minimum level: `debug`, `info`, `warn`, or `error` | +| `--component` | _(unset)_ | Filter by a case-insensitive component substring | +| `--match` | _(unset)_ | Filter by a case-insensitive message substring | +| `--summary` | `false` | Show the matched-log summary without individual entries | +| `--raw` | `false` | Print original log lines without formatting | +| `--no-color` | `false` | Disable ANSI colors | +| `--path` | configured log path | Override the log directory; the fallback is `~/.local/share/nightshift/logs` | + +`--since` and `--until` accept `now`, `today`, `yesterday`, `tomorrow`, +`YYYY-MM-DD`, `YYYY-MM-DD HH:MM`, `YYYY-MM-DD HH:MM:SS`, or RFC3339. Values +without an explicit offset use the local timezone. `--summary` cannot be +combined with `--follow`, and `--until` cannot be used while following logs. + +### Aggregate Statistics + +`nightshift stats` summarizes runs, task outcomes, tokens, budget projections, +and per-project activity. JSON output is available for scripts. + +```bash +nightshift stats +nightshift stats --period last-7d +nightshift stats --period last-night --json ``` -## Global Flags +| Flag | Default | Description | +|------|---------|-------------| +| `--period`, `-p` | `all` | Period: `all`, `last-7d`, `last-30d`, or `last-night` | +| `--json` | `false` | Output machine-readable JSON | + +### Run Reports + +`nightshift report` renders saved run reports. The default is a styled overview +of up to three runs from the last configured night window. + +```bash +nightshift report +nightshift report --period last-run --report tasks +nightshift report --period last-7d --runs 0 --format plain +nightshift report --since yesterday --until now --report budget +nightshift report --period today --format json +nightshift report --period last-night --format markdown +``` + +| Flag | Default | Description | +|------|---------|-------------| +| `--report`, `-r` | `overview` | View: `overview`, `tasks`, `projects`, `budget`, or `raw` | +| `--period`, `-p` | `last-night` | Period: `last-night`, `last-run`, `last-24h`, `last-7d`, `today`, `yesterday`, or `all` | +| `--runs`, `-n` | `3` | Maximum runs to include; `0` includes all matching runs | +| `--since` | _(unset)_ | Override the period start time | +| `--until` | _(unset)_ | Override the period end time | +| `--format` | `fancy` | Output: `fancy`, `plain`, `markdown`, or `json` | +| `--no-color` | `false` | Disable ANSI colors in styled output | +| `--paths` | `false` | Include report and log file paths | +| `--max-items` | `5` | Maximum highlights shown per run | + +Report time values accept the same forms as log times. Values without an +explicit offset use `schedule.window.timezone` when configured, otherwise the +local timezone. Setting either `--since` or `--until` overrides `--period`. +`plain` keeps the styled report layout but disables ANSI colors; `markdown` and +`json` emit dedicated machine-friendly representations. + +### Bus Factor + +`nightshift busfactor` uses Git history to report contributor concentration, +including bus factor, Herfindahl index, Gini coefficient, and a risk level. + +```bash +nightshift busfactor +nightshift busfactor ~/code/myapp --since 2025-01-01 +nightshift busfactor --path . --file "internal/**" --json +nightshift busfactor . --save +nightshift busfactor . --save --db ./nightshift.db +``` + +| Flag | Default | Description | +|------|---------|-------------| +| `[path]` | current directory | Repository or directory to analyze | +| `--path`, `-p` | _(unset)_ | Repository or directory; overrides the positional path | +| `--file`, `-f` | _(unset)_ | Restrict analysis to a file or pattern | +| `--since` | _(unset)_ | Include commits on or after an RFC3339 or `YYYY-MM-DD` date | +| `--until` | _(unset)_ | Include commits on or before an RFC3339 or `YYYY-MM-DD` date | +| `--json` | `false` | Output machine-readable JSON | +| `--save` | `false` | Save the analysis result to the database | +| `--db` | configured database | Override the database path used by `--save` | + +`--path` takes precedence over the positional path. JSON mode writes the report +and exits without saving, so use `--save` with the default human-readable mode. + +### Doctor + +`nightshift doctor` checks configuration loading, database and state access, +scheduling, service and daemon status, enabled provider CLIs and data paths, +budget readiness, snapshots, and tmux availability. + +```bash +nightshift doctor +nightshift --verbose doctor +``` + +The command has no command-specific flags. Warnings are reported without +failing the command; failed checks produce a non-zero exit status. + +### Budget Snapshot + +Usage snapshots combine local token counts with an optional provider percentage +scraped through tmux. Nightshift stores them for budget calibration and can infer +a weekly budget when both values are available. This is a `budget` subcommand; +there is no top-level `nightshift snapshot` command. + +```bash +nightshift budget snapshot +nightshift budget snapshot --provider claude +nightshift budget snapshot --provider codex --local-only +``` + +| Flag | Default | Description | +|------|---------|-------------| +| `--provider`, `-p` | all enabled providers | Provider: `claude`, `codex`, or `copilot` | +| `--local-only` | `false` | Skip tmux scraping and store only local usage data | + +Without `--local-only`, scraping also requires tmux, +`budget.calibrate_enabled: true`, and subscription billing mode. Local-only +snapshots remain available when scraping is disabled. + +## Shared Flags -| Flag | Description | -|------|-------------| -| `--verbose` | Verbose output | -| `--provider` | Select provider (claude, codex) | -| `--timeout` | Execution timeout (default 30m) | +| Flag | Scope | Description | +|------|-------|-------------| +| `--verbose` | Root command | Verbose output | diff --git a/website/docs/configuration.md b/website/docs/configuration.md index 4a7ee3d..f85697e 100644 --- a/website/docs/configuration.md +++ b/website/docs/configuration.md @@ -5,18 +5,55 @@ 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 guided bootstrap, `nightshift init` or `nightshift init --global` to create a config file, and `nightshift config` to inspect or edit the merged view. -## Config Location +## Bootstrap Workflow -- **Global:** `~/.config/nightshift/config.yaml` -- **Per-project:** `nightshift.yaml` or `.nightshift.yaml` in the repo root +```bash +nightshift setup +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 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 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 | +|------|----------| +| 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 +67,7 @@ providers: preference: - claude - codex + - copilot claude: enabled: true data_path: "~/.claude" @@ -38,6 +76,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 +88,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 +122,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 +179,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" ``` -Each task has a default cooldown interval to prevent the same task from running too frequently on a project. +- `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 +``` + +| 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 +221,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 @@ -124,7 +254,3 @@ projects: | 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`. - -## 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..2b41ca3 100644 --- a/website/docs/installation.md +++ b/website/docs/installation.md @@ -39,16 +39,52 @@ 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 before running `nightshift setup` or `nightshift run`: + +### Claude Code ```bash -# Claude Code claude /login +``` + +### Codex -# Codex +```bash codex --login ``` + +### GitHub Copilot + +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`. `nightshift setup` checks for both. + +If you use `gh copilot`, authenticate with `gh auth login` first. + +## Next Step + +Use the guided setup for the fastest path: + +```bash +nightshift setup +``` + +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 96d5e3f..4cba437 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,15 @@ claude /login ``` -## Codex +Nightshift looks for the `claude` binary on `PATH`. + +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 +44,44 @@ 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` +- `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 +# 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`. 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: + +- `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. The td reader imports every task from `td list --format json`; there is no tag filter. ```yaml integrations: @@ -40,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 b552a79..f16249c 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 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 -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 +`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 as a system service for automatic startup: +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,33 @@ 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. +- `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: ```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 +nightshift run --no-color # Disable ANSI colors ``` -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 `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 e998551..7614707 100644 --- a/website/docs/troubleshooting.md +++ b/website/docs/troubleshooting.md @@ -8,33 +8,41 @@ 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 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 ``` +**"No schedule configured"** +- Set either `schedule.cron` or `schedule.interval` in config +- 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` -- 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, 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