Skip to content

Commit 3072056

Browse files
committed
Added Cursor background agent docs
1 parent bc63edd commit 3072056

File tree

3 files changed

+107
-0
lines changed

3 files changed

+107
-0
lines changed

docs/docs.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,7 @@
377377
"guides/example-projects/claude-changelog-generator",
378378
"guides/example-projects/claude-github-wiki",
379379
"guides/example-projects/claude-thinking-chatbot",
380+
"guides/example-projects/cursor-background-agent",
380381
"guides/example-projects/human-in-the-loop-workflow",
381382
"guides/example-projects/mastra-agents-with-memory",
382383
"guides/example-projects/meme-generator-human-in-the-loop",
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
---
2+
title: "Background Cursor agent using the Cursor CLI"
3+
sidebarTitle: "Cursor background agent"
4+
description: "Run Cursor's headless CLI agent in a Trigger.dev task and stream the live output to the frontend using Trigger.dev Realtime Streams."
5+
---
6+
7+
import RealtimeLearnMore from "/snippets/realtime-learn-more.mdx";
8+
9+
## Overview
10+
11+
This example runs [Cursor's headless CLI](https://cursor.com/cli) in a Trigger.dev task. The agent spawns as a child process, and its NDJSON stdout is parsed and piped to the browser in real-time using [Realtime Streams](/realtime/streams). The result is a live terminal UI that renders each Cursor event (system messages, assistant responses, tool calls, results) as it happens.
12+
13+
**Tech stack:**
14+
15+
- **[Next.js](https://nextjs.org/)** for the web app (App Router with server actions)
16+
- **[Cursor CLI](https://cursor.com)** for the headless AI coding agent
17+
- **[Trigger.dev](https://trigger.dev)** for task orchestration, real-time streaming, and deployment
18+
19+
## Video
20+
21+
<video
22+
controls
23+
className="w-full aspect-video"
24+
src="https://github.com/user-attachments/assets/459aa160-6659-478e-868f-32e74f79d21a"
25+
></video>
26+
27+
**Features:**
28+
29+
- **Build extensions**: Installs the `cursor-agent` binary into the task container image using `addLayer`, demonstrating how to ship system binaries with your tasks
30+
- **Realtime Streams v2**: NDJSON from a child process stdout is parsed and piped directly to the browser using `streams.define()` and `.pipe()`
31+
- **Live terminal rendering**: Each Cursor event renders as a distinct row with auto-scroll
32+
- **Long-running tasks**: Cursor agent runs for minutes; Trigger.dev handles lifecycle, timeouts, and retries automatically
33+
- **Machine selection**: Uses the `medium-2x` preset for resource-intensive CLI tools
34+
- **LLM model picker**: Switch between models from the UI before triggering a run
35+
36+
## GitHub repo
37+
38+
<Card
39+
title="View the Cursor background agent repo"
40+
icon="GitHub"
41+
href="https://github.com/triggerdotdev/examples/tree/main/cursor-cli-demo"
42+
>
43+
Click here to view the full code for this project in our examples repository on GitHub. You can
44+
fork it and use it as a starting point for your own project.
45+
</Card>
46+
47+
## How it works
48+
49+
### Task orchestration
50+
51+
The task spawns the Cursor CLI as a child process and streams its output to the frontend:
52+
53+
1. A Next.js server action triggers the `cursor-agent` task with the user's prompt and selected model
54+
2. The task spawns the Cursor CLI binary using a helper that returns a typed NDJSON stream and a `waitUntilExit()` promise
55+
3. Each line of NDJSON stdout is parsed into typed Cursor events and piped to a Realtime Stream
56+
4. The frontend subscribes to the stream using `useRealtimeRunWithStreams` and renders each event in a terminal UI
57+
5. The task waits for the CLI process to exit and returns the result
58+
59+
### Build extension for system binaries
60+
61+
The example includes a custom build extension that installs the `cursor-agent` binary into the container image using `addLayer`. At runtime, the binary is copied to `/tmp` and given execute permissions; this is a workaround needed when the container runtime strips execute permissions from added layers.
62+
63+
```ts extensions/cursor-cli.ts
64+
export const cursorCli = defineExtension({
65+
name: "cursor-cli",
66+
onBuildComplete(params) {
67+
params.addLayer({
68+
id: "cursor-cli",
69+
image: {
70+
instructions: [
71+
`COPY cursor-agent /usr/local/bin/cursor-agent`,
72+
`RUN chmod +x /usr/local/bin/cursor-agent`,
73+
],
74+
},
75+
});
76+
},
77+
});
78+
```
79+
80+
### Streaming with Realtime Streams v2
81+
82+
The stream is defined with a typed schema and piped from the child process:
83+
84+
```ts trigger/cursor-stream.ts
85+
export const cursorStream = streams.define("cursor", cursorEventSchema);
86+
```
87+
88+
```ts trigger/cursor-agent.ts
89+
const { stream, waitUntilExit } = spawnCursorAgent({ prompt, model });
90+
cursorStream.pipe(stream);
91+
await waitUntilExit();
92+
```
93+
94+
On the frontend, the `useRealtimeRunWithStreams` hook subscribes to these events and renders them as they arrive.
95+
96+
## Relevant code
97+
98+
- **Build extension + spawn helper**: [extensions/cursor-cli.ts](https://github.com/triggerdotdev/examples/blob/main/cursor-cli-demo/extensions/cursor-cli.ts): installs the binary and provides a typed NDJSON stream with `waitUntilExit()`
99+
- **Task definition**: [trigger/cursor-agent.ts](https://github.com/triggerdotdev/examples/blob/main/cursor-cli-demo/trigger/cursor-agent.ts): spawns the CLI, pipes the stream, waits for exit
100+
- **Stream definition**: [trigger/cursor-stream.ts](https://github.com/triggerdotdev/examples/blob/main/cursor-cli-demo/trigger/cursor-stream.ts): Realtime Streams v2 stream with typed schema
101+
- **Terminal UI**: [components/terminal.tsx](https://github.com/triggerdotdev/examples/blob/main/cursor-cli-demo/components/terminal.tsx): renders live events using `useRealtimeRunWithStreams`
102+
- **Event types**: [lib/cursor-events.ts](https://github.com/triggerdotdev/examples/blob/main/cursor-cli-demo/lib/cursor-events.ts): TypeScript types and parsers for Cursor NDJSON events
103+
- **Trigger config**: [trigger.config.ts](https://github.com/triggerdotdev/examples/blob/main/cursor-cli-demo/trigger.config.ts): project config with the cursor CLI build extension
104+
105+
<RealtimeLearnMore />

docs/guides/introduction.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ Example projects are full projects with example repos you can fork and use. Thes
5656
| [Claude changelog generator](/guides/example-projects/claude-changelog-generator) | Automatically generate professional changelogs from git commits using Claude. || [View the repo](https://github.com/triggerdotdev/examples/tree/main/changelog-generator) |
5757
| [Claude GitHub wiki agent](/guides/example-projects/claude-github-wiki) | Generate and maintain GitHub wiki documentation with Claude-powered analysis. || [View the repo](https://github.com/triggerdotdev/examples/tree/main/claude-agent-github-wiki) |
5858
| [Claude thinking chatbot](/guides/example-projects/claude-thinking-chatbot) | Use Vercel's AI SDK and Anthropic's Claude 3.7 model to create a thinking chatbot. | Next.js | [View the repo](https://github.com/triggerdotdev/examples/tree/main/claude-thinking-chatbot) |
59+
| [Cursor background agent](/guides/example-projects/cursor-background-agent) | Run Cursor's headless CLI agent as a background task, streaming live output to the browser. | Next.js | [View the repo](https://github.com/triggerdotdev/examples/tree/main/cursor-cli-demo) |
5960
| [Human-in-the-loop workflow](/guides/example-projects/human-in-the-loop-workflow) | Create audio summaries of newspaper articles using a human-in-the-loop workflow built with ReactFlow and Trigger.dev waitpoint tokens. | Next.js | [View the repo](https://github.com/triggerdotdev/examples/tree/main/article-summary-workflow) |
6061
| [Mastra agents with memory](/guides/example-projects/mastra-agents-with-memory) | Use Mastra to create a weather agent that can collect live weather data and generate clothing recommendations. || [View the repo](https://github.com/triggerdotdev/examples/tree/main/mastra-agents) |
6162
| [OpenAI Agents SDK for Python guardrails](/guides/example-projects/openai-agent-sdk-guardrails) | Use the OpenAI Agents SDK for Python to create a guardrails system for your AI agents. || [View the repo](https://github.com/triggerdotdev/examples/tree/main/openai-agent-sdk-guardrails-examples) |

0 commit comments

Comments
 (0)