> ## Documentation Index
> Fetch the complete documentation index at: https://trigger.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Background Cursor agent using the Cursor CLI

> Run Cursor's headless CLI agent in a Trigger.dev task and stream the live output to the frontend using Trigger.dev Realtime Streams.

## Overview

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/react-hooks/streams). The result is a live terminal UI that renders each Cursor event (system messages, assistant responses, tool calls, results) as it happens.

**Tech stack:**

* **[Next.js](https://nextjs.org/)** for the web app (App Router with server actions)
* **[Cursor CLI](https://cursor.com/cli)** for the headless AI coding agent
* **[Trigger.dev](https://trigger.dev)** for task orchestration, real-time streaming, and deployment

## Video

<video controls className="w-full aspect-video" src="https://github.com/user-attachments/assets/459aa160-6659-478e-868f-32e74f79d21a" />

**Features:**

* **Build extensions**: Installs the `cursor-agent` binary into the task container image using `addLayer`, demonstrating how to ship system binaries with your tasks
* **Realtime Streams v2**: NDJSON from a child process stdout is parsed and piped directly to the browser using `streams.define()` and `.pipe()`
* **Live terminal rendering**: Each Cursor event renders as a distinct row with auto-scroll
* **Long-running tasks**: Cursor agent runs for minutes; Trigger.dev handles lifecycle, timeouts, and retries automatically
* **Machine selection**: Uses the `medium-2x` preset for resource-intensive CLI tools
* **LLM model picker**: Switch between models from the UI before triggering a run

## GitHub repo

<Card title="View the Cursor background agent repo" icon="GitHub" href="https://github.com/triggerdotdev/examples/tree/main/cursor-cli-demo">
  Click here to view the full code for this project in our examples repository on GitHub. You can
  fork it and use it as a starting point for your own project.
</Card>

## How it works

### Task orchestration

The task spawns the Cursor CLI as a child process and streams its output to the frontend:

1. A Next.js server action triggers the `cursor-agent` task with the user's prompt and selected model
2. The task spawns the Cursor CLI binary using a helper that returns a typed NDJSON stream and a `waitUntilExit()` promise
3. Each line of NDJSON stdout is parsed into typed Cursor events and piped to a Realtime Stream
4. The frontend subscribes to the stream using `useRealtimeRunWithStreams` and renders each event in a terminal UI
5. The task waits for the CLI process to exit and returns the result

### Build extension for system binaries

The example includes a custom build extension that installs `cursor-agent` into the container image using `addLayer`. The official install script is run at build time, then the resolved entry point and its dependencies are copied to a fixed path so the task can invoke them at runtime with the bundled Node binary.

```ts extensions/cursor-cli.ts theme={"theme":"css-variables"}
const CURSOR_AGENT_DIR = "/usr/local/lib/cursor-agent";

export const cursorCli = (): BuildExtension => ({
  name: "cursor-cli",
  onBuildComplete(context) {
    if (context.target === "dev") return;

    context.addLayer({
      id: "cursor-cli",
      image: {
        instructions: [
          "RUN apt-get update && apt-get install -y curl ca-certificates && rm -rf /var/lib/apt/lists/*",
          'ENV PATH="/root/.local/bin:$PATH"',
          "RUN curl -fsSL https://cursor.com/install | bash",
          `RUN cp -r $(dirname $(readlink -f /root/.local/bin/cursor-agent)) ${CURSOR_AGENT_DIR}`,
        ],
      },
    });
  },
});
```

### Streaming with Realtime Streams v2

The stream is defined with a typed schema and piped from the child process:

```ts trigger/cursor-stream.ts theme={"theme":"css-variables"}
export const cursorStream = streams.define("cursor", cursorEventSchema);
```

```ts trigger/cursor-agent.ts theme={"theme":"css-variables"}
const { stream, waitUntilExit } = spawnCursorAgent({ prompt, model });
cursorStream.pipe(stream);
await waitUntilExit();
```

On the frontend, the `useRealtimeRunWithStreams` hook subscribes to these events and renders them as they arrive.

## Relevant code

* **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()`
* **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
* **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
* **Terminal UI**: [components/terminal.tsx](https://github.com/triggerdotdev/examples/blob/main/cursor-cli-demo/components/terminal.tsx): renders live events using `useRealtimeRunWithStreams`
* **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
* **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

## Learn more about Trigger.dev Realtime

To learn more, take a look at the following resources:

* [Trigger.dev Realtime](/realtime) - learn more about how to subscribe to runs and get real-time updates
* [Realtime streaming](/realtime/react-hooks/streams) - learn more about streaming data from your tasks
* [Batch Triggering](/triggering#tasks-batchtrigger) - learn more about how to trigger tasks in batches
* [React hooks](/realtime/react-hooks) - learn more about using React hooks to interact with the Trigger.dev API
