Using the Cursor SDK to Build a Project Documenter
I've shared a few posts recently talking about how I'm using Cursor to learn and employ agentic development. Primarily that work has all been done via our Agent view, but this is just one of the surfaces you can use with the platform. I had a chance recently to try out the SDK and I thought I'd share a little demo I built with it.
First - some explanation would be helpful. You can use Cursor with the desktop application, on the web, via CLI, on iOS, even via API. But the SDK lets you use the platform from your code. There's an SDK for TypeScript, Python, and a bridge that embeds a TypeScript server and lets you use any language. Honestly I've never seen that before in a platform and it's pretty freaking cool. (And... just to remind folks, I do work at Cursor so I'm biased, but that's absolutely an honest opinion.)
With the SDK, you can do all the things you can usually do with the platform - run prompts in different modes - swap models at will, including the auto router which makes it easier, even kick off agents that run in the cloud. Definitely check the docs for a full detailed list of what you can do, but it's basically the platform itself - in your code.
I built a quick demo with the TypeScript SDK, but then switched over to Python as I felt it a bit easier for me to use. The quickstart shows how easy it is:
import os
from cursor_sdk import Agent, LocalAgentOptions
with Agent.create(
model="composer-2.5",
api_key="crsr_key",
local=LocalAgentOptions(cwd=os.getcwd()),
) as agent:
print(agent.send("Summarize what this repository does").text())
This returns the final result of the prompt, but you also have the ability to get everything that was generated, so for example, the detailed list of tool calls and such. You can also decide between streaming or just waiting and getting the final result.
All of this just works - which is what you want in a SDK - and the quick start example is one of my favorite things to do with Cursor - basically "what the heck is this repo/set of code doing" - and I thought it would be cool to turn this into a CLI tool.
To be clear, normally I'd use the Cursor Agent window, open the repo or folder, and use Ask mode to describe the project. But if I'm not planning to work with the code later and just want a good explanation, a CLI tool could be useful for this purpose instead.
Of course, the easiest way to build this is to use Cursor itself. I set up a new folder and started a new plan:
/plan create a Python CLI that makes use of the Cursor SDK. The CLI is a
tool that will scan a code base and generated a detailed report of the
application/code base of the folder being scanned. What it does, what
technologies it use, what frameworks are in place, and so forth.
The CLI should support a help command.
The CLI will scan the current directory by default, but supports an
argument to specify a path.
The CLI will output Markdown, but an argument allows for a PDF file output.
Require a filename to store the result.
This created the following plan:
By the way, the Architecture was a pretty Mermaid chart that's not rendering on my blog:
The end result - in terminal I can create a report in either Markdown or PDF. I'll share a link to the entire thing below, but let's take a look at the Python file responsible for analyzing the codebase via the Cursor SDK:
"""Run a local Cursor agent to produce a codebase Markdown report."""
from __future__ import annotations
import os
import sys
from pathlib import Path
from cursor_sdk import Agent, AgentOptions, CursorAgentError, LocalAgentOptions
PROMPT = """\
Explore this codebase thoroughly (manifests, configs, source layout, docs) and \
produce a detailed report about the application.
Cover at least:
- Overview / purpose of the project
- Primary languages and runtimes
- Frameworks and major libraries
- Architecture and top-level structure
- Entry points and how to run, build, and test (if discoverable)
- Notable tooling (CI, linters, package managers, etc.)
- Anything else material about how the app works
Rules:
- Do not modify, create, or delete any files.
- Return ONLY Markdown for the report (headings, lists, short code snippets as needed).
- Do not wrap the entire reply in a single fenced code block.
"""
class ScanError(Exception):
"""CLI-facing scan failure with an exit code."""
def __init__(self, message: str, exit_code: int) -> None:
super().__init__(message)
self.exit_code = exit_code
def _require_api_key() -> str:
api_key = os.environ.get("CURSOR_API_KEY", "").strip()
if not api_key:
raise ScanError(
"CURSOR_API_KEY is not set. Export it before running codebase-report.",
exit_code=1,
)
return api_key
def _extract_markdown(result: object) -> str:
text = getattr(result, "result", None)
if isinstance(text, str) and text.strip():
return text
raise ScanError("Agent finished but returned no report text.", exit_code=2)
def scan_codebase(scan_path: Path) -> str:
"""Analyze *scan_path* with a local Cursor agent and return Markdown."""
api_key = _require_api_key()
cwd = str(scan_path.resolve())
print(f"Scanning {cwd} with Cursor agent…", file=sys.stderr)
try:
result = Agent.prompt(
PROMPT,
AgentOptions(
api_key=api_key,
model="composer-2.5",
local=LocalAgentOptions(cwd=cwd),
),
)
except CursorAgentError as err:
retryable = getattr(err, "is_retryable", False)
raise ScanError(
f"startup failed: {err.message} (retryable={retryable})",
exit_code=1,
) from err
status = getattr(result, "status", None)
if status == "error":
run_id = getattr(result, "id", "unknown")
raise ScanError(f"run failed: {run_id}", exit_code=2)
return _extract_markdown(result)
This is pretty robust and the prompt it uses is really well written. (Ok, as a reminder folks, don't forget prompt writing is still important and you can cheat at that by asking your AI agent to improve your prompt before you actually run it.)
I did a quick run of this on my blog and got the following:
This is a rather simple example, but being able to use the Cursor platform in code like this could be really freaking powerful I think. If you've done something like this, I'd love to hear more, share a comment below. You can check out the full code here: https://github.com/cfjedimaster/cursor_python_sdk_cli_demo