Run This Book's Examples
Get the code this book runs, install the pinned Pi release, verify that the chapters and the code agree, and know what the resulting evidence does and does not prove.
Every typescript block in this book carries a marker naming the file it was taken
from, and a script fails the build if a chapter and its source have drifted apart. That
is the mechanism behind this book’s method: the code you read is code that ran, at a
release the text was checked against.
This page is how you get hold of it.
Get the code
The examples live in this book’s repository, in the examples/ directory:
ernanhughes/pi → examples/
Clone it and install from there:
git clone https://github.com/ernanhughes/pi.git
cd pi/examples
npm install
npm run verify-examples
Expected result at the pinned release:
> tsc -p .
(no output — clean)
checked 65 embedded block(s); all match their source
tests 279
pass 279
fail 0
Typecheck printing nothing is success. The three numbers come from three different
stages — check-embedded reports block synchronisation, and the tests/pass/fail
lines come from node --test — so a count of 65 blocks and a count of 277 tests are
expected to differ.
The repository is not public yet. At the time of writing
github.com/ernanhughes/piis private, so the clone command above will only work for someone with access to it. If you are reading this on a published copy of the book and the clone fails with a 404, that is why — not a typo in the command. The examples are also published as this book’s own source, and everytypescriptblock in every chapter is readable in full without any of this.
Work from a specific revision
The book’s claims describe one release, and the examples are pinned to it. If you want
the revision this text was written against rather than whatever main currently is:
git clone https://github.com/ernanhughes/pi.git
cd pi
git checkout 54e13e8 # the revision this page describes
cd examples
npm install
npm run verify-examples
That is worth doing when a check fails, because it separates “the book is wrong” from
“the repository has moved on”. A new commit to main is not a change to Pi’s
behaviour, and the examples do not drift with Pi — they are pinned to 1.0.4 by
package.json regardless of which revision of the book you check out.
The short version
If you already have the repository, this is the whole setup:
cd examples
npm install
npm run verify-examples
What follows is what each part means, and the prerequisites that are not obvious.
Before you start
| Requirement | Why | Check |
|---|---|---|
| Node.js 22.19 or newer | What Pi requires, and what runs TypeScript without a build step | node --version |
| npm | To install the pinned packages | npm --version |
A POSIX shell (bash) |
Two tests execute real shell scripts | bash --version |
| Git | The chapter 14 check script finds the repository with git rev-parse |
git --version |
The shell, on Windows
This is the prerequisite that catches people. On Windows, bash on your PATH is
usually C:\WINDOWS\system32\bash.exe — the WSL launcher. With no distribution
installed it exits non-zero and prints execvpe(/bin/bash) failed, which reads exactly
like a shell script that failed on purpose. Two tests in ch14-skill-files/ would fail
for that reason alone, with nothing wrong with the book or your checkout.
The test harness looks for Git Bash first (C:\Program Files\Git\bin\bash.exe) and
uses it in preference to the launcher. If neither a Git Bash nor a working WSL is
present, those two tests are skipped with a reason rather than failed, so a green
run tells you what it actually covered.
Git
Not for version control here, but because the chapter 14 check script discovers its
target repository with git rev-parse --show-toplevel. Chapter 14 explains why it asks
rather than counting parent directories.
Installing, and why the version is pinned
cd examples
npm install # or `npm ci`, for a reproducible tree
package.json pins all three Pi packages to the exact release this book describes:
"@earendil-works/pi-agent-core": "1.0.4",
"@earendil-works/pi-ai": "1.0.4",
"@earendil-works/pi-coding-agent": "1.0.4"
This is deliberate, and it is worth understanding rather than accepting. Every behavioural claim in this book was checked against 1.0.4. If you install a different release, the suite may still pass while the prose no longer describes what you are running — and that mismatch is exactly what chapter 40’s evidence discipline exists to catch. Chapter 2’s installation section is the reference for how this pin relates to the managed installer and to transitive dependencies.
What verify-examples does
npm run verify-examples
Three stages, in order, and each answers a different question. At the pinned release the expected end state is a clean typecheck (no output), 65 matching blocks, and 279 tests with 0 failures.
1. typecheck
tsc over the whole suite. This catches an example that no longer matches the pinned
type declarations — and since the declarations are the authority where Pi’s prose and
its types disagree (chapter 26 records one such disagreement), this is the stage that
keeps the book honest against its own grounding rule.
2. check-embedded
Compares all 65 embedded TypeScript blocks against their source files.
Each block in the manuscript is preceded by an HTML comment naming its source and what kind of block it is:
| Marker | Meaning | What is checked |
|---|---|---|
<!-- example: path --> |
the block is a whole file | the block equals the file |
<!-- excerpt: path --> |
the block is part of a file | every line appears, in order |
<!-- declaration: path --> |
a type declaration from Pi | as excerpt, plus equality against the real exported type |
<!-- documented-not-run --> |
real Pi API code that was not run | nothing; the prose must say so |
<!-- illustrative --> |
a fragment not meant to run | nothing |
A block with no marker fails this check, which is why the two kinds that exist —
documented-not-run and illustrative — are both honest admissions rather than
placeholders.
If you change an example that a chapter embeds, run npm run check-embedded -- --fix
to resynchronise the chapter from the source.
3. test
The suite, through node --test. At the pinned release it is green.
What the result proves, and what it does not
This is the part worth reading twice, because it is where a passing suite is most often over-claimed.
The suite substitutes a scripted provider — fauxProvider from pi-ai — for the
real model in most cases. That makes it free, fast and deterministic. It also makes
every case in it a case someone anticipated:
Tests that use the faux provider show that the code around a model is correct. They are never evidence about how a real model behaves.
A scripted provider will do whatever you tell it, including refusing, rambling, calling the wrong tool, or emitting a malformed submission — all of which are worth having in a suite. What it cannot do is surprise you. So a green run is strong evidence about your handling of a response and no evidence at all that a model produces it. Chapter 41 is about the three levels of testing and, in particular, about why the third cannot be substituted for the first.
Two more limits, both stated in the book wherever a result could be mistaken for more:
- Nothing here ran against a real model. There is no accepted real-model result in the evidence ledger. One attempt was retained and refused by the provider before the model saw a prompt; it is recorded explicitly as not a result.
- A small part of the suite runs the real executable. Chapters 31, 32, 33 and 35
spawn Pi as a child process through the harness, which resolves the binary through
the package’s own
binmapping — the bundled buildnpm exec piruns. A test asserts that mapping, so this evidence cannot quietly decay into “some module insidedist/”. Even so, the model is still scripted.
The evidence ledger
npm run evidence # rewrites examples/EVIDENCE.md and evidence.json
npm run sync-metadata # writes executable_evidence into metadata/*-chapter.yaml
Run both after a batch of changes rather than after each one. Every row carries two fields that are the method in machine-readable form:
| Field | Values | What it tells you |
|---|---|---|
claim_class |
DOCUMENTED, OBSERVED, PROPOSED |
Whose claim this is: Pi’s documentation, something that was run, or this book’s own pattern |
evidence_scope |
declarations, in_process_runtime, shipped_binary, real_model |
How far the run reached |
A reader can filter for PROPOSED and know exactly which parts of the book are the
author’s judgement rather than Pi’s contract.
One thing to expect: ledger rows and test cases are different counts and do not match. A row is a claim; a test case is an execution. Several tests can pin one claim, and one test can pin several.
The layout
One directory per chapter that has runnable code, named for the chapter:
examples/
├── README.md the practical version of this page
├── harness/ shared infrastructure, not any one chapter's code
├── ch01-agent-core/ chapter 1
├── ch38-typed-step/ chapter 38, with its 14 tests
├── ch14-skill-files/ chapter 14, with its 8 tests
├── ch40-composition/ chapter 40
├── evidence.json machine-readable ledger
└── EVIDENCE.md the same ledger as prose
harness/ is worth knowing about because it is where the isolation lives. Every test
gets a fresh PI_CODING_AGENT_DIR and PI_OFFLINE=1, so running the suite never
reads or writes your own Pi configuration, never reaches the network, and never needs a
credential.
Running one chapter
node --test ch38-typed-step/step.test.ts
The example files are plain modules with no build step — Node 22.19+ strips the types —
so you can also read one and run it directly with node path/to/file.ts.
Where to go next
- Chapter 11 decides which mechanism a requirement needs. If you came here to build something, start there and let it send you to the chapter you need.
- Part V (chapters 36 to 41) is where the runnable evidence is densest, and it builds up from a single model call to a pipeline to a test strategy.
- Chapter 42 is where any of this stops being about mechanisms, and starts being about what your agent is allowed to reach.