Skip to content

Commit 4f95cd6

Browse files
authored
Merge pull request #88 from triggerdotdev/claude-changelog-generator
Claude changelog generator
2 parents f1ef4f8 + 9e634a2 commit 4f95cd6

27 files changed

Lines changed: 15913 additions & 55 deletions

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,7 @@ yarn-error.log*
4848
apps/**/public/build
4949
.tests-container-id.txt
5050
/app/routes/_marketing-site.components
51+
52+
# Misc
53+
CLAUDE.md
54+
ARCHITECTURE.md

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 changelog generator](/changelog-generator) | Generate changelogs from a GitHub repository using the [Claude Agent SDK](https://docs.claude.com/en/docs/agent-sdk/overview) with Trigger.dev |
3031
| [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) |
3132
| [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 |
3233
| [Monorepos](/monorepos) | Examples of using Trigger.dev in monorepo setups with [Turborepo](https://turbo.build/) and [Prisma](https://www.prisma.io/) |

changelog-generator/.env.example

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Trigger.dev - get from https://cloud.trigger.dev
2+
TRIGGER_SECRET_KEY=tr_dev_xxx
3+
TRIGGER_PROJECT_REF=proj_xxx
4+
5+
# Anthropic - get from https://console.anthropic.com
6+
ANTHROPIC_API_KEY=sk-ant-xxx
7+
8+
# GitHub (optional) - for private repos, needs `repo` scope
9+
GITHUB_TOKEN=ghp_xxx

changelog-generator/.eslintrc.json

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+
}

changelog-generator/.gitignore

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

changelog-generator/README.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Changelog generator using the Claude Agent SDK and Trigger.dev
2+
3+
An AI agent that explores GitHub commits, investigates unclear changes by fetching diffs on demand, and generates developer-friendly changelogs. Built with the Claude Agent SDK and Trigger.dev.
4+
5+
## Tech Stack
6+
7+
- **[Next.js](https://nextjs.org)** – Frontend framework using App Router
8+
- **[Claude Agent SDK](https://github.com/anthropics/claude-agent-sdk)** – Anthropic's agent SDK for building AI agents with custom tools
9+
- **[Trigger.dev](https://trigger.dev)** – Background task orchestration with real-time streaming to the frontend, observability, and deployment.
10+
- **[Octokit](https://github.com/octokit/octokit.js)** – GitHub API client for fetching commits and diffs.
11+
12+
## Demo
13+
14+
<video src="https://content.trigger.dev/claude-changelog-generator.mp4" controls autoplay loop muted width="100%"></video>
15+
16+
## Running the project locally
17+
18+
1. **Install dependencies**
19+
20+
```bash
21+
npm install
22+
```
23+
24+
2. **Configure environment variables**
25+
26+
```bash
27+
cp .env.example .env
28+
```
29+
30+
- `TRIGGER_SECRET_KEY` – From [Trigger.dev dashboard](https://cloud.trigger.dev/)
31+
- `TRIGGER_PROJECT_REF` – Your project ref (starts with `proj_`)
32+
- `ANTHROPIC_API_KEY` – From [Anthropic Console](https://console.anthropic.com/)
33+
- `GITHUB_TOKEN` (optional) – For private repos, needs `repo` scope
34+
35+
3. **Start development servers**
36+
37+
```bash
38+
# Terminal 1: Next.js
39+
npm run dev
40+
41+
# Terminal 2: Trigger.dev
42+
npx trigger.dev@latest dev
43+
```
44+
45+
4. Open [http://localhost:3000](http://localhost:3000) in your browser to see the demo
46+
47+
## Features
48+
49+
- **Two-phase analysis** – Lists all commits first, then selectively fetches diffs only for ambiguous ones to minimize token usage
50+
- **Custom MCP tools**`list_commits` and `get_commit_diff` called autonomously by Claude
51+
- **Real-time streaming** – Changelog streams to the frontend as it's generated via Trigger.dev Realtime
52+
- **Live observability** – Agent phase, turn count, and tool calls broadcast via run metadata
53+
- **Markdown rendering** – Streamed output formatted with [Streamdown](https://github.com/vercel/streamdown) and Shiki syntax highlighting
54+
- **Private repo support** – Optional GitHub token for private repositories
55+
56+
## Relevant Files
57+
58+
- [trigger/generate-changelog.ts](trigger/generate-changelog.ts) – Main task with MCP tools
59+
- [trigger/changelog-stream.ts](trigger/changelog-stream.ts) – Stream definition
60+
- [app/api/generate-changelog/route.ts](app/api/generate-changelog/route.ts) – API endpoint
61+
- [app/response/[runId]/page.tsx](app/response/[runId]/page.tsx) – Streaming display page
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { tasks } from "@trigger.dev/sdk";
2+
import type { generateChangelog } from "@/trigger/generate-changelog";
3+
import { NextRequest, NextResponse } from "next/server";
4+
5+
export async function POST(request: NextRequest) {
6+
try {
7+
const { repoUrl, startDate, endDate } = 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 (!startDate || !endDate) {
18+
return NextResponse.json(
19+
{ error: "Start and end dates are 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 changelog task
34+
const handle = await tasks.trigger<typeof generateChangelog>(
35+
"generate-changelog",
36+
{ repoUrl, startDate, endDate }
37+
);
38+
39+
return NextResponse.json({
40+
runId: handle.id,
41+
accessToken: handle.publicAccessToken,
42+
});
43+
} catch (error: unknown) {
44+
console.error("Failed to trigger generate-changelog task:", error);
45+
const message = error instanceof Error ? error.message : "Failed to start changelog generation";
46+
return NextResponse.json(
47+
{ error: message },
48+
{ status: 500 }
49+
);
50+
}
51+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
@tailwind base;
2+
@tailwind components;
3+
@tailwind utilities;
4+
5+
/* GitHub Dark Mode Theme */
6+
@layer base {
7+
:root {
8+
color-scheme: dark;
9+
10+
/* GitHub dark: #0d1117 */
11+
--background: 215 28% 7%;
12+
/* GitHub text: #e6edf3 */
13+
--foreground: 210 40% 92%;
14+
15+
/* GitHub elevated: #161b22 */
16+
--card: 215 24% 11%;
17+
--card-foreground: 210 40% 92%;
18+
19+
--popover: 215 24% 11%;
20+
--popover-foreground: 210 40% 92%;
21+
22+
/* GitHub green: #238636 */
23+
--primary: 132 69% 36%;
24+
--primary-foreground: 0 0% 100%;
25+
26+
/* GitHub subtle: #21262d */
27+
--secondary: 215 19% 15%;
28+
--secondary-foreground: 210 40% 92%;
29+
30+
/* GitHub muted bg: #21262d */
31+
--muted: 215 19% 15%;
32+
/* GitHub muted text: #7d8590 */
33+
--muted-foreground: 215 8% 53%;
34+
35+
--accent: 215 19% 15%;
36+
--accent-foreground: 210 40% 92%;
37+
38+
/* GitHub red: #da3633 */
39+
--destructive: 1 68% 53%;
40+
--destructive-foreground: 0 0% 100%;
41+
42+
/* GitHub border: #30363d */
43+
--border: 212 14% 21%;
44+
--input: 212 14% 21%;
45+
46+
/* GitHub blue: #58a6ff */
47+
--ring: 212 100% 67%;
48+
49+
--chart-1: 132 69% 36%;
50+
--chart-2: 212 100% 67%;
51+
--chart-3: 30 80% 55%;
52+
--chart-4: 280 65% 60%;
53+
--chart-5: 340 75% 55%;
54+
55+
--radius: 0.5rem;
56+
}
57+
}
58+
59+
@layer base {
60+
* {
61+
@apply border-border;
62+
}
63+
body {
64+
@apply bg-background text-foreground;
65+
}
66+
}
67+
68+
/* Inline code styling */
69+
:not(pre) > code {
70+
@apply bg-secondary px-1.5 py-0.5 rounded font-mono text-sm;
71+
}
72+
73+
/* Date input calendar icon */
74+
input[type="date"] {
75+
position: relative;
76+
}
77+
78+
input[type="date"]::-webkit-calendar-picker-indicator {
79+
position: absolute;
80+
right: 12px;
81+
filter: invert(0.5);
82+
cursor: pointer;
83+
}

changelog-generator/app/layout.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
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: "Changelog Generator - AI-powered changelogs from GitHub commits",
9+
description:
10+
"Generate developer-friendly changelogs from any GitHub repository using AI",
11+
};
12+
13+
export default function RootLayout({
14+
children,
15+
}: {
16+
children: React.ReactNode;
17+
}) {
18+
return (
19+
<html lang="en">
20+
<body className={inter.className}>{children}</body>
21+
</html>
22+
);
23+
}

0 commit comments

Comments
 (0)