{
  "markdown": "# Unterm\n\n**The terminal AI agents can drive.**\n\n![Agent Cockpit: three agents working, the Inbox surfaces the one that needs you, Enter jumps to it](assets/demo/agent-cockpit.gif)\n\nCross-platform terminal (macOS / Linux / Windows) built on Unterm's native\n`next-core` terminal engine, with one design bet: the terminal itself is\ncontrollable from the outside by any AI agent over MCP. Claude Code, Codex,\nGemini CLI, Cursor, Aider, your own scripts — they all get the same JSON-RPC\nsurface (**149 authenticated methods plus `auth.login`**) to spawn shells, run\ncommands, read pane state, capture screenshots, change settings, and record\nsessions.\n\nSince v0.68 the terminal is also something an orchestrator can govern rather than merely call: it publishes what it can do and how dangerous each capability is, works under leases that expire and cannot be replayed, keeps agents inside workspaces that cannot see each other, and can hand you an evidence bundle for a task that somebody who was not there can verify.\n\nSince v0.55 the relationship runs both ways: agents drive the terminal from outside, and the terminal is an **Agent Cockpit** for the agents running inside it — live per-pane agent state, a waiting-first Inbox, fleets of N agents on one task in N isolated git worktrees, and a Review page to diff / merge / roll back what they produced.\n\nThe other 2026 terminals each pick a different side: Warp embeds AI inside a closed cloud (Oz), Ghostty stays out of your way and lets you bring your own tools, iTerm2 is Mac-only. Unterm picks the third side — terminal as MCP-controllable surface, deliberately keep AI *generation* out of the terminal, let external agents grip it through the API, and give the human one cockpit to run them all from.\n\nPractical implications:\n\n- Every Unterm window starts a local **MCP server** (line-delimited JSON-RPC over TCP) and a local **HTTP settings server** (Web Settings page) on auto-allocated ports. Both are auth-token gated, both are 127.0.0.1-only, no cloud round trip.\n- **Settings live in the browser**, not the terminal. Cell-grid TUIs can't deliver modern form UX (no proper text inputs, no live preview, no color picker). The in-terminal `▼` menu holds quick actions and links out to the Web Settings page — configuration itself happens in the browser.\n- **9 languages out of the box**: en / 简体中文 / 繁體中文 / 日本語 / 한국어 / Deutsch / Français / Italiano / हिन्दी. Auto-detects from system locale, can be overridden in Web Settings or via `unterm-cli lang set <code>`.\n- **Multi-instance discovery**: every running Unterm process owns one NATO-named instance (alpha, bravo, charlie…) and writes its ports + auth token to `~/.unterm/instances/<name>.json`. Agents that drive several windows at once enumerate that directory.\n- **Cross-platform parity is a correctness property**: if a feature works on Windows but bails on macOS or Linux, that's a bug, not \"not supported yet.\"\n- **Subtraction over decoration**: no AI chat overlay inside the terminal and\n  no cloud dependency for core operation. Proxy settings auto-detect the\n  system by default and also support explicit HTTP/SOCKS overrides, node pools,\n  rotation, and Clash/mihomo controllers. Finder integration on macOS uses the\n  native Finder right-click extension and Services.\n\nThe GUI and terminal runtime now use Unterm's native `next-core` engine. The\nrepository still carries selected upstream components and attribution where\nthey remain dependencies, but WezTerm mux/window state is no longer the\nproduct kernel.\n\n---\n\n## Agent Cockpit\n\nRun Claude Code, Codex, Gemini CLI, or Aider in any pane and Unterm sees them — no configuration, no wrapper. Five pillars, all local:\n\n- **Agent state engine** — every pane's agent and its state (working / waiting-for-you / idle / done), read from OSC progress + title signals, process fingerprints, and optional official hooks. Tab badges + a cross-window tally chip in the top bar.\n- **Inbox** (`Ctrl+Shift+A`) — every agent that's waiting for you in one queue, longest-waiting first. Enter jumps to the pane; one keystroke later you've answered its prompt.\n- **Fleet** — one task × N agents × N isolated git worktrees (`../<repo>.fleet/`), one tab each. Same agent ×3 for throughput, or `claude,codex,gemini` for a bake-off.\n- **Review** — agents get checkpointed before they touch a repo (dangling-commit snapshots; nothing touches your HEAD or index). A Web Review page shows per-member diffs with squash-merge (stops at staged — the commit stays yours), discard, and rollback. Since v0.57, Review also **verifies** each member (inferred or explicit validation command), **ranks** members by verification + change size, gates merge on a passing run, and can **retry** a failed member in its existing worktree.\n- **Everything scriptable** — the cockpit itself is MCP + CLI: `agent.status`, `cockpit.inbox`, `fleet.launch`, `review.merge`… an orchestrating agent can run fleets and review diffs with no human in the chair.\n\n```bash\nunterm-cli agent status                                  # who's running where, in what state\nunterm-cli agent inbox                                   # who's waiting for you\nunterm-cli agent enable-hooks                            # exact state via official hooks (merge-only, backed up)\nunterm-cli fleet launch --agents claude,codex \"fix the flaky auth test\"\nunterm-cli review verify --fleet <id> --member 1         # run the member's validation\nunterm-cli review list && unterm-cli review open         # ranked diffs in the browser\n```\n\nFull docs: [unterm.app/docs/agent-cockpit](https://unterm.app/docs/agent-cockpit).\n\n---\n\n## Install\n\nPre-built artifacts are published on GitHub Releases:\n\nhttps://github.com/zhitongblog/unterm/releases\n\n| Platform | Artifact                                                    |\n| -------- | ----------------------------------------------------------- |\n| macOS    | `Unterm-macos-<version>.dmg` (universal arm64+x86_64, signed + notarized) |\n| Linux    | `unterm-<version>.deb` or `Unterm-<version>-x86_64.AppImage` |\n| Windows  | `Unterm-<version>-x64.msi` or `Unterm-windows-x64-<version>.zip` |\n\n### macOS\n\nDouble-click `Unterm-macos-<version>.dmg`, then drag `Unterm.app` onto the\n`Applications` shortcut. The DMG is signed with a Developer ID and Apple-\nnotarized, so Gatekeeper opens it on first launch without warnings.\n\nFinder integration is bundled in the DMG. After the first launch, Finder's\nright-click menu can show `Open in Unterm` for folders and files; if macOS\ndoesn't refresh the extension immediately, run `Repair Finder Integration.app`\nfrom the DMG once.\n\n### Linux (Debian / Ubuntu)\n\n```bash\nsudo apt install ./unterm-<version>.deb\nunterm\n```\n\nOther distros — use the AppImage:\n\n```bash\nchmod +x Unterm-<version>-x86_64.AppImage\n./Unterm-<version>-x86_64.AppImage\n```\n\n### Windows\n\nRun the MSI installer; it places `unterm.exe` in `Program Files\\Unterm` and creates a Start Menu shortcut.\n\n---\n\n## What's new\n\n- **v0.68 — A terminal something else can govern.** Unterm now hosts CLI\n  agents as sessions rather than shelling out and waiting for an exit code\n  (`agent_session.*`: what it said, what it asked to run, how it ended,\n  with your own task ids carried through untouched). It can lease a browser\n  from Unzoo and be leased *from* in turn — `terminal.manifest` publishes\n  what this terminal can do and how dangerous each family is, taken from the\n  same table the gateway refuses by. Approvals can finally be answered:\n  Settings shows what an agent is waiting on, with \"allow once / for this\n  task / always\". Workspaces are roots that cannot see each other, and a\n  shell that `cd`s out stops being inside. The audit trail is hash-chained,\n  so an edit to it disagrees with the next line. `unterm-cli provider |\n  scope | artifact | evidence | system` — 46 new MCP methods (149 total).\n- **v0.57 — Fleet verification loop + new brand mark.** Review now verifies each fleet member automatically (Cargo / Go / npm / pnpm / yarn / Python / Maven / Gradle / .NET inferred, or your own command), ranks members by verification and change size, gates squash-merge on a passing run (audited `force` override), and retries failed members in their existing worktree without losing work — `review.verify` / `fleet.retry` over MCP + CLI. The sidebar gains repository-grouped navigation with always-on fuzzy search. Every logo surface moves to the new command-loop mark.\n- **v0.55 — Agent Cockpit.** The terminal now sees the agents inside it: live per-pane state with tab badges and a cross-window tally, the waiting-first Agent Inbox (`Ctrl+Shift+A`), fleets running one task across N agents in N isolated worktrees, and a Review page with checkpoints, diffs, rollback, and squash-merge. 12 new MCP methods, 3 new CLI families.\n- **v0.54 — 2.8× faster cold start** (~780ms → ~280ms) via five startup-path wins, and no more CPU core burned on Windows output floods (~91% → ~4%); MCP stays responsive mid-flood.\n- **v0.53 — Composer + Git panel.** A prompt queue (`Ctrl+Shift+J`) that runs batched prompts into an agent pane with smart auto-advance through confirmation prompts, and a read-only Git status panel (`Ctrl+Shift+G`).\n- **v0.52 — More agents out of the box.** Kimi Code CLI and Trae Agent join the baked manifest (7 agent CLIs total); reworked per-frame paint paths; steadier Windows clipboard and window sizing.\n\n---\n\n## Documentation\n\nThe full Unterm docs live at **https://unterm.app/docs/**:\n\n- [Agent Cockpit](https://unterm.app/docs/agent-cockpit) — agent state engine, Inbox, Fleet, Review: run and supervise CLI agents from one terminal\n- [Agent integration](https://unterm.app/docs/agent-integration) — how to drive Unterm from Claude Code / Cursor / Aider / your own client\n- [Agent recipes](https://unterm.app/docs/agent-recipes) — copy-paste patterns for common agent-drives-terminal workflows\n- [Product roadmap](https://unterm.app/docs/product-roadmap) — the five directions we are executing now\n- [Product requirements](docs/product-requirements.md) — complete product scope, functional requirements, MCP/CLI coverage, and acceptance criteria\n- [Detailed product planning](docs/product-planning-detailed-zh.md) — Chinese execution plan covering user scenarios, version roadmap, priorities, validation, and next-core migration\n- [Next-core product plan](docs/product-plan-next-core.md) — staged plan to stabilize the current engine while building Unterm's own terminal core\n- [Next-core technical architecture](docs/next-core-technical-architecture-zh.md) — Chinese architecture plan for replacing the WezTerm core without growing into a larger terminal monolith\n- [MCP reference](https://unterm.app/docs/mcp-reference) — every JSON-RPC method, parameters, return shape\n- [Multi-instance](https://unterm.app/docs/multi-instance) — NATO names, instances directory, picking the right window\n- [Identity profiles](https://unterm.app/docs/profiles) — one window per identity. Bind GitHub / AWS / npm / OpenAI tokens, git identity, SSH key routing all at once. CLI + MCP.\n- [CLI reference](https://unterm.app/docs/cli-reference) — `unterm-cli` subcommands, flags, exit codes\n- [Configuration](https://unterm.app/docs/configuration) — every file under `~/.unterm/`\n- [Architecture](https://unterm.app/docs/architecture) — what we forked from WezTerm and why\n\nThis README is the short version. The site is the long version.\n\n---\n\n## Features\n\n- **GPU-accelerated rendering** on all three platforms (Metal / OpenGL / DirectX via ANGLE).\n- **MCP server** on `127.0.0.1:<auto-port>` (default 19876) —\n  line-delimited JSON-RPC over TCP, loopback-only and auth-token gated. It\n  exposes 149 authenticated methods plus `auth.login`; `meta.surface` (or\n  `unterm-cli reference`) returns the authoritative live inventory in one\n  call.\n- **Agent Cockpit** — per-pane agent state, waiting-first Inbox, worktree fleets, checkpoint + review. See the section above.\n- **Governed agent work** — one gateway every door goes through (MCP, CLI,\n  brain, workflow, raw PTY write), capability leases with expiry and replay\n  protection, workspaces that cannot see each other, a hash-chained audit\n  trail, and evidence bundles somebody else can verify. An agent cannot drive\n  a browser around the front door: raw CDP, Playwright, Puppeteer and\n  Selenium are refused inside a managed session, with the supported path\n  named in the refusal.\n- **Web Settings UI** on `127.0.0.1:<auto-port>` (default 19877) — open in any browser via `unterm-cli settings open` or the `Settings (Web)` item in the `▼` menu. Tailwind-styled SPA, supports all 9 languages, keyboard + mouse.\n- **Proxy management** — reads macOS System Preferences / Windows registry /\n  GNOME gsettings / proxy environment variables, and falls back to common\n  local ports. `~/.unterm/proxy.json` also persists manual HTTP/SOCKS URLs,\n  `no_proxy`, named nodes, rotation, and Clash/mihomo controller settings.\n- **Region screenshots** from the status bar (left-click excludes the Unterm window, right-click includes it). PNG lands on disk under `~/.unterm/screenshots/`, on the system image clipboard, and the path on the text clipboard.\n- **Scrolling (long) screenshots**, both directions: `capture.scrollback` re-renders a pane's *entire* history into one tall PNG headlessly (exact fonts/theme, streaming-encoded, works while occluded); `capture.window_scroll` long-shots *another app's* window by synthesizing wheel events and stitching frames via row-hash matching with sticky-header/footer detection (macOS). Both also in the `▼` menu and `unterm-cli screenshot --scrollback / --scroll-app`.\n- **Session recording → markdown** with OSC 133 block segmentation and built-in redaction (GitHub tokens / `KEY=value` / 40+ char hex/base64 patterns are masked). Recordings are stored in the project directory under `<cwd>/.unterm/sessions/<date>/<tab>-<time>.md`, or in `~/.unterm/sessions/_orphan/` when no writable project context.\n- **Right-click in the terminal is a direct gesture**: with a selection it copies and clears; without selection it pastes. On the tab strip, right-click opens the tab context menu (new tab, split, rename, move, close) instead — chrome right-clicks never fall through to paste.\n- **Quick menu** on the tab bar's `▼` button, with live key chords from the binding table:\n  - New Tab / Split Right\n  - Directory Jump (cd current pane or open in new tab) / File Tree\n  - Git Panel / Toggle Left Tab Strip\n  - Find / Command Palette\n  - Toggle Session Recording / Export Current Session / Scrollback Long Screenshot\n  - Settings (Web), plus the version/website row\n- **macOS-native window decorations** (traffic-light buttons + native title bar); Windows uses Windows Terminal-style integrated title buttons; Linux uses client-side decorations.\n\n---\n\n## Identity profiles\n\nBind a window to a coherent developer identity — GitHub PAT, AWS keys, npm token, git author, SSH keys — all in one shot. New window for a different identity. The chip in the tab bar tells you which one you're in. Secrets live in the OS-native vault (Keychain / Credential Manager / Secret Service), never in `~/.unterm/`.\n\n```bash\nunterm-cli profile create \"Work — Acme\"\nunterm-cli profile set-secret \"Work\" GITHUB_TOKEN\nunterm-cli profile spawn \"Work\"           # → new window bound to Work\nunterm-cli profile set-default \"Work\"     # plain `unterm` now binds to Work\nunterm-cli profile import                 # scans gh/aws/npm/ssh/docker/gcloud/netrc\n                                          #   for existing credentials, read-only\n```\n\nInside a profile-bound shell:\n\n```bash\n$ env | grep UNTERM_PROFILE\nUNTERM_PROFILE=work-acme\n# GITHUB_TOKEN, GIT_AUTHOR_NAME, AWS_*, etc. all set from the profile\n```\n\nFull docs: [unterm.app/docs/profiles](https://unterm.app/docs/profiles).\n\n## Multi-instance\n\nEvery running Unterm process is one **instance** with a NATO-phonetic name: `alpha`, `bravo`, `charlie`, … `zulu`. The first window claims `alpha`, the second `bravo`, etc. When all 26 are taken at once, the next one wraps to `alpha2`. Names are easy to pronounce and AI agents handle them right — no UUIDs, no ports in your head.\n\nEach GUI instance writes its metadata (mcp_port, http_port, auth_token, pid, started_at, version, platform) to `~/.unterm/instances/<name>.json`. Agents that need to drive a specific instance enumerate that directory and pick by id, cwd, or title.\n\nThe headless Core writes `core.json` to its **platform data directory** — `%LOCALAPPDATA%\\Unterm` on Windows, `~/.local/share/Unterm` on Linux, `~/Library/Application Support/Unterm` on macOS — not to `~/.unterm`. (`UNTERM_STATE_DIR` overrides both, which is how the two got confused: every test that set it saw them agree.) `unterm-cli mcp-stdio` and MCP-backed CLI commands prefer that Core record so terminal sessions keep working across GUI restarts, and it is on `instance.list` as the instance `core` when no window is open — `unterm-cli --instance core` reaches it.\n\nAn instance is a front end, not a window: since v0.68 one process holds several windows, each with an id of its own. `instance.windows` lists them, `instance.new_window` opens one and returns its id, and `instance.focus` takes one.\n\nFor old single-target agents, `~/.unterm/active.json` points at the current live GUI instance, and `~/.unterm/server.json` mirrors that same record for backward compat.\n\nThe MCP `instance.*` namespace exposes this directly: `instance.list`, `instance.info`, `instance.set_title`, `instance.focus`. See [the multi-instance docs](https://unterm.app/docs/multi-instance) for examples and the discovery protocol.\n\n---\n\n## CLI\n\nThe `unterm-cli` binary exposes the full Unterm product surface, transparently routing to the local MCP server. New integrations should use `unterm-cli mcp-stdio` or `unterm-cli` directly; they resolve `core.json`, live GUI instance records, and legacy files in the right order. Scripts that bypass the CLI can read `core.json` in the Core's platform data directory (`%LOCALAPPDATA%\\Unterm`, `~/.local/share/Unterm`, `~/Library/Application Support/Unterm`) for the Core MCP endpoint, `~/.unterm/instances/<name>.json` for a specific GUI instance, or `~/.unterm/server.json` for the legacy active-GUI pointer. Note the two directories are different: only the Core's record lives outside `~/.unterm`.\n\n```bash\n# Settings + Web UI\nunterm-cli settings open                       # open the Web Settings page\nunterm-cli theme list / set <id>               # standard / midnight / daylight / classic / notion-dark / notion-light\nunterm-cli lang list / set <code> / current    # en-US / zh-CN / zh-TW / ja-JP / ko-KR / de-DE / fr-FR / it-IT / hi-IN\n\n# Proxy\nunterm-cli proxy status                        # auto-detect health\nunterm-cli proxy nodes / switch <name> / disable / env / rotation\n\n# Agent Cockpit\nunterm-cli agent status                        # per-pane agent state (working/waiting/idle/done)\nunterm-cli agent inbox                         # agents waiting for you, longest first\nunterm-cli agent enable-hooks [--dry-run]      # wire Claude Code / Codex / Aider lifecycle hooks\nunterm-cli fleet launch --agents claude,codex \"task\"   # N agents × N worktrees, one tab each\nunterm-cli fleet list / clean\nunterm-cli review list / diff / merge / discard / rollback\nunterm-cli review open                         # Review page in the browser\n\n# Capability providers — the browser and anything else outside this process\nunterm-cli provider list                       # what can be reached, and what conflicts\nunterm-cli provider bind unzoo                 # contact it; the first bind pins who answered\nunterm-cli provider diagnose unzoo             # handshake, lease, evidence, idempotency, replay\nunterm-cli provider acquire browser --ttl 300  # ask for a lease; answers `waiting` when it is not there\nunterm-cli provider call <lease> tab_list --seq 1 --capability browser\nunterm-cli provider chain <lease>              # lease → grant → approval → the calls made under it\nunterm-cli provider approvals                  # what is waiting on you (answer these in Settings)\nunterm-cli provider pause / resume / unbind / revoke <lease>\n\n# Workspaces — named roots that cannot see each other\nunterm-cli scope create alpha ~/code/alpha\nunterm-cli scope check <workspace> <path> [--access write]\nunterm-cli scope list / archive <workspace>\n\n# What tasks produced, and proving it to somebody who was not there\nunterm-cli artifact list [--task <id>] / usage / verify <id> / forget <id>\nunterm-cli evidence export <task> ./bundle     # the whole story as plain files + hashes\nunterm-cli evidence verify ./bundle            # recomputes; does not take your word for it\nunterm-cli evidence audit                      # walk the audit hash-chain, report the first break\n\n# The processes, and the data behind them\nunterm-cli system status                       # core / gui / mcp, and \"can work without a window\"\nunterm-cli system diagnostics [--out FILE]     # redacted: versions and health, no tokens or paths\nunterm-cli system snapshot / snapshots / restore <id>\nunterm-cli system upgrade --live X --staged Y --to 0.69.0   # rolls back if the new one does not answer\nunterm-cli system installs                     # every copy on this machine, and which ones fight\nunterm-cli system uninstall-plan [--remove-data]            # describes; never removes\n\n# Sessions / panes\nunterm-cli session list                        # list panes in active/latest instance\nunterm-cli instance list                       # discover alpha/bravo/... windows\nunterm-cli --instance bravo session list       # pin a command to one window\nunterm-cli session create [--cwd DIR] [-- CMD] # spawn a new tab\nunterm-cli --json session create -- pwsh.exe -NoLogo -NoProfile -Command \"Write-Output ok\"\nunterm-cli session record start [--id N]\nunterm-cli session record stop [--id N]\nunterm-cli session export [--id N] [-o FILE]\nunterm-cli sessions list [--project SLUG]\nunterm-cli sessions read <session-id>\n\n# Screenshots\nunterm-cli screenshot [--include-window] [-o FILE]\n# Long screenshot of a pane's ENTIRE scrollback (headless re-render -> tall PNG)\nunterm-cli screenshot --scrollback [--pane N] [--max-rows N] [-o FILE]\n# Long screenshot of ANOTHER app's window: scroll + stitch (macOS)\nunterm-cli screenshot --scroll-app Safari [--scroll-title SUBSTR] [--max-frames N] [-o FILE]\n```\n\nPass `--json` to any subcommand for raw JSON-RPC output (suitable for scripts); place it before `-- CMD` so it is parsed by `unterm-cli`, not the child command. `session create` preserves multi-token commands as argv, while a single command string still runs through the platform shell. Pass `--lang <code>` to override the locale for one invocation. Pass `--instance <id>` (or set `UNTERM_INSTANCE=<id>`) when several Unterm windows are open and you need a deterministic target.\n\nMulti-instance discovery is available through MCP and CLI: call\n`instance.list`, run `unterm-cli instance list`, or inspect\n`~/.unterm/instances/`.\n\n## AI agent auto-discovery\n\nUnterm makes every AI coding agent on the machine aware of it, so they can drive the terminal without manual setup. On first launch (per version) the GUI runs `unterm-cli setup-ai`, which detects installed agents — **Claude Code, Codex, Gemini CLI, Cursor, Windsurf, OpenCode** — and, for each:\n\n- registers the `unterm` MCP server into the agent's *global* config (merging into existing config, never clobbering), so the agent can list/run/read/screenshot the real terminal the moment it starts;\n- drops a short, marker-delimited Unterm note into the agent's global context file (`CLAUDE.md` / `AGENTS.md` / `GEMINI.md`) so even an agent that never loads the MCP server knows Unterm is here.\n\nThe registered bridge (`unterm-cli mcp-stdio`) self-discovers the live control server at connect time, preferring `unterm-core` and falling back to GUI instance records, so a static registration keeps working across restarts and multiple windows. Agents that connect also receive a usage brief via the MCP `initialize` `instructions` field.\n\n```bash\nunterm-cli setup-ai              # detect agents + register (idempotent; safe to re-run)\nunterm-cli setup-ai --dry-run    # show what would change, write nothing\nunterm-cli setup-ai --no-context # register the MCP server only, don't touch context files\nunterm-cli setup-ai --remove     # undo: strip the server entry + context block from every agent\n```\n\n---\n\n## Configuration\n\nUser config lives at:\n\n| Platform | Location                                 |\n| -------- | ---------------------------------------- |\n| macOS    | `~/.unterm/`                             |\n| Linux    | `~/.unterm/`                             |\n| Windows  | `%USERPROFILE%\\.unterm\\`                 |\n\nFiles:\n\n| File                         | Purpose                                          |\n| ---------------------------- | ------------------------------------------------ |\n| `core.json`                  | Headless Core endpoint + auth token + pid (preferred for MCP-backed automation) |\n| `server.json`                | Active GUI instance's MCP/HTTP ports + auth token + pid (auto, mirrors the active GUI for back-compat) |\n| `active.json`                | Pointer at the current active GUI instance id (auto, updated only when previous active dies) |\n| `instances/<name>.json`      | Per-instance metadata (NATO id, ports, token, pid, started_at, version, platform) |\n| `auth_token`                 | Legacy mirror of the active auth token (for back-compat) |\n| `proxy.json`                 | Auto/manual proxy URLs, exclusions, nodes, rotation, and Clash controller state |\n| `theme.json`                 | Active theme id                                  |\n| `lang.json`                  | Persisted locale override                        |\n| `compat.json`                | `{\"term_program\": \"...\"}` override for `$TERM_PROGRAM` |\n| `scrollback.json`            | Override the default scrollback line count       |\n| `update_check.json`          | Background update-poller state (last check, latest seen version) |\n| `onboarded.json`             | First-run flags (which `▼` items have been seen)  |\n| `recording.json`             | Recording config (redaction patterns, etc.)      |\n| `fleets.json`                | Live agent fleets: members, worktrees, branches, review state (Agent Cockpit) |\n| `checkpoints.json`           | Pre-agent-work snapshots per repo (dangling-commit SHAs, most recent 20 per repo) |\n| `sessions/`                  | Recording metadata index (per-project subdirs)   |\n| `screenshots/`               | Region screenshots (PNG)                         |\n\n---\n\n## Development\n\nPrereqs: a recent stable Rust toolchain. Linux additionally needs the system deps in `get-deps`.\n\n```bash\nmake build        # all binaries (debug)\nmake check        # static checks\nmake test         # tests\nmake clean-release-artifacts  # remove local dmg/msi/zip/deb/AppImage packages\n```\n\nBuild a release for the current platform:\n\n```bash\ncargo build --release -p unterm -p unterm-cli -p unterm-mux -p strip-ansi-escapes\n```\n\nBuild platform packages:\n\n```bash\n# macOS — universal .app + zip (run on macOS)\nci/deploy.sh\n\n# Linux — .deb\nci/deploy.sh\n# Linux — AppImage\nci/appimage.sh\n\n# Windows — staged release tree + zip\nbash ci/deploy.sh\n# Windows — MSI (requires WiX 6 at .\\.tools\\wix.exe — install via `dotnet tool install --tool-path .\\.tools wix --version 6.0.1`)\npwsh -File ci/build-msi.ps1\n```\n\nmacOS code-signing + notarization is **local-only** (no CI step) so the\nDeveloper ID `.p12` private key never has to leave your Mac. One-time\nsetup, on the Mac that holds the cert:\n\n```bash\nxcrun notarytool store-credentials UntermNotary \\\n  --apple-id <your-apple-id> --team-id 6NQM3XP5RF\n```\n\n### Release tagging\n\nUnterm release tags may use either minor tags (`v0.50`) or patch tags (`v0.50.0`). Use the tag form that matches the changelog and package version for the release. Cut a tag only when a coherent batch of fixes / features is ready to ship.\n\n```bash\ngit tag -a vX.Y.Z -m \"Unterm vX.Y.Z\" && git push origin vX.Y.Z\nmake release-mac                    # build universal + sign + notarize + upload\n```\n\n`make release-mac` reads the tag from `git describe --exact-match HEAD`,\nbuilds universal x86_64+aarch64 binaries, calls `ci/sign-macos.sh` with\n`NOTARY_PROFILE=UntermNotary`, then `gh release upload`s the resulting\nDMG to the matching GitHub Release. After local validation/upload, run\n`make clean-release-artifacts` to remove root-level release packages while\nkeeping build caches intact.\n\nCI on every PR runs `cargo check` against macOS, Linux, and Windows.\nTagged pushes (`vX.Y` or `vX.Y.Z`) trigger the `release-linux` and `release-windows`\nworkflows that publish those two platforms' artifacts to GitHub Releases.\nmacOS sits out of CI by design — see above.\n\n---\n\n## Repository\n\nThis repository is the main Unterm project:\n\nhttps://github.com/zhitongblog/unterm\n\nUnterm includes modified WezTerm components. Upstream WezTerm remains a separate project by Wez Furlong and contributors.\n",
  "bytes": 29094,
  "sha": "6d15e27b76bafde6cdb38744ad7a3269fea4a07becad73155cf9f9cf6ed129cb",
  "repo_slug": "zhitongblog/unterm",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_zhitongblog_unterm_ae891887/readme"
}