Cursor's Agent Loop Is Just 30 Lines of Code
Cursor, Copilot, and Claude Code all run the same pattern: a model in a loop calling tools. Understanding that loop — and how to isolate shell execution in a child process — is the difference between treating these tools as magic and building your own custom agent that actually ships code.
A mini-cursor built in under 300 lines of JavaScript strips AI coding assistants down to their core: a large language model bound to four tools — read file, write file, list directory, and execute command. The model decides which tool to invoke, and a Node.js child process runs long shell commands like `pnpm install` without blocking the agent.
The agent runs a ReAct loop that feeds tool results back into the conversation context, letting the model adjust its next move. A single prompt to create a React TodoList app triggers a sequence of Vite scaffolding, file writes, dependency installation, and dev-server startup — all driven by tool calls, not magic.
LangChain's `bindTools()` converts tool signatures into OpenAI function-calling format, while Zod schemas enforce parameter shapes. The system prompt includes explicit correct and incorrect usage examples to prevent the model from doubling up `cd` commands inside shell invocations.
The entire agent is a state machine where the only state is the message array; there is no planner, no tree search, and no separate memory module.
Error handling inside tools returns friendly strings rather than throwing exceptions, which lets the model read the failure and self-correct on the next loop iteration.
Using `spawn` instead of `exec` matters because `spawn` streams output — essential for long-running commands like `pnpm install` where the user needs to see progress.
The system prompt is doing heavy lifting: without the explicit rule against `cd` inside commands, the model reliably produces broken shell invocations.