WTA is a Rust command-line tool that bridges AI agent CLIs and Windows Terminal. It lets AI (GitHub Copilot, Claude, Gemini, Codex, or a custom command) drive your terminal directly — create tabs, split panes, run commands, read output — and surfaces an in-terminal chat UI inside a Windows Terminal agent pane.
Today's AI coding assistants can "talk about" code but can't "do" anything in the terminal. WTA fills that gap:
- AI wants to run a command? → WTA opens a pane in Windows Terminal and runs it
- AI wants to read command output? → WTA pulls the content from the terminal and returns it
- User wants to drive the terminal via natural-language chat? → WTA renders a TUI chat surface inside an agent pane; AI executes on your behalf
- A command just failed? → WTA's autofix detects it and offers a fix via the agent
WTA runs as a helper + master pair, never as a standalone process: Windows
Terminal spawns one wta-master singleton that owns the single connection to
the agent CLI, and one wta-helper per agent pane that renders the TUI and
talks ACP to master over a named pipe. Stateless CLI helpers provide one-shot
WT control, and the master-owned session MCP endpoint accepts typed terminal
action and user-input requests with per-session capabilities.
There is no standalone agent / TUI mode. Bare
wtawith neither a role flag nor a subcommand exits with an error (main.rs). The session MCP endpoint is not a general WT-control server and exposes no read or execution tools.
wta --master \\.\pipe\wta-master-<GUID>
Spawned once by the C++ SharedWta singleton (WindowEmperor side). It:
- Spawns the agent CLI subprocess (copilot / claude / gemini / codex) and wraps
its stdio in an
acp::ClientSideConnection— master is the client of the agent CLI. - Listens on the named pipe; accepts one
wta-helperper connect. - For each helper, runs an
acp::AgentSideConnection(master plays the agent role), forwards helper requests to the agent CLI, and routes inboundsession_notifications back to the owning helper via thesession_to_helpermap.
Implementation: src/master/mod.rs.
wta --connect-master \\.\pipe\wta-master-<GUID> [--owner-tab-id <GUID>] [--owner-window-id <ID>] [--start-stashed] …
Spawned once per agent pane by Windows Terminal (TerminalPage). It drives
the ratatui chat UI (app.rs) but, instead of spawning its own agent CLI,
connects to master over the pipe and speaks ACP JSON-RPC. From the helper's
perspective, master is the agent. The helper owns the user-facing side effects:
the TUI, permission prompts, ShellManager (for the agent's create_terminal),
autofix, and the per-tab session model.
Entry: src/helper/mod.rs → crate::run_default_tui_over_pipe (in main.rs).
wta list-windows # list all WT windows
wta list-tabs # list tabs
wta capture-pane -t 3 -l 50 # read the last 50 lines from pane 3
wta new-tab -c "pwsh.exe" -n "Build" # create a new tab
wta split-pane -h # split the current pane horizontally
wta delegate "fix this build" # open a delegate agent in a new tab
wta sessions list # inspect sessions known to master
wta hooks install # install the agent-hook bridge
wta resolve-command which --cwd . --json # resolve from cwd + PATH + shell-specific sources
Stateless, short-lived commands dispatched in src/main.rs. They talk directly
to Windows Terminal via CliChannel → wtcli.exe → COM and exit, except local
helpers such as resolve-command, which inspect cwd and machine state directly. Used by
humans debugging WTA and by agents that can shell out. (The agent CLI reaches WT
this way too — by shelling out to wta / wtcli. The session MCP endpoint
is separate and cannot perform these operations.)
Packaged builds register wta.exe as an App Execution Alias. WTA prepends the
current package family's alias directory to the agent process PATH, so a short
wta.exe invocation selects the matching Dev, Preview, or Store installation
even when multiple variants are installed. Unpackaged builds prepend the
running executable's directory instead.
wta-master owns one stateless Streamable HTTP endpoint on Windows loopback.
Host Agents use it directly; WSL Agents use an on-demand loopback relay inside
their distro, avoiding inbound Windows firewall requirements. Relays are
master-lifetime services with bounded request handling and a master-owned stdin
pipe that terminates the distro process if master exits; unexpected relay
failure is restarted on the same port so existing sessions recover. Each ACP
session's McpServer::Http configuration carries an independent public server
name and a distinct bearer capability, so name-keyed Agent caches cannot
overwrite another session's header. Master maps the capability to SessionId,
resolves the current Helper through session_to_helper, and forwards the typed
input over the existing ACP pipe.
The endpoint exposes run_command_in_current_shell, create_workspace, and
delegate_task_in_new_workspace, which return after the Helper confirms that
the recommendation card was presented, and request_user_input, which blocks
until the user answers, cancels, disconnects, or the request times out. The
latter is a WTA-owned fallback and does not intercept provider-native question
tools.
Windows Terminal (WindowEmperor, one WT process)
| spawns once (SharedWta) | spawns per agent pane
| --master <pipe> | --connect-master <pipe>
v v
+--------------+ named pipe +------------------+
| wta-master |<-------------->| wta-helper | (one per pane)
| (singleton) | ACP/JSON-RPC | TUI: app.rs + |
| master/mod.rs| | helper/mod.rs |
+------+-------+ +--------+---------+
| ACP/stdio | ShellManager
v | (create_terminal /
Agent CLI | permission)
(copilot/claude/ v
gemini/codex) CliChannel (WtChannel)
|
Human / agent shell-out: v
wta <subcommand> -----------------> wtcli.exe -> COM IProtocolServer
(main.rs CLI helpers) |
v
TerminalProtocolComServer
|
v
Windows Terminal
| Module | File | Responsibility |
|---|---|---|
| Entry / CLI | src/main.rs |
clap parsing, role/subcommand dispatch, protocol discovery, locale normalization |
| Master | src/master/mod.rs |
ACP multiplexer singleton: owns the lazy agent CLI pool, serves helpers over the pipe, routes per-session notifications |
| Helper | src/helper/mod.rs |
Thin per-pane entry; reuses run_default_tui_over_pipe with the pipe as ACP transport |
| App / TUI | src/app.rs (+ src/app/*.rs) |
TUI state machine and event loop; per-tab sessions, autofix, permission, session-management view |
| ACP client | src/protocol/acp/client.rs |
Agent-CLI client + helper-side WtaClient; prompt templating, model select, probe, failure handling |
| Coordinator | src/coordinator.rs |
?<prompt> delegate execution |
| Session tracking | src/agent_sessions.rs, src/session_registry.rs, src/session_watcher/* |
Session registry + CLI-log status classification (claude/copilot/codex/gemini) |
| ShellManager | src/shell/shell_manager.rs |
Terminal process manager: local child or WT pane |
| CliChannel | src/shell/wt_channel/cli_channel.rs |
Shells out to wtcli.exe (the only WT transport) |
| TUI views | src/ui/*.rs |
ratatui rendering: chat, input, permission, popups, agents view, status bar |
| Hooks installer | src/agent_hooks_installer.rs |
Install / upgrade the wt-agent-hooks bridge per CLI |
ACP (agent-client-protocol = "1.3.0", JSON-RPC 2.0) is spoken on two hops:
- master ↔ agent CLI (stdio): master is the ACP client; it lazily spawns and owns one process per distinct agent key.
- helper ↔ master (named pipe): master is the ACP agent (server), the helper is the client. Master forwards helper requests to the agent CLI and fans notifications back to the owning helper.
- Transport: every WT operation shells out to
wtcli.exe, which doesCoCreateInstance(WT_COM_CLSID)and calls WT'sIProtocolServer— includingsend_input(wtcli send-keys). - Discovery: the
WT_COM_CLSIDenvironment variable, set by WT at startup and inherited by every conpty child (sowtaandwtclisee it automatically). - Authorization: gated by Windows packaged-COM / terminal activation policy.
| Purpose | Crate |
|---|---|
| Async runtime | tokio |
| CLI parsing | clap 4 |
| TUI rendering | ratatui 0.30 + crossterm 0.29 |
| ACP protocol | agent-client-protocol 1.3.0 |
| Serialization | serde + serde_json |
| Error handling | anyhow |
| i18n | rust-i18n |
cd tools/wta
# Kill any live wta.exe first (a running shared-host locks target/debug/wta.exe)
# PowerShell: Get-Process wta -ErrorAction SilentlyContinue | Stop-Process -Force
cargo build
# Output binary: tools/wta/target/debug/wta.exe
# Run the WTA test suite (cargo build does NOT compile #[cfg(test)] code)
cargo testWTA is normally launched by Windows Terminal (master + helper), not run by hand. For ad-hoc inspection, the CLI helpers work standalone inside a WT pane:
wta pipe-id # show the inherited WT_COM_CLSID
wta list-windows # talk to WT over COM
wta capture-pane -l 5
wta sessions list # ask master for the session registryWTA lives under tools/wta/ of the Windows Terminal (Intelligent Terminal) source
tree. It is an independent Rust project but a companion to Windows Terminal:
- The C++ side ships
TerminalProtocolComServer, exposingIProtocolServervia local COM activation, andSharedWta, which spawns/owns thewta-mastersingleton. TerminalPagespawns onewta-helperper agent pane (pre-warmed per tab) and hosts itsTermControlinsideAgentPaneContent.- The Rust side reaches WT only indirectly, by shelling out to
wtcli.exe.
See doc/specs/Multi-window-agent-pane.md for the full helper+master design, and
tools/wta/AGENTS.md for the per-crate conventions (logging layout, session
liveness model, hooks auto-upgrade, third-party notice generation).
| Process | Binary | Lifetime | Role |
|---|---|---|---|
| Windows Terminal | WindowsTerminal.exe |
User-launched, long-lived | Window manager + renderer; hosts TerminalProtocolComServer; spawns master + helpers |
| wta-master | wta.exe --master |
Spawned once by SharedWta |
Owns the agent CLI pool; multiplexes ACP sessions for all helpers |
| wta-helper | wta.exe --connect-master |
One per agent pane | TUI + per-pane side effects; ACP client of master |
| Agent CLI | copilot, claude, gemini, codex, opencode |
Spawned lazily by master | One warm process per agent key; shared by helpers using that key |
| wtcli | wtcli.exe |
Per call (or long-running for listen) |
COM client for IProtocolServer; bridges wta → WT |
| Shell commands | pwsh, cargo, git, … |
Spawned by WT; exit when done | The actual tools doing the work |
- One agent CLI is shared by panes/tabs with the same agent key. A helper's
session/newround-trips to that CLI;initializeis cached per process. - Helpers are pre-warmed per tab at tab creation (
--start-stashed), so the ACP session connects in the background even before the user opens the pane — this is what lets autofix work on a stashed pane. - Toggling an agent pane stashes it (helper + conpty + ACP session survive);
the pane is only destroyed on tab close or
Ctrl+C ×2in the TUI. - If master dies, helpers exit on pipe EOF and
closeOnExit:"always"closes their panes. There is no reconnect or automaticsession/load; a later user-initiated pane open creates a fresh master, helper, and ACP session./restartapplies only while a live helper can explicitly request a fresh stack.
When the agent's ACP create_terminal lands on a helper, ShellManager picks:
ShellManager.create_terminal(config)
│
┌─────────┴─────────┐
│ has_wt_channel()? │
└─────────┬─────────┘
Yes │ No
┌───────────┴───────────┐
▼ ▼
Path A: WT pane Path B: local child
(via wtcli/COM) (tokio::process::Command)
visible to the user invisible, dies with WTA
Fallback: if WT pane creation fails, WTA downgrades to the local-child path.
- Helper+master architecture: ✅ current primary (and only) runtime model
- COM/CLI control plane: ✅ done; sole WT transport
- Autofix, delegate (
?<prompt>), session-management view, hooks auto-upgrade: ✅ shipped - MCP server mode, standalone single-process TUI: ❌ removed