diff --git a/AGENTS.md b/AGENTS.md index c17b2fd..83956bf 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -22,6 +22,7 @@ extensions/ pi/ # pi coding-agent bring-up: MCP bridge, keybindings, settings template mempalace.ts # Symlinked into ~/.pi/agent/extensions/ (MCP <→ pi glue) keybindings.json # Symlinked into ~/.pi/agent/ (mosh/tmux newline fix) + pi-env.zsh # Copied into ~/.oh-my-zsh/custom/ or sourced from .bashrc (loads ~/.config/pi/.env) settings.example.json # Template; user copies + edits (pi rewrites settings.json at runtime) README.md # Extension internals, schema-passthrough gotcha, env setup ``` diff --git a/README.md b/README.md index c11c048..8aa81dc 100644 --- a/README.md +++ b/README.md @@ -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. - [`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. -- [`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. +- [`extensions/pi/`](extensions/pi/) — pi coding-agent bridge: the MemPalace MCP extension (symlinked), a mosh/tmux-friendly keybindings file (symlinked), a `pi-env.zsh` shell loader (copied into `~/.oh-my-zsh/custom/` on zsh+omz hosts, or source'd from `.bashrc` / `.zshrc` otherwise), 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 want the full architecture story → read [`ARCHITECTURE.md`](ARCHITECTURE.md).** diff --git a/extensions/pi/README.md b/extensions/pi/README.md index c2d919e..49fad52 100644 --- a/extensions/pi/README.md +++ b/extensions/pi/README.md @@ -97,17 +97,22 @@ Run `pi --list-models` to confirm what your credentials can actually invoke. ### 5. Ensure AWS env vars are live in your shell -If you provisioned via step 1, `~/.config/pi/.env` exists and -`~/.oh-my-zsh/custom/pi-env.zsh` sources it on every new shell. Verify: +**On zsh + oh-my-zsh hosts:** step 3's `install.sh` already copied +`pi-env.zsh` into `~/.oh-my-zsh/custom/`, so every new shell sources +`~/.config/pi/.env` automatically. Verify: ```bash exec zsh echo "$AWS_PROFILE $AWS_REGION" # should print your values ``` -If empty, check that `~/.config/pi/.env` decrypted (`head ~/.config/pi/.env` -should show plain text, not binary). `git-crypt unlock` in step 1 is the -usual culprit when this is empty. +**On bash or plain zsh (no oh-my-zsh):** `install.sh` printed a +`source /extensions/pi/pi-env.zsh` snippet — add that one line to +`~/.bashrc` or `~/.zshrc`, open a fresh shell, verify as above. + +If vars are empty, check that `~/.config/pi/.env` decrypted +(`head ~/.config/pi/.env` should show plain text, not binary). +`git-crypt unlock` in step 1 is the usual culprit when this is empty. ### 6. Register mempalace MCP with opencode (if using opencode too) @@ -259,9 +264,26 @@ 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 +~/.oh-my-zsh/custom/pi-env.zsh ← installed by mempalace-toolkit install.sh + (sources the .env into every shell) ``` +The loader file `pi-env.zsh` is canonical here in `extensions/pi/` and +installed by `install.sh` in one of two ways: + +| Detected | Action | +|---|---| +| `~/.oh-my-zsh/custom/` exists | `cp` (not symlink) into that directory — auto-loaded by omz on every new shell. cp not symlink because that directory is part of the dotfiles backup, and a symlink into mempalace-toolkit would break when the backup is restored on another host. | +| No oh-my-zsh | Prints a shell-specific `source /extensions/pi/pi-env.zsh` snippet for `~/.zshrc` or `~/.bashrc`. Installer does not auto-edit rc files. | + +The loader itself is POSIX-compatible (`set -a` / `source` / `set +a`), +so bash users can source it directly — no zsh dependency in the file. + +Re-runs are idempotent: if the installed copy matches the repo, prints +"already installed". If it differs, leaves your edits alone and points +at `diff` for comparison. Uninstall only removes the file if it still +matches the repo copy; local edits are preserved. + 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` @@ -276,6 +298,7 @@ mempalace-toolkit/ ├── README.md ← this file ├── mempalace.ts ← symlinked into ~/.pi/agent/extensions/ ├── keybindings.json ← symlinked into ~/.pi/agent/ + ├── pi-env.zsh ← cp'd into ~/.oh-my-zsh/custom/ (or source'd manually for bash) └── settings.example.json ← template; copy + edit into ~/.pi/agent/ ``` diff --git a/extensions/pi/pi-env.zsh b/extensions/pi/pi-env.zsh new file mode 100644 index 0000000..82fc423 --- /dev/null +++ b/extensions/pi/pi-env.zsh @@ -0,0 +1,28 @@ +# Load pi coding-agent environment variables from ~/.config/pi/.env +# +# Canonical source: mempalace-toolkit/extensions/pi/pi-env.zsh +# Installed by mempalace-toolkit/install.sh via `cp` (not symlink) to keep +# ~/.oh-my-zsh/custom/ portable across machines with different $HOME paths. +# See extensions/pi/README.md#environment-setup for the full story. +# +# Sources ~/.config/pi/.env (AWS_PROFILE, AWS_REGION, and any future +# pi-scoped secrets) so pi's Bedrock provider works when spawned from any +# shell. The .env file itself is shipped (git-crypt encrypted) from the +# myconfigs dotfiles repo. +# +# `set -a` auto-exports every assignment in the sourced file, so plain +# KEY=VALUE lines become exported env vars without needing `export` in .env. +# Also works in bash (set -a and source are POSIX) — non-oh-my-zsh users +# can source this file directly from ~/.bashrc or ~/.zshrc instead. +# +# Historical note: these vars used to live in ~/.config/opencode/.env +# under a "# Environment variables for pi" block. Split out 2026-05-05 +# so each tool owns its own env file. + +_pi_env="${HOME}/.config/pi/.env" +if [[ -r "${_pi_env}" ]]; then + set -a + source "${_pi_env}" + set +a +fi +unset _pi_env diff --git a/install.sh b/install.sh index 4c1cdb1..7901add 100755 --- a/install.sh +++ b/install.sh @@ -29,6 +29,10 @@ PI_KEYS_DEST="${HOME}/.pi/agent/keybindings.json" PI_SETTINGS_EXAMPLE="${SCRIPT_DIR}/extensions/pi/settings.example.json" PI_SETTINGS_DEST="${HOME}/.pi/agent/settings.json" +# pi env loader (shell glue that sources ~/.config/pi/.env into every shell) +PI_ENV_SRC="${SCRIPT_DIR}/extensions/pi/pi-env.zsh" +PI_ENV_OMZ_DEST="${HOME}/.oh-my-zsh/custom/pi-env.zsh" + # ── args ───────────────────────────────────────────── ACTION="install" ASSUME_YES="no" @@ -58,6 +62,14 @@ What install does: - 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). + - If oh-my-zsh is detected (~/.oh-my-zsh/custom/ exists), copies + extensions/pi/pi-env.zsh into ~/.oh-my-zsh/custom/pi-env.zsh so every + new zsh shell sources ~/.config/pi/.env. Uses cp (not symlink) because + that dir gets backed up by rsync_copy and symlinks would break + portability. Re-runs are idempotent when content matches the repo; + warns and leaves local edits alone if they differ. + - If oh-my-zsh is NOT detected, prints a shell-specific source snippet + for ~/.zshrc or ~/.bashrc. Does not auto-edit rc files. - 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 @@ -292,6 +304,56 @@ install_pi_keybindings() { ok "Linked keybindings.json → $PI_KEYS_SRC" } +install_pi_env_loader() { + # Ship pi-env.zsh (sources ~/.config/pi/.env so AWS vars etc. are in + # every shell that starts pi). Two paths depending on shell setup: + # + # 1. oh-my-zsh present → cp into ~/.oh-my-zsh/custom/ (auto-loaded by + # omz). cp not symlink because that directory is typically part of + # a dotfiles backup (rsync_copy.sh in the myconfigs repo) and a + # symlink into mempalace-toolkit would break when restored on + # another host. + # 2. No oh-my-zsh → print a source snippet for ~/.zshrc or ~/.bashrc. + # We don't auto-edit rc files — too invasive for an optional glue + # file. The loader itself is POSIX-compatible (set -a / source / + # set +a), so bash users can source it directly. + + [[ -d "$PI_EXT_DEST_DIR" ]] || return 0 # no pi → skip + + if [[ -d "$HOME/.oh-my-zsh/custom" ]]; then + note "Installing pi-env.zsh into ~/.oh-my-zsh/custom/" + if [[ -f "$PI_ENV_OMZ_DEST" ]]; then + if cmp -s "$PI_ENV_SRC" "$PI_ENV_OMZ_DEST"; then + ok "pi-env.zsh already installed (content matches repo)" + return 0 + fi + warn "$PI_ENV_OMZ_DEST exists and differs from repo copy" + printf ' Leaving your edits alone. Compare with:\n' + printf ' diff %q %q\n' "$PI_ENV_OMZ_DEST" "$PI_ENV_SRC" + printf ' To adopt the repo version: rm that file and re-run install.sh\n' + return 0 + fi + cp "$PI_ENV_SRC" "$PI_ENV_OMZ_DEST" + ok "Copied pi-env.zsh → $PI_ENV_OMZ_DEST" + printf ' Open a new shell (or `exec zsh`) to load AWS_PROFILE / AWS_REGION.\n' + return 0 + fi + + # No oh-my-zsh — print shell-specific snippet. + note "oh-my-zsh not detected — manual shell setup needed" + local shell_name + shell_name="$(basename "${SHELL:-bash}")" + local rc_file + case "$shell_name" in + zsh) rc_file="~/.zshrc" ;; + bash) rc_file="~/.bashrc" ;; + *) rc_file="~/.${shell_name}rc # adjust for your shell" ;; + esac + printf ' Add this line to %s so every shell sources ~/.config/pi/.env:\n' "$rc_file" + printf ' source %q\n' "$PI_ENV_SRC" + printf ' (the loader itself is POSIX-compatible — works in bash and zsh.)\n' +} + # ── 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 @@ -370,6 +432,8 @@ do_install() { echo install_pi_keybindings echo + install_pi_env_loader + echo check_path echo check_wake_up_protocol @@ -436,6 +500,19 @@ do_uninstall() { ok "No pi keybindings symlink to remove" fi + echo + note "Removing pi-env.zsh loader (oh-my-zsh path)" + # Only remove if content still matches the repo copy — user may have + # local edits we shouldn't silently discard. + if [[ -f "$PI_ENV_OMZ_DEST" ]] && cmp -s "$PI_ENV_SRC" "$PI_ENV_OMZ_DEST"; then + rm "$PI_ENV_OMZ_DEST" + ok "Removed $PI_ENV_OMZ_DEST" + elif [[ -f "$PI_ENV_OMZ_DEST" ]]; then + warn "$PI_ENV_OMZ_DEST differs from repo copy — left alone" + else + ok "No pi-env.zsh loader to remove" + fi + # 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. local marker="$SKILL_DEST_DIR/.skill-source"