_ __ __ _ _ __ ___ | | ___ ___ _ __
| '_ \ / _` | '_ \ / _ \| |/ _ \ / _ \| '_ \
| | | | (_| | | | | (_) | | (_) | (_) | |_) |
|_| |_|\__,_|_| |_|\___/|_|\___/ \___/| .__/
|_|nanoloop is a tiny educational coding agent.
It exists to teach one idea clearly: how a language model can use tools in a loop.
user asks for something
-> model replies with text or tool calls
-> nanoloop runs those tools
-> tool results go back to the model
-> repeat until the model gives a final answerThat loop is one of the central ideas behind tools like Codex, Claude Code, Cursor agents, and other agentic coding tools. nanoloop is not an implementation of those products. It is a small, readable example of the core mechanism they build much larger systems around.
The project entrypoint is src/main.ts.
Read it in this order:
mainLoop: reads user input and prints answersrunOneUserTurn: runs the model-tool loop for one user messagerunToolCalls: executes the tool calls one at a timecreateAgent: creates the tools and keeps conversation state
nanoloop is:
- a learning project
- a minimal command-line coding agent
- a concrete example of model -> tool call -> tool result -> next model call
- a place to experiment with simple tools such as reading files, editing files, and running shell commands
nanoloop is not:
- a production coding agent
- a replacement for Codex, Claude Code, Cursor, or similar tools
- a secure sandbox
- a complete agent architecture
- a best-practices template for production automation
The code intentionally avoids a lot of machinery that real products need. The point is to make the loop small enough to read and modify.
The current agent has four tools:
read_file: read a file inside the current workspacewrite_file: create or overwrite a complete fileedit_file: replace one exact snippet in a filerun_command: run a shell command in the current workspace
These tools are intentionally plain. Their definitions show the JSON schema the model sees, and their implementations show the local code that runs when the model asks for a tool.
write_file and edit_file are both useful, but they teach different editing styles. write_file is
best for new files or whole-file rewrites. edit_file is best for small targeted changes where the
existing surrounding code should stay untouched.
nanoloop can edit files and run shell commands.
Run it only in a workspace you are comfortable changing. For learning, use a small test repo or a temporary directory. It does not provide the approval flows, sandboxing, permission controls, or recovery features that professional coding agents usually have.
Install dependencies:
pnpm installCreate a local environment file:
cp .env.example .envSet your OpenAI API key in .env:
OPENAI_API_KEY=your_api_key_hereStart the agent from the directory you want it to work in:
pnpm startThen type a request:
> read package.json and summarize the project- src/main.ts: the agent loop and command-line prompt
- src/tools/index.ts: the plain map of available tools
- src/tools/registry.ts: shared tool-call helpers
- src/tools/read-file.ts: file-reading tool
- src/tools/write-file.ts: whole-file writing tool
- src/tools/edit-file.ts: exact-snippet file editing tool
- src/tools/run_command.ts: shell command tool
If you only read one file, read src/main.ts.
Real tools build a lot around this simple loop:
- larger system prompts and instruction layers
- repository search and context selection
- patch application and review flows (it's YOLO mode per default)
- sandboxing and command approval
- long-running command handling
- tool error recovery
- git integration
- streaming user interfaces
- context compaction
- plugin or MCP tool ecosystems
- product-specific safety and policy logic
nanoloop leaves most of that out on purpose. Once the basic loop is clear, those features are easier to understand as additions instead of mysteries.