Skip to content

Pi Coding Agent

Slash Commands

Command Description
/login, /logout Manage OAuth or API-key credentials
/model Switch models
/scoped-models Enable or disable models for cycling
/settings Configure thinking level, theme, delivery mode, and transport
/new Start a new session
/session Show session file, ID, token usage, and cost
/compact Compact older context, optionally with custom instructions
/reload Reload keybindings, extensions, skills, prompts, and context files
/hotkeys Show all keyboard shortcuts
/quit Exit Pi

Skills are exposed as /skill:$NAME, and prompt templates are exposed as /$NAME.

Keyboard Shortcuts

Shortcut Description
Alt+Enter Queue a follow-up message
Alt+Up Restore queued messages to the editor
Esc Abort the current run
Ctrl+P Cycle to the next model
Shift+Tab Cycle thinking level

Keybindings can be customized in ~/.pi/agent/keybindings.json. After editing them, run /reload.

Pi Installation

Install Pi with the official install script:

curl -fsSL https://pi.dev/install.sh | sh

Uninstall Pi:

npm uninstall -g @earendil-works/pi-coding-agent

Adding model from a non supported provider

Modify ~/.pi/agent/models.json:

{
  "providers": {
    "scaleway-standard": {
      "baseUrl": "https://api.scaleway.ai/$PROJECT_ID/v1",
      "api": "openai-completions",
      "apiKey": "$SCALEWAY_API_KEY",
      "compat": {
        "supportsDeveloperRole": false,
        "supportsReasoningEffort": false
      },
      "models": [
        {
          "id": "qwen3.5-397b-a17b",
          "name": "Qwen 3.5 397B",
          "reasoning": true,
          "input": ["text"],
          "contextWindow": 131072,
          "maxTokens": 16384
        }
      ]
    },
    "scaleway-reasoning": {
      "baseUrl": "https://api.scaleway.ai/$PROJECT_ID/v1",
      "api": "openai-completions",
      "apiKey": "$SCALEWAY_API_KEY",
      "compat": {
        "supportsDeveloperRole": false,
        "supportsReasoningEffort": true
      },
      "models": [
        {
          "id": "glm-5.2",
          "name": "GLM-5.2 744B",
          "contextWindow": 1048576,
          "maxTokens": 16000
        }
      ]
    },
    "local-spark": {
      "baseUrl": "https://vllm-qwen3-5-122b-a10b-nvfp4-spark.vllm.apps.onmyowncorp.eu/v1",
      "api": "openai-completions",
      "apiKey": "vllm-dummy-key",
      "compat": {
        "supportsDeveloperRole": false,
        "supportsReasoningEffort": false
      },
      "models": [
        {
          "id": "nvidia/Qwen3.5-122B-A10B-NVFP4",
          "name": "Qwen 3.5 122B",
          "contextWindow": 131072,
          "maxTokens": 16000
        }
      ]
    }
  }
}

Extensions

Pi supports extensions that can enhance functionality.

Here are some useful extensions:

  • pi-footer: statusline extension for pi.
  • pi-loadout: adds a /loadout command for choosing which tools and skills are active in the current Pi session.
  • pi-linter: deterministic linter that renders findings above the input bar in pi.
  • pi-mcp-adapter: use MCP servers with Pi.
  • @juicesharp/rpiv-web-tools: let the model search the web and read pages.
  • @juicesharp/rpiv-ask-user-question: ask clarifying questions instead of guessing.
  • @juicesharp/rpiv-advisor: ask a stronger model for a second opinion before it acts.
  • @gotgenes/pi-permission-system: provides permission gates over tool, bash, MCP, skill, and special operations.
  • @gotgenes/pi-subagents: gives pi a focused, in-process sub-agent core.
  • @gotgenes/pi-subagents-worktrees: git worktree isolation for @gotgenes/pi-subagents.
  • @gotgenes/pi-autoformat: automatically formats files after the agent edits them.
  • pi-messenger-bridge: bridge common messengers into pi.
  • pi-lmstudio: integrating LM Studio with Pi, allowing you to use local LLMs.

Installation

After installation, you may need to run /reload to activate the extensions.

pi install npm:pi-footer
pi install npm:pi-loadout
pi install npm:pi-linter
pi install npm:pi-mcp-adapter
pi install npm:@juicesharp/rpiv-web-tools
pi install npm:@juicesharp/rpiv-ask-user-question
pi install npm:@juicesharp/rpiv-advisor
pi install npm:@gotgenes/pi-permission-system
pi install npm:@gotgenes/pi-subagents
pi install npm:@gotgenes/pi-subagents-worktrees
pi install npm:@gotgenes/pi-autoformat
pi install npm:pi-messenger-bridge
pi install npm:pi-lmstudio

Post Installation

File to modify: ~/.pi/agent/extensions/pi-footer.json:

{
  "version": 1,
  "enabled": true,
  "preset": "default",
  "lines": [
    [
      {
        "id": "model-provider-mqkmgzr8-a69yw3",
        "type": "model-provider",
        "enabled": true,
        "options": {
          "raw": false,
          "icon": "",
          "fg": "brightCyan",
          "bg": "default",
          "bold": false
        }
      },
      {
        "id": "thinking-level-mqkmgzr8-nu19hx",
        "type": "thinking-level",
        "enabled": true,
        "options": {
          "raw": false,
          "hideWhenEmpty": false,
          "icon": "",
          "text": "",
          "fg": "brightMagenta",
          "bg": "default",
          "bold": false
        }
      },
      {
        "id": "context-mqknp2ad-7m5n9n",
        "type": "context",
        "enabled": true,
        "options": {
          "raw": false,
          "icon": "",
          "fg": "brightYellow",
          "bg": "default",
          "bold": false,
          "contextConditionalColors": false,
          "contextWarningPercent": 70,
          "contextDangerPercent": 90,
          "warningFg": "yellow",
          "warningBg": "default",
          "dangerFg": "red",
          "dangerBg": "default"
        }
      },
      {
        "id": "tokens-mr4wxj6r-bj6zgf",
        "type": "tokens",
        "enabled": true,
        "options": {
          "raw": false,
          "icon": "",
          "fg": "brightCyan",
          "bg": "default",
          "bold": false,
          "tokenFormatStyle": "default"
        }
      },
      {
        "id": "total-speed-mr4x9dio-6jre70",
        "type": "total-speed",
        "enabled": true,
        "options": {
          "raw": false,
          "hideWhenZero": false,
          "icon": "",
          "fg": "brightGreen",
          "bg": "default",
          "bold": false,
          "tokenFormatStyle": "default"
        }
      }
    ],
    [
      {
        "id": "cwd-mqknjnms-ja69vr",
        "type": "cwd",
        "enabled": true,
        "options": {
          "raw": false,
          "icon": "",
          "fg": "brightRed",
          "bg": "default",
          "bold": false,
          "cwdDisplayStyle": "full-home",
          "segments": 2
        }
      },
      {
        "id": "git-branch-mqknims8-f95pb8",
        "type": "git-branch",
        "enabled": true,
        "options": {
          "raw": false,
          "hideWhenEmpty": false,
          "icon": "",
          "text": "",
          "fg": "brightGreen",
          "bg": "default",
          "bold": false,
          "gitBranchDisplayStyle": "round-brackets",
          "surroundLeft": "",
          "surroundRight": ""
        }
      }
    ]
  ],
  "separator": "pipe",
  "separatorFg": "default",
  "separatorBg": "default",
  "iconMode": "text",
  "minimalist": true,
  "terminal": {
    "widthMode": "full",
    "colorLevel": "ansi256"
  },
  "extensionStatusRow": {
    "hiddenKeys": [],
    "knownKeys": ["loadout"]
  }
}

pi-linter

File to modify: ~/.pi/pi-lint.json:

{
  "disabled": [],
  "enabled": [
    "vague-opener",
    "pronoun-soup",
    "reactive-noop",
    "imperative-only",
    "scope-creep",
    "reversal",
    "unbounded-loop",
    "naked-review-paste",
    "review-drip"
  ]
}

@juicesharp/rpiv-web-tools

Use slash commands directly in pi:

/web-tools

@gotgenes/pi-permission-system

File to modify: ~/.pi/agent/extensions/pi-permission-system/config.json:

{
  "permission": {
    "*": "ask",
    "path": {
      "*": "allow",
      "*.env": "deny",
      "*.env.*": "deny",
      "*.env.example": "allow"
    },
    "read": "allow",
    "write": "ask",
    "edit": "ask",
    "find": "allow",
    "ls": "allow",
    "grep": "allow",
    "web_search": "allow",
    "web_fetch": "allow",
    "advisor": "allow",
    "ask_user_question": "allow",
    "subagent": "allow",
    "get_subagent_result": "allow",
    "steer_subagent": "allow",
    "context7*": "allow",
    "prometheus*": "allow",
    "grafana_search*": "allow",
    "grafana_query*": "allow",
    "grafana_list*": "allow",
    "grafana_get*": "allow",
    "grafana_find*": "allow",
    "bitbucket_server_find*": "allow",
    "bitbucket_server_get*": "allow",
    "bitbucket_server_list*": "allow",
    "bitbucket_server_search*": "allow",
    "mcp_atlassian_confluence_get*": "allow",
    "mcp_atlassian_confluence_search": "allow",
    "mcp_atlassian_confluence_search*": "allow",
    "mcp_atlassian_jira_download*": "allow",
    "mcp_atlassian_jira_get*": "allow",
    "mcp_atlassian_jira_search": "allow",
    "mcp_atlassian_jira_search*": "allow",
    "revdiff_review": "allow",
    "bash": {
      "npm ls *": "allow",
      "revdiff": "allow",
      "revdiff *": "allow",
      "kubectl diff *": "allow",
      "git checkout -b *": "allow",
      "git push *": "allow",
      "kubectl cluster-info*": "allow",
      "npm list *": "allow",
      "dig *": "allow",
      "git symbolic-ref --short *": "allow",
      "nl *": "allow",
      "for *": "allow",
      "git merge-base *": "allow",
      "kubectl wait *": "allow",
      "kubectl debug *": "allow",
      "docker pull *": "allow",
      "true": "allow",
      "sleep *": "allow",
      "base64 *": "allow",
      "gh run *": "allow",
      "while *": "allow",
      "cd *": "allow",
      "if *": "allow",
      "xargs *": "allow",
      "pre-commit *": "allow",
      "gh pr create *": "allow",
      "gh --version*": "allow",
      "curl *": "allow",
      "cp *": "allow",
      "kubectl get *": "allow",
      "kubectl logs *": "allow",
      "kubectl describe *": "allow",
      "helm repo *": "allow",
      "ls *": "allow",
      "ls": "allow",
      "pwd": "allow",
      "cat *": "allow",
      "head *": "allow",
      "tail *": "allow",
      "less *": "allow",
      "more *": "allow",
      "file *": "allow",
      "stat *": "allow",
      "wc *": "allow",
      "tree *": "allow",
      "tree": "allow",
      "realpath *": "allow",
      "basename *": "allow",
      "dirname *": "allow",
      "readlink *": "allow",
      "find *": "allow",
      "grep *": "allow",
      "rg *": "allow",
      "ag *": "allow",
      "fd *": "allow",
      "awk *": "allow",
      "sed *": "allow",
      "sort *": "allow",
      "uniq *": "allow",
      "cut *": "allow",
      "tr *": "allow",
      "diff *": "allow",
      "jq *": "allow",
      "yq *": "allow",
      "echo *": "allow",
      "printf *": "allow",
      "env": "allow",
      "printenv *": "allow",
      "printenv": "allow",
      "date *": "allow",
      "date": "allow",
      "whoami": "allow",
      "hostname": "allow",
      "uname *": "allow",
      "uname": "allow",
      "id": "allow",
      "uptime": "allow",
      "which *": "allow",
      "whereis *": "allow",
      "type *": "allow",
      "command -v *": "allow",
      "git *": "ask",
      "git status": "allow",
      "git status *": "allow",
      "git diff": "allow",
      "git diff *": "allow",
      "git log": "allow",
      "git log *": "allow",
      "git show": "allow",
      "git show *": "allow",
      "git branch": "allow",
      "git branch *": "allow",
      "git remote": "allow",
      "git remote *": "allow",
      "git rev-parse *": "allow",
      "git ls-files *": "allow",
      "git ls-files": "allow",
      "git ls-tree *": "allow",
      "git blame *": "allow",
      "git config --get *": "allow",
      "git config -l": "allow",
      "git tag": "allow",
      "git tag -l*": "allow",
      "git describe *": "allow",
      "git stash list": "allow",
      "git reflog": "allow",
      "git reflog *": "allow",
      "git shortlog *": "allow",
      "gh auth status": "allow",
      "gh repo view *": "allow",
      "gh pr view *": "allow",
      "gh pr list *": "allow",
      "gh issue view *": "allow",
      "gh issue list *": "allow",
      "sudo *": "ask",
      "curl * | sh": "ask",
      "curl * | bash": "ask",
      "wget * | sh": "ask",
      "wget * | bash": "ask",
      "curl -o *": "ask",
      "curl -O *": "ask",
      "rm -rf *": "deny",
      "rm -fr *": "deny",
      "chmod 777 *": "deny",
      ":(){ :|:& };:": "deny"
    },
    "mcp": {
      "mcp_status": "allow",
      "context7": "allow"
    },
    "skill": { "*": "allow" },
    "external_directory": {
      "*": "ask",
      "/tmp": "allow",
      "/tmp/*": "allow"
    }
  }
}

@gotgenes/pi-subagents-worktrees

File to modify: ~/.pi/agent/subagents-worktrees.json:

{
  "worktreeAgents": ["general-purpose"]
}

@gotgenes/pi-autoformat

File to modify: ~/.pi/agent/extensions/pi-autoformat/config.json:

{
  "$schema": "https://raw.githubusercontent.com/gotgenes/pi-autoformat/main/schemas/pi-autoformat.schema.json",
  "formatters": {
    "prettier": {
      "command": ["npx", "prettier", "--write"]
    }
  },
  "chains": {
    "*": ["prettier"]
  }
}

Updates

Core:

pi update

Extensions:

pi update --extensions

Everything:

pi update --all

Starting a Session

Start Pi in the current project directory:

pi

Run a one-shot prompt:

pi -p "Summarize this codebase"

Run a one-shot prompt with a specific model:

pi --model gemma-4-31b-qat:high -p "Commit to git. Follow conventional commit. Then push and open a PR on GitHub."

Pipe stdin into a one-shot prompt:

cat README.md | pi -p "Summarize this text"

Reference files directly on the command line:

pi @README.md "Summarize this"
pi @src/app.ts @src/app.test.ts "Review these together"

Context Files

Pi loads project instructions from:

  • ~/.pi/agent/AGENTS.md
  • AGENTS.md in the current directory
  • AGENTS.md or CLAUDE.md in parent directories

Disable context file discovery with:

pi --no-context-files

System Prompt Files

Replace the default system prompt with:

  • .pi/SYSTEM.md for a project
  • ~/.pi/agent/SYSTEM.md globally

Append to the default prompt with APPEND_SYSTEM.md in either location.

Prompt Templates

Pi loads prompt templates from:

  • ~/.pi/agent/prompts/*.md
  • .pi/prompts/*.md
  • package prompts/ directories
  • --prompt-template <path>

If using the ai-lab repo, here is how to link it from the git repo:

ln -s $REPO_PATH/prompts/ ~/.pi/agent/

Example .pi/prompts/review.md:

---
description: Review staged git changes
---

Review the staged changes (`git diff --cached`). Focus on:

- Bugs and logic errors
- Security issues
- Error handling gaps

This becomes the /review command inside Pi.

Skills

Pi loads skills from:

  • ~/.pi/agent/skills/
  • ~/.agents/skills/
  • .pi/skills/
  • .agents/skills/
  • --skill <path>

If using the ai-lab repo, here is how to link it from the git repo:

ln -s $REPO_PATH/skills/ ~/.pi/agent/

Skills are directories containing a SKILL.md file and are available as /skill:$NAME.

Example skill structure:

my-skill/
├── SKILL.md
├── scripts/
└── references/

Agents

Pi loads agents from:

  • Global/user agents: ~/.pi/agent/agents/*.md
  • Project agents: .pi/agents/*.md

If using the agency-agents repo, here is how to link it from the git repo:

mkdir -p "$HOME/code" "$HOME/.pi/agent/agents" && { [ -d "$HOME/code/agency-agents" ] || git clone https://github.com/msitarzewski/agency-agents.git "$HOME/code/agency-agents"; } && cd "$HOME/code/agency-agents" && divs="$(jq -r '.divisions | keys | join(" ")' divisions.json)" && [ -n "$divs" ] && find $divs -name '*.md' -type f | sort | while read -r f; do [ "$(head -1 "$f")" = "---" ] && printf '%s\n' "$f"; done | while read -r f; do d="$HOME/.pi/agent/agents/agency__$(basename "$f")"; [ -e "$d" ] && echo "SKIP: agency__$(basename "$f")" || ln -s "$HOME/code/agency-agents/$f" "$d"; done