Skip to content

Implement wtcli, an application to query details about an existing Terminal instance - #20461

Open
PankajBhojwani wants to merge 23 commits into
mainfrom
dev/pabhoj/wtcli
Open

PankajBhojwani wants to merge 23 commits into
mainfrom
dev/pabhoj/wtcli

Conversation

@PankajBhojwani

@PankajBhojwani PankajBhojwani commented Jul 22, 2026 •

Copy link
Copy Markdown
Contributor

Summary of the Pull Request

Implements wtcli, a new command-line client for Windows Terminal Protocol: a local COM control surface that lets external processes inspect and drive a running Windows Terminal instance. It provides a tmux-style command vocabulary for the terminal.

wtcli currently exposes 10 commands:

  • Inspect: list-windows (lsw), list-tabs (lst), list-panes
    (lsp), active-pane, pane-status
  • Read output: capture-pane (capturep), including --last-prompt to
    grab the most recent completed shell command via OSC 133 shell integration
  • Mutate: new-tab (neww), split-pane (splitw), kill-pane
    (killp), focus-pane (focusp)

Every command supports --json for machine-readable output, otherwise results are rendered as human-readable tables.

References and Relevant Issues

Detailed Description of the Pull Request / Additional comments

A client activates the server directly with CoCreateInstance using a per-brand CLSID (Release/Preview/Canary/Dev, selected at compile time), and issues typed commands.

Components:
1. wtcli.exe: the CLI client (src/tools/wtcli/)
The user-facing tool. Parses subcommands, activates the protocol server via WT_COM_CLSID, and calls the interface methods.

2. ITerminalProtocol: the classic-COM interface (src/host/proxy/ITerminalProtocol.idl)
The contract between client and Terminal. A classic-COM interface marshaled by the MIDL proxy/stub in OpenConsoleProxy.dll (registered per-brand in the app manifests). Scalar arguments stay typed; every complex result crosses the boundary as a JSON BSTR.

3. TerminalProtocolComServer: the in-proc server (src/cascadia/WindowsTerminal/)
Implements ITerminalProtocol inside WindowsTerminal.exe.

4. TerminalPage protocol bridge (src/cascadia/TerminalApp/TerminalPage.Protocol.cpp)
The UI-thread methods that actually query and mutate live terminal state (windows, tabs, panes, process status, pane output) and return typed results.

5. TerminalProtocol shared library (src/cascadia/TerminalProtocol/)
Hosts the shared WinRT struct types (WindowInfo, TabInfo, PaneInfo, etc) consumed in-process by both the page bridge and the server. Also provides ProtocolParsing.h, a header of parsing helpers (ParseSplitDirection, ClassifyPaneOutputSource) shared by the server and the fuzzer.

6. Protocol fuzzer (src/cascadia/TerminalProtocol/ft_fuzzer/)
A LibFuzzer harness targeting the parsing functions (ParseSplitDirection, ClassifyPaneOutputSource).

Validation Steps Performed

In a dev build of terminal, all 10 of the commands work

PR Checklist

  • Closes #xxx
  • Tests added/passed
  • Documentation updated
    • If checked, please file a pull request on our docs repo and link it here: #xxx
  • Schema updated (if necessary)

@github-advanced-security github-advanced-security AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check-spelling found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.

@github-actions

This comment has been minimized.

@PankajBhojwani
PankajBhojwani marked this pull request as ready for review July 23, 2026 17:46
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@lhecker Leonard Hecker (lhecker) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW if we plan to just upstream this existing (?) code, I'm fine with just noting down some nits. Otherwise, I have some ideas how to improve it, like the STA/MTA thing.

Comment thread src/tools/wtcli/main.cpp

// Derive a per-install-path CLSID using the same v5 UUID formula as the server,
// so that unpackaged/portable clients find the correct matching server instance.
static GUID _portableClsid(const GUID& brandClsid)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we put these functions into src/types? We got CreateV5Uuid there already and we could link wtcli with it.

Unless you want to keep it portable of course.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to have it be standalone if possible! But if there's strong feelings in the other direction I'm alright to change it

Comment thread src/cascadia/TerminalApp/TerminalPage.Protocol.cpp

// Register the COM class factory on a dedicated MTA thread so that
// incoming COM calls are dispatched to MTA worker threads rather than
// the STA/UI thread. This keeps long-running calls off the UI thread —

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah here's the answer. But ...long-running? What calls do we foresee to be computationally expensive?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the comment, previous one was outdated. The COM methods call .get() and that's the actual reason for the MTA thread.

@PankajBhojwani

Copy link
Copy Markdown
Contributor Author

BTW if we plan to just upstream this existing (?) code, I'm fine with just noting down some nits. Otherwise, I have some ideas how to improve it, like the STA/MTA thing.

It's mostly existing, I just stripped the stuff that we don't need here that are more agent CLI specific. Happy to hear about the improvements though! And maybe I can bring those downstream too.

Comment thread src/host/proxy/ITerminalProtocol.idl Outdated
// LOAD BEARING (same discipline as ITerminalHandoff): OpenConsoleProxy.dll is a
// single shared proxy/stub DLL. Never change or reuse the UUIDs below.

// Terminal protocol — implemented by WindowsTerminal.exe, activated by the

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

emdash

@carlos-zamora

Carlos Zamora (carlos-zamora) commented Sep 1, 2026 •

Copy link
Copy Markdown
Contributor

Feedback from 9/1 bug bash:

  • uh oh, needs client token check:
image
  • wtcli capturep doesn't set the output CP to utf-8 before emitting utf-8 text, resulting in this:
image
  • Should we have capturep? I feel that there is danger there
  • wtcli lsp returns 0 panes until i specify a tab/window, even though wtcli lst shows tabs in Current Window
  • wtcli lst -w foo doesn't support named windows :"(
  • actually, wtcli uses a different window ID mechanism than the rest of terminal... that's kinda worrying actually (DH. MG:+1)
  • when running unpackaged, the [wtcli] WT_COM_CLSID not set. Must run inside an Intelligent Terminal pane. error message most definitely shouldn't mention Intelligent Terminal
    • MG: I'm a big dumb and was using the wtcli from the path not the cwd
  • wtcli args are different from wt args (shouldn't they be largely the same EXCEPT for the new ones? or can they not be?)
  • wtcli should support /? to be like other windowsy things
  • we don't need to support / OVERALL, but /? is a windows standard (alas)
  • split-pane alias is splitw. Should it be splitp?
  • new-tab alias is neww. Should it be newt?
  • Idea: can/should we gate some functionality behind "enable debugging features"?

@microsoft-github-policy-service microsoft-github-policy-service Bot added the Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something label Sep 1, 2026
@microsoft-github-policy-service microsoft-github-policy-service Bot removed the Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something label Sep 1, 2026
@microsoft-github-policy-service microsoft-github-policy-service Bot added Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something and removed Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something labels Oct 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something zBugBash-Consider

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants