This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Argus is a fast, server-rendered GitHub PR review interface. It prioritizes speed and code understanding over interaction density. Built with Fastify, TypeScript, SQLite, and the GitHub API.
# Development (watch mode with hot reload)
npm run dev
# Build TypeScript to JavaScript
npm run build
# Production
npm start
# Database migrations
npm run migrate
# Testing
npm test # Run all tests once
npm run test:watch # Watch modeHTTP Request → Authentication Middleware → Route Handler
↓
GitHub API (via Octokit) + Local Caching (SQLite)
↓
Data Processing (markdown, diff parsing, emoji conversion)
↓
EJS Server-Side Rendering
↓
HTML Response (with optional client-side JS enhancement)
src/routes/pr.ts - The main PR review interface (~600 lines)
- Handles GET
/pr/:owner/:repo/:numberfor PR display - POST endpoints for comments, reviews, inline comments, and merging
- Orchestrates parallel GitHub API calls for PR data
- Tracks PR revisions to detect force pushes
- Caches rendered diffs and PR snapshots by head SHA
src/lib/github.ts - GitHub API integration layer (~550 lines)
- Wraps Octokit REST API with caching
- ETag-based cache with configurable TTL
- Functions for fetching PRs, files, checks, comments, reviews, commits
- Functions for posting comments, submitting reviews, merging PRs
- All mutations go through GitHub API (Argus is read-mostly)
src/lib/diff-parser.ts - Unified diff format parser
- Parses git diff patches into structured data (files, hunks, lines)
- Handles binary files, renames, deletions
- Truncates large files based on
maxLinesPerFileconfig
src/lib/diff-renderer.ts - Diff to HTML converter
- Renders parsed diffs as HTML tables with line numbers
- Supports inline comment forms
- Handles comment threads on specific lines
- Generates file sidebar navigation
src/lib/git.ts - Git operations via shell commands
- Clones bare repos to
/tmp/argus-git-cache - Computes merge-base for PR base tracking
- Generates range-diffs for force push comparison
- Token sanitization in error messages
src/lib/markdown.ts - Markdown rendering
- Uses
markedfor GitHub-flavored markdown - Emoji shortcode conversion via
gemoji(:thumbsup:→ 👍) - Custom link renderer (opens in new tab)
- Task list checkbox support
SQLite with WAL mode. Key tables:
- api_cache - GitHub API response caching with ETags
- pr_snapshots - Immutable PR data snapshots by head SHA
- diff_cache - Rendered diff HTML cache per file
- pr_revisions - Timeline of PR head SHAs (force push detection)
- user_preferences - User settings (e.g., skip range-diff confirmation)
Migrations in migrations/ directory, applied on startup.
Personal Access Token (PAT) authentication via GITHUB_TOKEN environment variable. Token cached as single user object on startup. No OAuth flow currently implemented.
Required GitHub permissions:
- Pull requests: Read/Write
- Contents: Read
- Commit statuses: Read
Environment variables (see src/config.ts):
# Required
GITHUB_TOKEN=github_pat_...
# Optional
PORT=3000
HOST=0.0.0.0
DATABASE_PATH=./data/argus.db
CACHE_TTL=60000 # API cache TTL in ms
BASE_URL=http://localhost:3000public/js/pr.js - Progressive enhancement for PR view
- Polling for PR updates (shows banner when head SHA changes)
- Vim keybindings for file navigation (j/k/o/Enter in Files tab)
- Inline comment form toggling
- Expand/collapse all comments
- Reply button handlers (mention vs quote reply)
- No hydration needed - works without JavaScript
EJS templates in src/templates/. Key templates:
- pr.ejs - Main PR review page (conversation, commits, files tabs)
- layout.ejs - Base HTML wrapper with common header/footer
- range-diff.ejs - Force push comparison view
Templates receive data from route handlers and render server-side.
- Server-rendered HTML - No client-side framework, no hydration delay
- ETag caching - Minimize GitHub API calls while staying fresh
- SQLite with WAL - Simple embedded DB with good read concurrency
- Bare git clones - Efficient shallow fetches for range-diff computation
- Token-based auth - Simple PAT model for personal/team use
- Add function to
src/lib/github.ts:
export async function fetchFoo(octokit: Octokit, owner: string, repo: string) {
const response = await octokit.rest.someNamespace.someMethod({
owner,
repo,
});
return response.data;
}- Import and use in route handler:
import { fetchFoo } from '../lib/github.js';
const foo = await fetchFoo(octokit, owner, repo);- Add route in appropriate file under
src/routes/:
fastify.post('/path', async (request, reply) => {
if (!requireAuth(request, reply)) return;
// Extract params/body
// Call GitHub API
// Redirect back to PR or return JSON
});- Add form in template:
<form method="POST" action="/path">
<input name="field" />
<button type="submit">Submit</button>
</form>- Create migration file:
migrations/00X_description.sql - Run migration:
npm run migrate
Tests use Vitest. Focus on lib utilities (diff parsing, git operations). Route testing can use Fastify's inject method.
Multi-stage build. Migrations run on container startup. Mount /app/data volume for SQLite persistence.
docker compose up