# Background Cursor agent using the Cursor CLI

> Source: https://trigger.dev/docs/guides/example-projects/cursor-background-agent

[​](https://trigger.dev/docs/guides/example-projects/cursor-background-agent#overview)

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](https://trigger.dev/docs/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

[​](https://trigger.dev/docs/guides/example-projects/cursor-background-agent#video)

Video
--------------------------------------------------------------------------------------------

**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

[​](https://trigger.dev/docs/guides/example-projects/cursor-background-agent#github-repo)

GitHub repo
--------------------------------------------------------------------------------------------------------

View the Cursor background agent repo
-------------------------------------

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.

[​](https://trigger.dev/docs/guides/example-projects/cursor-background-agent#how-it-works)

How it works
----------------------------------------------------------------------------------------------------------

### 

[​](https://trigger.dev/docs/guides/example-projects/cursor-background-agent#task-orchestration)

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

### 

[​](https://trigger.dev/docs/guides/example-projects/cursor-background-agent#build-extension-for-system-binaries)

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.

extensions/cursor-cli.ts

    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}`,\
            ],
          },
        });
      },
    });
    

### 

[​](https://trigger.dev/docs/guides/example-projects/cursor-background-agent#streaming-with-realtime-streams-v2)

Streaming with Realtime Streams v2

The stream is defined with a typed schema and piped from the child process:

trigger/cursor-stream.ts

    export const cursorStream = streams.define("cursor", cursorEventSchema);
    

trigger/cursor-agent.ts

    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.

[​](https://trigger.dev/docs/guides/example-projects/cursor-background-agent#relevant-code)

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

[​](https://trigger.dev/docs/guides/example-projects/cursor-background-agent#learn-more-about-trigger-dev-realtime)

Learn more about Trigger.dev Realtime
------------------------------------------------------------------------------------------------------------------------------------------------------------

To learn more, take a look at the following resources:

*   [Trigger.dev Realtime](https://trigger.dev/docs/realtime)
     - learn more about how to subscribe to runs and get real-time updates
*   [Realtime streaming](https://trigger.dev/docs/realtime/react-hooks/streams)
     - learn more about streaming data from your tasks
*   [Batch Triggering](https://trigger.dev/docs/triggering#tasks-batchtrigger)
     - learn more about how to trigger tasks in batches
*   [React hooks](https://trigger.dev/docs/realtime/react-hooks)
     - learn more about using React hooks to interact with the Trigger.dev API

Was this page helpful?

YesNo

[Previous](https://trigger.dev/docs/guides/example-projects/claude-thinking-chatbot)
[Human-in-the-loop workflowThis example project creates audio summaries of newspaper articles using a human-in-the-loop workflow built with ReactFlow and Trigger.dev waitpoint tokens.\
\
Next](https://trigger.dev/docs/guides/example-projects/human-in-the-loop-workflow)

⌘I

Assistant

Responses are generated using AI and may contain mistakes.
