Centralized pi coding agent configuration — sync your full pi setup across machines, safely.
All tracked config files are sanitized: real API keys are replaced with __REQUIRED__ placeholders before they ever reach git. Your actual secrets live only in local gitignored files under private/.
- Repository Structure
- Security Model
- Required API Keys
- Setup on a Brand-New Machine
- Updating an Existing Machine
- Exporting Config from a Machine
- Secret Bootstrap Workflow
- What Gets Synced
pi-config/
├── config/ # Tracked, sanitized config (safe to commit)
│ ├── settings.json # pi settings, packages, skills list, theme
│ ├── models.json # model providers — apiKeys replaced with __REQUIRED__
│ ├── mcp.json # MCP servers — tokens replaced with __REQUIRED__
│ ├── web-search.json # web search — Gemini key replaced with __REQUIRED__
│ ├── SECRETS.md # internal docs on how secrets handling works
│ ├── skills-lock.json
│ └── root-skill-lock.json
├── private/ # Local-only secret-bearing config (gitignored, NEVER committed)
│ ├── models.json
│ ├── mcp.json
│ └── web-search.json
├── agents/ # Custom agent definitions
├── prompts/ # Custom prompt templates
├── themes/ # Custom themes
├── skills/ # Custom non-symlink skills
├── installed-skills/ # Mirror of ~/.agents/skills/
├── scripts/
│ └── sanitize_configs.py # Strips API keys during export
├── bin/ # Local binaries (gitignored where needed)
├── sync.sh # Export current machine config → this repo
├── restore.sh # Restore config from this repo → a machine
├── bootstrap-secrets.sh # Manage local private/ secrets
└── .gitignore # Blocks private/, auth.json, sessions, caches
| Layer | What happens |
|---|---|
Export (sync.sh export) |
Copies live config to private/ (real keys), then runs sanitize_configs.py to write config/ with __REQUIRED__ placeholders |
Restore (restore.sh) |
Prefers private/ if present (real keys). Falls back to config/ (placeholders) and warns you |
Bootstrap (bootstrap-secrets.sh) |
Captures/installs private/ locally without touching tracked files |
| Git | private/ is gitignored and has never been committed. auth.json is gitignored too |
auth.json (pi's own auth) is never exported, synced, or restored by this project.
The tracked config files contain __REQUIRED__ placeholders wherever an API key is needed. Below is the complete list. You must replace each one with a real key for the corresponding service to work.
| Placeholder location | Service | Key format | Where to get a key |
|---|---|---|---|
providers.openrouter.apiKey |
OpenRouter | sk-or-v1-... |
openrouter.ai/keys |
providers.nvidia-nim.apiKey |
NVIDIA NIM | nvapi-... |
build.nvidia.com |
providers.siemens.apiKey |
Siemens AI API | SIAK-... |
Internal Siemens developer portal |
Note: The current tracked
models.jsondoes not require keys for local-only providers unless you add them yourself later.
| Placeholder location | Service | Key format | Where to get a key |
|---|---|---|---|
geminiApiKey |
Google Gemini | AIzaSy... |
Google AI Studio |
| Placeholder location | Service | Key format | Where to get a key |
|---|---|---|---|
mcpServers.zai-web-reader.headers.Authorization |
Z.ai Web Reader | Bearer ... |
Z.ai developer console |
mcpServers.zai-vision.env.Z_AI_API_KEY |
Z.ai Vision MCP | Same Z.ai key | Z.ai developer console |
Tip: The Z.ai key is currently shared across 2 MCP entries in
config/mcp.json.
| # | Key | Used in | Free tier? |
|---|---|---|---|
| 1 | Google Gemini API key | web-search.json |
✅ Yes |
| 2 | OpenRouter API key | models.json |
✅ Free models available |
| 3 | NVIDIA NIM API key | models.json |
Check NVIDIA |
| 4 | Siemens AI API key | models.json |
Internal only |
| 5 | Z.ai API key | mcp.json (×2) |
Check Z.ai |
Use this when you have a fresh machine with pi installed but no config yet.
git clone https://github.com/legout/pi-config.git ~/coding/pi-config
cd ~/coding/pi-config./restore.shThis copies all agents, prompts, skills, themes, and sanitized config to ~/.pi/agent/ and ~/.pi/. It also runs pi update to install configured packages and extensions.
If you'd rather run pi update yourself later:
RUN_PI_UPDATE=0 ./restore.shSince there is no private/ directory yet, restore.sh installs the sanitized config with __REQUIRED__ placeholders. You need to add real keys:
Option A — Edit the live config files directly:
# Model providers
nano ~/.pi/agent/models.json
# MCP servers
nano ~/.pi/agent/mcp.json
# Web search
nano ~/.pi/web-search.jsonReplace every __REQUIRED__ with your actual key (see the Required API Keys table above).
Option B — Use the bootstrap helper (recommended):
If you have the keys handy:
# Create private/ with real keys (you'll need to create the files manually)
mkdir -p private
# For each file, copy the sanitized version and fill in real keys:
cp config/models.json private/models.json
cp config/mcp.json private/mcp.json
cp config/web-search.json private/web-search.json
# Now edit private/*.json and replace __REQUIRED__ with real keys
nano private/models.json
nano private/mcp.json
nano private/web-search.json
# Install into live pi config
./bootstrap-secrets.sh installpi # Should start with your configured default model
./bootstrap-secrets.sh status # Should show "present" (not "placeholder-only")Use this when you've already set up this machine before and want to pull the latest config changes.
cd ~/coding/pi-config
git pull
./restore.shrestore.sh will automatically use your existing private/*.json (real keys) over the sanitized config/*.json. No re-keying needed.
On the source machine (where the changes live):
cd ~/coding/pi-config
./sync.sh export # Re-export all config + agents + skills
git add -A
git commit -m "sync: update config"
git pushThen on every other machine:
cd ~/coding/pi-config
git pull
./restore.sh./bootstrap-secrets.sh statusThis shows whether private/ and the live pi config have real keys or still contain placeholders.
Run this on a machine that has a working pi setup to capture its config into this repo:
cd ~/coding/pi-config
./sync.sh exportThis will:
- Wipe the repo's generated directories (agents, prompts, skills, etc.) for a clean state
- Copy live config from
~/.pi/agent/and~/.pi/ - Save real secret-bearing copies to
private/(gitignored) - Sanitize and write tracked copies to
config/(safe to commit)
After export:
git add -A
git commit -m "sync: $(date +%Y-%m-%d)"
git pushNever commit the
private/directory. The.gitignoreblocks it, but always double-check withgit statusbefore pushing.
The bootstrap-secrets.sh helper manages the private/ directory without touching tracked files:
# Show current state of private/ and live config
./bootstrap-secrets.sh status
# Capture live secrets from ~/.pi into local private/
./bootstrap-secrets.sh capture
# Install private/ secrets into live ~/.pi (e.g. after a restore or reset)
./bootstrap-secrets.sh installFirst setup on a machine:
./restore.sh # Installs sanitized config
# Edit private/*.json with real keys
./bootstrap-secrets.sh installAfter a pi reset on the same machine (private/ still exists):
./restore.sh # Automatically uses private/ for real keysSwitching machines and want to bring keys along:
You need to securely transfer private/ yourself (USB, encrypted archive, password manager, etc.). This repo deliberately does not handle key transport.
| Synced (tracked in git) | Not synced (gitignored) |
|---|---|
pi settings (settings.json) |
auth.json |
| Sanitized model provider config | private/ (real API keys) |
| Sanitized MCP server config | Session data, history |
| Sanitized web search config | Crash logs, caches |
| Custom agents, prompts, themes | bin/fd and other binaries |
| Custom non-symlink skills | |
Installed skills from ~/.agents/skills/ |
|
| Skill lock files |
| Script | Purpose |
|---|---|
sync.sh export |
Export live pi config from this machine into the repo (sanitized to config/, real to private/) |
sync.sh status |
Show what exists in live pi config vs. repo |
restore.sh |
Restore repo config onto this machine (prefers private/ if present) |
bootstrap-secrets.sh status |
Show whether private/ and live config have real keys or placeholders |
bootstrap-secrets.sh capture |
Copy live pi secrets into local private/ |
bootstrap-secrets.sh install |
Copy private/ secrets into live pi config |
scripts/sanitize_configs.py |
Strip API keys from JSON config (used internally by sync.sh) |