RepoPilot AI is a single-page app that turns any public repository into an interactive, AI-explorable map of its codebase. Paste a repository URL and RepoPilot will clone it, statically analyze the source, render an interactive Mermaid.js architecture diagram, and let you chat with an AI that reads the actual source files to answer your questions.
✨ Live screenshot — connect screen, real analysis, and AI chat all in one place:
| Interactive architecture graph | Repository overview + AI chat |
|---|---|
![]() |
![]() |
| File browser with syntax highlighting |
|---|
![]() |
- 🧠 Automated Static Analysis — Downloads the repository as a tarball and parses
.ts,.js,.tsx,.jsx,.py,.java,.go, and.rsfiles with@babel/parserto build an AST and map real import/export relationships. Code is analyzed, never executed. - 📊 Interactive Architecture Visualization — Converts the file tree and dependency map into a live Mermaid.js graph rendered client-side, with module-level clustering based on real import edges.
- 💬 Deep-Context AI Chat — Powered by the Vercel AI SDK and OpenRouter. Before answering, the model receives the repository structure, the dependency map, and the currently selected file — injected via a token-limited context builder.
- 📂 Dynamic File Previews — Browse the real file tree and click any file to view its raw source with high-fidelity syntax highlighting (
react-syntax-highlighter). - ⚡ Ephemeral Server-Side Caching — Repositories are extracted into
os.tmpdir(). Stale copies (older than 1 hour) are pruned automatically on the next analysis. No database required. - 🏔 Large-Repository Support — Single-request tarball downloads (no
gitbinary needed, so it runs on any serverless runtime), a 5-minute route budget, and capped, concurrent import parsing keep big monorepos responsive. Files beyond the parse cap are still browsable — only deep dependency edges are skipped. - 🔒 Security First — Public-host URL validation, directory-traversal protection on the file endpoint, and no execution of untrusted code.
- Framework: Next.js 16 (App Router, Turbopack), React 19, TypeScript
- Styling: Tailwind CSS 4 with a custom GitHub-shell UI
- AI: Vercel AI SDK (
ai),@openrouter/ai-sdk-provider - Analysis:
@babel/parser,@babel/traverse,tar(archive extraction) - Visualization:
mermaid,react-syntax-highlighter
- Node.js 18+ (tested with Node 24)
pnpmandgiton your machine
pnpm installCreate a .env.local file in the project root (or copy .env.example):
OPENROUTER_API_KEY=your_openrouter_api_key_hereGet a key at https://openrouter.ai/keys.
| Variable | Required | Default | Description |
|---|---|---|---|
OPENROUTER_API_KEY |
✅ Yes | — | Your OpenRouter API key |
OPENROUTER_MODEL |
❌ No | google/gemini-2.5-flash |
Chat model override |
OPENROUTER_MAX_TOKENS |
❌ No | 2048 |
Cap on AI completion tokens (lower = cheaper on limited credits) |
MAX_ANALYZED_FILES |
❌ No | 3000 |
Cap on files parsed for import edges (keeps large repos fast) |
ANALYZE_CONCURRENCY |
❌ No | 16 |
Parallelism while parsing imports |
pnpm run devOpen http://localhost:3000, paste a public repository URL (e.g. https://github.com/owner/repo), and click Analyze repository.
pnpm build
pnpm startgraph TD
U([User]) --> FE[Next.js Single-Page UI]
FE -->|"POST /api/analyze (gitUrl)"| AN[Analyze Route]
AN -->|git clone| TMP[(os.tmpdir cache)]
AN -->|AST parse via Babel| AST[Babel Parser & Analyzer]
AST -->|imports / exports| DEP[Dependency Map]
AST -->|file tree| TREE[File Tree]
TREE --> GRAPH[Graph Builder]
DEP --> GRAPH
GRAPH -->|Mermaid DSL| FE
FE -->|"GET /api/file?repoPath&filePath"| FAPI[File Route]
FAPI -->|path-traversal check| TMP
FAPI -->|source + syntax highlight| FE
FE -->|"POST /api/chat"| CHAT[Chat Route]
CHAT -->|buildSystemPrompt + buildCodeContext| CTX[Context Builder]
CTX -->|reads cached files, truncates to token limit| TMP
CHAT -->|streams prompt| AI[OpenRouter via Vercel AI SDK]
AI -->|streamed tokens| FE
The pipeline:
- Fetch — The backend downloads the repository as a tarball (GitHub, GitLab, Bitbucket, and Codeberg all expose one for the default branch) and extracts it into
os.tmpdir(). Nogitbinary is required, so this works on any serverless runtime. - Analyze — A custom AST traversal (
@babel/parser+@babel/traverse) scans supported source files to discover local and external imports and build a nested file tree. Parsing runs concurrently and is capped byMAX_ANALYZED_FILESso huge monorepos stay fast. - Graph — The file tree and dependency map are fused into a Mermaid.js architecture graph with module-level nodes and dependency edges.
- Context injection — When you chat,
lib/context-builder.tsreads the relevant cached files and the selected file, truncates everything to a token budget, and streams the model's answer back into the UI.
| Endpoint | Method | Description | Request | Response |
|---|---|---|---|---|
/api/analyze |
POST |
Clone & statically analyze a public repo | FormData field gitUrl |
{ success: boolean, data: AnalysisResult } |
/api/file |
GET |
Fetch a source file from the cached clone | Query repoPath, filePath |
{ success: boolean, data: { content: string } } |
/api/chat |
POST |
Stream an AI answer grounded in repo context | JSON { message, repositoryAnalysis, selectedFile } |
text/event-stream |
All endpoints accept multipart/form-data / JSON as noted, return 400 for invalid input, 403 for path-traversal attempts, and 500 with a human-readable error field on failure.
├── app/
│ ├── page.tsx # Single-page app: analyze, graph, files, chat
│ ├── layout.tsx # Root layout & fonts
│ ├── globals.css # GitHub-shell theme + UI styles
│ └── api/
│ ├── analyze/route.ts # Clone + AST analysis (with stale-clone cleanup)
│ ├── chat/route.ts # OpenRouter streaming chat
│ └── file/route.ts # Serve raw file contents (path-safe)
├── components/ui/ # Reusable UI primitives (Button, Input)
├── lib/
│ ├── analyzer.ts # Babel parsing, file tree & dependency extraction
│ ├── graph-builder.ts # Mermaid.js architecture graph generation
│ ├── context-builder.ts # LLM context assembly & token limiting
│ ├── types.ts # Shared TypeScript interfaces
│ └── utils.ts # Small helpers (cn)
├── public/
│ └── screenshots/ # README screenshots
├── .env.local # Local secrets (git-ignored)
├── .env.example # Documented environment template
├── eslint.config.mjs # ESLint 9 flat config
└── next.config.mjs # Next.js config (server external packages)
- Only
httpsURLs on public git hosts (GitHub, GitLab, Bitbucket, Codeberg) are accepted; anything else is rejected with a400. - The file API normalizes and resolves paths against the clone root, blocking
../traversal. - Clones live in
os.tmpdir()and are garbage-collected after 1 hour on the next analysis; uploads are removed immediately after analysis. - Repositories are read and parsed — never executed — so untrusted code is safe to analyze.
- In the UI, folder contents are capped at 250 items per directory to keep very large trees rendering smoothly.
Contributions are welcome! Open an issue or a pull request on GitHub.
Built to demonstrate robust software engineering, scalable architecture, and an obsession with developer experience.



