pi-custom-system-prompt
v0.1.1
Published
Pi extension that loads a custom system prompt from `~/.pi/agent/system-prompts/*.md` and injects it on every agent turn, with commands to select, toggle, reload, and switch between replace and append modes.
Maintainers
Readme
pi-custom-system-prompt
A pi extension that loads a custom system prompt from a markdown file and injects it into every agent turn. Works with any model or provider — nothing is hardcoded.
Multiple .md files can live in the prompt directory; pick which one is active with /system-prompt-select. All changes take effect on the very next message you send — no /new or session restart required.
Commands
| Command | What it does |
|---|---|
| /system-prompt-info | Show loaded path, size, mode, enabled state, available files |
| /system-prompt-toggle | Enable or disable the custom prompt |
| /system-prompt-reload | Re-read the selected prompt file from disk |
| /system-prompt-mode [replace\|append] | Toggle or set the merge mode |
| /system-prompt-show | Print the first ~800 chars of the loaded prompt |
| /system-prompt-select | Pick a different prompt file from the directory |
Modes
append (default) — keep Pi's default system prompt as the base, and add the custom prompt as an extra section. Safest for most models, since Pi's tool descriptions stay authoritative.
replace — use the custom prompt as the base system prompt. Pi appends the following after it, so nothing Pi would normally load is lost: the available-tools listing (with a note to use those tools instead of any fictional ones mentioned in the custom prompt), any --append-system-prompt text, project context files (e.g. AGENTS.md, .pi/rules) wrapped in <project_context>, the <available_skills> block listing loadable SKILL.md files, the current date, and the working directory.
The project-context and skills blocks are mirrored from Pi's own prompt assembly, so in replace mode the model sees the same project instructions and skill list it would in append mode — the custom prompt just becomes the base instead of an add-on.
Setup
1. Install the extension
pi install npm:pi-custom-system-promptOr try it without installing:
pi -e npm:pi-custom-system-prompt2. Create the prompt directory
mkdir -p ~/.pi/agent/system-promptsThe extension reads from this directory by default. To use a different location, set the PI_SYSTEM_PROMPT_DIR environment variable.
3. Add a markdown file
# Example: a focused prompt for a specific model
cat > ~/.pi/agent/system-prompts/claude-code.md <<'EOF'
You are a careful, terse coding assistant.
- Read files before editing them.
- Prefer minimal diffs.
- Explain non-obvious choices in one sentence.
EOF
# Another example: a personality-style prompt
cat > ~/.pi/agent/system-prompts/pirate.md <<'EOF'
You are a pirate captain. Speak in pirate vernacular but stay accurate
about technical content. Never break character.
EOFThe first file (alphabetical) is auto-selected on first run. Use /system-prompt-select to switch between them.
4. Verify and toggle
# inside pi:
/system-prompt-info # confirm the file loaded
/system-prompt-toggle off # disable without deleting the file
/system-prompt-toggle on # re-enableThe footer shows the active state:
system-prompt: claude-code.md # enabled, showing the file
system-prompt: enabled # enabled, no file selected
system-prompt: disabled # disabledHow it works
- The extension subscribes to
before_agent_start, which fires on every user message. It reads the selected.mdfile from the prompt directory, then either appends it to or replaces Pi's resolved system prompt before sending to the model. - In
replacemode, the extension reconstructs the prompt ascustomPrompt + tools + appendSystemPrompt + <project_context> + <available_skills> + date + cwd, matching Pi's own assembly order so project context files and skills survive the swap. The available-skills block is emitted by a small inlined helper that mirrors Pi'sformatSkillsForPromptexactly (same XML escaping, samedisableModelInvocationfiltering); it is inlined rather than imported so the extension takes no runtime dependency on the host package and stays resolvable regardless ofnode_modulestopology. - State (
enabled,mode,selectedFile) persists to~/.pi/agent/state/system-prompt.jsonand is reloaded on the next start. - All commands are non-destructive: they mutate in-memory state, save to the state file, and take effect on the next message.
- If the prompt directory is missing, has no
.mdfiles, or the selected file is empty/unreadable, the extension logs the reason to/system-prompt-infoand falls back to Pi's default prompt with no error.
Removing the extension
pi remove npm:pi-custom-system-promptThis unloads the extension but does not delete your prompt files in ~/.pi/agent/system-prompts/ or your saved state in ~/.pi/agent/state/system-prompt.json. Delete those manually if you want a clean uninstall:
rm -rf ~/.pi/agent/system-prompts
rm -f ~/.pi/agent/state/system-prompt.jsonEnvironment variables
| Variable | Default | Effect |
|---|---|---|
| PI_SYSTEM_PROMPT_DIR | ~/.pi/agent/system-prompts | Override the directory the extension scans for .md prompt files |
Development
The extension lives in extensions/system-prompt.ts. To load it from a local checkout during development:
pi -e /absolute/path/to/pi-custom-system-prompt/extensions/system-prompt.tsFor a hot-reload loop, symlink it into the global extensions directory:
ln -s "$(pwd)/extensions/system-prompt.ts" ~/.pi/agent/extensions/system-prompt.tsThen /reload inside pi after each edit.
Layout
pi-custom-system-prompt/
├── extensions/
│ └── system-prompt.ts
├── package.json
├── tsconfig.json
├── README.md
├── CHANGELOG.md
└── LICENSEThe extensions/ directory is a pi convention: any .ts file inside it is auto-discovered. The pi-package keyword in package.json makes the package appear in the pi package gallery.
