An open API service indexing awesome lists of open source software.

https://github.com/zac15987/zpit

TUI-based AI development cockpit that orchestrates Claude Code agents across projects with automated issue lifecycle, cross-agent channel communication, and a 5-layer safety system.
https://github.com/zac15987/zpit

ai-agents automation bubble-tea claude-code cli code-review developer-tools forgejo github go tui worktree

Last synced: 19 days ago
JSON representation

TUI-based AI development cockpit that orchestrates Claude Code agents across projects with automated issue lifecycle, cross-agent channel communication, and a 5-layer safety system.

Awesome Lists containing this project

README

          

# Zpit

**Zpit** (zac + cockpit) — a TUI-based AI development cockpit that orchestrates [Claude Code](https://claude.ai/code) agents across multiple projects. Zpit acts as a **dispatch center** — it selects projects, launches agents in separate terminal windows, monitors their progress, coordinates the full issue lifecycle from requirement clarification to PR, and enables real-time cross-agent communication via a built-in HTTP broker + MCP channel.

> **Key principle:** Claude Code runs in independent terminal windows. Zpit never wraps or embeds it — it monitors via session logs, coordinates via issue trackers, and bridges agents via a local channel broker.

## TUI Preview

### Main View

Four independently scrollable dock panels — Projects, Active Terminals, Loop Engine (left column, stacked), Hotkeys (right column). Catppuccin Mocha palette with a single-column `▎` mauve bar marking the focused panel.

```
Zpit v0.1 04/19 15:04 Windows Terminal

▎ PROJECTS 7 HOTKEYS
────── ──────
› AI Inspection Cleaning Demo ⚪ not deployed [Enter] Launch Claude Code
machine │ wpf, ethercat, basler [c] Clarify requirement
[l] Loop auto-implement
ENR DUC ⚪ not deployed [r] Review changes
machine │ wpf, secsgem [f] Efficiency agent
[s] Status overview
DisplayProfileManager ⚪ not deployed [o] Open project folder
desktop │ wpf, nlog [i] Open Issue Tracker
[p] Open PR
Zpit 🟢 deployed [u] Undeploy agents
terminal │ go, bubbletea [d] Redeploy all agents
[m] Channel communication
Zplex ⚪ not deployed [g] Git status
desktop │ go, electron, xterm [G] Open lazygit
[U] Run claude update
Zacfuse 🟢 deployed [a] Add project
web │ astro, typescript, docs [e] Edit config
[x] Close Terminal
[Tab] Switch Panel
ACTIVE TERMINALS 1 [?] Help
────── [q] Quit
›[1] Zpit │ 🟡 Waiting for input 00:15
Q: Commit 2198be6 pushed to `origin/dev`, working tre

Press ? for help, q to quit
```

Tab cycles focus between Projects → Active Terminals (when any) → Loop Engine (when any slot exists); Hotkeys stays docked to the right as read-only reference. `↑↓/PgUp/PgDn` scroll the focused panel only; mouse wheel scrolls whichever panel the cursor hovers. Below ~40 cols the left/right widths auto-shrink, but Hotkeys never drops below the other panels.

### Status View

```
Zpit v0.1 03/27 14:04 Windows Terminal

Issues — AI Inspection Cleaning Demo
────────────────────────────────────────────────────────────

› #25 [pending] feat(manual-control): Safety Interlock + Soft Limit + Reset Zero

[y] Confirm (pending→todo) [i] Open in browser [Esc] Back
```

## How It Works

```
You (TUI) Claude Code Agents

├─ [c] Clarify ──────────► Clarifier agent (new terminal)
│ requirement asks questions, creates structured issue
│ (press multiple times) agents auto-discover via agent_type, enter Facilitator/Advisor meeting mode

├─ [l] Loop ──────────────► Coding agent (worktree + new terminal)
│ auto-implement implements, commits, opens PR
│ │
│ └─ PR appears ───► Reviewer agent (same worktree)
│ │ checks AC, writes review report
│ ├─ PASS ────► waits for human merge
│ └─ NEEDS CHANGES → auto-retry coding (up to N rounds)

├─ [s] Status ────────────► shows issue list from tracker
├─ [r] Review ────────────► launches reviewer on demand
├─ [f] Efficiency ────────► lightweight agent (no hooks, no tracker, self-review)
├─ [d] Redeploy ──────────► undeploy + re-write all agents/hooks/docs (no launch)
└─ [Enter] ───────────────► launches Claude Code directly
```

## Features

- **Multi-project dashboard** — switch between projects with arrow keys, mouse scroll support
- **Loop engine** — fully automated: poll todo issues → create worktree → coding agent → reviewer → PR merge → cleanup
- **Task decomposition** — when an Issue Spec contains `## TASKS`, the coding agent delegates to `task-runner` subagents (sequential, or parallel batches with per-subagent `isolation: "worktree"`)
- **Agent monitoring** — real-time status via session log parsing (Working / Waiting / Permission / Ended), auto-detects running sessions on startup, survives `/resume` session switches
- **Notifications** — Windows Toast + sound when an agent needs your input or awaits tool permission
- **Issue tracker integration** — Forgejo/Gitea and GitHub via REST API + MCP
- **Cross-agent channel** — real-time agent-to-agent communication via HTTP broker + MCP; supports same-project, cross-project, and global broadcast messaging
- **Meeting mode** — multiple clarifier agents auto-discover via `agent_type` tracking, assign Facilitator/Advisor roles, and converge to a structured issue through coordinated channel communication
- **5-layer safety system** — agent-guidelines.md, allowed tools, PreToolUse hooks, git worktree isolation, human PR review
- **Per-issue branch control** — clarifier asks target branch, coding agent enforces it
- **Auto-retry** — reviewer judges NEEDS CHANGES → coding agent auto-fixes → re-review (configurable rounds)
- **i18n** — TUI chrome localized to English or Traditional Chinese (zh-TW) via `locale.T()`; all agent output (Issue Specs, commits, PR bodies, channel messages) is always English regardless of TUI locale, for token efficiency
- **Per-role model selection** — `[agent_models]` lets you choose a model per agent role (defaults to Opus across all roles with 1M context, tuned for single-round coding→review accuracy); override any value in config
- **SSH remote access** — `zpit serve` runs a headless SSH daemon (Wish), multiple clients share one dashboard with real-time state sync; `auto_serve` mode starts the server automatically when running `zpit`, enabling seamless mobile access without workflow interruption
- **Desktop agent** — `[w]` launches a global Claude Code session that drives the OS (mouse, keyboard, screenshots, accessibility actions) through a policy-enforced MCP proxy. Backed by [`zpit-desktop-mcp`](https://github.com/zac15987/computer-use-mcp), our fork of [`@zavora-ai/computer-use-mcp`](https://github.com/zavora-ai/computer-use-mcp). Single-instance, macOS + Windows only.

## Session sync (cross-machine /resume)

When you work across multiple machines (laptop at home, desktop at the office) and want to continue a long Claude Code conversation on the other machine, the session JSONL file is the unit of replay — but Claude Code's `~/.claude/projects//` directory uses an OS-specific encoded folder name and embeds the absolute project path inside every session line. A naive file copy is invisible to `claude --resume` on the other side.

Zpit's **`[h] History`** view bridges this. From the main dock press `h` to open the Session Browser:

- Top level: every encoded folder under `~/.claude/projects/`. Each row shows session count, total size, last-modified time, and a 🟢 marker when at least one session is currently alive on this machine.
- Drill into a folder: every `*.jsonl` session with multi-select checkboxes. 🧩 marks sessions that have a sibling `/subagents/` directory; 🟢 marks live sessions.

### Export

In the session list, select one or more sessions with `Space` (or `[a]` to toggle all). Press `[e]` to export. Zpit warns if any selected session is currently active (informational — you can still proceed) and writes a zip bundle containing:

- One `.jsonl` per selected session at the zip root.
- One `/subagents/` subtree per selected session that has subagents on disk (preserved verbatim).
- A `manifest.json` describing the source OS and absolute project path so the importer can rewrite paths.
- Optionally a `memory/` subtree (opt-in via the `[ ] Include memory/` checkbox at export time — off by default to avoid leaking project-private notes).

Default output path: `~/.zpit/exports/-.zip`.

You can also press `[E]` (capital) on a folder row in the top-level view to export every session in that folder in one shot.

### Import

From the top-level folder list, press `[i]` (or select the `[+] Import bundle...` row + Enter) to open the import wizard. Steps:

1. Bundle path entry — type the path to a `.zip` produced by the exporter above.
2. Manifest preview — Zpit reads `manifest.json` and shows source OS, source path, session count, memory inclusion. Per-session checkboxes let you deselect individual sessions.
3. Destination path — type the absolute path of the destination project on this machine.
4. Final preview — Zpit shows the resolved `~/.claude/projects//` and the action plan. Confirm to run.
5. Run — Zpit rewrites `cwd` fields in each session JSONL line to the destination path (only the JSON `cwd` field, never literal path text in chat content), copies subagents verbatim, and optionally writes `memory/` if the bundle included it.

If the destination already has a session with the same ID, you get a 3-button collision modal: **Overwrite**, **Skip this session**, or **Cancel entire import**. The same prompt applies to the `memory/` directory.

After import, `claude --resume ` on this machine sees the new file.

### Bundle format

The zip bundle contains:

```

├── manifest.json # format_version, source_os, source_cwd,
│ # source_encoded_cwd, sessions[], exported_at,
│ # include_memory
├── .jsonl # one per session (lines streamed)
├── /subagents/... # one per session with subagents (verbatim)
└── memory/... # only when include_memory=true
```

`source_cwd` is sourced from any session line's `cwd` field when available; only when no line has one does the exporter fall back to a lossy reverse-derivation of the encoded folder name.

## Requirements

- [Go](https://go.dev/) 1.26+
- [Claude Code](https://claude.ai/code) CLI installed and authenticated
- Windows Terminal (Windows) or tmux (Linux/WSL)
- A Forgejo/Gitea or GitHub issue tracker

## Quick Start

```bash
# Build
go build -o zpit .

# First run — creates config template at ~/.zpit/config.toml
./zpit
# Edit the config with your projects and tracker tokens, then:
./zpit

# SSH server mode (remote access)
./zpit serve # Start headless SSH daemon (default port 2200)
./zpit connect # SSH connect to local server

# Or enable auto_serve in config — then just "./zpit" starts
# the SSH server automatically and connects to it.
# You can SSH in from your phone at any time.
```

## Configuration

Config lives at `~/.zpit/config.toml`. Override with `ZPIT_CONFIG` env var.

```toml
language = "en" # en | zh-TW
broker_port = 17731 # HTTP broker port for cross-agent channel
# zpit_bin = "/usr/local/bin/zpit" # explicit binary path for .mcp.json generation

[terminal]
windows_mode = "new_tab" # new_tab | new_window
tmux_mode = "new_window" # new_window | new_pane
# windows_terminal_profile = "PowerShell 7" # WT profile name for -p flag

[notification]
tui_alert = true
windows_toast = true
sound = true
# sound_file = "D:/sounds/notify.mp3" # custom notification sound (WAV/MP3/M4A/OGG)
re_remind_minutes = 2

[worktree]
base_dir_windows = "D:/worktrees"
base_dir_wsl = "/mnt/d/worktrees"
max_per_project = 5
poll_seconds = 10 # todo issue polling interval
pr_poll_seconds = 10 # PR merge polling interval (only used when auto_merge = false)
max_review_rounds = 3 # auto-retry rounds before needs-human
# dir_format = "{project_id}/{issue_id}--{slug}"
# auto_cleanup = false

# Per-role model selection — passed to Claude Code via --model at launch.
# Aliases (opus/sonnet/haiku) resolve per provider; append [1m] to opt
# into the 1M-context tier. Pin to a full ID (e.g. claude-opus-4-7[1m])
# if you need cross-provider consistency.
[agent_models]
clarifier = "opus[1m]" # requirement clarification — deepest reasoning (1M context)
coding = "opus[1m]" # feature implementation (1M context)
reviewer = "opus[1m]" # PR review (1M context)
task_runner = "opus[1m]" # advisory — subagents inherit the coding session's model
efficiency = "opus[1m]" # efficiency-review agent (manual [f]) — deep reasoning

# Tracker providers — token read from env var, never stored in config
[providers.tracker.my-forgejo]
type = "forgejo_issues"
url = "https://your-forgejo.example.com"
token_env = "FORGEJO_TOKEN"

# Git providers (optional — for Forgejo/Gitea PR API)
# [providers.git.my-forgejo]
# type = "forgejo"
# url = "https://your-forgejo.example.com"
# token_env = "FORGEJO_TOKEN"

# Projects
[[projects]]
name = "My Project"
id = "my-project"
profile = "machine" # display tag: machine | desktop | web | android | terminal (for TUI icon)
hook_mode = "strict" # strict | standard | relaxed
log_policy = "standard" # strict | standard | minimal — agent logging strictness
tracker = "my-forgejo"
# tracker_project = "My_Project" # tracker project name if different from repo
# git = "my-forgejo" # git provider for PR operations
repo = "org/repo"
base_branch = "dev"
channel_enabled = false # enable cross-agent channel communication
channel_listen = [] # subscribe to other projects' events, e.g. ["_global", "other-proj"]
# auto_merge = false # when true, Zpit calls the tracker merge API after ai-review PASS (opt-in)
# merge_method = "squash" # squash | merge | rebase (used when auto_merge = true)
tags = ["go"]

[projects.path]
windows = "D:/Projects/my-project"
wsl = "/mnt/d/Projects/my-project"

# SSH server (optional — for remote TUI access)
# [ssh]
# port = 2200
# host = "0.0.0.0"
# host_key_path = "~/.zpit/ssh/host_ed25519"
# password_env = "ZPIT_SSH_PASSWORD"
# authorized_keys_path = "~/.ssh/authorized_keys"
# auto_serve = false # when true, "zpit" auto-starts SSH server + connects
```

## Hotkeys

| Key | Action |
|-----|--------|
| `Enter` | Launch Claude Code in new terminal |
| `c` | Clarify — open clarifier agent to create structured issue |
| `l` | Loop — toggle automated coding + review cycle |
| `r` | Review — launch reviewer agent |
| `f` | Efficiency — lightweight agent (no hooks, no tracker, self-review) |
| `s` | Status — view issue list from tracker |
| `o` | Open project folder |
| `i` | Open issue tracker in browser |
| `p` | Open pull request in browser (in Loop Slot focus: the slot's PR; falls back to `/pulls?head=` if not yet open) |
| `u` | Undeploy — remove deployed agents, docs, hooks |
| `d` | Redeploy — undeploy then re-write all 4 agents + hooks + docs (no Claude launch) |
| `m` | Channel — view cross-agent communication events |
| `g` | Git Status — view branches (local + remote-only) and commit graph; [f] fetch, [p] pull (--ff-only) |
| `G` | Open lazygit in new terminal (project root; in Loop Slot focus: slot's worktree) |
| `U` | Run `claude update` in new terminal (stays open to show result) |
| `a` | Add project (coming soon) |
| `e` | Edit config — sub-menu: toggle channel, edit channel_listen, open in $EDITOR |
| `w` | Window — launch desktop agent (macOS + Windows only; single instance across all clients) |
| `x` | Close Terminal — force-close selected terminal (when Terminals panel focused) |
| `Tab` | Switch focus between panels (Projects, Terminals, Loop Slots) |
| `?` | Help |
| `q` | Quit |

## Loop Engine

The loop engine automates the full coding cycle:

1. **Poll** tracker for `todo` issues (configurable interval)
2. **Create worktree** — isolated git worktree from `base_branch`
3. **Launch coding agent** — writes implementation, commits, opens PR, sets `review` label
4. **Detect completion** — polls issue labels for `review` (agents don't need to exit)
5. **Launch reviewer** — checks acceptance criteria, writes review report, sets verdict label
6. **Detect verdict** — polls issue labels for `ai-review` (PASS → wait for human merge) or `needs-changes` (auto-retry up to `max_review_rounds`)
7. **Cleanup** — after PR merge, removes worktree and branch

Multiple issues run in parallel, limited by `max_per_project`.

## Safety System

Zpit enforces 5 layers of safety to prevent agents from causing damage:

| Layer | Mechanism | Scope |
|-------|-----------|-------|
| 1 | agent-guidelines.md behavioral rules | Soft — agent reads on startup |
| 2 | `--allowedTools` per agent role | Medium — Claude Code enforced |
| 3 | PreToolUse hooks | Hard — enforced even with `--bypass-all-permissions` |
| 4 | Git worktree isolation | Physical — agents can't touch main repo |
| 5 | Final merge gate (conditional) | When `auto_merge = false` (default): human PR review is the final gate. When `auto_merge = true`: the AI reviewer's `ai-review` PASS label replaces the human gate and triggers the tracker's merge API. Only enable `auto_merge` when you trust the reviewer model quality on your repo. |

**PreToolUse hooks:**
- `path-guard.sh` — confines Write/Edit to worktree directory
- `bash-firewall.sh` — blocks destructive commands (rm -rf, curl|bash, force push, etc.)
- `git-guard.sh` — push whitelist (only `feat/*` branches), blocks merge, rebase, branch-delete, force push

**Notification hook:**
- `notify-permission.sh` — writes signal file when Claude Code needs tool permission approval; TUI detects and shows 🟠 status + toast notification

Hook strictness is per-project: `strict` (all hooks), `standard` (path-guard + git-guard), `relaxed` (git-guard only). Notification hook is always active in all modes.

## Issue Spec Format

The clarifier agent produces structured issues:

```markdown
## CONTEXT
[Problem description with specific file names and behavior]

## APPROACH
[Selected solution + reasoning]

## ACCEPTANCE_CRITERIA
AC-1: [Specific, verifiable condition]
AC-2: ...

## SCOPE
[modify] path/to/file (reason)
[create] path/to/new-file (reason)

## CONSTRAINTS
[Hard limits]

## BRANCH
[Optional: PR target branch, defaults to project base_branch]

## TASKS
[Optional: Task decomposition — triggers subagent delegation]
T1: [task description] | [modify] path/to/file
T2: [task description] [P] | [modify] path/to/other # [P] = parallelizable
T3: [task description] [depends:T1] | [create] path/to/new

## COORDINATES_WITH
[Optional: Cross-agent coordination for parallel work]
#42: Brief description of related issue

## REFERENCES
[Optional: URLs, related files]
```

## Development

```bash
go build ./... # Build
go test ./... # Run all tests
make test-hooks # Run hook tests (requires bash)
go run . # Local TUI (or auto-serve if ssh.auto_serve=true)
go run . serve # SSH server mode
go run . connect # SSH client shortcut
```

Logs: `~/.zpit/logs/zpit-YYYY-MM-DD.log` — daily rotation, 30-day retention.

## Desktop Agent

Press `[w]` from the main view to launch the desktop agent — a standalone Claude Code session that controls the operating system (mouse, keyboard, screenshots, window/app management, accessibility actions). Unlike project-scoped agents, it is global (cwd = `$HOME` / `%USERPROFILE%`) and limited to one active instance across all connected TUI clients.

The desktop agent is backed by [`zpit-desktop-mcp`](https://github.com/zac15987/computer-use-mcp) — our fork of [`@zavora-ai/computer-use-mcp`](https://github.com/zavora-ai/computer-use-mcp) by [James Karanja Maina / zavora.ai](https://zavora.ai). The fork adds Windows AUMID launch support in `open_application`, a stdio-entrypoint fix for Windows backslash paths, and tracks the upstream `@modelcontextprotocol/sdk` Zod 4 bump. Many thanks to the upstream authors — none of this would exist without their original work.

Safety is enforced by `zpit serve-desktop-proxy`, a Go MCP proxy that sits between Claude Code and the `npx zpit-desktop-mcp` subprocess. Every JSON-RPC `tools/call` frame is intercepted, evaluated against `~/.zpit/desktop-policy.toml` (auto-created on first run), and either forwarded or rejected with a structured error. Hard-blocked tools include `run_script`, `filesystem`, `process_kill`, `registry`, `notification`, and all virtual-desktop tools; `deny_keys` blocks OS-level escape hatches like `win+r`, `ctrl+alt+del`, and `alt+f4`. The conventional 5-layer hook stack does **not** apply to the desktop agent — the proxy is the safety layer.

Platform support: macOS and Windows. On Linux, `[w]` is a no-op (the upstream Rust NAPI module has no Linux backend).

See [docs/architecture/desktop-agent.md](docs/architecture/desktop-agent.md) for the full design rationale (why proxy over hooks, tool-by-tool allowlist justification, default `deny_keys` per platform).

## Architecture

See [docs/architecture/](docs/architecture/) for the full architecture documents (split by topic, with an [index](docs/architecture/README.md)).

## Open Source Attributions

Zpit is built on top of the following open source libraries:

| Library | Purpose | License |
|---------|---------|---------|
| [Bubble Tea](https://github.com/charmbracelet/bubbletea) | TUI framework | MIT |
| [Bubbles](https://github.com/charmbracelet/bubbles) | TUI components (list, text input, etc.) | MIT |
| [Lip Gloss](https://github.com/charmbracelet/lipgloss) | TUI styling and layout | MIT |
| [Huh](https://github.com/charmbracelet/huh) | Form and confirm dialogs | MIT |
| [Wish](https://github.com/charmbracelet/wish) | SSH server for TUI remote access | MIT |
| [BurntSushi/toml](https://github.com/BurntSushi/toml) | TOML config parser | MIT |
| [fsnotify](https://github.com/fsnotify/fsnotify) | Filesystem watcher (session log monitoring) | BSD-3-Clause |
| [go-colorful](https://github.com/lucasb-eyer/go-colorful) | Color math for terminal rendering | MIT |
| [muesli/termenv](https://github.com/muesli/termenv) | Terminal environment detection | MIT |
| [rivo/uniseg](https://github.com/rivo/uniseg) | Unicode text segmentation | MIT |
| [mattn/go-runewidth](https://github.com/mattn/go-runewidth) | Rune display width calculation | MIT |
| [bubbletea-overlay](https://github.com/rmhubbert/bubbletea-overlay) | Overlay rendering for confirm dialogs | MIT |
| [golang.org/x/sys, x/text](https://pkg.go.dev/golang.org/x) | Go extended standard library | BSD-3-Clause |

All Charmbracelet libraries (`bubbletea`, `bubbles`, `lipgloss`, `huh`, `wish`, `ssh`) are copyright © Charmbracelet, Inc., licensed under the MIT License.
`fsnotify` and `golang.org/x/*` are BSD-3-Clause; their copyright notices are retained as required.

### Desktop agent — upstream credit

The [`[w]` desktop agent](#desktop-agent) is backed by [`zpit-desktop-mcp`](https://github.com/zac15987/computer-use-mcp), our fork of [`@zavora-ai/computer-use-mcp`](https://github.com/zavora-ai/computer-use-mcp) (forked at v6.1.0). The original `computer-use-mcp` package — including the Rust NAPI native backend, the MCP server scaffolding, and the full macOS + Windows toolset — is the work of [James Karanja Maina](mailto:james@zavora.ai) / [zavora.ai](https://zavora.ai), released under the MIT License. Zpit's fork adds Windows AUMID launch support, the stdio-entrypoint backslash fix, and the SDK Zod 4 bump; everything else is upstream. Sincere thanks to the zavora.ai team for making this layer of zpit possible.

| Package | Purpose | License |
|---------|---------|---------|
| [`zpit-desktop-mcp`](https://github.com/zac15987/computer-use-mcp) (zpit fork) | Desktop-control MCP server for the `[w]` agent | MIT |
| [`@zavora-ai/computer-use-mcp`](https://github.com/zavora-ai/computer-use-mcp) (upstream) | Original MCP server + Rust NAPI native backend | MIT |

## License

MIT