Files
obsidian-vault/300 areas/350 AI/Pi Agent Extensions & Skills.md

41 KiB

created, modified, type, tags, aliases
created modified type tags aliases
2026-05-16 2026-08-03 note
ai
dev-ops

Pi Agent Extensions & Skills

Source Repositories

Source Location
Gitea (package) git:https://gitea.lab.audasmedia.com.au/sam/pi-config
Local filesystem ~/.agents/
Project settings sys_config/.pi/settings.json, ai_setup/.pi/settings.json

OmniRoute — LLM Provider Router

OmniRoute is the central LLM routing proxy running on .13 (port 20128/20129). All three machines route pi's LLM requests through it.

Aspect Detail
What it is Docker-based LLM proxy with combo routing — you define a prioritized list of providers and it tries them in order until one succeeds
Where .13:20129 via Docker, exposed through Caddy on .35 for remote access
Provider registered in pi as omni (not omniroute) — the omniroute-pi-ext-integration npm package registers the omni provider
Pi default model default-opencode-go-ds-flash — a combo on OmniRoute that prioritises OpenCode-Go's DeepSeek V4 Flash ($5/month sub) before falling back to other providers
Combo chain User-created combo default-opencode-go-ds-flash tries providers in order: OpenCode-Go → OpenRouter → DeepSeek direct → Google Gemini
Sub-agent routing Sub-agents route through the same combo — individual model IDs like opencode-go/deepseek-v4-flash match the combo and fall through the same priority chain
Models 484 models available via OmniRoute (synced with /omni sync), available in pi's Ctrl+P model picker
How pi connects The omniroute-pi-ext-integration extension registers all models + the omni provider. URL + API key set once via /omni setup. Re-sync via /omni sync.

Files & Commands

Item Location / Command
Docker compose /home/sam/Docker/Containers/omniroute/docker-compose.yml on .13
pi extension omniroute-pi-ext-integration (npm package, installed via pi install npm:omniroute-pi-ext-integration)
Extension config ~/.pi/agent/models.json — stores URL + API key for omni provider, plus model list
Setup /omni setup (one-time: URL + API key)
Sync /omni sync (re-fetch model list)
Access (local) http://192.168.20.13:20129/v1
Access (via Caddy) https://omniroute.lab.audasmedia.com.au/v1
API key sk-fff5c0d55c0bc0bf-b58ed0-76da5716 (stored in ~/.config/environment.d/10-secrets.conf on .27/.51, hardcoded in settings.json on .13)

Open WebUI — Chat Frontend

Open WebUI v0.11.0 runs on .13 as a native NixOS process (not Docker), managed via Home Manager. Provides a chat UI that can connect to any OpenAI-compatible API — including OmniRoute.

Aspect Detail
URL http://192.168.20.13:3000
Package open-webui-0.11.0 (NixOS nixpkgs)
How to connect OmniRoute Admin Panel ⚙️ → Settings → Connections → OpenAI API → URL: http://192.168.20.13:20129/v1 (include /v1), Key: OmniRoute API key
Also works with Any OpenAI-compatible API (TokenRouter, OpenRouter, DeepSeek) — add each as a separate connection
Port note :3000 is taken by Open WebUI. Langfuse was bumped to :3001.

Ollama — Local LLM Inference (REMOVED)

Runs on .13 with qwen2.5-coder:7b (Q4_K_M, 7.6B params). Removed August 2026. Redundant — OmniRoute provides 485 models including superior qwen/qwen3.5-9b. The 4.7GB disk + RAM cost on a 15.5GB server wasn't justified.

Pi default model selection model

Machines route through omni provider with defaultModel: "default-opencode-go-ds-flash":

pi → omni provider → POST /v1/chat/completions { model: "default-opencode-go-ds-flash" }
  → OmniRoute matches combo "default-opencode-go-ds-flash"
  → Tries: OpenCode-Go → OpenRouter → DeepSeek direct → Google Gemini
  → Returns first successful response

Per-machine setup state

Machine Package installed Provider config /omni setup done Models synced
.27 In home.nix omni
.13 pi install omni
.51 pi install omni

Extensions

Extension Source Purpose
pi-config ~/.agents /config-add, /config-remove, /config-show, /config-setup — manage which extensions/skills are active in a project
tavily-search Gitea tavily_search — web search via Tavily API (AI-optimized)
web-fetch ~/.agents web_fetch — fetch any URL and return clean markdown (HTML, PDF, JS-rendered with Jina fallback)
ask-user-question ~/.agents ask_user_question — LLM presents structured multiple-choice / text questions with keyboard UI
video-extract ~/.agents video_extract — extract frames from YouTube/local video + full Gemini analysis (requires ffmpeg + yt-dlp + GEMINI_API_KEY)
filechanges ~/.agents /filechanges, /filechanges-accept, /filechanges-decline — tracks every file LLM edits/writes, diff review, revert
pi-prompt-template-model npm (global) Model-switching prompt templates with frontmatter. See #Prompt Templates section below
pi-mcp-adapter npm (global) Single proxy tool (~200 tokens) replaces hundreds of MCP tool definitions. /mcp command for management. Lazy server connections
pi-graphify ~/.agents Knowledge graph tools: build, query, path tracing, explain, watch, add, update
plannotator ~/.agents Interactive plan review with browser UI, annotations, code review
caveman ~/.agents Ultra-compressed communication mode
markitdown ~/.agents Convert files (PDF, Word, Excel, PPTX, images, HTML, etc.) to Markdown. Image analysis via Qwen 2.5 VL 72B on OpenRouter.
@tintinweb/pi-subagents npm (global) 18 custom agent types, background agents, mid-run steering, session resume, worktree isolation, scheduling, cross-extension RPC. See Pi Subagent for full documentation
@tintinweb/pi-tasks npm (global) Task management with dependency tracking, auto-cascade, background process tracking, TaskExecute spawns subagents via RPC
gentle-engram ~/.agents Memory service connecting to engram via ENGRAM_URL. Replaces memory-vault. Session capture, compaction recovery
headroom-bridge ~/.agents compress_for_agent tool — compresses >20K chars via Headroom Docker on .13:8787. 60-95% token reduction
pi-langfuse ~/.agents (vendored from npm 1.5.8, commit bc91a15) Langfuse LLM observability for pi — one trace per conversation, grouped by pi session, with tokens + cost. Activate per project via /config-add ext pi-langfuse. See #pi-langfuse — LLM Observability for Pi

pi-subagents (@tintinweb)

v0.10.2, installed globally. 18 custom agent types in ~/.pi/agent/agents/~/.agents/agents/. Tools: Agent(), get_subagent_result(), steer_subagent(). /agents command for interactive management. Features: background agents with concurrency (4 default), mid-run steering, session resume, worktree isolation, scheduling, persistent widget showing live agent status. Cross-extension RPC event bus. Patched: 24h agent survival (was 10min), clearDisabled on session start. See Pi Subagent for full documentation.

pi-tasks (@tintinweb)

v0.7.0, installed globally. 7 task tools: TaskCreate, TaskList, TaskGet, TaskUpdate, TaskOutput, TaskStop, TaskExecute. /tasks command. Features: dependency tracking (blocks/blockedBy), auto-cascade, background process tracking, persistent widget. TaskExecute spawns subagents via RPC.


Skills

Skill Purpose
nixos-workflow STRICT workflow for managing Pi assets via Gitea on NixOS
system-architect Multi-machine NixOS infrastructure (Snapcast, MQTT, Docker, Nvim)
obsidian-cli Interact with Obsidian vault (notes, search, plugin dev, theme dev)
graphify Full-pipeline knowledge graph orchestration
caveman Caveman communication mode
openspec-propose Propose new changes with design docs, specs, tasks
openspec-apply-change Implement tasks from an OpenSpec change
openspec-archive-change Archive completed changes
openspec-explore Explore ideas and clarify requirements
npm-security Scan packages with SafeDep Vet, check typosquatting with npq, wrap installs with Socket Firewall
ste-writing Rewrite prose (docs, READMEs, PRs, errors) into ASD-STE100 Simplified Technical English. Removes AI slop. Two modes: strict (procedures) and STE-flavored (general prose). Includes heuristic anti-slop linter (ste-lint.py).
design-build Generate production-ready HTML/Tailwind code from design specifications and DESIGN.md design tokens.
design-explore Generate UI design mockups as images for exploration and ideation. Supports DESIGN.md for design-token-accurate mockups.
markitdown Convert files (PDF, Word, Excel, PowerPoint, images, HTML, CSV, JSON, XML, ZIP, EPubs, YouTube) to Markdown for LLM consumption. Image analysis via Qwen 2.5 VL 72B on OpenRouter.

markitdown

Convert various file formats to Markdown. Useful for feeding documents and images into LLMs.

What it converts

Format Input Notes
PDF .pdf Preserves structure (headings, lists, tables)
Word .docx mammoth + lxml
PowerPoint .pptx python-pptx
Excel .xlsx, .xls openpyxl + pandas
Images .jpg, .png, etc. EXIF metadata (free) + LLM vision description (via OpenRouter)
HTML .html beautifulsoup4
CSV / JSON / XML .csv, .json, .xml Structured data → Markdown tables
ZIP .zip Iterates contents, converts each file
EPubs .epub
YouTube URLs Transcript extraction

CLI usage

# Convert file to Markdown (stdout)
markitdown document.pdf

# Write to file
markitdown document.pdf -o document.md

# Image with LLM vision description
markitdown-vision photo.jpg

Image analysis

Two levels:

  1. EXIF metadata only (free, no API key): markitdown photo.jpg
  2. LLM vision description (via OpenRouter, requires API key): markitdown-vision photo.jpg

The markitdown-vision wrapper auto-sources OPENROUTER_API_KEY from ~/.config/environment.d/10-secrets.conf and uses qwen/qwen2.5-vl-72b-instruct.

Missing / can be added

Feature What's needed
Audio transcription pip install markitdown[audio-transcription] (pydub + speechrecognition)
Azure AI Document Intelligence pip install markitdown[az-doc-intel] + Azure credentials
Azure Content Understanding pip install markitdown[az-content-understanding] + Azure credentials
markitdown-ocr plugin Installed but needs OpenRouter key enabled to activate

falcode-zellij

Zellij plugin + agent extensions that track all active AI coding panes (pi, OpenCode, Claude Code) across Zellij sessions in a floating popup. Jump to any pane with one keystroke. Shows attention icons on Zellij tabs when an agent starts/stops working.

Components

Component Location Purpose
Zellij WASM plugin ~/.config/zellij/plugins/falcode-zellij-sessions.wasm Floating popup UI showing all agent panes
pi extension ~/.pi/agent/extensions/falcode.ts Reports pi pane status (working/idle) to the Zellij plugin
attention WASM ~/.config/zellij/plugins/zellij-attention.wasm Shows / icons on Zellij tabs when agent is active/done
detection script ~/.local/state/falcode-zellij/ Shared state directory for pane status snapshots

Keybindings

Key Action
Alt a Launch/focus falcode floating popup (config.kdl shared_except "locked")

pi integration

The falcode.ts extension auto-detects Zellij via ZELLIJ_PANE_ID/ZELLIJ_SESSION_NAME env vars. Outside Zellij it's a no-op.

  • agent_start event → writes "working" status
  • agent_end event → writes "waiting_user_input" status
  • Heartbeat every 60s to keep pane alive
  • FALCODE_NOTIFY_SCRIPT=/bin/true in home.nix (disables macOS notifications on Linux)

Install on new machine

# pi extension
mkdir -p ~/.pi/agent/extensions
curl -L https://raw.githubusercontent.com/victor-falcon/falcode-zellij/main/pi-extension/falcode.ts \
  -o ~/.pi/agent/extensions/falcode.ts

# WASM plugins
mkdir -p ~/.config/zellij/plugins
curl -L https://github.com/victor-falcon/falcode-zellij/releases/latest/download/falcode-zellij-sessions.wasm \
  -o ~/.config/zellij/plugins/falcode-zellij-sessions.wasm
curl -L https://github.com/victor-falcon/falcode-zellij/releases/latest/download/zellij-attention.wasm \
  -o ~/.config/zellij/plugins/zellij-attention.wasm

Claude Code integration

Also has a hook at ~/.local/state/falcode-zellij/falcode-hook.sh for Claude Code status reporting. See README for Claude config.

Zellij config (config.kdl)

Already configured in Home Manager:

plugins {
    falcode location="file:/home/sam/.config/zellij/plugins/falcode-zellij-sessions.wasm" {
        state_dir "/home/sam/.local/state/falcode-zellij"
    }
    attention location="file:/home/sam/.config/zellij/plugins/zellij-attention.wasm"
}

load_plugins {
    "file:/home/sam/.config/zellij/plugins/zellij-attention.wasm" {
        enabled "true"
        waiting_icon "⏳"
        completed_icon "✅"
    }
}

keybinds {
    shared_except "locked" {
        bind "Alt a" {
            LaunchOrFocusPlugin "falcode" {
                floating true
                move_to_focused_tab true
            }
        }
    }
}

Security Tools (npm Global)

Three tools installed globally at ~/.local/share/npm-global/bin/ to guard package installs.

SafeDep Vet (vet)

Scans local directories for multi-language malware signatures. Catches obfuscated code, suspicious imports, base64 payloads.

# Scan a cloned repo before touching it
vet scan -D . --format json --filter "package.malware == true"

# Scan package metadata from npm registry
vet scan package <name> --format json

Socket Firewall (socket)

Wraps npm/pip installs with real-time scanning. Blocks malicious packages at install time.

# Safe npm install
socket npm install <package>

# Safe pip install
socket pip install -r requirements.txt

npq

Checks package names against typosquatting lists before install. Lightweight, local, no phoning home.

npq check <package> --json

Workflow

1. vet scan → checks for malware in the code/package
2. npq check → checks the package name for typosquatting
3. socket install → wraps the actual install with runtime scanning

The npm-security skill instructs the Pi agent to follow this workflow before any install.

Headroom

Headroom is a context compression layer that reduces prompt token usage by 60-95% for heavy analysis/code/devops workloads. It runs as a Docker container on the server (192.168.20.13) and is triggered by the headroom-bridge extension.

How it works

  1. headroom-bridge detects analysis/code/devops contexts
  2. Tags read, discuss, search never trigger compression (these are fast paths)
  3. For all other tags, if accumulated context exceeds ~5K tokens, headroom-bridge calls compress()
  4. Messages are sent to the Headroom proxy at 192.168.20.13:8787
  5. Headroom compresses the context (using SmartCrusher for JSON, CodeCompressor for AST, Kompress-base ML for text)
  6. Compressed messages are returned and forwarded to the LLM
  7. If the proxy is down, messages pass through unchanged (graceful fallback)

Architecture

Desktop (.27)                         Server (.13)
─────────────                         ────────────
headroom-bridge                       headroom proxy (Docker)
    │                                     │
    │  if compress needed:                │
    │  compress_for_agent(content) ──────►│
    │  HTTP POST 192.168.20.13:8787       │
    │  ◄────────── compressed content     │
    │                                     │
    │  return to agent                    │
    │                                     │
    │  if proxy down: pass through        │

Compression thresholds

Condition Action
Tag is read/discuss/search Skip — no compression
Context < 5K tokens Skip — too small to benefit
Context ≥ 5K tokens + analysis/code/devops tag Compress
Proxy unreachable Pass through unchanged

headroom-bridge

Path: ~/.agents/extensions/headroom-bridge/index.ts. Tool: compress_for_agent({ content }) — compresses content >20K chars via Headroom Docker on .13:8787. 60-95% token reduction. See #Function Calls for signature.

Management

# Check status
ssh 192.168.20.13 "docker ps --filter name=headroom"

# View logs
ssh 192.168.20.13 "docker logs --tail 20 headroom"

# Restart
ssh 192.168.20.13 "docker restart headroom"

# Update image
ssh 192.168.20.13 "cd /home/sam/Docker/Containers/headroom && docker compose pull && docker compose up -d"

Files

File Purpose
~/.agents/extensions/headroom-bridge/index.ts compress_for_agent tool implementation
/home/sam/Docker/Containers/headroom/docker-compose.yml Docker service definition (on .13)
/home/sam/Docker/Containers/headroom/.env Environment file (on .13)

pi-langfuse — LLM Observability for Pi

Sends pi's LLM traffic to Langfuse (self-hosted on .13:3001) for tracing, token usage, and cost-per-session. One trace per user prompt, grouped by pi session.

Aspect Detail
What it is pi extension (npm package pi-langfuse v1.5.8, by gooyoung) that captures pi runs — agent steps, LLM generations, tool calls, final output, usage, cost — into Langfuse
Where it runs Per-project — vendored at ~/.agents/extensions/pi-langfuse/, activated with /config-add ext pi-langfuse then /reload. Keys read globally from ~/.pi/agent/pi-langfuse/config.json
Config file ~/.pi/agent/pi-langfuse/config.json (mode 600): { "publicKey": "pk-lf-…", "secretKey": "sk-lf-…", "host": "http://192.168.20.13:3001" }
Env var fallback LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY, LANGFUSE_BASE_URL (used only when config.json is missing/incomplete)
Commands /langfuse-setup (interactive key entry), /langfuse-status (show config state, masked keys, capture policy)
Requirements Node ≥ 22 (machines run 24); peer dep @earendil-works/pi-coding-agent: *
What you get Root agent, per-request generation, and per-tool tool observations; token usage + cost; privacy controls (input/output/tool redaction, path hashing, secret redaction)
Dashboard http://192.168.20.13:3001

Install (per project)

Run inside the target project folder (uses the standard ~/.agents workflow — see the nixos-workflow skill):

/config-add ext pi-langfuse
/reload

pi installs the extension's npm dependencies automatically (deps are gitignored in ~/.agents).

Global install (all projects / machines)

The global ~/.pi/agent/settings.json is a Nix-store symlink (read-only). To enable everywhere, add npm:pi-langfuse to the packages list in /etc/nixos/home/sam/home.nix and rebuild Home Manager.

Why not the OmniRoute langfuse plugin?

OmniRoute's example langfuse plugin is broken against the 3.8.48 runtime (verified in source, 2026-08-03):

  • Plugin config is stored in SQLite but never delivered to hook payloadsPluginContext has no config field
  • onRequest metadata is not threaded to onResponse (each hook gets a fresh metadata: {})
  • Streaming requests (what pi uses) receive response: { status: 200, streamed: true } — no response body to trace

pi-langfuse traces at the pi layer instead, which works for streaming and gives per-session grouping. The plugin files were removed from .13 (compose restored, container recreated clean).

codebase-memory-mcp

Code intelligence MCP server by DeusData. Single static C binary (~13MB), zero dependencies, 158 languages. Indexes a codebase into a persistent knowledge graph — average repo in milliseconds. 15 MCP tools for structural queries. Runs locally, code never leaves your machine.

Install:

curl -fsSL https://raw.githubusercontent.com/DeusData/codebase-memory-mcp/main/install.sh | bash

Installed to ~/.local/bin/codebase-memory-mcp.

Index a project:

mcp({ tool: "index_repository", args: '{"repo_path": ".", "mode": "fast"}' })

15 Tools:

Tool What it does
index_repository Index a repo (full/moderate/fast/cross-repo-intelligence modes)
search_graph BM25 full-text search + semantic vector search for code
query_graph Cypher queries — multi-hop patterns, complexity analysis
trace_path Follow call chains, data flow, or cross-service HTTP via Route nodes
get_code_snippet Read source code for a function/class/symbol
get_graph_schema Show available node labels and edge types
get_architecture High-level architecture: packages, clusters, routes, entry points
search_code Grep + graph enrichment, ranked by structural importance
list_projects List all indexed projects
delete_project Remove a project from the graph
index_status Check index freshness and stats
detect_changes Find files changed since last index
manage_adr Architecture Decision Records
ingest_traces Import OpenTelemetry traces into the graph

MCP config (~/.pi/agent/mcp.json):

{
  "mcpServers": {
    "codebase-memory": {
      "command": "/home/sam/.local/bin/codebase-memory-mcp",
      "lifecycle": "lazy"
    }
  }
}

Deployed on all machines (.27, .13, .51):

~/.local/bin/codebase-memory-mcp --version  # v0.9.0

Path not in shell PATH on .13/.51 — MCP config uses absolute path /home/sam/.local/bin/codebase-memory-mcp so still works.

Install command (if needed on new machine):

curl -fsSL https://raw.githubusercontent.com/DeusData/codebase-memory-mcp/main/install.sh | bash

UI mode (graph visualization at localhost:9749):

curl -fsSL .../install.sh | bash -s -- --ui
codebase-memory-mcp --ui=true --port=9749

Paper: arXiv:2603.27277


code-review-graph

Structural code intelligence MCP server by tirth8205. Parses source code with Tree-sitter AST into a knowledge graph (functions, classes, imports, calls, inheritance, tests). Stored in SQLite. 28+ MCP tools for token-efficient code review, blast-radius analysis, and architectural insights. Per-project — each repo gets its own .code-review-graph/graph.db.

Install:

uv tool install code-review-graph  # or: pipx install code-review-graph

Installed to ~/.local/bin/code-review-graph v2.3.7.

Build a graph for a project:

cd /etc/nixos
code-review-graph build    # parses codebase → .code-review-graph/graph.db

Key MCP tools:

Tool What it does
get_review_context Compact review context (callers, callees, tests, risks)
get_impact_radius Blast radius — every caller/dependent/test affected by a change
query_graph Direct graph queries (traverse call chains, dependency paths)
semantic_search_nodes Semantic (embedding-based) code search
detect_changes Diff analysis: what changed and what's affected
traverse_graph Walk the graph in any direction (BFS/DFS from any node)
get_architecture_overview High-level structure: packages, clusters, entry points
get_affected_flows Execution paths impacted by a change

Complement to codebase-memory-mcp: code-review-graph captures what your code is (structure, dependencies), codebase-memory-mcp captures what agents learn (decisions, patterns, runbooks). They solve different layers — install both.

Installed on: .27 (uv tool install), .51 (nix-shell -p uv → uv tool install)

GitHub: tirth8205/code-review-graph (28K+ stars)


Pi Dashboard

A multi-component system for live agent visibility across all machines. Every pi session on every machine (plus sub-agents) reports its state; the TUI shows them all in one table and can attach to them, review their diffs, or open their task boards.

Architecture

pi session (any machine, any terminal: zellij / tmux / plain)
  └─ dashboard.ts extension
       ├─ writes ~/.pi/agent/dashboard/<session>.json   (heartbeat every 15s + on events)
       ├─ tracks tasks → <project>/todo.txt
       └─ sends NTFY / Apprise / notify-send notifications
                                                     │ SSH pull (cat *.json)
pi-dashboard (Go TUI on .27) ◄───────────────────────┴── .13 + .51 state dirs
Component Type Purpose
dashboard.ts pi extension (~/.pi/agent/extensions/dashboard.ts; source ~/.agents/extensions/dashboard.ts → Gitea pi-config) Per-session telemetry: heartbeat, cwd, started/closed times, agent status, tool count; task tools; notifications
pi-dashboard Go binary (~/.local/bin/pi-dashboard) Bubble Tea TUI over all machines' state files
Tuxedo Rust binary (tuxedo, nix) todo.txt task manager (vim keys, phone capture QR) — per-project boards
Hunk Node CLI (hunk, nix / npm hunkdiff) Review-first terminal diff viewer for agent-authored changes

Quick start

pi-dashboard                 # full TUI
pi-dashboard --list          # plain-text snapshot of local sessions
pi-dashboard --help          # keybindings + config reference

Day-to-day usage (the mental model)

The pi terminal is for talking; the dashboard TUI is for watching. You never type tool names or run hunk/tuxedo inside the pi input.

You want to… What you do What happens
Add / list / complete tasks Tell pi: "add a task: …", "what tasks do I have?", "mark … done" The agent calls register_task / list_tasks / complete_task, which write lines to <project>/todo.txt at the project root
See the task board Press Tab in the dashboard TUI Tuxedo opens the selected session's todo.txt (vim keys: j/k, dd complete, u undo, s phone QR)
Review what an agent changed Press d on its row in the dashboard TUI Hunk opens in the agent's folder: cd <cwd> && hunk diff --watch — shows all uncommitted changes in that repo (not a two-file compare)
Jump into a session Press Enter on its row tmux attach / zellij attach / zellij action switch-session

Key points:

  • register_task/complete_task/list_tasks are agent tools — you ask in English, the AI calls them. They feed todo.txt, which is what Tuxedo displays.
  • Hunk's "first/second file" mode is hunk diff <left> <right> for comparing two concrete files. The dashboard d key uses hunk diff --watch (whole working tree) instead.
  • Both task systems coexist: the dashboard tools → todo.txt → Tuxedo (vim board), while @tintinweb/pi-tasks (TaskCreate, TaskExecute, /tasks) is a separate dependency-tracked task engine that can spawn subagents.

State model

Each session writes ~/.pi/agent/dashboard/<session>.json (atomic write):

Field Meaning
session pi session name
cwd full working directory the session runs in (the Folder column)
session_started_at / closed_at session start / graceful-close times
last_seen_at heartbeat — refreshed every 15 s + on every event
agent_status idle / running / blocked / error (the agent turn)
session_state open / closed (the process liveness)
terminal_type tmux / zellij / tmux+zellij / direct
zellij_session / tmux_session / pid attach targets for Enter
is_subagent true for rows named <Agent>#<8hex> (pi-subagents)

Closed detection — a session counts as closed when:

  • the extension wrote session_state: "closed" on graceful shutdown, or
  • last_seen_at is older than stale_after (default 45 s) — the terminal was killed (pane closed, kill -9) without a shutdown event.

Status labels: ● running · ○ idle · ⚠ blocked · ✕ error · ✗ closed (graceful) · ✗ lost (died without shutdown).

TUI keybindings

Key Action
↑↓ Select agent
Enter Attach: tmux attach -t <name> / zellij attach <name> (dashboard outside zellij) / zellij action switch-session <name> (dashboard inside zellij) — local, or over SSH for remote rows
d Hunk — review the selected agent's changes in its own folder: cd <cwd> && hunk diff --watch
Tab Tuxedo — open the selected agent's project task board: <cwd>/todo.txt (created if missing; falls back to global board)
s Cycle sort: smart (live first → running first → last activity) → activity → started → folder
x Toggle hiding closed sessions (dead sessions sink to the bottom by default; x removes them from the view, press again to restore)
z Toggle hiding sub-agent rows (marked )
r Force refresh
q Quit

Selecting a row shows a detail pane: full folder path, started / closed / last-seen times, terminal + zellij/tmux session + pid, model, tool count, current task, blocked prompt.

Session naming & rename

Name resolution order on start: pi session name → PI_SESSION env → tmux session name → zellij session name (only when it isn't zellij's auto-generated word-word animal name like chatty-echidna) → working-directory basename.

Recommended workflow — one named zellij session per pi session, same name for both:

zellij -s computer_software        # create a named zellij session…
# …pi started inside it auto-inherits "computer_software" as its pi session name

Rename mid-session (pi session + zellij session + dashboard row together):

/dash-name <name>

pi's built-in /name only renames the pi session and cannot be hooked by extensions — /dash-name renames all three (pi, zellij, dashboard row). Use /name or Ctrl+R in /tree when you only want to rename the pi session.

Long-running / background sessions (tmux survival layer)

To keep a pi session running after zellij (or the terminal) closes — e.g. a long agent job on a remote machine — run pi inside a tmux session inside the zellij pane:

tmux new -s deploy-job            # inside the zellij pane
pi                                # start pi inside tmux
# detach with Ctrl-b d — tmux (and pi) keep running after zellij closes
tmux attach -t deploy-job         # reattach whenever

The extension detects the TMUX env var: rows show , and Enter does tmux attach — the session survives zellij closing. Rows in bare zellij panes show ; tmux+zellij shows ⓉⓏ; plain terminals show ·.

Tasks & Tuxedo

  • Agents register tasks via the register_task / complete_task / list_tasks tools.
  • Task files are per project: <project>/todo.txt at the project root (standard todo.txt format) — visible in ls, easy to open, and tracked in git when the project is a repo: task changes are versioned (progress history) and visible to collaborators who clone the repo. (No gitignore — it's a tiny file; the only caveat is that tasks in a public/shared repo are public, so keep secrets out of task titles.)
  • In the dashboard, Tab opens Tuxedo on the selected row's project board; with nothing selected it falls back to ~/.pi/agent/dashboard/tasks/todo.txt.
  • Tuxedo: vim keys (j/k, dd, gg/G), u undo (50 levels), s QR phone capture → https://github.com/webstonehq/tuxedo

Hunk

  • d in the dashboard runs hunk diff --watch in the selected agent's folder (over SSH for remote rows) — review exactly what that agent changed.
  • Standalone: hunk diff --watch (live review of the working tree), hunk show (last commit). Multi-file sidebar, inline AI annotations, split/stack/responsive layouts. → https://github.com/modem-dev/hunk

Cross-machine config (~/.config/pi-dashboard.yaml)

poll_interval: 2
stale_after: 45        # seconds without heartbeat ⇒ session considered closed
hide_closed: false     # start with closed sessions hidden (toggle with x)
local:
  path: /home/sam/.pi/agent/dashboard/
remote:
  - host: 192.168.20.13
    user: sam
    path: /home/sam/.pi/agent/dashboard/
  - host: 192.168.20.51
    user: sam
    path: /home/sam/.pi/agent/dashboard/

Remote polling is plain ssh … "cat <path>/*.json" (BatchMode, 5 s connect timeout); unreachable remotes are skipped silently.

Deployment

  • Extension — source of truth: ~/.agents/extensions/dashboard.ts (Gitea pi-config). Edit there, commit + push, then copy to ~/.pi/agent/extensions/dashboard.ts on each machine (.27, .13, .51).
  • Binarycd ~/src/pi-dashboard && CGO_ENABLED=0 go build -o ~/.local/bin/pi-dashboard ., then scp to .13/.51.
  • After updating the extension on a machine, run /reload in running pi sessions (or restart) to activate it.
  • Dead state files accumulate by design (they just show as closed); the archive/ subfolder holds pruned files.

engram + gentle-engram

engram v1.16.1 runs on nixos-desktop (.13) at ~/.local/bin/engram. Systemd user service auto-starts. Binds 127.0.0.1:7437, accessed via SSH tunnel: ssh -fNL 7437:127.0.0.1:7437 192.168.20.13.

gentle-engram connects via ENGRAM_URL=http://127.0.0.1:7437. Replaces memory-vault. Features: session capture, compaction recovery, private block redaction.

⚠️ The SSH tunnel must be running for engram to work. It does not auto-start. Re-establish with: ssh -fNL 7437:127.0.0.1:7437 192.168.20.13


MCP Servers

pi-mcp-adapter connects Pi to external services via the Model Context Protocol.

Config files: ~/.pi/agent/mcp.json (pi global), ~/.config/mcp/mcp.json (shared), .mcp.json (project)

// ~/.pi/agent/mcp.json — pi MCP servers
{
  "mcpServers": {
    "codebase-memory": {
      "command": "/home/sam/.local/bin/codebase-memory-mcp",
      "lifecycle": "lazy"
    },
    "code-review-graph": {
      "command": "/home/sam/.local/bin/code-review-graph",
      "args": ["serve"],
      "lifecycle": "lazy"
    }
  }
}

Shared config at ~/.config/mcp/mcp.json:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/sam"]
    }
  }
}

Find MCP servers at:

Usage:

  • /mcp — interactive panel to manage servers
  • mcp({ search: "..." }) — search available tools
  • mcp({ tool: "tool_name", args: '{}' }) — call a tool
  • Servers are lazy (connect on first use, disconnect after 10 min idle)

Configuration Files

Global (~/.pi/agent/settings.json)

  • Nix store symlink — managed via /etc/nixos/home/sam/home.nix
  • Contains: providers (opencode-go, openrouter, google), packages (pi-memctx, pi-prompt-template-model, Gitea)
  • Read-only — cannot be modified by pi install or /config-add

Project (<project-dir>/.pi/settings.json)

  • Overrides global settings (arrays replace, not merge)
  • Contains: ~/.agents package (extensions + skills), Gitea package (tavily-search)
  • Modified via /config-add / /config-remove commands

Per-folder Memory (via pi-memctx)

  • Memory stored in <chat-folder>/.pi/memory-vault/packs/
  • Workspace map at ~/.pi/agent/memory-vault/00-system/workspace-map.json
  • Each chat folder has isolated memory (prevents sibling directory contamination)

models.json (Provider Routing)

Path: ~/.pi/agent/models.json (symlinked from ~/.agents/models.json for Gitea). Injects OpenRouter provider routing for KV cache sharing. DeepSeek cache discount: 91.7% ($0.145/M vs $1.74/M input). Configured: deepseek, qwen, minimax, moonshotai. Mechanism: pi-core reads model.compat.openRouterRouting → injects provider: { order: [...] }.

subagents.json

Path: ~/.pi/agent/subagents.json. Configuration for pi-subagents agent types, default models, and providers.


Useful Commands

Command What it does
/config-setup One-shot: creates .pi/, settings.json, memory vault in current folder
/config-add ext <name> Activate an extension from ~/.agents
/config-add skill <name> Activate a skill from ~/.agents
/config-show Show active extensions and skills
/agents Interactive agent management (pi-subagents)
/tasks Interactive task management (pi-tasks)
/memctx-init Scan folder, build initial memory pack
/memctx-status Show memory status
/memctx-refresh Re-scan and enrich memory
/filechanges Review changed files, diffs, accept/decline
/filechanges-accept Accept all changes
/filechanges-decline Revert all changes
markitdown <file> Convert file to Markdown (PDF, Word, Excel, PPTX, images, HTML, etc.)
markitdown-vision <file> Describe image using Qwen 2.5 VL 72B via OpenRouter
Agent() Spawn subagent (pi-subagents)
get_subagent_result() Retrieve results from background agent
steer_subagent() Send mid-run steering message
compress_for_agent() Compress large content via Headroom
/langfuse-setup Set Langfuse keys interactively (pi-langfuse)
/langfuse-status Show pi-langfuse config state (masked keys, host, capture policy)

Agent Roster (18)

Agent Model Provider
chat-search google/gemini-2.5-flash:free openrouter
code-analysis deepseek-r1-distill-qwen-32b opencode-go
code-ingest google/gemini-2.5-flash:free openrouter
coder-basic deepseek/deepseek-chat openrouter
coder-pro deepseek/deepseek-v4-pro openrouter
database deepseek-r1-distill-qwen-32b opencode-go
devops-basic deepseek/deepseek-chat openrouter
devops-pro deepseek/deepseek-v4-pro openrouter
document-writer deepseek-r1-distill-qwen-32b opencode-go
file-ops qwen-coder-32b-instruct opencode-go
home-automation deepseek-r1-distill-qwen-32b opencode-go
image-maker black-forest-labs/flux-1-schnell openrouter
iot-coder qwen-coder-32b-instruct opencode-go
iot-hardware moonshotai/kimi-k2.6 openrouter
obsidian deepseek-r1-distill-qwen-14b opencode-go
research google/gemini-2.5-flash:free openrouter
video-analyze qwen/qwen-2.5-vl openrouter
vscode-setup qwen/qwen-3-coder-next openrouter

Function Calls

Agent({ subagent_type, prompt, description, model?, thinking?, max_turns?, run_in_background?, resume?, isolated?, isolation?, inherit_context? })
get_subagent_result({ agent_id, wait?, verbose? })
steer_subagent({ agent_id, message })
compress_for_agent({ content })

Skipped / Bookmarked

Extension/Skill Reason
web-search (amosblomqvist) Redundant — Tavily does this
subagents (amosblomqvist) Redundant — pi-subagents already installed
bash-guard (amosblomqvist) Too aggressive — would interrupt flow
google-image-search (amosblomqvist) Would need Google Search API + CSE setup
pdf-reader (amosblomqvist) Bookmarked — Python + pymupdf setup needed
notify (mitsuhiko) Minor QoL — desktop notifications on task complete
audio/voice Not practical

Tasks

  • Rebuild NixOS to activate new packages 2026-06-11
  • Migrate to @tintinweb/pi-subagents with 18 agent types 2026-06-14
  • Deploy models.json with OpenRouter provider pinning (only: provider) 2026-06-14
  • Deploy engram + gentle-engram memory service on .13 2026-06-13
  • Install pi-tasks (@tintinweb/pi-tasks) v0.7.0 2026-06-13
  • Patch pi-subagents: 24h cleanup, disable clearCompleted 2026-06-14
  • Add memory: project to all 18 agent frontmats 2026-06-14
  • Remove custom subagent-registry skill (built-in /agents menu is sufficient) 2026-06-14
  • Update Pi Subagent.md and Pi Agent Extensions & Skills.md documentation 2026-06-14
  • Update pi-subagents to v0.10.3 2026-06-14
  • Update pi-tasks to v0.7.0 2026-06-13
  • Install pi-langfuse tracing extension (pi → Langfuse on .13:3001) 2026-08-03
  • Pi Dashboard v2: heartbeat + cwd + started/closed columns, hide/sort, /dash-name (pi+zellij), hunk in agent folder, tuxedo project boards, zellij/tmux attach 2026-08-04
  • Verify video-extract works with Gemini
  • Clean up workspace-map.json entries for any stale memory packs