AI-powered GitHub PR code review, in a terminal.
A developer tool that analyzes GitHub pull requests using Claude AI and presents actionable code review comments in a retro CRT terminal UI. The goal is to ease human code reviews by doing the heavy lifting — showing developers exactly what to post and where.
- PR Analysis: Paste any GitHub PR URL and get a full AI code review with severity-rated comments (critical, warning, suggestion, nitpick)
- Actionable Comments: Each review comment shows the exact file and line number, with a one-click button to post it directly to the GitHub PR
- GitHub Device Flow Auth: Prompted only when needed — public PRs work without login. Private repos trigger a device flow login with a one-time code
- CRT Terminal UI: Retro phosphor-green terminal aesthetic with scanlines, glow effects, ASCII boot sequence, and a blinking cursor
- Three Themes: System (follows OS dark/light), Dark (CRT green-on-black), and Light (paper cream)
- Stateless: No database, no accounts — API keys live in env vars, GitHub tokens held in memory only
- Bun >= 1.0
- An Anthropic API key
- (Optional) A GitHub OAuth App with Device Flow enabled, for private repo access
git clone https://github.com/yourusername/optics.git
cd optics
bun install
cp .env.example .env.local
# Edit .env.local with your ANTHROPIC_API_KEY (and optionally GITHUB_CLIENT_ID)
bun devOpen http://localhost:3000.
bun run test # run all 67 unit tests (Vitest + jsdom)
bun run test:watch # run tests in watch mode
bun run test:ui # open Vitest UI in browser
bun run type-check # TypeScript strict check
bun run lint # ESLint
bun run build # production build| Concern | Choice | Why |
|---|---|---|
| Framework | Next.js 16 App Router | Server-side API routes for secrets, client-side terminal UI |
| AI | Claude Sonnet via @anthropic-ai/sdk |
Structured JSON output for code review comments |
| GitHub | Native fetch |
Only 4 endpoints needed — no Octokit dependency |
| Auth | GitHub Device Flow | Zero-config for public PRs, prompted only when needed |
| Styling | Tailwind CSS v4 | CSS-based config with custom properties for CRT/Paper themes |
| Validation | Zod | Request/response validation on API routes and AI output |
| Font | IBM Plex Mono | Readable monospace that fits the terminal aesthetic |
| Testing | Vitest + Testing Library | Jest-compatible API, Vite-native speed |
User enters PR URL
-> POST /api/analyze
-> fetch GitHub PR metadata + files (parallel)
-> send diff to Claude AI
-> Zod-validate structured JSON response
-> return { metadata, review }
<- render ReviewCards with severity badges
User clicks POST TO GITHUB
-> POST /api/comment
-> post review comment to GitHub PR via API
<- mark comment as posted
optics/
├── app/
│ ├── layout.tsx # Root layout, IBM Plex Mono font
│ ├── globals.css # Tailwind v4, CRT/Paper themes, animations
│ ├── page.tsx # Main terminal page (state machine)
│ └── api/
│ ├── analyze/route.ts # POST: fetch PR + call Claude
│ ├── comment/route.ts # POST: post review comment to GitHub
│ └── auth/
│ ├── device/route.ts # POST: initiate GitHub device flow
│ └── poll/route.ts # POST: poll for device flow token
├── components/
│ ├── Terminal.tsx # Window chrome, scanlines, theme toggle
│ ├── TerminalInput.tsx # Input with blinking cursor
│ ├── TerminalOutput.tsx # Boot sequence, output history, progress bar
│ ├── ReviewCard.tsx # Severity-coded review comment with actions
│ └── StatusBar.tsx # Phase label, stats summary, restart
├── lib/
│ ├── types.ts # All TypeScript types
│ ├── utils.ts # cn() utility
│ ├── github.ts # GitHub API helpers (parse, fetch, post, URL builder)
│ └── ai.ts # Claude API: analyze PR with structured JSON output
└── __tests__/ # Mirrors source structure
├── lib/ # utils, github, ai
└── components/ # Terminal, TerminalInput, TerminalOutput, ReviewCard, StatusBar
Try first, prompt on failure. Public PRs are analyzed without authentication. If GitHub returns 401/403/404, the user is prompted to log in via device flow. This keeps the happy path frictionless.
No streaming. Claude returns complete JSON; the progress bar animation runs client-side while waiting. This simplifies parsing and validation.
CSS-only CRT effects. Scanlines (repeating-linear-gradient), phosphor glow (text-shadow), and cursor blink (keyframes) are all GPU-accelerated CSS — no canvas or WebGL.
Green-only palette. The terminal uses bright/normal/dim green for all UI elements. Pink/red accent is reserved strictly for errors and severity-critical badges. This maintains the authentic CRT look.
API key server-side only. The Anthropic API key lives in ANTHROPIC_API_KEY env var and never touches the client. GitHub tokens are held in React state during the session only, never persisted.
For private repo access via device flow:
- Go to github.com/settings/developers
- Click New OAuth App
- Set Homepage URL to
http://localhost:3000 - Set Callback URL to
http://localhost:3000(not used for device flow, but required) - Check Enable Device Flow
- Copy the Client ID into
GITHUB_CLIENT_IDin.env.local
No client secret needed — device flow uses only the client ID.
- Stream Claude responses for real-time progress
- Batch-post multiple review comments at once
- Persist theme preference to localStorage
- Support GitHub Enterprise URLs
- Deploy to Vercel with edge runtime