From 9a8f6faeaa0805f36dfe522f9c6747d7413dd38a Mon Sep 17 00:00:00 2001 From: Joakim Persson Date: Wed, 17 Jun 2026 10:26:38 +0200 Subject: [PATCH] install: symlink global AGENTS.md (auto-load pi-extensions skill at session start) Add pi-global-AGENTS.md, symlinked by install.sh to ~/.pi/agent/AGENTS.md (pi's global-instructions file, loaded at every startup). Directs the agent to read the pi-extensions skill at session start and carries a core fork/recall cheat-sheet, since on-demand skill description-matching was leaving the extensions under-utilised. Symlinked (not cp'd) like keybindings.json: pi never rewrites AGENTS.md, and the entrypoint re-runs install.sh on every container start, so the directive self-heals across container recreation / volume wipes. --- AGENTS.md | 1 + install.sh | 42 ++++++++++++++++++++++++++++++++++++++++++ pi-global-AGENTS.md | 27 +++++++++++++++++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 pi-global-AGENTS.md diff --git a/AGENTS.md b/AGENTS.md index b60cca0..c4654c0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -19,6 +19,7 @@ This file is for agents modifying the repo. 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 +pi-global-AGENTS.md # ~/.pi/agent/AGENTS.md (symlink) — global agent instructions settings.example.json # Template for ~/.pi/agent/settings.json (copy + edit) README.md # User-facing quickstart + new-machine deploy recipe. AGENTS.md # This file. diff --git a/install.sh b/install.sh index 0c855ed..eda6643 100755 --- a/install.sh +++ b/install.sh @@ -6,6 +6,9 @@ # and AWS_REGION are in every shell that launches pi. # - keybindings.json : mosh/tmux-friendly newline bindings # (shift+enter, ctrl+j, alt+j). +# - pi-global-AGENTS.md : global agent instructions, symlinked to +# ~/.pi/agent/AGENTS.md so pi loads it at every start +# (e.g. "read the pi-extensions skill at session start"). # - settings.example.json : template for ~/.pi/agent/settings.json so pi # starts without --provider/--model. Copy + edit. # @@ -28,6 +31,11 @@ PI_AGENT_DIR="${HOME}/.pi/agent" PI_KEYS_SRC="${SCRIPT_DIR}/keybindings.json" PI_KEYS_DEST="${HOME}/.pi/agent/keybindings.json" +# global instructions — symlinked (pi doesn't rewrite AGENTS.md at runtime). +# pi loads ~/.pi/agent/AGENTS.md as global instructions at every startup. +PI_AGENTS_SRC="${SCRIPT_DIR}/pi-global-AGENTS.md" +PI_AGENTS_DEST="${HOME}/.pi/agent/AGENTS.md" + # settings template — NOT installed, only referenced (pi rewrites settings.json) PI_SETTINGS_EXAMPLE="${SCRIPT_DIR}/settings.example.json" PI_SETTINGS_DEST="${HOME}/.pi/agent/settings.json" @@ -56,6 +64,8 @@ Usage: What install does: - Requires pi installed (~/.pi/agent/ must exist). Aborts cleanly otherwise. - Symlinks keybindings.json into ~/.pi/agent/keybindings.json. + - Symlinks pi-global-AGENTS.md into ~/.pi/agent/AGENTS.md (global + instructions loaded by pi at every start). - If oh-my-zsh is present (~/.oh-my-zsh/custom/), copies pi-env.zsh there so every new zsh shell sources ~/.config/pi/.env. Uses cp (not symlink) for dotfile-backup portability. Prints source snippet otherwise. @@ -64,6 +74,7 @@ What install does: What uninstall does: - Removes keybindings.json symlink if it points into this repo. + - Removes the AGENTS.md symlink if it points into this repo. - Removes pi-env.zsh copy ONLY if its content still matches the repo. - Never touches settings.json (it's your file, not managed here). @@ -128,6 +139,25 @@ install_keybindings() { ok "Linked keybindings.json → $PI_KEYS_SRC" } +install_agents_md() { + # Global agent instructions. Symlinked so edits flow through git and the + # managed default survives container recreation (entrypoint re-runs this + # installer on every start). pi never rewrites AGENTS.md at runtime. + note "Linking pi-global-AGENTS.md → $PI_AGENTS_DEST" + if [[ -e "$PI_AGENTS_DEST" || -L "$PI_AGENTS_DEST" ]]; then + if link_if_into_repo "$PI_AGENTS_DEST"; then + ok "pi global AGENTS.md already linked" + return 0 + fi + # Back up any existing real file / foreign symlink. + local backup="${PI_AGENTS_DEST}.bak.$(date +%Y%m%d-%H%M%S)" + mv "$PI_AGENTS_DEST" "$backup" + warn "Existing $PI_AGENTS_DEST backed up to $backup" + fi + ln -s "$PI_AGENTS_SRC" "$PI_AGENTS_DEST" + ok "Linked pi-global-AGENTS.md → $PI_AGENTS_SRC" +} + install_env_loader() { # Copy pi-env.zsh into ~/.oh-my-zsh/custom/ (auto-loaded by omz). # cp not symlink because that dir is typically part of a dotfiles backup @@ -217,6 +247,7 @@ do_install() { echo echo "==> Installation plan:" echo " Symlink keybindings.json → $PI_KEYS_DEST" + echo " Symlink pi-global-AGENTS.md → $PI_AGENTS_DEST" if [[ -d "$HOME/.oh-my-zsh/custom" ]]; then echo " Copy pi-env.zsh → $PI_ENV_OMZ_DEST" else @@ -227,6 +258,8 @@ do_install() { echo install_keybindings echo + install_agents_md + echo install_env_loader echo check_pi_settings @@ -253,6 +286,15 @@ do_uninstall() { ok "No pi keybindings symlink to remove" fi + echo + note "Removing pi global AGENTS.md symlink" + if link_if_into_repo "$PI_AGENTS_DEST"; then + rm "$PI_AGENTS_DEST" + ok "Removed pi global AGENTS.md symlink" + else + ok "No pi global AGENTS.md 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 diff --git a/pi-global-AGENTS.md b/pi-global-AGENTS.md new file mode 100644 index 0000000..b0aa97c --- /dev/null +++ b/pi-global-AGENTS.md @@ -0,0 +1,27 @@ +# Global agent instructions + +## Session start: load the pi-extensions skill + +If the `fork` and/or `recall` tools are present in your tool list (you are +running inside the **pi** harness with the pi-fork / pi-observational-memory +packages), **read `~/.agents/skills/pi-extensions/SKILL.md` before doing any +non-trivial work.** These extensions are routinely under-utilised when left to +on-demand description matching; reading the skill up front fixes that. + +Core triggers (cheat-sheet — the skill has the full guidance): + +- **Fork** (`fork(task=..., effort=fast|balanced|deep)`) when a subtask needs + reading many files you won't keep, runs in parallel, or is a well-scoped + one-shot whose detail would pollute the main thread. Tiers: `fast`=haiku + (mechanical/lookups), `balanced`=sonnet (default: exploration/impl/test), + `deep`=opus (architecture, security, ambiguous debugging). Always state + decision authority, pass verified context, specify the deliverable, ask for + an "unsure about" section. Don't fork trivial or iterative work. +- **Recall** (`recall(<12-char-hex-id>)`) before a load-bearing action (edit + code, ship a change, assert a fact) that rests on a `[high]`/`[critical]` + observation or a reflection you did not produce this turn. The compaction + summary is lossy by design; one recall is cheap, redoing finished work is not. + Not a search tool — you must already have the ID. + +For depth on tier selection, fork-brief design, boundary discipline, and the +observational-memory model, read the full skill.