# pi-chat **Repository Path**: RexHuang936/pi-chat ## Basic Information - **Project Name**: pi-chat - **Description**: No description available - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-06-06 - **Last Updated**: 2026-06-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # pi-chat A pi extension that bridges Discord and Telegram channels to a sandboxed pi session. Each connected channel gets its own [Gondolin](https://github.com/earendil-works/gondolin) micro-VM with persistent workspace, shared storage, memory, and skills. ## Quick Start ```bash # Install pi install /path/to/pi-chat # or pi -e /path/to/pi-chat # Configure accounts and channels /chat-config # Connect /chat-connect ``` ### Requirements - [QEMU](https://www.qemu.org/) installed (`brew install qemu` on macOS) - Gondolin guest image (downloaded automatically on first connect) - A Discord bot token or Telegram bot token - `tmux` for multi-channel worker orchestration --- ## Features - **Discord server channels** and **Telegram DMs/groups** - **Gondolin VM sandbox** per connection — tools run inside an isolated Alpine Linux micro-VM - **Persistent workspace** and **shared storage** across sessions - **Streamed preview** responses with edit-in-place - **Reply-to-trigger** — bot replies are attached to the triggering message - **Durable memory** — account-wide and channel-specific memory files - **Skills** — agent-created reusable tools, auto-discovered and injected into the prompt - **Encrypted secret exchange** — securely pass credentials via browser-based encryption - **Remote control** — stop, compact, new session, and status via chat commands - **Chat history** tool for searching older messages - **File attachments** — send and receive files between chat and the VM --- ## Setup ### Discord 1. Create a bot at [Discord Developer Portal](https://discord.com/developers/applications) 2. Enable **Message Content Intent** under Bot settings 3. Run `/chat-config` → Create account → Discord 4. Enter your bot token 5. Invite the bot to a server (the setup flow provides the invite URL) 6. Select a server and configure channels ### Telegram 1. Create a bot via [@BotFather](https://t.me/BotFather) 2. Run `/chat-config` → Create account → Telegram 3. Enter your bot token 4. Add DMs or groups through the guided setup --- ## Commands | Command | Description | |---------|-------------| | `/chat-config` | Configure accounts, channels, and secrets | | `/chat-connect` | Connect to a configured channel | | `/chat-disconnect` | Disconnect the current channel | | `/chat-status` | Show connection status, model, usage, context | | `/chat-list` | List configured channels | | `/chat-spawn-all` | Spawn every configured channel in detached tmux/pi sessions | | `/chat-spawn-all --restart` | Restart those tmux/pi sessions | | `/chat-workers` | Show managed tmux/pi worker status | | `/chat-open-all` | Open running workers in a tiled tmux dashboard | | `/chat-kill-all` | Kill all managed tmux/pi workers | | `/chat-new` | Start a new pi session, keeping the chat connection | Workers also write status snapshots every 15 seconds under `~/.pi/agent/chat/worker-status/`. The `chat_workers` tool exposes the same status to an orchestrating pi agent. --- ## Remote Control Users in the connected chat can send these commands (with or without mentioning the bot): | Command | Effect | |---------|--------| | `stop` | Abort the current turn | | `status` | Show model, usage, context stats | | `compact` | Trigger context compaction | | `new` | Start a new pi session | --- ## Storage Layout Everything lives under `~/.pi/agent/chat/`: ``` ~/.pi/agent/chat/ ├── config.json # Accounts, channels, secrets ├── cache/ # Discovery cache └── accounts// ├── shared/ # Mounted as /shared in VM │ ├── memory.md # Account-wide persistent memory │ └── skills/ # Account-wide skills └── channels// ├── channel.jsonl # Chat log ├── .lock # Runtime lock ├── workspace/ # Mounted as /workspace in VM │ ├── memory.md # Channel-specific persistent memory │ ├── skills/ # Channel-specific skills │ ├── incoming/ # Downloaded attachments │ ├── .secrets/ # Encrypted secrets │ └── SYSTEM.md # Environment modification log └── gondolin/ # VM state └── session.json ``` --- ## VM Environment Each connection starts a Gondolin micro-VM with: - **Alpine Linux** with bash pre-installed - `/workspace` → channel workspace directory - `/shared` → account shared directory - Tools: `read`, `write`, `edit`, `bash` - All outbound HTTP/TLS open by default The agent sees `/workspace` as its working directory. --- ## Memory Two persistent memory files, injected into the system prompt on every turn: | File | VM Path | Scope | |------|---------|-------| | Account memory | `/shared/memory.md` | Shared across all channels for this account | | Channel memory | `/workspace/memory.md` | Specific to this channel | The agent is instructed to write durable facts and preferences to these files when asked to remember something. Account-wide goes to `/shared/memory.md`, channel-specific to `/workspace/memory.md`. --- ## Skills The agent can create reusable tools as skills, following the [Agent Skills standard](https://agentskills.io): - **Account-wide:** `/shared/skills/` - **Channel-specific:** `/workspace/skills/` A skill is either a single `.md` file (e.g. `skills/foo.md`) or a directory with `SKILL.md` plus supporting files (e.g. `skills/foo/SKILL.md`, `skills/foo/run.sh`). Each skill needs YAML frontmatter: ```yaml --- name: skill-name description: Short description of what this skill does --- ``` Skills are automatically discovered and listed in the system prompt. The agent reads the full skill file before using it. --- ## Secrets ### Config Secrets (Gondolin HTTP hooks) Configure secrets at three levels via `/chat-config`: - **Global** — shared across all accounts - **Per account** — shared across channels of that account - **Per channel** — specific to one channel Each secret has a value and allowed host patterns. Gondolin replaces placeholder env vars with real values only for outbound HTTP requests to allowed hosts. The agent never sees the real secret value. ### Runtime Secrets (encrypted exchange) For credentials the agent needs at runtime (API keys for skills, OAuth files, etc.): 1. Agent calls the `chat_request_secret` tool 2. A link to `pi.dev/secret` is sent to the chat with an embedded public key 3. User clicks, pastes the secret, and gets an encrypted blob 4. User pastes the blob back into chat 5. pi-chat decrypts it (RSA-OAEP + AES-256-GCM) and stores it at `/workspace/.secrets/` 6. Agent is notified and can use the file The encrypted blob is useless without the ephemeral private key held in pi-chat's memory. --- ## Tools | Tool | Description | |------|-------------| | `read` | Read files (routed through Gondolin VM) | | `write` | Create/overwrite files | | `edit` | Precise in-place edits | | `bash` | Execute commands (runs `/bin/bash` in the VM) | | `chat_history` | Search older messages from the chat log | | `chat_attach` | Queue files to send with the next reply | | `chat_request_secret` | Request a secret from the user via encrypted exchange | --- ## Credits pi-chat includes vendored/adapted logic inspired by [Vercel Chat SDK](https://github.com/vercel/ai) (MIT): - `src/render/format.ts` - `src/render/streaming-markdown.ts` - `src/render/streaming.ts` --- ## License MIT