{"id":48865422,"url":"https://github.com/ekristen/guppi","last_synced_at":"2026-04-15T18:05:48.799Z","repository":{"id":344516524,"uuid":"1180285779","full_name":"ekristen/guppi","owner":"ekristen","description":"all tmux sessions, all agents, one interface","archived":false,"fork":false,"pushed_at":"2026-03-15T22:32:15.000Z","size":247,"stargazers_count":1,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-03-30T18:37:19.492Z","etag":null,"topics":["ai-agent","ai-agent-monitoring","ai-agents","browser","browser-notifications","desktop-notifications","interface","notifications","tmux"],"latest_commit_sha":null,"homepage":"https://guppi.sh","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ekristen.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"ekristen"}},"created_at":"2026-03-12T22:21:38.000Z","updated_at":"2026-03-20T18:35:24.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ekristen/guppi","commit_stats":null,"previous_names":["ekristen/guppi"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/ekristen/guppi","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekristen%2Fguppi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekristen%2Fguppi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekristen%2Fguppi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekristen%2Fguppi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ekristen","download_url":"https://codeload.github.com/ekristen/guppi/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekristen%2Fguppi/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31853294,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-15T15:24:51.572Z","status":"ssl_error","status_checked_at":"2026-04-15T15:24:39.138Z","response_time":63,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agent","ai-agent-monitoring","ai-agents","browser","browser-notifications","desktop-notifications","interface","notifications","tmux"],"created_at":"2026-04-15T18:05:48.736Z","updated_at":"2026-04-15T18:05:48.791Z","avatar_url":"https://github.com/ekristen.png","language":"Go","funding_links":["https://github.com/sponsors/ekristen"],"categories":["HarmonyOS"],"sub_categories":["Windows Manager"],"readme":"# GUPPI\n\nall your tmux sessions, all your agents, one interface\n\nget notified when it matters\n\n---\n\n## What is GUPPI?\n\nguppi gives you a real-time web interface for your tmux sessions. It renders full terminal output in the browser using xterm.js backed by PTY connections, so you get the exact same view as your local terminal — borders, splits, colors, and all.\n\nIt also tracks AI coding agents (Claude Code, Codex, Copilot, OpenCode) running inside your sessions, surfacing their status so you know when an agent needs input, hits an error, or finishes a task.\n\n### Key features\n\n- **Full terminal in the browser** — PTY-backed xterm.js rendering. Type, scroll, resize — it just works.\n- **Real-time session discovery** — sessions, windows, and panes update live via tmux control mode.\n- **AI agent monitoring** — see which agents are active, waiting for input, or errored across all sessions at a glance.\n- **Push notifications** — get browser/desktop notifications when an agent needs attention, even with the tab backgrounded.\n- **Quick switcher** — Ctrl+K to jump between sessions and windows instantly, hands never leave the keyboard.\n- **Single binary** — Go backend with the React frontend embedded. No separate processes, no Node runtime needed in production.\n- **Unix socket + HTTP** — local CLI notifications go through a Unix socket for zero-config, with HTTP as fallback.\n- **TLS first** -- TLS out of the gate, with easy instructions on trusting your CA certificate.\n\n### Non-goals\n\n- **Multi-user** — guppi is a single-user tool. One person, one dashboard. There are no user accounts, roles, or shared access controls.\n- **Agent orchestration** — guppi doesn't start, stop, or control your agents. It watches and reports. You run your agents however you want; guppi just tells you what they're doing.\n- **tmux management** — guppi doesn't configure or manage your tmux setup. Your `.tmux.conf`, layouts, and workflows stay yours.\n\n## Installation\n\n### Using dist (recommended)\n\n[dist](https://github.com/ekristen/distillery) installs binaries from GitHub releases with checksum verification and multi-version support.\n\n```bash\ndist install ekristen/guppi\n```\n\n### Quick install\n\n```bash\ncurl -sSL https://get.guppi.sh | sh\n```\n\nThis detects your platform, downloads the latest release, and puts `guppi` in `/usr/local/bin` (or `~/.local/bin` if not writable). You can pin a version with `VERSION=v0.1.0 curl -sSL ... | sh`.\n\n### From source\n\nRequires [Go](https://go.dev/) 1.25+ and [Node.js](https://nodejs.org/) 18+.\n\n```bash\ngit clone https://github.com/ekristen/guppi.git\ncd guppi\nmake build\n# Binary is at ./dist/guppi\n```\n\n## Usage\n\n### 1. Start the server\n\nMake sure [tmux](https://github.com/tmux/tmux) is running with at least one session, then:\n\n```bash\nguppi server\n```\n\nOpen https://localhost:7654 in your browser. On first launch you'll set a password, then guppi will guide you through agent setup.\n\n### 2. Configure agent hooks\n\nguppi tracks AI agents running in your tmux sessions, but agents need hooks configured so they can report their status. Run:\n\n```bash\nguppi agent-setup\n```\n\nThis auto-detects which agents you have installed and configures their hooks:\n\n- **Claude Code** — hooks in `~/.claude/settings.json`\n- **Codex** — `notify` command in `~/.codex/config.toml`\n- **GitHub Copilot CLI** — hooks in `~/.copilot/hooks/guppi.json`\n- **OpenCode** — plugin in `~/.config/opencode/plugins/guppi.js`\n\nIf you're running guppi in a multi-host setup, run `guppi agent-setup` on each machine where you use agents.\n\nYou can check hook status any time in the web UI under **Settings \u003e Agents**, or by visiting `/setup`.\n\nSee [docs/agent-setup.md](docs/agent-setup.md) for manual setup instructions.\n\n### 3. Use it\n\nOnce hooks are configured, agent status shows up automatically:\n\n- The **Overview** page shows all sessions and any agents that need attention.\n- The **sidebar** badges sessions with active/waiting/errored agents.\n- **Push notifications** alert you when an agent needs input, even with the tab closed (enable in Settings \u003e Notifications).\n### Keyboard shortcuts\n\nPress `Ctrl+/` (or `Cmd+/` on macOS) to see all shortcuts, or click the `?` in the status bar.\n\n| Shortcut | Action |\n|----------|--------|\n| `Ctrl+K` | Quick switcher — jump between sessions and windows |\n| `Ctrl+J` | Jump to next alert (cycles through waiting/error agents) |\n| `Ctrl+H` | Overview |\n| `Ctrl+,` | Settings |\n| `Ctrl+\\` | Toggle sidebar |\n| `Ctrl+L` | Lock / sign out |\n| `Ctrl+/` | Keyboard shortcuts help |\n\n### Manual notifications\n\nYou can also send status updates from scripts or the command line:\n\n```bash\nguppi notify -t claude -s waiting -m \"Needs approval\"\nguppi notify -t codex -s active\nguppi notify -t claude -s completed\n```\n\nThe tmux session, window, and pane are auto-detected when run inside tmux.\n\n### Development\n\n```bash\n# Frontend dev server (hot reload)\ncd web \u0026\u0026 npm install \u0026\u0026 npm run dev\n\n# Go server (watches for tmux changes)\ngo run . server\n```\n\n## Architecture\n\n```\nBrowser  \u003c──WebSocket──\u003e  Go Server  \u003c──PTY──\u003e  tmux attach-session\n                              │\n                              ├── Control mode (real-time state changes)\n                              ├── Session discovery (polling fallback)\n                              ├── Tool event tracker (agent status)\n                              └── Unix socket (local CLI notifications)\n```\n\nEach browser tab gets its own PTY process running `tmux attach-session`. tmux handles all rendering natively — guppi just bridges the PTY output to xterm.js over a WebSocket. Window switching uses the tmux `select-window` command; tmux re-renders through the existing PTY connection.\n\nState changes (new sessions, window renames, pane activity) are detected via tmux control mode and broadcast to all connected clients over a separate WebSocket.\n\n## UI concepts\n\n### Session status\n\nSessions in the sidebar and overview show as **active** or **idle**:\n\n- **Active** — at least one pane in the session has a foreground process that isn't a shell. For example: `vim`, `claude`, `node`, `python`, `go build`, etc.\n- **Idle** — every pane is sitting at a shell prompt (`bash`, `zsh`, `fish`, `sh`, `dash`, `ksh`, `csh`, `tcsh`, `tmux`, `login`).\n\nThis is driven by tmux's `pane_current_command`, which reports the foreground process of each pane. The server receives this via tmux control mode (or polling) and broadcasts it over WebSocket.\n\n### Alerts\n\nAlerts surface when an AI agent needs attention. They appear in the **alert banner** at the top of every page and in the **Pending Alerts** section on the overview.\n\n- **Waiting** — the agent is waiting for user input (e.g., tool approval in Claude Code).\n- **Error** — the agent hit an error.\n- **Active** — the agent is running normally (shown as badges in the sidebar, not as alerts).\n\nAlerts are live state from the server — they always reflect the current status and survive page refreshes. Dismissing an alert hides it from the UI but doesn't affect the agent.\n\nPush alerts (via the Web Push API) work independently of the browser tab, including when logged out or when the tab is closed.\n\n## Configuration\n\n### Environment variables\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `GUPPI_PORT` | `7654` | HTTP server port |\n| `GUPPI_SOCKET` | auto | Unix socket path for local CLI |\n| `GUPPI_DISCOVERY_INTERVAL` | `2` | Session polling interval (seconds) |\n| `GUPPI_NO_CONTROL_MODE` | `false` | Disable tmux control mode |\n| `GUPPI_URL` | `https://localhost:7654` | Server URL for notify/agent-setup |\n| `GUPPI_NO_AUTH` | `false` | Disable authentication |\n| `GUPPI_NO_TLS` | `false` | Disable TLS (serve plain HTTP) |\n| `GUPPI_TLS_CERT` | auto | Path to TLS certificate file |\n| `GUPPI_TLS_KEY` | auto | Path to TLS private key file |\n| `GUPPI_TLS_SAN` | | Additional TLS SANs (IPs or hostnames) |\n| `GUPPI_HUB` | | Hub address for peer mode |\n| `GUPPI_LOCAL_ONLY` | `false` | Only show local sessions in the web UI |\n| `GUPPI_INSECURE` | `false` | Skip TLS verification when connecting to hub |\n| `GUPPI_TLS_RELOAD_INTERVAL` | `60s` | Interval between TLS cert file change checks |\n\n### CLI flags\n\n```\nguppi server [flags]\n  -p, --port int                  HTTP server port (default 7654)\n      --discovery-interval int    Session discovery interval in seconds (default 2)\n      --no-control-mode           Disable tmux control mode (use polling only)\n      --socket string             Unix socket path (auto-detected if omitted)\n      --no-auth                   Disable authentication (not recommended for remote access)\n      --no-tls                    Disable TLS (serve plain HTTP)\n      --tls-cert string           Path to TLS certificate file (auto-generated if omitted)\n      --tls-key string            Path to TLS private key file (auto-generated if omitted)\n      --tls-san strings           Additional TLS SANs (IPs or hostnames, repeatable)\n      --hub string                Hub address for peer mode (e.g. https://desktop.ts.net:7654)\n      --local-only                Only show local sessions in the web UI\n      --insecure                  Skip TLS verification when connecting to hub\n      --tls-reload-interval duration  Interval between TLS cert file change checks (default 60s)\n```\n\n## FAQ\n\n### How do I copy text from the terminal?\n\nThe terminal captures mouse events, so normal click-and-drag selects text inside tmux rather than copying to your clipboard. Hold a modifier key while selecting to override this and copy to the system clipboard:\n\n| Platform | Select to copy |\n|----------|---------------|\n| **macOS** | Hold `Option` and drag to select, then `Cmd+C` to copy |\n| **Linux** | Hold `Shift` and drag to select, then `Ctrl+Shift+C` to copy |\n| **iOS (Safari)** | Touch-select doesn't work in the terminal. Connect a mouse or trackpad and use `Option`+drag, then copy from the context menu |\n\nThis is standard xterm.js behavior — the modifier key tells the browser to handle the selection instead of sending the mouse events to tmux.\n\n## Tech stack\n\n- **Backend:** Go, chi v5, gorilla/websocket, creack/pty\n- **Frontend:** React 19, TypeScript, Vite, Tailwind CSS v4, xterm.js\n- **Build:** Single binary with `//go:embed`, GoReleaser for releases\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fekristen%2Fguppi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fekristen%2Fguppi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fekristen%2Fguppi/lists"}