Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ For information on how to run each project, see the README in each directory.
| [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) |
| [Claude thinking chatbot](/claude-thinking-chatbot) | A chatbot that uses Claude's thinking capabilities to generate responses |
| [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 |
| [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) |
| [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 |
| [Monorepos](/monorepos) | Examples of using Trigger.dev in monorepo setups with [Turborepo](https://turbo.build/) and [Prisma](https://www.prisma.io/) |
| [Next.js server actions](/nextjs-server-actions) | A [Next.js app](https://nextjs.org/) that triggers Trigger.dev tasks using Server Actions |
Expand Down
8 changes: 8 additions & 0 deletions claude-agent-github-wiki/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Trigger.dev Configuration
# Get these from https://cloud.trigger.dev
TRIGGER_PROJECT_REF=your_project_ref
TRIGGER_SECRET_KEY=your_secret_key

# Claude API Key
# Get from https://console.anthropic.com
ANTHROPIC_API_KEY=your_anthropic_api_key
3 changes: 3 additions & 0 deletions claude-agent-github-wiki/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "next/core-web-vitals"
}
62 changes: 62 additions & 0 deletions claude-agent-github-wiki/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

CLAUDE.md

postgres-data
# dependencies
node_modules
.pnp
.pnp.js

# testing
coverage

# next.js
.next/
out/
dist
packages/**/dist

# Tailwind
apps/**/styles/tailwind.css
packages/**/styles/tailwind.css

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env.docker
.docker/*.env
.env.local
.env.development.local
.env.test.local
.env.production.local

# turbo
.turbo
.vercel
.cache
.env
.output
apps/**/public/build
.tests-container-id.txt
.sentryclirc
.buildt

**/tmp/
/test-results/
/playwright-report/
/playwright/.cache/

.cosine
.trigger
.tshy*
.yarn
*.tsbuildinfo
.claude
105 changes: 105 additions & 0 deletions claude-agent-github-wiki/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# GitHub repository analyzer with Claude Agent SDK

AI-powered repository analyzer that lets you ask questions about any public GitHub repository. Uses Anthropic's Claude Agent SDK with agentic tools to explore codebases and provide detailed answers, with real-time streaming responses to the frontend via Trigger.dev.

## Tech Stack

- [**Next.js**](https://nextjs.org/) – React framework with App Router
- [**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
- [**Trigger.dev**](https://trigger.dev/) – runs the agent in a long-running background task with real-time streaming to the frontend

## Features

- **Ask anything about any public repo** – Architecture, security vulnerabilities, API endpoints, testing strategies, etc.
- **Claude Agent SDK exploration** – Claude explores the codebase and provide detailed answers
- **Cancel anytime** – Abort long-running Trigger.dev task with cleanup
- **Trigger.dev Realtime streaming** – Watch Claude's analysis stream in as it's generated
- **Progress tracking using Trigger.dev Realtime** – See clone status, analysis progress, and repo size

## Setup & Running Locally

1. **Clone the repository**

```bash
git clone <repository-url>
cd claude-agent-github-wiki
```

2. **Install dependencies**

```bash
npm install
```

3. **Copy environment variables and configure**

```bash
cp .env.example .env
```

Fill in the required variables:

- `TRIGGER_SECRET_KEY` – Get from [Trigger.dev dashboard](https://cloud.trigger.dev/)
- `TRIGGER_PROJECT_REF` – Your Trigger.dev project ref (starts with `proj_`)
- `ANTHROPIC_API_KEY` – Get from [Anthropic Console](https://console.anthropic.com/)

4. **Start development servers**

```bash
# Terminal 1: Start Next.js dev server
npm run dev

# Terminal 2: Start Trigger.dev CLI
npx trigger.dev@latest dev
```

Open [http://localhost:3000](http://localhost:3000)

## How It Works

Trigger.dev orchestrates the repository analysis through a single long-running task:

1. **`analyzeRepo`** – Main task that:
- Clones the repository to a temp directory (shallow clone for speed)
- Spawns a Claude agent with file system tools
- Streams Claude's response in real-time via Trigger.dev Realtime Streams
- Cleans up temp directory on completion or error

**Process flow:**

```
User enters GitHub URL + question
API triggers analyzeRepo task
Clone repo to temp directory
Claude Agent SDK explores codebase with tools
Response streams via Trigger.dev Realtime → Frontend
Cleanup temp directory
```

**Claude's available tools:**

- **Bash** – Run shell commands to explore the repo
- **Glob** – Find files by pattern (e.g., `**/*.ts`)
- **Grep** – Search file contents with regex
- **Read** – Read file contents

## Relevant Code

- **Main analysis task** – Clones repo, runs Claude agent, streams response ([`trigger/analyze-repo.ts`](trigger/analyze-repo.ts))
- **Stream definition** – Typed stream for real-time text responses ([`trigger/agent-stream.ts`](trigger/agent-stream.ts))
- **API endpoint** – Triggers the task and returns access token ([`app/api/analyze-repo/route.ts`](app/api/analyze-repo/route.ts))
- **Response page** – Real-time streaming display with progress ([`app/response/[runId]/page.tsx`](app/response/[runId]/page.tsx))
- **Landing page** – Repository URL input with example repos ([`app/page.tsx`](app/page.tsx))
- **Trigger.dev config** – Project settings with external SDK bundle ([`trigger.config.ts`](trigger.config.ts))

## Learn More

- [**Trigger.dev Realtime Streams**](https://trigger.dev/docs/realtime/streams) – Stream data from tasks to your frontend
- [**Trigger.dev React Hooks**](https://trigger.dev/docs/realtime/react-hooks/overview) – `useRealtimeStream` for consuming streams
- [**Claude Agent SDK**](https://platform.claude.com/docs/en/agent-sdk/overview) – Run Claude with agentic tool usage
- [**Trigger.dev schemaTask**](https://trigger.dev/docs/tasks/schemaTask) – Type-safe task payloads with Zod
29 changes: 29 additions & 0 deletions claude-agent-github-wiki/app/api/abort/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { runs } from "@trigger.dev/sdk";
import { NextRequest, NextResponse } from "next/server";

export async function POST(request: NextRequest) {
try {
const { runId } = await request.json();

// Validate input
if (!runId || typeof runId !== "string") {
return NextResponse.json(
{ error: "Run ID is required" },
{ status: 400 }
);
}

// Cancel the running task
// This will trigger the AbortController in the task, which propagates to the Claude agent
await runs.cancel(runId);

return NextResponse.json({ success: true });

} catch (error: any) {
console.error("Failed to abort task:", error);
return NextResponse.json(
{ error: error.message || "Failed to abort task" },
{ status: 500 }
);
}
}
54 changes: 54 additions & 0 deletions claude-agent-github-wiki/app/api/analyze-repo/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { tasks } from "@trigger.dev/sdk";
import type { analyzeRepo } from "@/trigger/analyze-repo";
import { NextRequest, NextResponse } from "next/server";

export async function POST(request: NextRequest) {
try {
const { repoUrl, question } = await request.json();

// Validate inputs
if (!repoUrl || typeof repoUrl !== "string") {
return NextResponse.json(
{ error: "Repository URL is required" },
{ status: 400 },
);
}

if (!question || typeof question !== "string") {
return NextResponse.json(
{ error: "Question is required" },
{ status: 400 },
);
}

// Basic GitHub URL validation
const githubUrlPattern = /^https?:\/\/(www\.)?github\.com\/[\w-]+\/[\w.-]+/;
if (!githubUrlPattern.test(repoUrl)) {
return NextResponse.json(
{ error: "Invalid GitHub URL format" },
{ status: 400 },
);
}

// Trigger the analyze task
const handle = await tasks.trigger<typeof analyzeRepo>(
"analyze-repo",
{ repoUrl, question },
);

// Get public access token from handle (auto-generated, expires in 15 min)
const accessToken = handle.publicAccessToken;

// Return run details
return NextResponse.json({
runId: handle.id,
accessToken,
});
} catch (error: any) {
console.error("Failed to trigger analyze-repo task:", error);
return NextResponse.json(
{ error: error.message || "Failed to start analysis" },
{ status: 500 },
);
}
}
102 changes: 102 additions & 0 deletions claude-agent-github-wiki/app/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

:root {
--foreground-rgb: 0, 0, 0;
--background-start-rgb: 214, 219, 220;
--background-end-rgb: 255, 255, 255;
}

@media (prefers-color-scheme: dark) {
:root {
--foreground-rgb: 255, 255, 255;
--background-start-rgb: 0, 0, 0;
--background-end-rgb: 0, 0, 0;
}
}

@layer base {
:root {
--background: 0 0% 100%;
--foreground: 0 0% 3.9%;
--card: 0 0% 100%;
--card-foreground: 0 0% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 0 0% 3.9%;
--primary: 0 0% 9%;
--primary-foreground: 0 0% 98%;
--secondary: 0 0% 96.1%;
--secondary-foreground: 0 0% 9%;
--muted: 0 0% 96.1%;
--muted-foreground: 0 0% 45.1%;
--accent: 0 0% 96.1%;
--accent-foreground: 0 0% 9%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 0 0% 89.8%;
--input: 0 0% 89.8%;
--ring: 0 0% 3.9%;
--chart-1: 12 76% 61%;
--chart-2: 173 58% 39%;
--chart-3: 197 37% 24%;
--chart-4: 43 74% 66%;
--chart-5: 27 87% 67%;
--radius: 0.5rem;
}
.dark {
--background: 0 0% 3.9%;
--foreground: 0 0% 98%;
--card: 0 0% 3.9%;
--card-foreground: 0 0% 98%;
--popover: 0 0% 3.9%;
--popover-foreground: 0 0% 98%;
--primary: 0 0% 98%;
--primary-foreground: 0 0% 9%;
--secondary: 0 0% 14.9%;
--secondary-foreground: 0 0% 98%;
--muted: 0 0% 14.9%;
--muted-foreground: 0 0% 63.9%;
--accent: 0 0% 14.9%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 0 0% 14.9%;
--input: 0 0% 14.9%;
--ring: 0 0% 83.1%;
--chart-1: 220 70% 50%;
--chart-2: 160 60% 45%;
--chart-3: 30 80% 55%;
--chart-4: 280 65% 60%;
--chart-5: 340 75% 55%;
}
}

@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}

@keyframes bounce {
0%, 100% {
transform: translateY(0);
}
50% {
transform: translateY(-0.5rem);
}
}

.animate-bounce {
animation: bounce 0.6s ease-in-out infinite;
}

.line-clamp-3 {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
Loading