Architecture
Technical architecture of Pi Session Manager — frontend, backend, and multi-protocol communication.
"Architecture is the thoughtful making of space." — Louis Kahn
Pi Session Manager is built on a three-layer architecture: a React frontend, a Rust backend, and a multi-protocol communication layer that bridges them.
Overview
┌─────────────────────────────────────────────────────────────────────┐
│ Clients │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────────┐ │
│ │ Desktop │ │ Mobile │ │ Web Browser │ │
│ │ (Tauri App) │ │ (PWA/Web) │ │ (Chrome/Safari/Firefox) │ │
│ └──────┬───────┘ └──────┬───────┘ └────────────┬─────────────┘ │
└─────────┼─────────────────┼───────────────────────┼────────────────┘
│ │ │
└─────────────────┼───────────────────────┘
│
┌───────────────────────────▼─────────────────────────────────────────┐
│ Frontend (React 18 / TypeScript / Vite) │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 172 Components · 41 Hooks · Plugin System · i18n (6 langs) │ │
│ │ React Flow · Recharts · dnd-kit · cmdk · Virtual Scroll │ │
│ └─────────────────────────────────────────────────────────────┘ │
├───────────────────────────┬───────────────────┬─────────────────────┤
│ Tauri IPC │ WebSocket │ HTTP + Embedded UI │
│ (Desktop) │ http://:52131 (WS at /ws) │
└───────────────────────────┴───────────────────┴─────────────────────┘
│
┌───────────────────────────▼─────────────────────────────────────────┐
│ Rust Backend (Tauri 2) │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Scanner · SQLite Cache · FTS5 · Tantivy · File Watcher │ │
│ │ PTY Terminal · Auth · Export · Config · Stats · Tags │ │
│ │ Pi Live Registry · Subagent Tracking · Write Buffer │ │
│ └─────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘Frontend
| Technology | Purpose |
|---|---|
| React 18 | UI framework with hooks and concurrent features |
| TypeScript | Type safety across 172 components |
| Vite | Build tool with HMR for development |
| Tailwind CSS | Utility-first styling with CSS custom properties for theming |
| i18next | Internationalization (en-US, zh-CN, ja-JP, de-DE, fr-FR, es-ES) |
| xterm.js | Terminal emulator in the browser |
| React Flow | Graph visualization for flow view |
| Recharts | Charts for the dashboard |
| dnd-kit | Drag-and-drop for Kanban board |
| cmdk | Command palette |
| @tanstack/react-virtual | Virtual scrolling for large session lists |
Key Patterns
- Transport abstraction —
transport.tsprovides a unified interface that auto-detects the runtime (Tauri IPC vs. WebSocket vs. HTTP) and routes commands accordingly - Plugin system — search plugins in
src/plugins/allow extending search sources - Context providers —
TransportContext,SettingsContext,SessionViewContextmanage shared state - 41 custom hooks — encapsulate reusable logic (keyboard shortcuts, file watcher, mobile detection, Pi live sync, session viewer virtual scroll, in-message search, session tree lookup, etc.)
Backend
| Technology | Purpose |
|---|---|
| Tauri 2 | Desktop app framework with native APIs |
| Rust | Systems language for performance and safety |
| Tokio | Async runtime for concurrent I/O |
| Axum | HTTP/WebSocket server framework |
| SQLite (rusqlite) | Persistent cache, settings, tags, favorites |
| Tantivy | Secondary full-text search index (Lucene-like, results merged with FTS5) |
| portable-pty | PTY terminal sessions |
| rust-embed | Embed frontend assets into binary |
| notify | File system watcher |
Module Structure
src-tauri/src/
├── main.rs # Entry: CLI args, window, adapter startup
├── lib.rs # Module declarations, command registration
├── dispatch.rs # Pure business logic shared by WS/HTTP/CLI
├── config.rs # TOML configuration loader
├── auth.rs # Token-based auth for non-local access
├── export.rs # Session export (HTML, Markdown, JSON)
├── stats.rs # Aggregated session statistics
├── subagent.rs # Subagent cost tracking
├── settings_store.rs # SQLite-backed app settings
├── compression.rs # Gzip compression utilities
├── metrics.rs # Prometheus-style metrics collection
├── api_readonly.rs # Read-only HTTP API for external consumers
├── commands/ # Tauri IPC command handlers (17 modules)
│ ├── auth.rs # API token management
│ ├── config_bundle.rs # Config import/export
│ ├── config_versions.rs # Settings version history
│ ├── favorites.rs # Favorite sessions
│ ├── model_config.rs # Model config CRUD + backup/restore
│ ├── models.rs # Legacy model settings
│ ├── pi_live.rs # Pi CLI live session registry
│ ├── search.rs # Full-text search (session + message FTS)
│ ├── session.rs # Session rename, delete, open
│ ├── session_file.rs # File-level session operations
│ ├── session_list.rs # Paginated session listing
│ ├── session_open.rs # Session open in editor
│ ├── settings.rs # App settings CRUD
│ ├── skills.rs # Skills/models/pi resource management
│ ├── tags.rs # Hierarchical tag management
│ └── terminal.rs # PTY terminal management
├── core/ # Pure business logic (no Tauri deps)
│ ├── delete.rs # Session deletion logic
│ ├── intel.rs # Structured recall / intent detection
│ ├── parser.rs # JSONL session parser
│ ├── scanner.rs # Multi-path session scanner + incremental rescan
│ └── write_buffer.rs # Async write batching for SQLite
├── data/
│ ├── search/ # Search engine layer
│ │ ├── client.rs # Unified search client (FTS5 + Tantivy merge)
│ │ ├── embedding.rs # Embedding service for semantic search
│ │ ├── index.rs # Tantivy index management
│ │ └── tantivy.rs # Tantivy full-text search implementation
│ └── sqlite/ # SQLite data access layer
│ ├── bootstrap.rs # DB init, WAL mode, schema creation
│ ├── deps.rs # Shared SQLite dependencies
│ ├── details_cache.rs # Session details caching
│ ├── favorites.rs # Favorites table operations
│ ├── legacy_fts.rs # Legacy session-level FTS (deprecated)
│ ├── maintenance.rs # Vacuum, cleanup, preload
│ ├── message_index.rs # message_entries + FTS5 triggers
│ ├── migrations.rs # Versioned schema migrations
│ ├── schema.rs # Schema version management (v6)
│ ├── sessions.rs # Session upsert / query
│ ├── subagent_meta.rs # Subagent metadata caching
│ ├── tags.rs # Tags table operations
│ ├── types.rs # SQLite type definitions
│ └── util.rs # SQLite utilities
├── domain/ # Domain models and business rules
├── server/ # Protocol adapters
│ ├── http/ # HTTP server (Axum)
│ │ ├── mod.rs # Router setup, middleware, CORS
│ │ ├── common.rs # Shared HTTP handlers
│ │ ├── readonly_routes.rs# Read-only API routes
│ │ ├── realtime.rs # WebSocket / SSE event handling
│ │ ├── embedding.rs # Embedding API endpoints
│ │ ├── sessions.rs # Session HTTP routes
│ │ └── static_assets.rs # Embedded frontend (rust-embed)
│ └── ws.rs # Standalone WebSocket server (legacy)
└── utils/ # Utility functions
├── mod.rs
├── payload.rs
└── string.rsPure Modules
The core business logic modules (scanner.rs, search.rs, tags.rs, etc.) have no Tauri dependency. The commands/ layer is a thin wrapper that bridges Tauri IPC to the pure logic. This design enables the CLI binary to reuse the same code without pulling in Tauri.
Multi-Protocol Communication
All three protocols share a single command router — dispatch():
| Protocol | Address | Use Case |
|---|---|---|
| Tauri IPC | invoke() | Desktop app (GUI mode only) |
| WebSocket | ws://127.0.0.1:52131/ws | Real-time bidirectional (browser) |
| HTTP POST | http://127.0.0.1:52131/api | Stateless single calls (curl, integrations) |
Single-Port Architecture: WebSocket is now served on the same port as HTTP via the /ws path, simplifying deployment and configuration.
Adding a new command requires only one match arm in dispatch(). WebSocket and HTTP inherit it automatically.
Transport Auto-Detection
The frontend detects its runtime environment and selects the appropriate transport:
- Tauri IPC — when
window.__TAURI__is available (desktop app) - WebSocket — default for browser access (real-time updates via SSE fallback)
- HTTP — fallback for mobile web (POST for commands, SSE for events)
Embedded Frontend
The HTTP server embeds the frontend via rust-embed, so the packaged binary serves the full UI at http://localhost:52131 — no external dist/ directory needed. The embedded assets add ~12MB to the binary size.
The CLI binary (pi-session-cli) serves API, WebSocket (/ws), and the embedded frontend all on a single port (52131) using one axum Router.
Incremental Updates
The backend uses a multi-layer caching and update strategy:
- Scanner cache — persistent in-memory cache with atomic version counter
- File watcher —
notifycrate withRecursiveMode::Recursive, batches changed paths - Incremental rescan — only re-parses changed JSONL files
- SessionsDiff — pushes diffs to frontend via WebSocket/SSE
- Frontend patch —
patchSessions()merges diffs without full reload