Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
f0eec34
initial commit
D-K-P Nov 14, 2025
9904d13
First pass
D-K-P Nov 17, 2025
04a741f
Started skeletoning out broadcasts
D-K-P Nov 18, 2025
e3ad906
Started cleanup
D-K-P Nov 19, 2025
c8e9db5
Simpified architecture
D-K-P Nov 19, 2025
b3595c7
More experimentation
D-K-P Nov 19, 2025
df16170
More tweaks
D-K-P Nov 20, 2025
ad4ae4a
Simplify
D-K-P Nov 20, 2025
aa50329
Updated the streams to v2
D-K-P Nov 20, 2025
36bcdc1
Now getting a message back but it’s a single chunk
D-K-P Nov 20, 2025
57bd696
Parts coming through now
D-K-P Nov 21, 2025
a35b332
Fixing UI
D-K-P Nov 21, 2025
ce6ca5f
Merge branch 'main' into claude-agent-github-wiki
D-K-P Dec 5, 2025
444c68b
Updated trigger packages
D-K-P Dec 5, 2025
48384a7
Removed duplicate parts streaming
D-K-P Dec 5, 2025
412fdbc
Removed unused code and console logs
D-K-P Dec 5, 2025
a90ae0d
Updated readme
D-K-P Dec 5, 2025
e25ddba
Delete unused file
D-K-P Dec 5, 2025
0537dc6
Added example to the main table
D-K-P Dec 5, 2025
282be2c
Improved the readme tech stack
D-K-P Dec 5, 2025
040c27e
Fixed links
D-K-P Dec 5, 2025
1fd637b
Added missing ‘type’ and updated trigger package
D-K-P Dec 5, 2025
ca78be9
Updated nextjs, removed reactmarkdown and added streamdown
D-K-P Dec 9, 2025
58ca84d
Updated styling
D-K-P Dec 9, 2025
036f5e1
Improved styling and task code
D-K-P Dec 9, 2025
580475e
Updated the readme
D-K-P Dec 10, 2025
e47d632
Fixed text, updated readme
D-K-P Dec 10, 2025
d563f1f
Added video
D-K-P Dec 10, 2025
03dbd99
Updated trigger ver
D-K-P Dec 16, 2025
1ad2055
Added a space
D-K-P Dec 16, 2025
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
86 changes: 86 additions & 0 deletions claude-agent-github-wiki/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# GitHub repository analyzer agent using Claude and Trigger.dev

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.

## Demo video

<video src="https://content.trigger.dev/Claude%20GitHub%20Wiki-example.mp4" controls autoplay loop muted width="100%"></video>

## Tech stack

- [**Next.js**](https://nextjs.org/) – Frontend framework using the 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 environment variables:

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

4. **Start the 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 to the frontend in real-time via Trigger.dev's Realtime Streams
- Cleans up the temp directory on completion or error

## 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 a public 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;
}
22 changes: 22 additions & 0 deletions claude-agent-github-wiki/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import './globals.css';
import type { Metadata } from 'next';
import { Inter } from 'next/font/google';

const inter = Inter({ subsets: ['latin'] });

export const metadata: Metadata = {
title: 'Repo Wiki Chat - Chat with any GitHub repository',
description: 'Ask questions about any GitHub repository and watch AI analyze the code in real-time with live reasoning and tool usage.',
};

export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
</html>
);
}
Loading