Initial commit: pi harness bring-up split out of mempalace-toolkit
Pi-generic config artifacts (no mempalace dependency): - pi-env.zsh: shell loader sourcing ~/.config/pi/.env for AWS_PROFILE / AWS_REGION. POSIX-compatible (works in bash and zsh). - keybindings.json: mosh/tmux newline bindings (shift+enter, ctrl+j, alt+j). - settings.example.json: ~/.pi/agent/settings.json template so pi starts without --provider/--model. Region-specific (Bedrock inference-profile prefix). install.sh mirrors mempalace-toolkit + opencode-toolkit patterns: - require_pi_installed: hard exit 4 if ~/.pi/agent/ missing (cannot do anything useful; user must install pi first). - symlink keybindings.json (safe: pi doesn't rewrite it). - cp pi-env.zsh into ~/.oh-my-zsh/custom/ (portability over symlink, that dir is part of dotfiles backups). Print source snippet for bash / plain-zsh users. - settings.example.json NOT installed \u2014 pi rewrites settings.json at runtime. check_pi_settings probe prints the cp command instead. - check_aws_env: gated on settings.json selecting amazon-bedrock; silent for non-Bedrock providers or missing settings. - All probes warn + return 0, never halt. - Non-destructive: backup on symlink collision, cmp-based drift detection on the cp path, uninstall only removes copies whose content still matches repo. Split rationale: opencode-devbox's mempalace opt-out (~300 MB saved) wants pi available without mempalace. That dependency asymmetry is cleanest when pi's own config lives in its own repo, same shape as opencode-toolkit split out earlier today. The pi\u2194mempalace MCP bridge (mempalace.ts) stays in mempalace-toolkit where it belongs \u2014 it imports pi's ExtensionAPI but only exists to bridge to the palace. Verified on tor-ms22: fresh install \u2192 drift detect \u2192 adopt canonical \u2192 uninstall \u2192 reinstall \u2192 zsh -ic loads AWS vars. Bash fallback path also tested via HOME=/tmp/fake SHELL=/bin/bash.
This commit is contained in:
@@ -0,0 +1,197 @@
|
||||
# AGENTS.md
|
||||
|
||||
## What this is
|
||||
|
||||
Harness-side bring-up for the [pi coding-agent](https://github.com/mariozechner/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`](https://gitea.jordbo.se/joakimp/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`](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` → `cp` into `~/.oh-my-zsh/custom/`. That dir is
|
||||
typically part of a dotfiles backup (e.g. `myconfigs`'s
|
||||
`rsync_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.json` at runtime (`lastChangelogVersion` bumps
|
||||
on upgrade), so any symlink back to the repo would dirty the
|
||||
working tree. Installer prints the `cp` command 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 early
|
||||
`exit 4` from `require_pi_installed` because 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 via `cmp -s`, prints a `diff` hint, leaves the file alone.
|
||||
- **Do not auto-edit rc files.** If oh-my-zsh isn't present, print the
|
||||
`source` snippet the user manually adds to `~/.zshrc` or `~/.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-toolkit`
|
||||
on purpose), it must degrade gracefully when mempalace is absent.
|
||||
- **POSIX-compatible shell glue.** `set -a` / `source` / `set +a` work
|
||||
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 later
|
||||
`mempalace-toolkit` install has somewhere to symlink into.
|
||||
|
||||
Always (once pi is present):
|
||||
- Symlinks `keybindings.json` into `~/.pi/agent/`. Backs up any
|
||||
pre-existing real file.
|
||||
|
||||
oh-my-zsh path (gated on `~/.oh-my-zsh/custom/` existing):
|
||||
- Copies `pi-env.zsh` into that directory. Drift-safe — prints a `diff`
|
||||
hint if installed content differs from repo, doesn't clobber.
|
||||
|
||||
No oh-my-zsh path:
|
||||
- Prints a shell-specific source snippet for `~/.zshrc` or `~/.bashrc`
|
||||
(selected from `$SHELL`). User pastes manually.
|
||||
|
||||
Probes (non-halting):
|
||||
- `~/.pi/agent/settings.json` exists. Without it pi refuses to start
|
||||
without `--provider`/`--model`. Prints the `cp settings.example.json`
|
||||
command.
|
||||
- `AWS_PROFILE` + `AWS_REGION` are set, **only if** `settings.json`
|
||||
selects `amazon-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:
|
||||
|
||||
1. **One file at repo root.** Flat layout; no `extensions/` subdir yet.
|
||||
Revisit if five+ artifacts ever accumulate.
|
||||
2. **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`.
|
||||
3. **One install step + one uninstall step** in `install.sh`, guarded by
|
||||
`link_if_into_repo` (for symlinks) or `cmp -s` (for copies). Never
|
||||
remove user edits silently.
|
||||
4. **One probe per external dependency** the artifact implies. `warn` +
|
||||
`return 0`.
|
||||
5. **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's `ExtensionAPI`, registers MCP tools, injects wake-up
|
||||
context.
|
||||
- The `install_pi_extension` function 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:
|
||||
|
||||
```bash
|
||||
./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:
|
||||
|
||||
```bash
|
||||
SHELL=/bin/bash HOME=/tmp/fake ./install.sh --yes # should print ~/.bashrc snippet
|
||||
```
|
||||
|
||||
Environment verification (after install + `exec zsh` or new shell):
|
||||
|
||||
```bash
|
||||
zsh -ic 'echo $AWS_PROFILE $AWS_REGION' # should print values from ~/.config/pi/.env
|
||||
```
|
||||
|
||||
Drift simulation:
|
||||
|
||||
```bash
|
||||
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/mariozechner/pi-coding-agent.
|
||||
- **`settings.example.json` is region-specific.** The shipped default
|
||||
uses `eu.` Bedrock inference-profile prefixes. Users on us-east need
|
||||
to swap to `us.` 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_REGION` are irrelevant. The
|
||||
probe gates on `grep -q '"amazon-bedrock"' settings.json` to stay
|
||||
quiet in those cases.
|
||||
- **Mosh strips modifiers upstream of tmux.** The keybindings file's
|
||||
`ctrl+j` / `alt+j` fallbacks are specifically because mosh's vt220-ish
|
||||
emulation does not forward `Shift+Enter` as CSI-u — tmux's
|
||||
`extended-keys csi-u` setting 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/.env` should 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`](https://gitea.jordbo.se/joakimp/mempalace-toolkit)
|
||||
— adds a pi↔mempalace MCP bridge on top of this toolkit. Installs the
|
||||
`mempalace.ts` extension into `~/.pi/agent/extensions/`. Optional.
|
||||
- [`opencode-toolkit`](https://gitea.jordbo.se/joakimp/opencode-toolkit)
|
||||
— sibling pattern for the opencode coding-agent. Same install.sh
|
||||
shape.
|
||||
- [`opencode-devbox`](https://gitea.jordbo.se/joakimp/opencode-devbox)
|
||||
— Docker containers; composes any subset of these toolkits via
|
||||
independent install.sh invocations.
|
||||
- [`myconfigs`](https://gitea.jordbo.se/joakimp/myconfigs) — dotfiles
|
||||
repo where `~/.config/pi/.env` is 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.
|
||||
Reference in New Issue
Block a user