Skip to content

Commit 5bacf16

Browse files
authored
Merge pull request #87 from triggerdotdev/claude-agent-github-wiki
2 parents e50a0ad + 2f259b8 commit 5bacf16

30 files changed

+14513
-1
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ For information on how to run each project, see the README in each directory.
2727
| [Building effective agents](/building-effective-agents) | 5 different patterns for building effective AI agents with Trigger.dev; [Prompt chaining](/building-effective-agents/src/trigger/trigger/translate-copy.ts), [Routing](/building-effective-agents/src/trigger/trigger/routing-questions.ts), [Parallelization](/building-effective-agents/src/trigger/trigger/parallel-llm-calls.ts), [Orchestrator-workers](/building-effective-agents/src/trigger/trigger/orchestrator-workers.ts) |
2828
| [Claude thinking chatbot](/claude-thinking-chatbot) | A chatbot that uses Claude's thinking capabilities to generate responses |
2929
| [Claude agent SDK](/claude-agent-sdk-trigger) | A simple example of how to use the [Claude Agent SDK](https://docs.claude.com/en/docs/agent-sdk/overview) with Trigger.dev |
30+
| [Claude agent GitHub wiki](/claude-agent-github-wiki) | AI-powered repository analyzer that lets you ask questions about any public GitHub repository using Anthropic's [Claude Agent SDK](https://platform.claude.com/docs/en/agent-sdk/overview), with real-time streaming via [Trigger.dev Realtime](https://trigger.dev/docs/realtime/overview) |
3031
| [Deep research agent using the AI SDK](/vercel-ai-sdk-deep-research-agent/) | An intelligent deep research agent using the Vercel [AI SDK](https://sdk.vercel.ai/docs/introduction) and Trigger.dev |
3132
| [Monorepos](/monorepos) | Examples of using Trigger.dev in monorepo setups with [Turborepo](https://turbo.build/) and [Prisma](https://www.prisma.io/) |
3233
| [Next.js server actions](/nextjs-server-actions) | A [Next.js app](https://nextjs.org/) that triggers Trigger.dev tasks using Server Actions |
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Trigger.dev Configuration
2+
# Get these from https://cloud.trigger.dev
3+
TRIGGER_PROJECT_REF=your_project_ref
4+
TRIGGER_SECRET_KEY=your_secret_key
5+
6+
# Claude API Key
7+
# Get from https://console.anthropic.com
8+
ANTHROPIC_API_KEY=your_anthropic_api_key
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"extends": "next/core-web-vitals"
3+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
CLAUDE.md
4+
5+
postgres-data
6+
# dependencies
7+
node_modules
8+
.pnp
9+
.pnp.js
10+
11+
# testing
12+
coverage
13+
14+
# next.js
15+
.next/
16+
out/
17+
dist
18+
packages/**/dist
19+
20+
# Tailwind
21+
apps/**/styles/tailwind.css
22+
packages/**/styles/tailwind.css
23+
24+
# misc
25+
.DS_Store
26+
*.pem
27+
28+
# debug
29+
npm-debug.log*
30+
yarn-debug.log*
31+
yarn-error.log*
32+
33+
# local env files
34+
.env.docker
35+
.docker/*.env
36+
.env.local
37+
.env.development.local
38+
.env.test.local
39+
.env.production.local
40+
41+
# turbo
42+
.turbo
43+
.vercel
44+
.cache
45+
.env
46+
.output
47+
apps/**/public/build
48+
.tests-container-id.txt
49+
.sentryclirc
50+
.buildt
51+
52+
**/tmp/
53+
/test-results/
54+
/playwright-report/
55+
/playwright/.cache/
56+
57+
.cosine
58+
.trigger
59+
.tshy*
60+
.yarn
61+
*.tsbuildinfo
62+
.claude

claude-agent-github-wiki/README.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# GitHub repository analyzer agent using Claude and Trigger.dev
2+
3+
This demo shows how to build a simple AI-powered repository analyzer that lets you ask questions about any public GitHub repository, using [Trigger.dev](https://trigger.dev/) for workflow orchestration, streaming, and showing progress on the frontend and [Anthropic's Claude Agent SDK](https://platform.claude.com/docs/en/agent-sdk/overview) for the agentic loop.
4+
5+
## Demo video
6+
7+
<video src="https://content.trigger.dev/Claude%20GitHub%20Wiki-example.mp4" controls autoplay loop muted width="100%"></video>
8+
9+
## Tech stack
10+
11+
- [**Next.js**](https://nextjs.org/) – Frontend framework using the App Router
12+
- [**Claude Agent SDK**](https://platform.claude.com/docs/en/agent-sdk/overview) – Anthropic's SDK for building AI agents; provides an agentic loop with shell, file, and search tools
13+
- [**Trigger.dev**](https://trigger.dev/) – runs the agent in a long-running background task with real-time streaming to the frontend
14+
15+
## Features
16+
17+
- **Ask anything about any public repo** – Architecture, security vulnerabilities, API endpoints, testing strategies, etc.
18+
- **Claude Agent SDK exploration** – Claude explores the codebase and provide detailed answers
19+
- **Cancel anytime** – Abort long-running Trigger.dev task with cleanup
20+
- **Trigger.dev Realtime streaming** – Watch Claude's analysis stream in as it's generated
21+
- **Progress tracking using Trigger.dev Realtime** – See clone status, analysis progress, and repo size
22+
23+
## Setup & running locally
24+
25+
1. **Clone the repository**
26+
27+
```bash
28+
git clone <repository-url>
29+
cd claude-agent-github-wiki
30+
```
31+
32+
2. **Install dependencies**
33+
34+
```bash
35+
npm install
36+
```
37+
38+
3. **Copy environment variables and configure**
39+
40+
```bash
41+
cp .env.example .env
42+
```
43+
44+
Fill in the required environment variables:
45+
46+
- `TRIGGER_SECRET_KEY` – Get this from the [Trigger.dev dashboard](https://cloud.trigger.dev/)
47+
- `TRIGGER_PROJECT_REF` – Your Trigger.dev project ref (starts with `proj_`)
48+
- `ANTHROPIC_API_KEY` – Get this from the [Anthropic Console](https://console.anthropic.com/)
49+
50+
4. **Start the development servers**
51+
52+
```bash
53+
# Terminal 1: Start Next.js dev server
54+
npm run dev
55+
56+
# Terminal 2: Start Trigger.dev CLI
57+
npx trigger.dev@latest dev
58+
```
59+
60+
Open [http://localhost:3000](http://localhost:3000)
61+
62+
## How it works
63+
64+
Trigger.dev orchestrates the repository analysis through a single long-running task:
65+
66+
1. **`analyzeRepo`** – Main task that:
67+
- Clones the repository to a temp directory (shallow clone for speed)
68+
- Spawns a Claude agent with file system tools
69+
- Streams Claude's response to the frontend in real-time via Trigger.dev's Realtime Streams
70+
- Cleans up the temp directory on completion or error
71+
72+
## Relevant code
73+
74+
- **Main analysis task** – Clones repo, runs Claude agent, streams response ([`trigger/analyze-repo.ts`](trigger/analyze-repo.ts))
75+
- **Stream definition** – Typed stream for real-time text responses ([`trigger/agent-stream.ts`](trigger/agent-stream.ts))
76+
- **API endpoint** – Triggers the task and returns a public access token ([`app/api/analyze-repo/route.ts`](app/api/analyze-repo/route.ts))
77+
- **Response page** – Real-time streaming display with progress ([`app/response/[runId]/page.tsx`](app/response/[runId]/page.tsx))
78+
- **Landing page** – Repository URL input with example repos ([`app/page.tsx`](app/page.tsx))
79+
- **Trigger.dev config** – Project settings with external SDK bundle ([`trigger.config.ts`](trigger.config.ts))
80+
81+
## Learn more
82+
83+
- [**Trigger.dev Realtime Streams**](https://trigger.dev/docs/realtime/streams) – Stream data from tasks to your frontend
84+
- [**Trigger.dev React Hooks**](https://trigger.dev/docs/realtime/react-hooks/overview)`useRealtimeStream` for consuming streams
85+
- [**Claude Agent SDK**](https://platform.claude.com/docs/en/agent-sdk/overview) – Run Claude with agentic tool usage
86+
- [**Trigger.dev schemaTask**](https://trigger.dev/docs/tasks/schemaTask) – Type-safe task payloads with Zod
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { runs } from "@trigger.dev/sdk";
2+
import { NextRequest, NextResponse } from "next/server";
3+
4+
export async function POST(request: NextRequest) {
5+
try {
6+
const { runId } = await request.json();
7+
8+
// Validate input
9+
if (!runId || typeof runId !== "string") {
10+
return NextResponse.json(
11+
{ error: "Run ID is required" },
12+
{ status: 400 }
13+
);
14+
}
15+
16+
// Cancel the running task
17+
// This will trigger the AbortController in the task, which propagates to the Claude agent
18+
await runs.cancel(runId);
19+
20+
return NextResponse.json({ success: true });
21+
22+
} catch (error: any) {
23+
console.error("Failed to abort task:", error);
24+
return NextResponse.json(
25+
{ error: error.message || "Failed to abort task" },
26+
{ status: 500 }
27+
);
28+
}
29+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { tasks } from "@trigger.dev/sdk";
2+
import type { analyzeRepo } from "@/trigger/analyze-repo";
3+
import { NextRequest, NextResponse } from "next/server";
4+
5+
export async function POST(request: NextRequest) {
6+
try {
7+
const { repoUrl, question } = await request.json();
8+
9+
// Validate inputs
10+
if (!repoUrl || typeof repoUrl !== "string") {
11+
return NextResponse.json(
12+
{ error: "Repository URL is required" },
13+
{ status: 400 },
14+
);
15+
}
16+
17+
if (!question || typeof question !== "string") {
18+
return NextResponse.json(
19+
{ error: "Question is required" },
20+
{ status: 400 },
21+
);
22+
}
23+
24+
// Basic GitHub URL validation
25+
const githubUrlPattern = /^https?:\/\/(www\.)?github\.com\/[\w-]+\/[\w.-]+/;
26+
if (!githubUrlPattern.test(repoUrl)) {
27+
return NextResponse.json(
28+
{ error: "Invalid GitHub URL format" },
29+
{ status: 400 },
30+
);
31+
}
32+
33+
// Trigger the analyze task
34+
const handle = await tasks.trigger<typeof analyzeRepo>(
35+
"analyze-repo",
36+
{ repoUrl, question },
37+
);
38+
39+
// Get public access token from handle (auto-generated, expires in 15 min)
40+
const accessToken = handle.publicAccessToken;
41+
42+
// Return run details
43+
return NextResponse.json({
44+
runId: handle.id,
45+
accessToken,
46+
});
47+
} catch (error: any) {
48+
console.error("Failed to trigger analyze-repo task:", error);
49+
return NextResponse.json(
50+
{ error: error.message || "Failed to start analysis" },
51+
{ status: 500 },
52+
);
53+
}
54+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
@tailwind base;
2+
@tailwind components;
3+
@tailwind utilities;
4+
5+
:root {
6+
--foreground-rgb: 0, 0, 0;
7+
--background-start-rgb: 214, 219, 220;
8+
--background-end-rgb: 255, 255, 255;
9+
}
10+
11+
@media (prefers-color-scheme: dark) {
12+
:root {
13+
--foreground-rgb: 255, 255, 255;
14+
--background-start-rgb: 0, 0, 0;
15+
--background-end-rgb: 0, 0, 0;
16+
}
17+
}
18+
19+
@layer base {
20+
:root {
21+
--background: 0 0% 100%;
22+
--foreground: 0 0% 3.9%;
23+
--card: 0 0% 100%;
24+
--card-foreground: 0 0% 3.9%;
25+
--popover: 0 0% 100%;
26+
--popover-foreground: 0 0% 3.9%;
27+
--primary: 0 0% 9%;
28+
--primary-foreground: 0 0% 98%;
29+
--secondary: 0 0% 96.1%;
30+
--secondary-foreground: 0 0% 9%;
31+
--muted: 0 0% 96.1%;
32+
--muted-foreground: 0 0% 45.1%;
33+
--accent: 0 0% 96.1%;
34+
--accent-foreground: 0 0% 9%;
35+
--destructive: 0 84.2% 60.2%;
36+
--destructive-foreground: 0 0% 98%;
37+
--border: 0 0% 89.8%;
38+
--input: 0 0% 89.8%;
39+
--ring: 0 0% 3.9%;
40+
--chart-1: 12 76% 61%;
41+
--chart-2: 173 58% 39%;
42+
--chart-3: 197 37% 24%;
43+
--chart-4: 43 74% 66%;
44+
--chart-5: 27 87% 67%;
45+
--radius: 0.5rem;
46+
}
47+
.dark {
48+
--background: 0 0% 3.9%;
49+
--foreground: 0 0% 98%;
50+
--card: 0 0% 3.9%;
51+
--card-foreground: 0 0% 98%;
52+
--popover: 0 0% 3.9%;
53+
--popover-foreground: 0 0% 98%;
54+
--primary: 0 0% 98%;
55+
--primary-foreground: 0 0% 9%;
56+
--secondary: 0 0% 14.9%;
57+
--secondary-foreground: 0 0% 98%;
58+
--muted: 0 0% 14.9%;
59+
--muted-foreground: 0 0% 63.9%;
60+
--accent: 0 0% 14.9%;
61+
--accent-foreground: 0 0% 98%;
62+
--destructive: 0 62.8% 30.6%;
63+
--destructive-foreground: 0 0% 98%;
64+
--border: 0 0% 14.9%;
65+
--input: 0 0% 14.9%;
66+
--ring: 0 0% 83.1%;
67+
--chart-1: 220 70% 50%;
68+
--chart-2: 160 60% 45%;
69+
--chart-3: 30 80% 55%;
70+
--chart-4: 280 65% 60%;
71+
--chart-5: 340 75% 55%;
72+
}
73+
}
74+
75+
@layer base {
76+
* {
77+
@apply border-border;
78+
}
79+
body {
80+
@apply bg-background text-foreground;
81+
}
82+
}
83+
84+
@keyframes bounce {
85+
0%, 100% {
86+
transform: translateY(0);
87+
}
88+
50% {
89+
transform: translateY(-0.5rem);
90+
}
91+
}
92+
93+
.animate-bounce {
94+
animation: bounce 0.6s ease-in-out infinite;
95+
}
96+
97+
.line-clamp-3 {
98+
display: -webkit-box;
99+
-webkit-line-clamp: 3;
100+
-webkit-box-orient: vertical;
101+
overflow: hidden;
102+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import './globals.css';
2+
import type { Metadata } from 'next';
3+
import { Inter } from 'next/font/google';
4+
5+
const inter = Inter({ subsets: ['latin'] });
6+
7+
export const metadata: Metadata = {
8+
title: 'Repo Wiki Chat - Chat with any GitHub repository',
9+
description: 'Ask questions about any GitHub repository and watch AI analyze the code in real-time with live reasoning and tool usage.',
10+
};
11+
12+
export default function RootLayout({
13+
children,
14+
}: {
15+
children: React.ReactNode;
16+
}) {
17+
return (
18+
<html lang="en">
19+
<body className={inter.className}>{children}</body>
20+
</html>
21+
);
22+
}

0 commit comments

Comments
 (0)