Windows Terminal wt 命令行参数设计全解:从 607 设计规格到 CLI11 源码实现
发布时间:2026/9/7 4:32:56 锦皓数字建站

Windows Terminal wt 命令行参数设计全解从 #607 设计规格到 CLI11 源码实现【免费下载链接】terminalThe new Windows Terminal and the original Windows console host, all in the same place!项目地址: https://gitcode.com/GitHub_Trending/term/terminal本文以仓库中 doc/specs/#607 - Commandline Arguments for the Windows Terminal.md 设计规格为主体系统讲解 Windows Terminal 的wt命令行参数体系为什么采用“命令 参数”双段式设计、new-tab/split-pane/move-focus等子命令与参数如何组合使用、分号分隔与转义规则背后的取舍并结合当前仓库中 AppCommandlineArgs.cpp、Commandline.cpp 等源码验证规格设计是如何落地的、后续又演化成了什么样。背景为什么需要 wt 命令行参数规格的 Abstract 部分开宗明义这套参数用于支持“定制化启动场景”例如直接以指定 profile 或指定目录启动终端。其灵感来源Inspiration与几个历史需求直接相关自wt.exe这个执行别名出现后社区一直希望它能接受参数从而描述“以何种方式启动”issue #576 希望任务栏 jumplist 中显示 Windows Terminal 的入口但当时无法向 Terminal 传达“要启动哪个 profile”因此被阻塞issue #1060 希望资源管理器右键菜单的“在此处打开 Windows Terminal”更强大——能指定在该目录中以某个特定 profile 启动issue #2068 希望从 Terminal 内部不仅能打开默认 profile 的新窗口还能打开指定 profile 的新窗口。规格还提到最终的参数设计深受tmux命令行参数风格的启发——后者同样支持通过命令行参数完成复杂的启动编排。14 个用户故事需求侧的完整清单规格文档列举了 14 个用户故事来引导设计这也是理解参数体系完备性的基准。完整继承如下以默认 profile 打开 Windows Terminal只需wt已天然支持以 profile 列表中的某个特定 profile 打开以默认 profile 打开但运行一条不同于平常的命令查看wt.exe支持的参数列表查看 profile 列表以便从中挑选一个打开不打开终端窗口直接打开设置文件不打开终端窗口查看当前 Windows Terminal 版本在屏幕的特定位置打开终端窗口在特定目录中打开终端以特定尺寸打开终端只使用默认设置、忽略用户设置打开终端同时打开多个标签页各标签页使用不同 profile、不同启动目录甚至不同命令行同时打开多个标签页和窗格各自拥有不同 profile、启动目录、命令行并指定分割大小用一个文件提供可复用的多步骤启动配置避免每次手敲命令行。这 14 个故事覆盖了“信息查询、窗口控制、多标签/多窗格编排、可复用配置”四大类诉求后面的命令与参数设计逐一回应它们。设计演进从“纯参数”到“命令 参数”方案一纯参数风格被否决规格最初考虑的参数风格是--help: 显示帮助 --version: 显示版本信息 --list-profiles: 显示可用 profile 列表 --all 同时显示 hidden profile --verbose? 是否同时显示 GUID --open-settings: 打开设置文件 --profile name: 以指定名称的 profile 启动 --guid guid: 以指定 GUID 的 profile 启动 --startingDirectory path: 在指定目录启动 --initialRows rows, --initialCols cols: 以特定尺寸启动 --initialPosition x,y: 在屏幕特定位置启动 -- commandline: 用指定命令行启动规格明确指出该方案的致命缺陷难以表达“同时启动多个标签页或窗格”。用户如何为每个窗格指定不同命令行配置越复杂命令行就越难解析和理解。方案二命令Commands 参数Parameters最终设计按职责把参数分为两类这是理解wt语法的基石命令Commands触发某件事的参数使用kebab-case如new-tab、split-pane可带若干可选或必需参数参数Parameters为命令提供附加信息的参数有长格式--camelCase双连字符 驼峰命名与短格式-c单连字符 单个字母两种。wt 命令行的总体语法wt命令行分为两大部分——“Options选项”与“Commands命令”wt [options] [command ; ]...Options是一组作用于整个wt命令行行为的开关与参数Commands是用分号;分隔的命令及其参数列表。两条关键规则这也是规格中最容易被忽略、但源码中确有实现保障的行为缺省命令是new-tab如果某个 command 没有显式写出命令名就默认视为new-tab。因此wt cmd.exe等价于wt new-tab cmd.exe空命令也是new-tabwt ; ; ;会打开 Windows Terminal 并创建4 个新标签页等价于wt new-tab ; new-tab ; new-tab ; new-tab。关于“默认命令应该是new-window还是new-tab”规格中保留了一段设计者的手稿笔记原文以 HTML 注释形式留在文档里new-window适合承载--initialPosition、--initialRows/--initialCols并隐含new-tab但同一窗口内的后续命令必须显式写new-tab否则会各开一个窗口若默认是new-tab则后续new-tab会继承父窗口尺寸、忽略尺寸参数——这在语义上可以接受第一个 tab 决定窗口大小后其余 tab 确实无法再改。最终结论是new-tab作为默认命令。完整示例命令行规格原文继承以下示例逐条对应上面的用户故事可直接复制使用PowerShell 下的转义注意事项见后文# 以新标签页运行 Windows Powershell profile用户故事 2 wt new-tab --profile Windows Powershell wt --profile Windows Powershell wt -p Windows Powershell # 以新标签页运行默认 profile并执行 cmd.exe用户故事 3 wt cmd.exe # 显示帮助文本用户故事 4 wt help wt --help wt -h wt -? wt /? # 输出 profile 列表用户故事 5 wt list-profiles # 不打开终端窗口直接打开设置文件用户故事 6 wt open-settings # 显示 Windows Terminal 版本信息用户故事 7 wt version wt --version wt -v # 在目录 c:/Users/Foo/dev/MyProject 中启动默认 profile用户故事 9 wt new-tab --startingDirectory c:/Users/Foo/dev/MyProject wt --startingDirectory c:/Users/Foo/dev/MyProject wt -d c:/Users/Foo/dev/MyProject # Windows 风格路径同样有效 wt -d c:\Users\Foo\dev\MyProject # 组合以 Windows Powershell profile 在指定目录打开新标签用户故事 2、9 wt new-tab --profile Windows Powershell --startingDirectory c:/Users/Foo/dev/MyProject wt --profile Windows Powershell --startingDirectory c:/Users/Foo/dev/MyProject wt -p Windows Powershell -d c:/Users/Foo/dev/MyProject # 一个标签用 Windows Powershell另一个标签用 cmd profile用户故事 12 wt new-tab --profile Windows Powershell ; new-tab --profile cmd wt --profile Windows Powershell ; new-tab --profile cmd wt --profile Windows Powershell ; --profile cmd wt --p Windows Powershell ; --p cmd # 以新标签运行 my-commandline.exe with some args wt new-tab my-commandline.exe with some args wt my-commandline.exe with some args # 第一个标签运行带字面分号的命令第二个标签运行 another.exe wt my-commandline.exe with some args and a \; literal semicolon ; new-tab another.exe running in a second tab # 启动 cmd.exe然后垂直分割前者 70%、新窗格 30%在新窗格中运行 wsl.exe用户故事 13 wt cmd.exe ; split-pane --target 0 -V -% 30 wsl.exe wt cmd.exe ; split-pane -% 30 wsl.exe # 默认 profile 新窗口 → 垂直分割默认 profile→ 在第二个窗格中水平分割并运行 media.exe用户故事 13 wt new-tab ; split-pane -V ; split-pane --target 1 -H media.exe wt new-tab ; split-pane -V ; split-pane -t 1 -H media.exe选项Options参考选项作用--help,-h,-?,/?执行help命令--version,-v执行version命令--session,-s session-id在已存在的 Windows Terminal 会话中执行这些命令从而可以在已经在运行的窗口中打开新标签。规格中注明该特性依赖其他计划内的工作当时仅作为示例详见下文“未来展望”--file,-f configuration-file从配置文件读取命令列表用于可复用的启动配置用户故事 14命令Commands参考规格定义的完整命令集如下每个命令的语法、参数与语义完整保留。helphelp显示帮助信息。versionversion显示 Windows Terminal 的版本信息。open-settingsopen-settings [--defaults,-d]打开设置文件。当它是唯一的命令时不会打开终端窗口规格在“潜在问题”一节还特别强调wt open-settings本身不应隐含new-tab。--defaults,-d打开defaults.json而不是profiles.json。list-profileslist-profiles [--all,-A] [--showGuids,-g]按行列出每个可用 profile 的名称。--all,-A显示全部 profile包括标记了hidden: true的--showGuids,-g除名称外同时列出 profile 的 GUID。规格建议 GUID 放在每行最前面以便脚本解析输出。new-tabnew-tab [--initialPosition x,y]|[--maximized]|[--fullscreen] [--initialRows rows] [--initialCols cols] [terminal_parameters]以给定自定义方式打开新标签页。第一次调用时同时创建新窗口之后的new-tab都在同一个窗口内创建标签。--initialPosition x,y以像素坐标在屏幕指定位置创建新窗口。仅在最初创建窗口时使用后续new-tab忽略与--maximized/--fullscreen组合会向用户显示“参数组合非法”的报错--initialRows rows以rows行字符行创建窗口缺省则使用用户设置中的值。同样仅在首次创建窗口时生效与--maximized/--fullscreen冲突时报错--initialCols cols以cols列创建窗口规则同上[terminal_parameters]见下文“terminal_parameters”。split-panesplit-pane [--target,-t target-pane] [-H]|[-V] [--percent,-% split-percentage] [terminal_parameters]在当前聚焦标签页中将指定窗格按垂直或水平方向分割出新窗格。--target,-t target-pane在指定窗格上做分割。每个窗格在标签页内有唯一索引按创建顺序分配缺省为当前聚焦窗格的索引-H/-V指定分割方向。-V是“vertical”想象[|]-H是“horizontal”想象[-]。缺省为“auto”——沿当前窗格的较大维度分割若-H与-V同时给出取垂直--percent,-% split-percentage新窗格占父窗格空间的百分比缺省 50%[terminal_parameters]同上。focus-tabfocus-tab [--target,-t tab-index]把焦点移动到指定标签页。--target,-t tab-index移动到索引为tab-index的标签缺省为0第一个标签。focus-panefocus-pane [--target,-t target-pane]在当前聚焦标签页内把焦点移动到指定窗格。--target,-t target-pane移动到指定索引的窗格索引按创建顺序分配缺省为当前聚焦窗格等价于 no-op。move-focusmove-focus [--direction,-d direction]在当前聚焦标签页内按方向移动焦点。--direction,-d directiondirection取值为left、right、up、down之一缺省则不移动焦点no-op。[terminal_parameters]new-tab、split-pane这类“创建新终端实例”的命令都接受一组[terminal_parameters][--profile,-p profile-name] [--startingDirectory,-d starting-directory] [commandline]--profile,-p profile-name以指定 profile 打开新标签/窗格profile-name可以是 profile 的name或guid如果不匹配任何profile则回落到默认 profile--startingDirectory,-d starting-directory覆盖所选 profile 的startingDirectory改为在starting-directory启动commandline替换所选 profile 的默认命令行。如果该命令行本身需要包含;必须写成\;转义。规格还对“为什么参数长这样”给出了设计论证从原理上说所有profile 属性都可以被命令行参数覆盖。实践上没有必要为每个 Profile 属性都做短格式参数但长格式完全合理之所以只选了这几个参数是因为它们既有 profile 属性的特例guid、name又是高优先级属性。name/guid本身没有覆盖意义于是被“征用”为选择 profile 的参数commandline是特殊案例——没有用显式参数标记它的起点目的是避免对用户命令行做二次解析与转义startingDirectory是被强烈请求的参数因此在规格中被优先收录。源码印证规格是如何落地的规格在 Implementation Details 一节记录了关键技术决策当前仓库的源码可以逐条印证并展示了规格之后发生的设计演化。CLI11 ActionAndArgs解析层与动作层的分工规格确定使用开源库 CLI11 解析参数2019 年 11 月 18 日当周的调研结论在 CLI11 之上增加“以;分离命令”的逻辑。每个命令解析后构造一个ActionAndArgs复用终端内部已有的动作模型开新标签、开新窗格、移动焦点等。这一决策在 AppCommandlineArgs.cpp 中直接可见解析器就是一个CLI::App _app{ wt - the Windows Terminal }各子命令通过add_subcommand构建ParseCommand 负责解析单条命令解析出的动作统一推入_startupActionsstd::vectorActionAndArgs。规格提到的另一个工程难点——启动时子控件尚未初始化不能一次性创建所有分割与标签否则会开出 0x0 大小的窗格——因此采用“逐条分发启动动作等前一个动作对应的终端初始化完成后再分发下一个”的策略。这与 CommandlineTest.cpp 中的验证用例共同构成了该特性的可测试性基础。分号分隔与\;转义的实现规格规定wt命令行以;分隔多个命令命令行文本内的字面分号写作\;。这一规则在源码中的实现分两层切分AppCommandlineArgs::BuildCommands 把原始 argv 切成多个Commandline对象。内部使用正则^;|[^\\];见 AppCommandlineArgs.cpp 第 13 行注释即“行首的;或前面不是\的;匹配未转义的分界符。值得注意的细节在 _addCommandsForArg每切出一个新命令都会先向其中注入占位首参wt.exe第 952 行这样后续每条命令都能像用户单独敲出wt一样被统一解析——这也解释了为什么wt ; ; ;会展开成 4 条命令反转义Commandline.h 定义了Delimiter{ L; }与EscapedDelimiter{ L\\; }两个常量Commandline::AddArg 在参数入列时循环查找并把\;替换回;保证下游拿到的就是字面分号。规格“Potential Issues”中预判“转义是出了名的难做对需要大量测试”——仓库中的 CommandlineTest.cpp 印证了这一点除TestEscapeDelimiters外ParseSimpleCommandline第 120-180 行专门断言了wt.exe、new-tab ;、;、; ;这些边界输入各自切分出正确数量的命令且后续命令的首参是占位符wt.exe。隐式 new-tab 的双重保障规格“Potential Issues”一节讨论过如果new-tab不是第一个命令例如wt split-pane -V ; new-tab怎么办团队最终结论是假定存在一条隐式new-tab先执行以保证“wt.exe不带任何参数时本来就是隐式new-window/new-tab”这一易用性语义不被破坏。这个决定在源码中有两层落地ParseCommand如果一条命令解析完后没有任何子命令_noCommandsProvided()为真就把剩余参数当作new-tab子命令重新解析。这解释了为什么wt cmd.exe与wt new-tab cmd.exe等价ValidateStartupCommands如果动作队列为空、或队首动作不是NewTab就在队首补插一条NewTab动作。CommandlineTest.cpp中的ValidateFirstCommandIsNewTab与ParseNoCommandIsNewTab测试方法正是针对这两条路径的验证。规格的演化从 2020 年草稿到当前实现规格文档的“Implementation plan”用勾选框记录了分步落地过程重构ShortcutAction分发为独立类、新增带split参数的SplitPane动作、给NewTabArgs/SplitPaneArgs加入TerminalParameters对象、给SplitPane加percent参数、在TerminalApp中加入解析与测试等。对照当前仓库可以观察到规格之后发生的几处可确认的演化以下均以当前源码为准窗口尺寸/位置参数换名规格中的--initialPosition x,y、--initialRows、--initialCols在当前实现中演化为--pos按名称指定位置见 LaunchPositionFromString 回调与--sizeSizeFromString解析第 191-194 行--maximized与--fullscreen则收敛为全局 flag-M/-F并新增了-f,--focus专注模式三者之间通过 CLI11 的excludes约束互斥关系第 166-194 行命令集扩充当前解析器_buildParser包含new-tab/nt、split-pane/sp、focus-tab/ft、move-focus/mf、move-pane/mp、swap-pane、focus-pane/fp、x-save等子命令——规格中设想的短格式命令别名“new-tab变nt、split-pane变sp”已经落地且split-pane的参数也从规格的--percent,-%演化成了取值范围0.01~0.99的-s,--size浮点参数第 271-278 行并新增-D,--duplicate复制当前窗格terminal_parameters 大幅扩展_addNewTerminalArgs 除了规格定义的-p/--profile、-d/--startingDirectory与位置参数commandline还增加了--sessionId、--title、--tabColor、--colorScheme、--suppressApplicationTitle/!--useApplicationTitle、--appendCommandLine、--inheritEnvironment/!--reloadEnvironment等长格式参数——这正是规格“长格式覆盖 profile 属性完全合理”论断的后续展开会话支持落地规格中标注为“依赖其他工作”的--session概念在 AppCommandlineArgs.h 中体现为-w,--window指定目标窗口与GetTargetWindow()ValidateStartupCommands中还有“单一x-save命令时把目标指向当前窗口”的特判list-profiles/open-settings未出现在当前解析器中从源码结构看这两个规格的查询类命令没有被纳入当前_buildParser的子命令集合属于规格中未保留下来的部分。需要说明的是规格是 2020-01-15 的草稿文档头部last updated字段它完整记录了设计动机与 1.0 时期的决策脉络当前源码是其之后的演进状态。阅读规格时应把它当作“设计蓝图 决策档案”而具体参数拼写以wt --help与当前源码为准。潜在问题转义、子系统选择与命令顺序规格用大量篇幅记录了三个真实存在过的工程难题这部分对实际使用者同样重要。命令行转义因为用;分隔命令而命令行本身也可能含;所以字面分号必须写作\;。更棘手的是 PowerShell 也用;分隔命令——在 PowerShell 里调用多命令wt用户需要先给 PowerShell 转义、再给wt转义wt new-tab ; split-pane在 PowerShell 中要写成wt new-tab ; split-pane含字面分号的版本则变成wt new-tab ; split-pane commandline \; with \; semicolons——先用;对 PowerShell 转义分号再用反斜杠对wt转义另一种思路是用引号包裹分号wt new-tab ; split-pane commandline \; with \; semicolons。规格的结论是这种行为在 PowerShell 下确实不舒服但没有更痛的替代方案熟悉 PowerShell 的用户能理解这种转义。同时引用了 jantari 的建议PowerShell 的--%停止解析操作符可以整体规避问题# wt.exe 仍需被 PowerShell 解析它是 PATH 中的命令但其后的内容原样传递 wt.exe --% cmd.exe ; split-pane --target-pane 0 -V -% 30 wsl.exe/SUBSYSTEM:Windows还是/SUBSYSTEM:ConsoleWindows 上的应用要么链接为 Windows 子系统、要么为 Console 子系统wt面临两难若是Console应用从命令行启动时 shell 立即回到前台进程的控制台输出会与 shell 输出混排若是Windows应用从开始菜单/运行对话框等非控制台上下文启动时系统会自动创建一个控制台窗口——即使只想弹出自己的窗口屏幕上也会短暂闪一下控制台。Python 系工具通常同时发布python.exeConsole与pythonw.exeWindows两个可执行文件来规避但这会造成大量用户困惑wtw.exe -d .vswt.exe /?各自“该用哪个”。规格最终提议参照msiexec /?的做法作为 Windows 子系统应用用MessageBox显示帮助文本。理由比控制权返回 shell 混排更清晰、比闪控制台窗口更体面、且有现成的先例。这一点在源码中同样可见ParseCommand 手工识别-?//?抛出CallForHelp_handleExit 把 CLI11 的 stdout/stderr 输出收集进_exitMessage字符串并置_shouldExitEarly由上层决定如何展示——而不是直接写控制台。当new-tab不是第一个命令时以wt.exe split-pane -V ; new-tab为例未来或许可以假定这些命令作用于“当前 Windows Terminal 窗口”但 1.0 不具备会话寻址能力尤其在未附着到任何 Terminal 会话的 conhost 窗口里根本找不到“当前会话”。规格的结论是假定一条隐式new-tab先行执行以创建窗口团队讨论后确认这是正确行为引 DHowett-MSFT 的论断wt.exe无参数时本来就是隐式new-window/new-tab不能收回这份易用性。同时open-settings单独出现时不应隐含new-tab——只应打开用户所选的.json编辑器。能力与风险自评Capabilities规格对自身特性做了标准的能力维度自评完整继承如下可访问性作为命令行特性其可访问性基本取决于调用方环境conhost.exe或 Windows Terminal 本身暴露可访问性通知的能力两者都已支持基本的可访问性模式安全性解析用户输入固有缓冲区长度、输入取值等担忧。所幸命令行经由winMain与CommandLineToArgvW由操作系统处理并传入但解析时仍应格外小心——当前实现中 ParseArgs 对-Embedding、--from-toast等内部哨兵参数先行短路避免内部调用被误解析正是这种谨慎的体现可靠性无特殊担忧兼容性不回归任何既有行为性能/功耗/效率对启动时间等无明显影响。未来展望Future Considerations规格最后列出了一批依赖其他特性的前瞻设计作为该设计空间的完整档案附着到已有会话wt --session [some-session-id] [commands]让命令作用于其他已运行的窗口如wt --session 0 cmd.exe在另一个窗口开新标签。依赖 #2080 所述的“管理器进程”方案list-sessions列出所有活跃的 Windows Terminal 实例及其会话 ID输出格式与上面的--session兼容--elevated请求以提权上下文启动进程服务于 #632 的需求--file,-f configuration-file从配置文件读取命令列表实现用户故事 14 的可复用启动配置。处理“一整文件启动命令”时的语义假定是文件中的第一个new-tab创建窗口后续new-tab都在该窗口内建标签defaultConfiguration曾有如 #756 的“默认以多标签/多窗格启动”的需求。设想在profiles.json中加入defaultConfiguration属性指向一个命令文件窗口创建时像解析命令行一样解析它若用户命令行显式给了文件则忽略profiles.json中的值PowerShell 参数补全调研Register-ArgumentCompleter为wt参数提供自动补全短格式命令别名如wt ; sp less some-log.txt ; fp -t 0。值得一提的是其中“短命令别名”一项已在当前源码中兑现nt/sp/ft/mf/mp/fp见 AppCommandlineArgs.cpp而--session/--window也以演化后的形态存在-w,--windowGetTargetWindow。小结这篇 #607 规格的价值在于它完整展示了 Windows Terminal 命令行体系的设计全貌用 14 个用户故事锚定需求用“命令 参数”双段式语法解决多标签/多窗格编排的表达力问题用分号分隔 \;转义平衡可读性与安全性用隐式new-tab守住无参数启动的易用性底线。规格中记录的技术决策——CLI11 解析、ActionAndArgs复用、启动动作逐条分发——都能在 src/cascadia/TerminalApp/ 与 src/cascadia/LocalTests_TerminalApp/CommandlineTest.cpp 中找到一一对应的实现与测试。对使用者而言掌握new-tab、split-pane及其参数、-p/-d组合与 PowerShell 下的转义规则就足以覆盖绝大多数定制化启动场景对研究者而言这份规格加上当前源码是理解 Windows Terminal 启动链路的最佳入口。【免费下载链接】terminalThe new Windows Terminal and the original Windows console host, all in the same place!项目地址: https://gitcode.com/GitHub_Trending/term/terminal创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。