@garyhuangdev/nightowl
v0.1.1
Published
NightOwl is a local code review CLI built with the GitHub Copilot SDK.
Maintainers
Readme
NightOwl
Status: Early development (v0.1.0) — APIs, output formats, and the command-line interface may change.
NightOwl is a local code review CLI powered by the GitHub Copilot SDK. It drives an AI agent to automatically perform structured code reviews on Git changes and produce traceable Markdown review reports.
Why NightOwl?
- Structured: every review follows the same multi-step workflow and output format
- Traceable: every finding maps to a specific file, line number, or diff hunk
- Reproducible: the same inputs produce a consistent review structure, not free-form conversation
The generated reports can serve as a starting point for self-review or human review.
Getting Started
This section gets you from zero to your first review report. If you only want to try NightOwl without setting up Copilot, jump to step 4 and use --dry-run.
1. Check prerequisites
- Node.js ≥ 22.18.0 (
node --versionto confirm) - For real reviews, one of:
- Copilot mode (default) — a GitHub Copilot subscription and an authenticated GitHub Copilot CLI
- BYOK mode — a provider API key (OpenAI, Azure, or Anthropic) supplied via an environment variable. See Model Provider
2. Install the nightowl command
Install NightOwl globally from npm:
npm install -g @garyhuangdev/nightowlOr run it without a global install:
npx @garyhuangdev/nightowl --checkTo use a source checkout instead of the published npm package:
git clone https://github.com/GaryGaryHuang/NightOwl.git
cd NightOwl
npm install # Install dependencies
npm run build # Produce dist/
npm link # Make the `nightowl` command available on your PATH3. Authenticate (Copilot mode only)
Copilot mode is the default and requires a signed-in Copilot CLI. Sign in once:
copilot auth loginThen verify NightOwl can reach Copilot:
nightowl --checkThis prints GitHub Copilot is available. on success.
nightowl --checkonly validates Copilot availability. It does not validate BYOK credentials, and it is not required before--dry-run.
4. Run your first review
nightowl main feature-branchNightOwl prints progress to the terminal and writes the report under .nightowl/review/<session_id>/ inside the repository. Open index.md in that folder to read the review.
Usage
nightowl <base_ref> <head_ref> [--repo <path>] [--context <value>] [--dry-run]
nightowl --checkbase_ref and head_ref are required; NightOwl reviews the changes from base_ref to head_ref.
| Flag | Description |
|------|-------------|
| --repo <path> | Path to the Git repository (default: current working directory) |
| --context <value> | Background context for the review (PR description, root cause, expected behavior, spec links). Repeatable |
| --dry-run | Run the pipeline locally without calling GitHub Copilot |
| --check | Check that GitHub Copilot is available, then exit |
Examples:
nightowl main feature-branch
nightowl main HEAD --repo /path/to/repo
nightowl main HEAD --context "Performance optimization PR" --context "https://link-to-spec"
nightowl main feature-branch --dry-runProviding --context is recommended: NightOwl feeds it into the review as source-of-truth background (stated requirements, expected behavior, root cause, business context), which produces more relevant findings.
Review Modes
| Mode | How to enable | Requires | Use it for |
|------|---------------|----------|------------|
| Copilot (default) | nothing — it's the default | Copilot subscription + authenticated Copilot CLI | Normal reviews |
| BYOK | set modelProvider.kind: "byok" in config | A provider API key in an env var | Using your own OpenAI/Azure/Anthropic credentials |
Review Output
A review run prints progress to the terminal and writes artifacts to disk:
Starting review run for main...feature-branch.
Output: /path/to/repo/.nightowl/review/feature-branch_03131430
Review run completed.
Planned files: 3
Successful files: 2
Skipped files: 1Output Artifacts
Each run produces output under <repo_root>/.nightowl/review/<session_id>/:
| File | Description |
|------|-------------|
| index.md | Start here. Landing page with review overview, change context, and grouped per-file note links |
| files/*.md | Structured review notes for each file selected for review |
| changeset-overview.md | Run-level overview of the reviewed changeset |
| tool-audit.jsonl | Best-effort tool usage audit log for allow/deny decisions |
Configuration
All configuration is optional. Place a configuration file at <repo_root>/.nightowl/reviewconfig.json:
{
"maxConcurrentFiles": 5,
"modelProvider": {
"kind": "copilot"
},
"mcpServers": {},
"webFetchAllowedHosts": ["docs.example.com", "*.github.com"],
"webFetchDeniedHosts": ["internal.corp.com"]
}| Field | Default | Description |
|-------|---------|-------------|
| maxConcurrentFiles | 5 | Number of files processed in parallel |
| modelProvider | Copilot mode with gpt-5.4-mini | Review model provider configuration |
| mcpServers | {} | Additional MCP servers the AI agent can access during review |
| webFetchAllowedHosts | — | Hosts the AI agent may fetch from via HTTPS during review |
| webFetchDeniedHosts | — | Hosts blocked from AI agent HTTPS fetches; deny rules override allow rules |
To exclude files from review, add a <repo_root>/.nightowl/reviewignore file using .gitignore syntax.
Model Provider
Use explicit Copilot mode to keep Copilot authentication while overriding the model:
{
"modelProvider": {
"kind": "copilot",
"model": "gpt-5.4-mini"
}
}Use BYOK mode to send review sessions through a configured provider:
{
"modelProvider": {
"kind": "byok",
"type": "openai",
"baseUrl": "https://api.openai.com/v1",
"model": "gpt-5.4-mini",
"apiKeyEnv": "OPENAI_API_KEY"
}
}BYOK fields:
| Field | Required | Description |
|-------|----------|-------------|
| kind | Yes | Must be byok for BYOK mode |
| type | Yes | Provider type: openai, azure, or anthropic |
| baseUrl | Yes | Provider API endpoint URL |
| model | Yes | Model name used for every review session |
| apiKeyEnv | One credential required | Environment variable name containing the provider API key |
| bearerTokenEnv | One credential required | Environment variable name containing a bearer token; takes precedence over apiKeyEnv when both are configured |
| wireApi | No | OpenAI/Azure wire API: completions or responses |
| azure.apiVersion | No | Azure API version when using type: "azure" |
Never put secret values in
.nightowl/reviewconfig.json. Store them in environment variables (e.g.OPENAI_API_KEY) and set only the variable name in the config (apiKeyEnv/bearerTokenEnv).
How It Works
NightOwl runs a three-stage review pipeline:
- Changeset Overview: scans the entire changeset once to build global context (scope of changes, cross-file relationships, user-provided context).
- Per-file semantic review: NightOwl runs four steps for each file selected for review: Review Basis, Candidate Findings, Semantic Validation, and Review Summary. Semantic Validation can send a file back through Candidate Findings before Review Summary when more evidence is needed. Files are processed in parallel with bounded concurrency (default 5), while steps remain strictly sequential within each file.
- Run-level finalization: writes the index with review overview, change context, and grouped per-file sections after every file selected for review finishes.
Each per-file step attempt runs in its own Copilot SDK session and must pass deterministic validation before NightOwl uses the result. Per-file steps use three total attempts; if a step fails after those attempts, the file is skipped.
Development
This section is for contributors building on or extending NightOwl. If you just want to run reviews, see Getting Started.
NightOwl is written in TypeScript (strict mode, ESM). Tests use the Node.js built-in test runner (node:test).
npm install # Install dependencies
npm run build # Produce dist/
npm link # Symlink the built `nightowl` command locally
npm test # Build + verify manifest + run all tests
npm run test:unit # Run fast deterministic unit tests
npm run test:integration # Run boundary/collaboration tests
npm run test:e2e # Run published CLI surface checks
npm run typecheck # Type check (tsc --noEmit)The primary test commands (npm test, test:unit, test:integration, test:e2e) run npm run build first, verify test/test-tier-manifest.json, and then execute source test files under test/.
Run a single test file:
npm run build && node --test test/core/orchestrator-bounded-concurrency.test.tsRun locally without building (uses the source entry point directly):
npm run nightowl -- main feature-branchSee TESTING.md for tier decision criteria, test patterns, fixture catalog, and manifest maintenance rules.
Architecture
src/
├── bin/ CLI entry point
├── cli/ CLI argument parsing → RunRequest
├── app/ Composition root: dependency wiring, lifecycle, signal handling
├── core/ Business logic: orchestrator, step runner, steps, finalizers
├── providers/ External I/O adapters (Git, filesystem, config)
└── services/ Copilot SDK session management, tool policy, MCP setupSee AGENTS.md for detailed architecture, layer boundaries, and design rules.
License
This project is licensed under the MIT License.
