@balanza/pi-codetour
v0.3.0
Published
A pi extension that guides you through a codebase by driving an editor in a terminal split.
Readme
@balanza/pi-codetour
A pi extension that turns the agent into a guided code tour: when you ask how something works, pi can open an editor in a terminal split and point it at the exact file/line it is talking about, while you browse an interactive list of the relevant spots.
How it works
you ask a question
│
▼
pi calls the `code_tour` tool with a list of "stops"
│
▼
extension splits the terminal (wezterm → tmux) and launches an editor (nvim)
│
▼
you get an interactive list of stops; moving the cursor drives the editor- Split: the bigger dimension of the pi pane is split, so a wide terminal splits side-by-side and a tall terminal splits top/bottom.
- Multiplexer: WezTerm if available, otherwise tmux.
- Editor: Neovim (LazyVim), driven over a
--listensocket and opened read-only (-R+:view) since this is a navigation pane. The editor layer is abstracted so more editors can be added later. - Lifecycle: the editor pane is created on the first tour and closed when you quit the tour; the next tour reopens a fresh one.
Install
pi install npm:@balanza/pi-codetourUsage
Or load it directly during development:
pi --extension /path/to/pi-codetour/index.tsThen just ask the agent to explain part of the codebase. When it wants to show
you code it will open the tour. Navigate with ↑/↓ (the editor follows),
enter to focus the editor pane, esc/q to close the tour (which also closes
the editor pane).
Re-open the most recent tour any time with /codetour.
Chat about the code you are viewing
You do not have to close the tour to talk to the agent about what you are
looking at. Press Ctrl+Alt+T to toggle between the tour list and the
chat input:
- Tour → chat: the list hands focus back to the chat while the editor pane
stays open on the current stop. A banner above the chat input (and a
📍 file:linemarker in the footer) stays visible the whole time, so it is always obvious you are inside a tour and what you are viewing. - Chat → tour: press
Ctrl+Alt+Tagain to jump back into the list, resumed on the exact stop you left.
While a tour is active, every message you send silently carries the stop you are
viewing (file, line, label, and its explanation) as context, so you can ask
"why is this here?" or "what calls this?" and the agent answers about that
code — all in the same conversation, no forking. Quit the tour (esc/q) to
clear the marker and stop injecting that context.
Development
npm run lint # Biome lint + format check
npm run format # apply Biome fixes
npm test # node:test suite over the pi-free engine
npm run typecheck # tsc --noEmit (needs the pi host packages present)CI (.github/workflows/ci.yml) runs lint, tests, and typecheck on every push
and pull request. The pure engine (src/terminal.ts, src/editor.ts) has no
pi imports and is unit-tested directly; index.ts and src/tour-ui.ts are the
pi adapter layer and are covered by the typecheck step.
Releasing
Publishing to npm is automated by .github/workflows/release.yml, which runs on
any pushed v*.*.* tag. One-time setup:
Authentication uses npm Trusted Publishing (OIDC), so no npm token is stored anywhere. One-time setup:
- Publish the first version manually, because a trusted publisher can only be
configured on a package that already exists:
npm login && npm publish - On npmjs.com: Packages → @balanza/pi-codetour → Settings → Trusted
Publisher → GitHub Actions, with organization
balanza, repositorypi-codetour, workflow filenamerelease.yml, and the npm publish action allowed. Fields are case-sensitive and are not validated on save. The configuration expires if no publish succeeds within 2 days. - Keep
repository.urlinpackage.jsonmatching this repo exactly — npm rejects OIDC publishes otherwise. - Once a CI publish has succeeded, harden it: Settings → Publishing access → "Require two-factor authentication and disallow tokens".
Provenance is generated automatically for OIDC publishes, so no --provenance
flag is needed. The workflow pins Node 24 because trusted publishing requires
npm ≥ 11.5.1, which Node 22 does not ship.
Then cut a release. The version is derived from the conventional commits made
since the last v* tag:
- any breaking change (
type!:or aBREAKING CHANGE:footer) → major - otherwise any
feat→ minor - otherwise → patch
npm run version:next # print the next version without changing anything
npm run version:next -- --json # same, as JSON
npm run release # bump package.json + create the vX.Y.Z commit & tag
git push --follow-tags # the Release workflow publishes the matching versionThe --json form prints the full decision as one compact line, so it pipes
directly into jq:
$ npm run version:next -- --json | jq -r .nextVersion
0.2.0{"lastVersion":"0.1.0","nextVersion":"0.2.0","numCommits":13,"bump":"minor","source":"package.json","lastTag":null}(The project .npmrc sets loglevel=silent so npm's > pkg@version script
banner stays off stdout; CI overrides it with NPM_CONFIG_LOGLEVEL=notice.)
bump is null when there are no commits since the last tag (then
nextVersion equals lastVersion).
The workflow re-runs lint/test/typecheck, verifies the tag matches
package.json version, publishes with --access public, and creates a GitHub
release for the tag with auto-generated notes and the npm tarball attached.
