A native desktop application that wraps the pi coding agent CLI with project management, session persistence, and a rich chat UI. Built with Tauri v2 (Rust backend) and Lit web components (TypeScript frontend).
See CHANGELOG.md for recent updates.
- Project Management -- Create projects with custom names, icons, directory access tiers, system prompts, and model configurations
- Session Persistence -- Sessions are stored as JSONL files; browse, search (full-text), rename, delete, and export sessions as HTML
- Live Chat Interface -- Streaming message display with collapsible messages, auto-scroll, and tool execution visualization
- Session Outline Sidebar -- Tree view of session structure (prompts, responses, tool results) with click-to-navigate, user-prompt forking, and resizable panel
- Slash Commands & Skills UI -- Command discovery, slash autocomplete, source-aware badges, and a dedicated Commands & Skills panel with filtering
- Extension UI Bridging -- Handles extension-driven
select/confirm/inputinteractions over the RPC channel - Permission System -- Tiered directory access control (unrestricted / prompt / blocked) enforced via a bundled extension
- Native macOS Menus -- Edit, Session (export, compact), and Window menus
- Session Debug Helpers -- Error-state action to view the exact
pi --mode rpclaunch command in a modal with scrolling, copy, backdrop close, andEscdismiss
Pi Desktop supports slash command discovery and source-aware interactions when using pi --mode rpc.
- Command discovery -- Loads available slash commands from the running agent (
get_commands) and merges them with desktop built-ins. - Source-aware commands -- Distinguishes command sources:
builtin,extension,prompt, andskill. - Slash autocomplete -- Type
/in the composer to see matching commands. Use keyboard navigation with:↑/↓to move through suggestionsTabto apply the selected suggestionEnterto apply highlighted suggestionEscto clear highlight
- Commands & Skills panel -- Open from toolbar or
/commands(or/help) to browse commands, search by name/description, and filter by source. - Message badges -- User messages display badges for slash interactions (
slash:ext,slash:prompt,slash:skill,slash:unknown) so command-driven turns are visible in conversation history. - Built-in desktop slash commands:
/compact-- Runs session compaction./export-- Exports the current session to HTML./helpand/commands-- Opens command help and the Commands & Skills panel.
Pi Desktop now handles extension UI requests from the agent event stream:
notifysetStatussetWidgetsetTitleset_editor_text- interactive requests:
select,confirm,input, andeditor(responded to withextension_ui_response)
Forking is available from the session outline for user prompts.
- Fork target rules -- Only user prompt nodes are forkable.
- Correct entry resolution -- The desktop app maps tree selection to valid session
entryIdvalues fromget_fork_messagesbefore sendingfork. - Post-fork prompt prefill -- After a successful fork, the selected prompt text is loaded into the composer so you can immediately rerun or edit it.
When a session reports an error, use View pi launch command to inspect the exact runtime command.
- Opens in a dedicated modal overlay (not inline in the transcript).
- Supports long commands with a scrollable viewport.
- Includes a Copy action for full command text.
- Can be dismissed with Close, backdrop click, or
Esc.
- Node.js >= 18
- Rust toolchain (stable) with
cargo - pi CLI installed and available on
PATH - Tauri v2 prerequisites: see Tauri Getting Started
To build on Linux, you need the following system libraries. If you encounter errors like Package webkit2gtk-4.1 was not found, ensure you have installed the -dev (or -devel) packages listed below.
AppImage Note: AppImage bundling requires libfuse2 (or fuse-libs on Fedora). If bundling fails with failed to run linuxdeploy, ensure FUSE is installed or use ./scripts/build-linux.sh --skip-appimage.
Ubuntu/Debian:
sudo apt update
sudo apt install libwebkit2gtk-4.1-dev build-essential curl wget file libxdo-dev libssl-dev libayatana-appindicator3-dev librsvg2-dev libsoup-3.0-dev libfuse2Fedora:
sudo dnf install webkit2gtk4.1-devel openssl-devel curl wget file libayatana-appindicator-gtk3-devel librsvg2-devel libxdo-devel libsoup3-devel fuse-libs
sudo dnf group install "C Development Tools and Libraries"Arch Linux:
sudo pacman -S --needed webkit2gtk-4.1 base-devel curl wget file openssl appmenu-gtk-module libappindicator-gtk3 librsvg xdotool libsoup3If the AppImage build fails with failed to run linuxdeploy (common on newer Fedora, Arch, or Ubuntu versions):
- Check FUSE: Ensure
libfuse2(Ubuntu) orfuse-libs(Fedora) is installed. - Strip Failures (.relr.dyn): If you see
unknown type [0x13] section .relr.dyn, it's becauselinuxdeployuses an oldstriptool. Thebuild-linux.shscript automatically setsNO_STRIP=1to bypass this. - librsvg Failures: If you see
there is no 'libdir' variable for 'librsvg-2.0', ensure you have installedlibrsvg2-dev(Ubuntu) orlibrsvg2-devel(Fedora). - Use Verbose Build: Run
./scripts/build-linux.shwhich now uses--verboseandNO_STRIP=1. - Unknown provider "google-vertex-claude": Ensure you have installed the required extension:
pi install npm:@isaacraja/pi-vertex-claude. - Skip AppImage / Target Specific Formats: If you only need
.debor.rpmpackages, use the skip flag or specific format flags:./scripts/build-linux.sh --skip-appimage ./scripts/build-linux.sh --rpm-only ./scripts/build-linux.sh --deb-only
- Environment: AppImage creation is most reliable on older base systems (like Ubuntu 22.04 or 20.04). If building on a bleeding-edge distro, consider using a Docker container for the build.
# Install dependencies
npm install
# Run in development mode (hot-reload)
npm run tauri dev
# Build for production
./scripts/build-macos.sh # macOS
./scripts/build-linux.sh # LinuxThe build produces:
- macOS:
src-tauri/target/release/bundle/macos/PiDesktop.appand.dmg - Linux:
src-tauri/target/release/bundle/deb/*.debandbundle/appimage/*.AppImage
Pass options for debug builds or to skip AppImage:
./scripts/build-linux.sh --debug # Linux debug build
./scripts/build-linux.sh --skip-appimage # Build only .deb and .rpmPi Desktop defaults to routing Claude requests through Google's Vertex AI gateway using the pi-vertex-claude provider extension. This lets you use Claude models (Opus, Sonnet, Haiku) hosted on Google Cloud infrastructure rather than calling the Anthropic API directly.
CRITICAL: The default provider google-vertex-claude is not built into the pi CLI. You must install the extension manually:
pi install npm:@isaacraja/pi-vertex-claudeWithout this, Pi Desktop will fail to start with an "Unknown provider" error.
-
Install the gcloud CLI if you don't already have it:
brew install google-cloud-sdk # macOS -
Authenticate with Application Default Credentials:
gcloud auth application-default login
-
Enable the Vertex AI API on your GCP project:
gcloud services enable aiplatform.googleapis.com --project=YOUR_PROJECT_ID -
Activate Claude models in Vertex AI Model Garden. Search for "Claude" and enable the model variants you want (Opus, Sonnet, Haiku).
Pi Desktop forwards these environment variables to the pi subprocess. Set them in your shell profile (e.g., ~/.zshrc):
# Required -- your GCP project ID
export GOOGLE_CLOUD_PROJECT="your-gcp-project-id"
# Required -- GCP region where Claude models are available
export GOOGLE_CLOUD_LOCATION="us-east5" # or europe-west1, etc.
# Optional -- path to service account key (if not using gcloud auth)
# export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"
# Optional -- alternative project ID variables (some setups use these)
# export ANTHROPIC_VERTEX_PROJECT_ID="your-gcp-project-id"
# export CLOUD_ML_REGION="us-east5"Note: If you launch Pi Desktop from the macOS Dock or Finder, your shell profile may not be sourced. Either launch from a terminal (
open -a PiDesktopornpm run tauri dev) or uselaunchctl setenvto set variables globally.
Open a project's settings and set:
| Field | Value |
|---|---|
| Provider | google-vertex-claude |
| Default Model | claude-opus-4-6 |
These are the defaults, so a fresh project is already configured for Vertex. Available model IDs include:
| Model | ID |
|---|---|
| Claude Opus 4.6 | claude-opus-4-6 |
| Claude Sonnet 4.6 | claude-sonnet-4-6 |
| Claude Sonnet 4 | claude-sonnet-4@20250514 |
| Claude Haiku 3.5 | claude-haiku-4-5-20251001 |
Start a new session. If credentials or configuration are wrong, you'll see an error like:
Model returned empty response (0 tokens). Provider "google-vertex-claude" may not have valid credentials...
Check:
gcloud auth application-default print-access-tokenreturns a tokenGOOGLE_CLOUD_PROJECTandGOOGLE_CLOUD_LOCATIONare set in the environment where Pi Desktop runs- The Claude model is activated in your project's Model Garden
To use the Anthropic API instead of Vertex, install a direct provider or set:
export ANTHROPIC_API_KEY="sk-ant-..."Then change the project's Provider to the appropriate provider name and update the Default Model accordingly.
┌──────────────────────────────────────────────────────────┐
│ Tauri Webview (Frontend) │
│ Lit components + Tailwind CSS │
│ ┌────────────┐ ┌─────────────┐ ┌───────────────────┐ │
│ │ AppShell │ │ SessionView │ │ TreeSidebar │ │
│ │ (routing) │ │ (chat UI) │ │ (outline nav) │ │
│ └────────────┘ └──────┬──────┘ └───────────────────┘ │
│ │ RpcAgentAdapter │
│ │ (Tauri IPC events) │
├─────────────────────────┼────────────────────────────────┤
│ Tauri Rust Backend │ │
│ ┌──────────────┐ ┌────┴─────────┐ ┌───────────────┐ │
│ │ ProjectMgr │ │ ProcessMgr │ │ SessionIndex │ │
│ │ (CRUD JSON) │ │ (spawn pi) │ │ (SQLite+FTS) │ │
│ └──────────────┘ └────┬─────────┘ └───────────────┘ │
├─────────────────────────┼────────────────────────────────┤
│ Child Processes │ │
│ pi --mode rpc ─────────┘ │
│ (one per session, JSONL over stdin/stdout) │
└──────────────────────────────────────────────────────────┘
| File | Purpose |
|---|---|
src/app-shell.ts |
Top-level layout with hash-based routing and persistent title bar |
src/rpc-agent-adapter.ts |
Bridges the Agent interface to Tauri IPC; manages state, subscriptions, and event processing |
src/views/session-view.ts |
Active session: chat panel, toolbar, outline sidebar with resizable splitter |
src/views/project-list-view.ts |
Home screen with project cards |
src/views/session-list-view.ts |
Browse/search sessions with pagination |
src/views/project-settings-view.ts |
Project configuration editor |
src/components/session-tree-sidebar.ts |
Outline tree container |
src/components/session-tree-node.ts |
Individual tree node with role-based rendering |
src/types/session.ts |
TreeNode interface and outline tree builders |
src/types/project.ts |
ProjectConfig, ModelConfig, DirectoryEntry interfaces |
| File | Purpose |
|---|---|
src-tauri/src/lib.rs |
Tauri app setup, plugin registration, macOS menu bar |
src-tauri/src/process_manager.rs |
Spawn and manage per-session pi --mode rpc processes; stdin/stdout/stderr piping; graceful shutdown |
src-tauri/src/project_manager.rs |
CRUD for project configs stored as JSON in ~/.pi-desktop/projects/ |
src-tauri/src/session_index.rs |
SQLite index of session JSONL files with FTS5 full-text search |
src-tauri/src/types.rs |
Rust structs mirroring frontend types |
src-tauri/src/commands/agent.rs |
agent_spawn, agent_send, agent_kill, get_home_dir |
src-tauri/src/commands/project.rs |
project_list, project_get, project_create, project_update, project_delete |
src-tauri/src/commands/session.rs |
session_list, session_search, session_delete, session_rename, session_reindex |
| Directory | Purpose |
|---|---|
extensions/pi-desktop-permissions/ |
TypeScript extension enforcing directory access tiers via beforeToolCall hook |
~/.pi-desktop/
├── projects/
│ ├── <project-id>.json # Project configuration
│ └── icons/
│ └── <project-id>.png # Custom project icons
└── sessions.db # SQLite index (sessions + FTS)
~/.pi/agent/sessions/
└── <session-id> # Session JSONL files (managed by pi)
Hash-based routing (no server required):
| Route | View |
|---|---|
#/ |
Project list |
#/project/{id} |
Session list for project |
#/project/{id}/settings |
Project settings editor |
#/project/{id}/session/{sessionId} |
Active chat session |
- Desktop framework: Tauri v2
- Frontend: Lit 3.x web components, Tailwind CSS 4.x
- Backend: Rust with Tokio async runtime
- Database: SQLite via sqlx with FTS5
- Build tool: Vite 6.x
- Language: TypeScript 5.7, Rust (2021 edition)
| Script | Description |
|---|---|
npm run dev |
Start Vite dev server (port 1420) |
npm run build |
TypeScript check + Vite production build |
npm run tauri dev |
Launch Tauri in development mode with hot-reload |
npm run tauri build |
Production build of the native app |
npm run build:macos |
Full macOS .app + .dmg build |
npm run build:macos:debug |
Debug macOS build |
Apache License 2.0 -- see LICENSE.md.