feat(extensions/pi): keybindings symlink + settings template + AWS/pi probes

Round out the pi bring-up story so a fresh machine can reach a working
pi+mempalace install with just `git clone && ./install.sh`:

- extensions/pi/keybindings.json: generic mosh/tmux newline fix
  (shift+enter, ctrl+j, alt+j). Safe on any machine — not
  region/account-specific. Symlinked into ~/.pi/agent/.
- extensions/pi/settings.example.json: template for `settings.json`
  so pi can start without --provider/--model. NOT symlinked — pi
  rewrites settings.json at runtime (lastChangelogVersion bumps),
  which would dirty the repo. Installer prints the cp + edit hint.
- install.sh: new install_pi_keybindings + uninstall mirror; new
  check_pi_settings probe (warns if settings.json missing); new
  check_aws_env probe (warns if AWS_PROFILE/AWS_REGION unset and
  settings.json selects amazon-bedrock). All new steps gated on
  pi being installed (~/.pi/agent/extensions/ exists).
- extensions/pi/README.md: documents keybindings rationale,
  settings bootstrap, and the recommended ~/.config/pi/.env +
  ~/.oh-my-zsh/custom/pi-env.zsh env layout (paired with the
  myconfigs commit 884e329 that split AWS vars out of
  ~/.config/opencode/.env).

Verified on tor-ms22: full install → uninstall → reinstall cycle,
new shell loads AWS_PROFILE/AWS_REGION from the new pi-env.zsh hook.

Works on macOS and Linux (plain ln -s, POSIX bash).
This commit is contained in:
2026-05-05 13:59:20 +02:00
parent ef1d022fbc
commit 854ae41f65
5 changed files with 181 additions and 6 deletions
+1 -1
View File
@@ -8,7 +8,7 @@ Producer-side tooling for [MemPalace](https://github.com/MemPalace/mempalace)
- `bin/mempalace-docs` — mines project directories into MemPalace while excluding source code, keeping the palace signal-dense. - `bin/mempalace-docs` — mines project directories into MemPalace while excluding source code, keeping the palace signal-dense.
- [`ARCHITECTURE.md`](ARCHITECTURE.md) — **canonical spec**: architecture diagram, component details, setup recipe, operational notes, upstream-retirement roadmap. - [`ARCHITECTURE.md`](ARCHITECTURE.md) — **canonical spec**: architecture diagram, component details, setup recipe, operational notes, upstream-retirement roadmap.
- [`SKILL.md`](SKILL.md) — the companion agent skill, symlinked into `~/.agents/skills/opencode-mempalace-bridge/` on install. - [`SKILL.md`](SKILL.md) — the companion agent skill, symlinked into `~/.agents/skills/opencode-mempalace-bridge/` on install.
- [`extensions/pi/`](extensions/pi/) — the [pi coding-agent](https://github.com/mariozechner/pi-coding-agent) extension that bridges pi to the MemPalace MCP server (wake-up auto-injection, `/mempalace-diary` command, schema passthrough). Symlinked into `~/.pi/agent/extensions/` on install when pi is detected. - [`extensions/pi/`](extensions/pi/) — pi coding-agent bridge: the MemPalace MCP extension (symlinked), a mosh/tmux-friendly keybindings file (symlinked), and a `settings.example.json` template for starting pi without `--model`. `install.sh` also probes for `AWS_PROFILE`/`AWS_REGION` (needed by pi's Bedrock provider) and points at the recommended `~/.config/pi/.env` layout if missing.
**If you're just trying to get this working on a new machine → jump to [Setup](#setup).** **If you're just trying to get this working on a new machine → jump to [Setup](#setup).**
**If you want the full architecture story → read [`ARCHITECTURE.md`](ARCHITECTURE.md).** **If you want the full architecture story → read [`ARCHITECTURE.md`](ARCHITECTURE.md).**
+59 -5
View File
@@ -73,17 +73,71 @@ If you ever need to re-loosen the schema for debugging, fall back to
the `Type.Object({}, { additionalProperties: true })` default only for the `Type.Object({}, { additionalProperties: true })` default only for
that specific tool, not globally. that specific tool, not globally.
## Keybindings (mosh/tmux newline fix)
`keybindings.json` is symlinked so edits flow through git. Default:
```json
{
"tui.input.newLine": ["shift+enter", "ctrl+j", "alt+j"]
}
```
Rationale: when pi runs over `kitty → mosh → tmux`, shift+enter doesn't
forward cleanly (mosh uses vt220-ish emulation, no kitty-keyboard-protocol
or csi-u extended keys). `ctrl+j` and `alt+j` pass through as plain
control/meta bytes and give you reliable newline insertion.
## Settings template (start pi without `--model`)
`settings.example.json` is a template — **not symlinked**. pi rewrites
its `settings.json` at runtime (`lastChangelogVersion` bumps on upgrade),
which would dirty a symlinked repo file. Instead, bootstrap with:
```bash
cp /path/to/mempalace-toolkit/extensions/pi/settings.example.json \
~/.pi/agent/settings.json
$EDITOR ~/.pi/agent/settings.json
```
The Bedrock inference-profile prefix on model IDs (`eu.`, `us.`) is
**region-specific** and must match `AWS_REGION` in `~/.config/pi/.env`.
For a bare Anthropic provider (non-Bedrock) drop the prefix entirely
and use `anthropic:claude-...`. Run `pi --list-models` to confirm what
your credentials can actually invoke.
`install.sh` warns (non-fatal) if `settings.json` is missing.
## Environment setup
pi with `defaultProvider=amazon-bedrock` needs `AWS_PROFILE` and
`AWS_REGION` exported into the shell that launches it. Recommended
layout (matches the tor-ms22 dotfiles pattern):
```
~/.config/pi/.env ← AWS_PROFILE=..., AWS_REGION=...
(git-crypt encrypted in dotfiles repo)
~/.oh-my-zsh/custom/pi-env.zsh ← set -a; source ~/.config/pi/.env; set +a
```
Historical note: these vars used to live under a `# Environment variables
for pi` block inside `~/.config/opencode/.env`. Split out 2026-05-05 so
each tool owns its own env file. `install.sh` runs a `check_aws_env`
probe that warns if the vars are missing and points back here.
## File layout ## File layout
``` ```
mempalace-toolkit/ mempalace-toolkit/
└── extensions/ └── extensions/
└── pi/ └── pi/
├── README.md ← this file ├── README.md ← this file
── mempalace.ts ← symlinked into ~/.pi/agent/extensions/ ── mempalace.ts ← symlinked into ~/.pi/agent/extensions/
├── keybindings.json ← symlinked into ~/.pi/agent/
└── settings.example.json ← template; copy + edit into ~/.pi/agent/
``` ```
`install.sh` detects pi by probing for `~/.pi/agent/extensions/` and `install.sh` detects pi by probing for `~/.pi/agent/extensions/` and
only creates the symlink when that directory exists. On machines only creates symlinks when that directory exists. On machines without
without pi the file stays dormant in the repo. Re-runs are idempotent pi the files stay dormant in the repo. Re-runs are idempotent (same
(same pattern as `bin/` and `SKILL.md`). pattern as `bin/` and `SKILL.md`).
+3
View File
@@ -0,0 +1,3 @@
{
"tui.input.newLine": ["shift+enter", "ctrl+j", "alt+j"]
}
+12
View File
@@ -0,0 +1,12 @@
{
"_comment": "Template for ~/.pi/agent/settings.json. Copy to that path and adjust for your region/account — this file is NOT symlinked by install.sh because pi rewrites settings.json at runtime (lastChangelogVersion bumps), which would dirty the repo. This template exists so a fresh machine can start pi without --model by copying + editing.",
"_comment_models": "The 'eu.' prefix on Bedrock model IDs is an inference-profile prefix tied to the AWS region. Must match AWS_REGION in ~/.config/pi/.env. For us-east use 'us.anthropic.*'; for bare Anthropic provider (non-Bedrock) use the raw 'anthropic:claude-*' IDs. Run `pi --list-models` to see what your credentials can actually invoke.",
"defaultProvider": "amazon-bedrock",
"defaultModel": "eu.anthropic.claude-sonnet-4-6",
"enabledModels": [
"eu.anthropic.claude-sonnet-4-6",
"eu.anthropic.claude-opus-4-7",
"eu.anthropic.claude-haiku-4-5-20251001-v1:0"
]
}
+106
View File
@@ -21,6 +21,14 @@ PI_EXT_SRC="${SCRIPT_DIR}/extensions/pi/mempalace.ts"
PI_EXT_DEST_DIR="${HOME}/.pi/agent/extensions" PI_EXT_DEST_DIR="${HOME}/.pi/agent/extensions"
PI_EXT_DEST="${PI_EXT_DEST_DIR}/mempalace.ts" PI_EXT_DEST="${PI_EXT_DEST_DIR}/mempalace.ts"
# pi keybindings (generic mosh/tmux newline fix — safe on any machine)
PI_KEYS_SRC="${SCRIPT_DIR}/extensions/pi/keybindings.json"
PI_KEYS_DEST="${HOME}/.pi/agent/keybindings.json"
# pi settings template (NOT symlinked — pi rewrites this file at runtime)
PI_SETTINGS_EXAMPLE="${SCRIPT_DIR}/extensions/pi/settings.example.json"
PI_SETTINGS_DEST="${HOME}/.pi/agent/settings.json"
# ── args ───────────────────────────────────────────── # ── args ─────────────────────────────────────────────
ACTION="install" ACTION="install"
ASSUME_YES="no" ASSUME_YES="no"
@@ -45,6 +53,13 @@ What install does:
reach Claude Code and Kiro) reach Claude Code and Kiro)
- If pi (~/.pi/agent/extensions/) exists, symlinks extensions/pi/mempalace.ts - If pi (~/.pi/agent/extensions/) exists, symlinks extensions/pi/mempalace.ts
into ~/.pi/agent/extensions/mempalace.ts (pi bridge). Skipped otherwise. into ~/.pi/agent/extensions/mempalace.ts (pi bridge). Skipped otherwise.
- If pi exists, symlinks extensions/pi/keybindings.json into
~/.pi/agent/keybindings.json (generic mosh/tmux newline fix).
- If pi exists, warns if ~/.pi/agent/settings.json is missing and points
at extensions/pi/settings.example.json as a template (NOT symlinked —
pi rewrites this file at runtime).
- Warns if AWS_PROFILE / AWS_REGION are unset (only relevant to users
whose pi settings.json selects amazon-bedrock as defaultProvider).
- Drops a .skill-source marker in the skill dir so sibling tooling - Drops a .skill-source marker in the skill dir so sibling tooling
(deploy-skills.sh, agents-sync.zsh) knows the dir is externally owned (deploy-skills.sh, agents-sync.zsh) knows the dir is externally owned
@@ -52,6 +67,7 @@ What uninstall does:
- Removes symlinks in ~/.local/bin/ that point into this repo - Removes symlinks in ~/.local/bin/ that point into this repo
- Removes the skill symlink if it points into this repo - Removes the skill symlink if it points into this repo
- Removes the pi extension symlink if it points into this repo - Removes the pi extension symlink if it points into this repo
- Removes the pi keybindings symlink if it points into this repo
- Removes the .skill-source marker and empty skill dir - Removes the .skill-source marker and empty skill dir
EOF EOF
exit 0 ;; exit 0 ;;
@@ -257,6 +273,80 @@ install_pi_extension() {
printf ' at startup only).\n' printf ' at startup only).\n'
} }
install_pi_keybindings() {
# Generic mosh/tmux newline fix. Non-destructive: if a real
# keybindings.json exists we back it up rather than clobber.
[[ -d "$PI_EXT_DEST_DIR" ]] || return 0 # no pi → no keybindings
note "Linking pi keybindings → $PI_KEYS_DEST"
if [[ -e "$PI_KEYS_DEST" || -L "$PI_KEYS_DEST" ]]; then
if link_if_into_repo "$PI_KEYS_DEST"; then
ok "pi keybindings already linked"
return 0
fi
local backup="${PI_KEYS_DEST}.bak.$(date +%Y%m%d-%H%M%S)"
mv "$PI_KEYS_DEST" "$backup"
warn "Existing $PI_KEYS_DEST backed up to $backup"
fi
ln -s "$PI_KEYS_SRC" "$PI_KEYS_DEST"
ok "Linked keybindings.json → $PI_KEYS_SRC"
}
# ── Verify ~/.pi/agent/settings.json exists ──────────────────────────
# If pi is installed but settings.json is missing, `pi` refuses to start
# without `--provider ... --model ...` on every invocation. The toolkit
# ships extensions/pi/settings.example.json as a template with a working
# Bedrock (eu-west-1) stanza — copy + edit for your region/account.
#
# NOT symlinked: pi rewrites settings.json at runtime (lastChangelogVersion
# bumps on upgrade), which would dirty the repo and cause merge noise.
# Template-only install is the right trade-off.
check_pi_settings() {
[[ -d "$PI_EXT_DEST_DIR" ]] || return 0 # no pi → nothing to check
if [[ -f "$PI_SETTINGS_DEST" ]]; then
ok "pi settings.json present at $PI_SETTINGS_DEST"
return 0
fi
warn "pi settings.json NOT found at $PI_SETTINGS_DEST"
printf ' Without it, pi must be invoked with --provider/--model on every run.\n'
printf ' Bootstrap from the shipped template:\n'
printf ' cp %q %q\n' "$PI_SETTINGS_EXAMPLE" "$PI_SETTINGS_DEST"
printf ' $EDITOR %q # adjust region prefix + model IDs\n' "$PI_SETTINGS_DEST"
printf ' See extensions/pi/README.md for the eu./us./anthropic: prefix rules.\n'
return 0
}
# ── Verify AWS env vars are present for Bedrock-backed pi ────────────
# Only meaningful if pi's settings.json selects amazon-bedrock. We do a
# best-effort grep rather than parsing JSON — false positives are cheap
# (one extra probe) and the check is gated on pi being installed at all.
check_aws_env() {
[[ -d "$PI_EXT_DEST_DIR" ]] || return 0 # no pi → nothing to check
# Only warn if settings.json selects amazon-bedrock. If pi uses a
# non-Bedrock provider (bare anthropic, openai, ...) AWS creds are
# irrelevant and this probe would be noise.
if [[ -f "$PI_SETTINGS_DEST" ]] \
&& ! grep -q '"amazon-bedrock"' "$PI_SETTINGS_DEST" 2>/dev/null; then
return 0
fi
if [[ -n "${AWS_PROFILE:-}" && -n "${AWS_REGION:-}" ]]; then
ok "AWS env present (AWS_PROFILE=$AWS_PROFILE, AWS_REGION=$AWS_REGION)"
return 0
fi
warn "AWS_PROFILE and/or AWS_REGION not set in this shell"
printf ' pi with defaultProvider=amazon-bedrock needs both to invoke Bedrock.\n'
printf ' Recommended layout (matches the tor-ms22 dotfiles pattern):\n'
printf ' ~/.config/pi/.env # AWS_PROFILE=..., AWS_REGION=...\n'
printf ' ~/.oh-my-zsh/custom/pi-env.zsh # set -a; source ~/.config/pi/.env; set +a\n'
printf ' See extensions/pi/README.md#environment-setup for the template.\n'
return 0
}
do_install() { do_install() {
echo echo
echo "mempalace-toolkit installer" echo "mempalace-toolkit installer"
@@ -267,6 +357,7 @@ do_install() {
echo " Symlink SKILL.md into $SKILL_DEST" echo " Symlink SKILL.md into $SKILL_DEST"
if [[ -d "$PI_EXT_DEST_DIR" ]]; then if [[ -d "$PI_EXT_DEST_DIR" ]]; then
echo " Symlink extensions/pi/mempalace.ts into $PI_EXT_DEST" echo " Symlink extensions/pi/mempalace.ts into $PI_EXT_DEST"
echo " Symlink extensions/pi/keybindings.json into $PI_KEYS_DEST"
fi fi
echo echo
confirm || { echo "Aborted."; exit 0; } confirm || { echo "Aborted."; exit 0; }
@@ -277,12 +368,18 @@ do_install() {
echo echo
install_pi_extension install_pi_extension
echo echo
install_pi_keybindings
echo
check_path check_path
echo echo
check_wake_up_protocol check_wake_up_protocol
echo echo
check_opencode_mcp check_opencode_mcp
echo echo
check_pi_settings
echo
check_aws_env
echo
ok "Done." ok "Done."
echo echo
echo "Next: ./bin/mempalace-session --dry-run" echo "Next: ./bin/mempalace-session --dry-run"
@@ -330,6 +427,15 @@ do_uninstall() {
ok "No pi extension symlink to remove" ok "No pi extension symlink to remove"
fi fi
echo
note "Removing pi keybindings symlink"
if link_if_into_repo "$PI_KEYS_DEST"; then
rm "$PI_KEYS_DEST"
ok "Removed pi keybindings symlink"
else
ok "No pi keybindings symlink to remove"
fi
# Remove the marker and the now-empty skill directory, but only if # Remove the marker and the now-empty skill directory, but only if
# the marker was written by us and the directory has nothing else in it. # the marker was written by us and the directory has nothing else in it.
local marker="$SKILL_DEST_DIR/.skill-source" local marker="$SKILL_DEST_DIR/.skill-source"