Companion to the same addition in the cloud-init and ansible repos. Caught real drift in those repos in a recent session only because the user explicitly asked. Codify the sweep with concrete, repo- specific drift hotspots rather than a vague 'watch for drift' rule that gets ignored. Each AGENTS.md addition lists the doc files most likely to fall behind code changes here, plus a quick-triage one-liner using 'git diff --name-only HEAD | xargs grep -l ...' so the rule is actionable not aspirational.
9.6 KiB
AGENTS.md
What this is
Harness-side bring-up for the pi coding-agent. Installs three pi-generic config artifacts into the right places and runs a couple of non-halting probes. Does not depend on MemPalace.
Sibling to opencode-toolkit —
same shape: one install.sh at the root, cp-or-symlink the config files,
probe the environment, compose independently of the palace memory layer.
Read README.md first for the user-facing walk-through.
This file is for agents modifying the repo.
Structure
install.sh # Idempotent installer (symlink + cp + probes)
pi-env.zsh # Shell loader sourcing ~/.config/pi/.env (POSIX-compatible)
keybindings.json # ~/.pi/agent/keybindings.json — mosh/tmux newline fix
settings.example.json # Template for ~/.pi/agent/settings.json (copy + edit)
README.md # User-facing quickstart + new-machine deploy recipe.
AGENTS.md # This file.
LICENSE # MIT.
Conventions
- One install step per artifact, with a matching uninstall step.
- Symlink what's safe to symlink, cp what's part of a dotfiles backup,
template what the harness rewrites.
keybindings.json→ symlink. pi doesn't rewrite it; the symlink lets edits flow through git without a re-install step.pi-env.zsh→cpinto~/.oh-my-zsh/custom/. That dir is typically part of a dotfiles backup (e.g.myconfigs'srsync_copy.sh); a symlink into this repo's absolute path breaks when the backup is restored on another host.settings.example.json→ not installed. pi rewrites~/.pi/agent/settings.jsonat runtime (lastChangelogVersionbumps on upgrade), so any symlink back to the repo would dirty the working tree. Installer prints thecpcommand and walks away.
- Probes warn, never halt.
warn+return 0. The installer's only hard-fail path is "pi isn't installed at all" — that's an earlyexit 4fromrequire_pi_installedbecause there's nothing useful to do without~/.pi/agent/. - Non-destructive. Existing real files at symlink destinations get
backed up with a timestamp (
.bak.YYYYMMDD-HHMMSS) before linking. The shell loader's cp path refuses to clobber local edits: detects drift viacmp -s, prints adiffhint, leaves the file alone. - Do not auto-edit rc files. If oh-my-zsh isn't present, print the
sourcesnippet the user manually adds to~/.zshrcor~/.bashrc. Invasive shell-rc edits belong in a dotfiles installer, not here. - No hard dependency on mempalace. If the surface ever grows
mempalace-aware (unlikely — those pieces live in
mempalace-toolkiton purpose), it must degrade gracefully when mempalace is absent. - POSIX-compatible shell glue.
set -a/source/set +awork in bash and zsh both. Don't add zsh-only constructs to files that may end up sourced from~/.bashrc.
What install.sh does
Hard-required:
require_pi_installed— aborts with exit 4 if~/.pi/agent/is missing. Creates~/.pi/agent/extensions/proactively so a latermempalace-toolkitinstall has somewhere to symlink into.
Always (once pi is present):
- Symlinks
keybindings.jsoninto~/.pi/agent/. Backs up any pre-existing real file.
oh-my-zsh path (gated on ~/.oh-my-zsh/custom/ existing):
- Copies
pi-env.zshinto that directory. Drift-safe — prints adiffhint if installed content differs from repo, doesn't clobber.
No oh-my-zsh path:
- Prints a shell-specific source snippet for
~/.zshrcor~/.bashrc(selected from$SHELL). User pastes manually.
Probes (non-halting):
~/.pi/agent/settings.jsonexists. Without it pi refuses to start without--provider/--model. Prints thecp settings.example.jsoncommand.AWS_PROFILE+AWS_REGIONare set, only ifsettings.jsonselectsamazon-bedrock. Silent for non-Bedrock providers. Silent if settings.json is missing (check_pi_settings already handled that case).
Adding a new artifact
Follow the same shape keybindings.json / pi-env.zsh / settings.example.json use:
- One file at repo root. Flat layout; no
extensions/subdir yet. Revisit if five+ artifacts ever accumulate. - Choose symlink / cp / template per the conventions above. Document
the choice in a comment next to the variable declarations at the top
of
install.sh. - One install step + one uninstall step in
install.sh, guarded bylink_if_into_repo(for symlinks) orcmp -s(for copies). Never remove user edits silently. - One probe per external dependency the artifact implies.
warn+return 0. - Update this file's Structure block and
README.md.
Adding mempalace-aware functionality
Don't. Those pieces belong in mempalace-toolkit/extensions/pi/:
- The mempalace MCP bridge TypeScript extension (
mempalace.ts) — imports pi'sExtensionAPI, registers MCP tools, injects wake-up context. - The
install_pi_extensionfunction that symlinks it in. - Any probes that check for mempalace being reachable through pi.
That boundary is load-bearing for opencode-devbox's slim container
path: a container built with INSTALL_MEMPALACE=false should install
pi-toolkit cleanly and get a functional pi without dragging in
chromadb + embedding models (~300 MB).
Testing
No framework. Manual:
./install.sh --help # flags
./install.sh --yes # fresh install
./install.sh --yes # re-run (idempotent)
./install.sh --uninstall --yes # remove
./install.sh --yes # reinstall
oh-my-zsh fallback simulation:
SHELL=/bin/bash HOME=/tmp/fake ./install.sh --yes # should print ~/.bashrc snippet
Environment verification (after install + exec zsh or new shell):
zsh -ic 'echo $AWS_PROFILE $AWS_REGION' # should print values from ~/.config/pi/.env
Drift simulation:
echo "# local edit" >> ~/.oh-my-zsh/custom/pi-env.zsh
./install.sh --yes # should warn "differs from repo" and leave alone
Gotchas
- pi must be installed upstream first.
~/.pi/agent/is created by pi on first run, not by this installer. Missing → exit 4 with pointer to https://github.com/earendil-works/pi. settings.example.jsonis region-specific. The shipped default useseu.Bedrock inference-profile prefixes. Users on us-east need to swap tous.before first run, or pi will reject the model ID.- Bedrock is not the only provider. If the user is on bare
Anthropic or OpenAI,
AWS_PROFILE/AWS_REGIONare irrelevant. The probe gates ongrep -q '"amazon-bedrock"' settings.jsonto stay quiet in those cases. - Mosh strips modifiers upstream of tmux. The keybindings file's
ctrl+j/alt+jfallbacks are specifically because mosh's vt220-ish emulation does not forwardShift+Enteras CSI-u — tmux'sextended-keys csi-usetting doesn't help over mosh (only helps on direct ssh / local / WireGuard). Documented in README. - The shell loader runs on every shell start. Keep it fast. If it
grows beyond a few lines, gate on
[[ $- == *i* ]]so non-interactive shells skip the work. ~/.config/pi/.envshould be chmod 600. It's plaintext on disk; git-crypt encryption only applies in the dotfiles repo. The installer does not enforce this because it doesn't ship the file.
Related repos
mempalace-toolkit— adds a pi↔mempalace MCP bridge on top of this toolkit. Installs themempalace.tsextension into~/.pi/agent/extensions/. Optional.opencode-toolkit— sibling pattern for the opencode coding-agent. Same install.sh shape.opencode-devbox— Docker containers; composes any subset of these toolkits via independent install.sh invocations.myconfigs— dotfiles repo where~/.config/pi/.envis tracked (git-crypt encrypted).
History
Split out of mempalace-toolkit/extensions/pi/ on 2026-05-05. Previously
the pi-generic config artifacts (env loader, keybindings, settings
template) lived alongside the mempalace.ts MCP bridge inside
mempalace-toolkit because that's where the pattern first crystallized.
The split was motivated by opencode-devbox's mempalace opt-out and
future pi-option: a container built with mempalace off should still be
able to install a functional pi, and that dependency asymmetry is
cleanest when pi's own config lives in its own repo. Mirrors the
2026-05-05 split of opencode-toolkit out of the same parent.
Documentation drift sweep
Before committing any non-trivial change, check that prose still matches code. Drift hotspots in this repo:
README.md— install instructions, the file/artifact table, the testing recipe. The installer's behaviour and the README's description of it must stay in lockstep — the README is what users follow.AGENTS.md(this file) — theConventionssection codifies symlink-vs-cp-vs-template decisions per artifact; if you change how an artifact is installed, update the conventions too.install.sh— contains its own usage block at the top; keep the--helpoutput and the README in sync.settings.example.json— the canonical template for pi settings; if pi adds a new top-level setting that this toolkit blesses with defaults, update the example here.
Quick triage: git diff --name-only HEAD | xargs -I{} grep -l 'thing-you-changed' README.md AGENTS.md install.sh.