gitdiagram (Agent Skills)

GitHub

Free, simple, fast interactive diagrams for any GitHub repository

15,889 stars TypeScript 1 Rule Files Full Docs MCP View JSON API #ai#code#github#system-design

CLAUDE.md

# CLAUDE.md

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

## What this is

GitDiagram turns a GitHub repository into an interactive Mermaid architecture diagram. It is **one Next.js 16 App Router application** (React 19, TypeScript, Tailwind 4, Bun runtime). There is no separate backend β€” the generation API lives in Next.js Route Handlers under `src/app/api/`. Vercel is the only live deployment; the `Dockerfile` and `railway.json` are a dormant Railway disaster-recovery recipe, not a live standby.

## Commands

Bun is the package manager and runtime (`bun install`; `bun ci` for frozen lockfile).

```bash
bun run dev            # dev server (Turbopack) at localhost:3000
bun run test           # all tests (vitest run)
bun run test src/server/generate/graph.test.ts   # single test file
bun run test:watch     # vitest watch mode
bun run lint           # eslint
bun run typecheck      # tsc --noEmit
bun run check          # lint + typecheck
bun run build          # production build
```

Full pre-PR gate: `bun run lint && bun run typecheck && bun run test && bun run build`.

Vitest runs two projects (see `vitest.config.ts`): **server** (`node` env: `src/server/**`, `src/app/api/**`) and **client** (`jsdom` env with testing-library: everything else). Tests are colocated `*.test.ts(x)` files. Path alias `~` β†’ `src/`.

## Architecture

### Generation pipeline (the core of the app)

`/api/generate/stream` (`src/app/api/generate/stream/route.ts`, `runtime = "nodejs"`, `maxDuration = 300`) streams SSE through this pipeline, mostly in `src/server/generate/`:

1. **Ingestion** (`github.ts`) β€” fetch default branch, recursive tree, README via GitHub API; reject truncated/oversized input before any model call.
2. **Explanation stage** β€” streams a plain-English architecture explanation.
3. **Graph stage** (`graph-planner.ts`, `openai.ts`) β€” model returns a strict, size-bounded graph AST (groups/nodes/edges/labels/paths), validated by `graph.ts` (identifiers, connectivity, limits, every linked path checked against the real repo tree). Structural failures are retried with focused feedback up to `MAX_GRAPH_ATTEMPTS`; a graph whose *only* fault is unresolvable node paths is repaired in place instead (`stripUnknownNodePaths`), since a path only drives a node's GitHub link.
4. **Compilation** (`compileDiagramGraph` in `graph.ts`) — deterministic AST→Mermaid compiler with total text escaping and GitHub-only links. `mermaid.ts` is only a re-export of the JSDOM-backed parser in `mermaid-validator.ts`; that parser is intentionally **test-only** (`mermaid.test.ts` contract tests) to keep the server bundle small — do not import it into production code.
5. **Client rendering** (`src/components/mermaid-diagram.tsx`, `src/features/diagram/mermaid-security.ts`) β€” sanitize source, render Mermaid with `securityLevel: "antiscript"` and `htmlLabels: false`, sanitize the resulting SVG with DOMPurify, then re-enforce the GitHub-only link allowlist. (`strict` is not usable here: it disables the `click` directives the diagram depends on, so the allowlist enforcement is what carries that weight.)

Other routes: `/api/generate/cost` (pre-run estimate), `/api/generate/cancel` (distributed cancellation via Redis), `/api/diagram-state` (persisted result contract), `/api/healthz`.

`generation-policy.ts` centralizes model/token/effort constants; `model-config.ts` selects the provider (`AI_PROVIDER` = openai | openrouter β€” both via the OpenAI SDK); `pricing.ts` + `complimentary-gate.ts` handle cost accounting and the free-tier daily token gate.

### Layering

- `src/server/` β€” server-only code (imports `server-only`): generation pipeline, GitHub auth (`github-auth.ts` supports single PAT, PAT pool, or GitHub App), storage, HTTP guards, OG image generation.
- `src/server/http/` β€” `same-origin.ts` / `same-origin-json.ts` / `request-credentials.ts`: mutating API routes require same-origin requests; user GitHub tokens travel per-request and are never persisted server-side. `client-ip.ts` resolves the caller for abuse control only β€” it trusts forwarding headers and is never an authentication signal.
- **Abuse control** β€” generations billed to the server's own key pass through a per-IP fixed-window limiter (`generate/rate-limit.ts`, `GENERATION_RATE_LIMIT_MAX` / `GENERATION_RATE_LIMIT_WINDOW_SECONDS`) before the daily complimentary quota. It fails open on Redis errors because the daily quota still bounds total spend. Callers supplying their own API key are not throttled.
- `src/server/storage/` β€” R2 (`r2.ts`, `artifact-store.ts`) for diagram artifacts, with a **separate private namespace derived from `CACHE_KEY_SECRET`** for private repos (`cache-key.ts`); Upstash Redis (`upstash.ts`) for quota (`quota-store.ts`), cancellation, short-lived failure state (`status-store.ts`), and `distributed-lock.ts` (newest-session-wins persistence in `generation-persistence.ts`).
- `src/features/` β€” client/shared domain logic per feature (diagram SSE parsing, export, github-url parsing, credentials, browse catalog). The graph AST schema/types in `src/features/diagram/graph.ts` are shared between server validation and client.
- `src/hooks/useDiagram.ts` + `src/hooks/diagram/` β€” orchestrate the client generation lifecycle (cost check β†’ stream β†’ render β†’ persist).
- `src/app/[username]/[repo]/` β€” the diagram page; also `/browse`, `/recent`, `/preview`, `/sponsor`.

### Environment

Copy `.env.example` β†’ `.env`. Minimum to run generation locally: R2 vars, `CACHE_KEY_SECRET`, Upstash vars, and one AI provider key. See `docs/dev-setup.md` for the full list.

## Conventions

- Prettier with `prettier-plugin-tailwindcss` (`bun run format:write`); ESLint 9 flat config (`eslint.config.mjs`).
- Server code must not leak into client bundles β€” keep it under `src/server/` behind `server-only`.
- Diagram output safety is defense-in-depth (server validation β†’ deterministic compiler β†’ client sanitization); changes to any layer should keep the others intact and are covered by `mermaid-security.test.ts` and the compiler contract tests.