Skip to content

Latest commit

 

History

History
207 lines (153 loc) · 5.81 KB

File metadata and controls

207 lines (153 loc) · 5.81 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

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 Commands

# 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 mode

Architecture

Request Flow

HTTP 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)

Core Components

src/routes/pr.ts - The main PR review interface (~600 lines)

  • Handles GET /pr/:owner/:repo/:number for 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 maxLinesPerFile config

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 marked for GitHub-flavored markdown
  • Emoji shortcode conversion via gemoji (:thumbsup: → 👍)
  • Custom link renderer (opens in new tab)
  • Task list checkbox support

Database Schema

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.

Authentication

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

Configuration

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:3000

Client-Side JavaScript

public/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

Templates

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.

Key Architectural Decisions

  1. Server-rendered HTML - No client-side framework, no hydration delay
  2. ETag caching - Minimize GitHub API calls while staying fresh
  3. SQLite with WAL - Simple embedded DB with good read concurrency
  4. Bare git clones - Efficient shallow fetches for range-diff computation
  5. Token-based auth - Simple PAT model for personal/team use

Code Patterns

Adding a new GitHub API call

  1. 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;
}
  1. Import and use in route handler:
import { fetchFoo } from '../lib/github.js';

const foo = await fetchFoo(octokit, owner, repo);

Adding a new POST endpoint

  1. 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
});
  1. Add form in template:
<form method="POST" action="/path">
  <input name="field" />
  <button type="submit">Submit</button>
</form>

Adding a new database table

  1. Create migration file: migrations/00X_description.sql
  2. Run migration: npm run migrate

Testing

Tests use Vitest. Focus on lib utilities (diff parsing, git operations). Route testing can use Fastify's inject method.

Docker

Multi-stage build. Migrations run on container startup. Mount /app/data volume for SQLite persistence.

docker compose up