A 55-file repository explains the agent loop in Chinese
The 55-file PI from Scratch repository is both an article and a working TypeScript program. The primary material is Chinese, including the README, 2 tutorial chapters, web interface, and most source comments. There is no English tutorial in the checkout. The author strips the upstream pi design down to its data flow: a model streams text or tool calls, the agent executes tools, results return to context, and the loop continues until the model stops.
That small scope makes the project readable. The checkout has about 5,469 lines of source, including a Next.js lesson site, diagrams, tests, and pre-generated traces. Source appears beside the article and fills in as the reader advances. A trace debugger lets readers pause and follow execution. The hosted lesson uses static trace data, so opening it does not spend API credit or send prompts to a model provider.
Four tools can change files and execute host commands
The 55-file repository registers read_file, write_file, edit, and run_bash as its 4 built-in tools. The edit tool requires its old string to match exactly once, which prevents an ambiguous replacement. Long command or file output keeps the last 200 lines and stores the full text in a temporary file. These are sensible teaching choices because each behavior stays visible in a short function.
They are not a security boundary. The source comments say the teaching version passes tool arguments to execute without validating them against the declared JSON schema. write_file overwrites its target, and run_bash sends the requested command to the host shell with a 30-second timeout. The README does not describe a filesystem jail, command allowlist, or container runtime. Run it only in a directory and account whose contents you can afford to change.
What happened when we ran it
Our sandbox installed 54 npm packages in 11 seconds and used 65 MB on disk. The TypeScript build succeeded in 9 seconds. The test command also succeeded, finishing in 25 seconds, and npm audit found 0 known vulnerabilities across the installed dependency set. That is a clean result for commit 599d0ba in our unprivileged Debian container.
The repository itself was 11.1 MB checked out, even though its source count was only about 5,469 lines. It had a tests directory but no GitHub Actions workflow and no Dockerfile. A passing local suite is useful evidence for the code we cloned; the absence of repository CI means a reader cannot point to an automated workflow in this checkout that repeats those checks on every proposed change.
Our measurement setup had 3 CPUs, 8 GB of RAM, Node.js 22, and no secrets. We did not make a live model call because the container had no API credentials. The tests therefore establish that the implemented modules behave as asserted, while they do not rate model output, tool selection, or the safety of commands a live model might request.
Node.js 22 and one API key start the terminal agent
Node.js 22 or newer, NANOPI_API_KEY, and the development command are enough for the local path. NANOPI_MODEL selects the model, while NANOPI_BASE_URL points at an OpenAI-compatible chat-completions service and defaults to OpenAI. The root package has no runtime dependencies, only development packages for TypeScript execution, compilation, Node types, and Vitest.
The web lesson is a separate application under web, with its own package install and development server. That split is appropriate because someone reading traces does not need to run nano-pi or hold an API key. There is no published GitHub release. Anyone embedding the code should pin commit 599d0ba or another reviewed commit rather than expecting a tagged compatibility promise.
Context compression teaches the idea and exposes a bug
At 50 messages, the agent asks the model to summarize older history, replaces it with one summary, and retains the latest 20 messages. This makes the context-management idea easy to inspect. The source explains that upstream pi uses far more code for token estimation, safe cut points, and turns that cross boundaries, while nano-pi deliberately uses message count as a rough substitute.
Issue 6 identifies a consequence in session persistence. The file writer decides what to append by comparing the stored message count with the current in-memory count. After compaction reduces 51 messages to 31, a newly added message can still leave the current count below the stored count, so it is not appended. That report is directly about nano-pi's persistence path. Long sessions need a fix before their history can be trusted.
Abort handling is careful, while execution has no step cap
The Node.js 22 agent preserves message structure when a user presses Ctrl+C. If interruption happens before tools run, it drops unfinished tool calls. If some calls already ran, it adds error results for the skipped calls so every call still has a paired result. A response cut off by the model's token limit is also handled conservatively: incomplete tool arguments are not executed, and an error goes back into context for another turn.
The teaching version executes multiple tool calls in sequence and has no hard maximum number of agent steps. Its own comment contrasts that with an omitted upstream stop callback. Combined with unrestricted shell execution, that omission matters more in unattended use than it does during a guided lesson. The project was last pushed on August 18, 2026, had 1,132 stars, and showed 1 open issue and pull request when fetched. It is active teaching code, not a packaged production agent.

