Skip to main content
Glama

terminal

Read console output, send input, or run commands and wait for quiet, pattern, or exit completion to capture results.

Instructions

Purpose: Interact with a terminal window: read output, send input, or run+wait+read in one call. action='read' / action='send' absorb the formerly-standalone read/send tools (Phase 4). Details: action='run' is the recommended high-level workflow: send command → wait until quiet/pattern/timeout → read output. The command text is passed as input (the legacy parameter name command is also accepted as a deprecated alias — see issue #245). Returns completion={reason, elapsedMs} first-class plus outputIntegrity:'ok'|'baseline_lost' so callers can detect when scrollback could not be anchored to the pre-send buffer. action='read' reads current text via UIA TextPattern (falls back to OCR); use sinceMarker for incremental diff. action='send' sends a command with focus management. Prefer: action='run' for command execution + result. For long-running commands (test runners, builds, deploys) use until:{mode:'pattern', pattern:''} — the default quiet mode is tuned for short interactive commands and may complete prematurely on multi-second silent gaps mid-run. Use action='read'/'send' for fine-grained control or when you need to interleave other actions. read/send/run also accept a launch_console paneId (pass the paneId field, NOT windowTitle) to keep targeting a pane after its title changes. Caveats: Do not screenshot the terminal — action='read' is cheaper and structured. action='run' supports completion reasons: quiet | pattern_matched | exited | timeout | window_closed | window_not_found | send_failed (send rejected on a live window — see warnings for the underlying error code). until:{mode:'exit', shell:'bash'|'powershell'} (issue #386) returns completion.exitCode + reason:'exited' via an echo-immune sentinel that works for multiline input that pattern mode cannot anchor; pass shell explicitly (auto fails as ExitModeShellAmbiguous on WT/conhost/SSH), cmd is unsupported (ExitModeShellUnsupported), open-construct input is rejected (ExitModeUnsafeInput). When outputIntegrity:'baseline_lost' is returned, output is forced to '' and readError.code='BaselineMarkerLost' is set: rerun with until:{mode:'pattern',...} or longer timeoutMs. action='run' may also emit warnings prefixed FileLockCollision: when output reveals an EBUSY/Windows-lock/EAGAIN-EDEADLK file collision (issue #236). Default quietMs=1500 (issue #196); long silences require pattern mode. preferClipboard=true (send default) replaces the clipboard. Hidden-input prompts emit verifyDelivery.unverifiable (reason:'hidden_input_prompt') — use method:'foreground'. action='read' typed errors: TerminalWindowNotFound, TerminalTextPatternUnavailable (force source:'ocr'); stale sinceMarker → hints.terminalMarker.previousMatched:false on ok:true (omit sinceMarker). FG-path Win11 foreground refusal returns code:'ForegroundRestricted' — switch to method:'background' or DTM_BG_AUTO=1. Off-desktop target → WindowOnOtherDesktop, not sent. BG path auto-engages only when the target class is ConsoleWindowClass (conhost: cmd / PowerShell / pwsh) OR env DTM_BG_AUTO=1. Windows Terminal (CASCADIA_HOSTING_WINDOW_CLASS) is EXCLUDED (issue #173): WT runs on WinUI/XAML and silently drops WM_CHAR, so the FG path is default — pass sendOptions:{method:'background'} only if your WT build accepts BG input. Examples: terminal({action:'run', windowTitle:'PowerShell', input:'npm test', until:{mode:'pattern', pattern:'Test Files'}}) → recommended for test runners; matches when vitest summary appears terminal({action:'run', windowTitle:'pwsh', input:'ls'}) → quiet 1500ms wait, returns output (short interactive) terminal({action:'run', windowTitle:'pwsh', command:'ls'}) → identical to the above; command is a deprecated alias of input (issue #245) terminal({action:'read', windowTitle:'PowerShell', sinceMarker:'...'}) → incremental diff using the read action terminal({action:'send', windowTitle:'PowerShell', input:'echo hello'}) → sends text + Enter using the send action

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
inputNo'send': Text to send (max 10,000 chars). 'run': Command to send (Enter is appended automatically). Either `input` or its deprecated alias `command` is required.
linesNoTail N lines (default 50).
untilNo
actionYesAction selector — one of: read, send, run. Per-action required fields are enforced at call time (see the tool description); this flat schema lists every action's fields as optional.
methodNoInput routing channel. 'auto' defaults to background (WM_CHAR) when the target is a known terminal class (Windows Terminal / cmd / PowerShell / conhost) so user-side focus changes mid-stream cannot divert keystrokes. DTM_BG_AUTO=1 enables BG globally; 'auto' falls back to foreground for non-terminal targets. 'background' forces WM_CHAR injection (no focus change). 'foreground' forces the current behavior (SetForegroundWindow + clipboard paste). 'foreground_flash' (ADR-013 Option E) is an explicit opt-in 妥協 BG path for Windows Terminal: temporarily steals foreground (~50-80ms), pastes via clipboard, sends Ctrl+V + Enter (when pressEnter=true), restores foreground + clipboard. Single-line + < 5KiB only. `typingLeakRisk: true` in hints. Default 'auto'.auto
paneIdNo'read': Pane handle from key_locker launch_console — either the decimal hwnd of a classic console, or the 'wt:…' form for a Windows Terminal tab. Targets THIS pane even after its title changes; takes precedence over windowTitle. NOTE: read still resolves the pane's text by title under the hood, so it declines if the pane's current title is no longer unique among windows (a 'wt:…' pane additionally reads only while its tab is the ACTIVE tab of its Windows Terminal window). 'send': Pane handle from key_locker launch_console — either the decimal hwnd of a classic console (bound directly by hwnd, surviving a title change, e.g. after an ssh login the title becomes user@host), or the 'wt:…' form for a Windows Terminal tab (delivered to its Windows Terminal window while that tab is ACTIVE). Takes precedence over windowTitle. 'run': Pane handle from key_locker launch_console — a decimal console hwnd, or the `wt:<pid>:<startMs>` form for a Windows Terminal tab. Targets THIS pane for the whole run+wait+read: the pane title is re-resolved before every read, so a mid-run retitle (e.g. a classic console renaming to `user@host` after an ssh login) is still tracked. Takes precedence over windowTitle. This is the paneId FIELD of launch_console's result — NOT its windowTitle. A Windows Terminal pane is tracked while its tab is the ACTIVE tab (switching away pauses the reads until you switch back).
sourceNo'auto' = UIA TextPattern then OCR fallback; 'uia' = TextPattern only (fail on miss); 'ocr' = OCR only.auto
commandNo[Deprecated alias of `input`] Accepted for callers that mis-remember the parameter name; new code should use `input`. If both are set, `input` wins.
includeNoOptional response-shape opt-in. `['envelope']` returns the self-documenting envelope (`_version` / `data` / `as_of` / `confidence`). `['raw']` forces raw shape (overrides DESKTOP_TOUCH_ENVELOPE=1 server default). Default behaviour is raw shape (compat with existing clients).
pasteKeyNoPaste key combo. 'auto' picks ctrl+shift+v for WSL/bash/mintty/wezterm/alacritty, ctrl+v elsewhere. Only used when preferClipboard=true.auto
settleMsNoMilliseconds to wait after sending before checking foreground window (default 300).
chunkSizeNoSplit long input into chunks of this many characters in background mode to prevent terminal input queue saturation. Default 100. Only applies when method results in background.
stripAnsiNoStrip ANSI escape sequences (default true).
timeoutMsNoHard timeout in ms (default 30s)
focusFirstNoFocus the terminal before sending (default true).
forceFocusNoWhen true, bypass Windows foreground-stealing protection via AttachThreadInput before focusing the terminal window. Default: follows env DESKTOP_TOUCH_FORCE_FOCUS (default false).
pressEnterNoPress Enter after typing (default true).
trackFocusNoWhen true (default), detect if focus was stolen after sending. Reports focusLost in the response.
ocrLanguageNoBCP-47 language tag for OCR fallback. Auto-detects from system locale when omitted.
readOptionsNoExtra options forwarded to terminal read (lines, source, ocrLanguage, etc.)
sendOptionsNoExtra options forwarded to terminal send (method, chunkSize, etc.)
sinceMarkerNoMarker returned from a previous call. If found in current text, only the diff is returned.
windowTitleNo'read' / 'run': Partial title of the terminal window (e.g. 'PowerShell', 'pwsh', 'WindowsTerminal'). Provide windowTitle OR paneId (paneId takes precedence). 'send': Partial title of the terminal window. Provide windowTitle OR paneId (paneId takes precedence).
restoreFocusNoRestore the previously-focused window after sending (default true).
preferClipboardNoPaste the input from the clipboard instead of typing it — safe for long text and not run through IME conversion (does not help while an IME composition is already in progress: the paste keystroke is consumed by the IME and nothing arrives, though the call still answers ok; hints.clipboard.imeOpen says when the IME was on at the paste). Your clipboard is replaced for the duration of the call and put back afterwards, but the restore is skipped when another process wrote to the clipboard first, when its contents are too large for an addon-less build to carry back, or when saving it failed; hints.clipboard reports which backend served the paste and whether the restore ran. Default true.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed27 schema fields changedv2.3.1
    • addedInput schema / $schema
      Added value: +"http://json-schema.org/draft-07/schema#"
    • removedInput schema / additionalProperties
      Removed value: -false
    • addedInput schema / properties / chunkSize
      Added value: +{
      +  "default": 100,
      +  "description": "Split long input into chunks of this many characters in background mode to prevent terminal input queue saturation. Default 100. Only applies when method results in background.",
      +  "maximum": 10000,
      +  "minimum": 1,
      +  "type": "integer"
      +}
    • addedInput schema / properties / focusFirst
      Added value: +{
      +  "default": true,
      +  "description": "Focus the terminal before sending (default true).",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / forceFocus
      Added value: +{
      +  "description": "When true, bypass Windows foreground-stealing protection via AttachThreadInput before focusing the terminal window. Default: follows env DESKTOP_TOUCH_FORCE_FOCUS (default false).",
      +  "type": "boolean"
      +}
    • changedInput schema / properties / input / description
      Previous value: -"Command to send (Enter is appended automatically). Either `input` or its deprecated alias `command` is required."New value: +"'send': Text to send (max 10,000 chars).\n'run': Command to send (Enter is appended automatically). Either `input` or its deprecated alias `command` is required."
    • addedInput schema / properties / lines
      Added value: +{
      +  "default": 50,
      +  "description": "Tail N lines (default 50).",
      +  "maximum": 2000,
      +  "minimum": 1,
      +  "type": "integer"
      +}
    • addedInput schema / properties / method
      Added value: +{
      +  "default": "auto",
      +  "description": "Input routing channel. 'auto' defaults to background (WM_CHAR) when the target is a known terminal class (Windows Terminal / cmd / PowerShell / conhost) so user-side focus changes mid-stream cannot divert keystrokes. DTM_BG_AUTO=1 enables BG globally; 'auto' falls back to foreground for non-terminal targets. 'background' forces WM_CHAR injection (no focus change). 'foreground' forces the current behavior (SetForegroundWindow + clipboard paste). 'foreground_flash' (ADR-013 Option E) is an explicit opt-in 妥協 BG path for Windows Terminal: temporarily steals foreground (~50-80ms), pastes via clipboard, sends Ctrl+V + Enter (when pressEnter=true), restores foreground + clipboard. Single-line + < 5KiB only. `typingLeakRisk: true` in hints. Default 'auto'.",
      +  "enum": [
      +    "auto",
      +    "background",
      +    "foreground",
      +    "foreground_flash"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / ocrLanguage
      Added value: +{
      +  "description": "BCP-47 language tag for OCR fallback. Auto-detects from system locale when omitted.",
      +  "maxLength": 20,
      +  "type": "string"
      +}
    • addedInput schema / properties / paneId / description
      Added value: +"'read': Pane handle from key_locker launch_console — either the decimal hwnd of a classic console, or the 'wt:…' form for a Windows Terminal tab. Targets THIS pane even after its title changes; takes precedence over windowTitle. NOTE: read still resolves the pane's text by title under the hood, so it declines if the pane's current title is no longer unique among windows (a 'wt:…' pane additionally reads only while its tab is the ACTIVE tab of its Windows Terminal window).\n'send': Pane handle from key_locker launch_console — either the decimal hwnd of a classic console (bound directly by hwnd, surviving a title change, e.g. after an ssh login the title becomes user@host), or the 'wt:…' form for a Windows Terminal tab (delivered to its Windows Terminal window while that tab is ACTIVE). Takes precedence over windowTitle.\n'run': Pane handle from key_locker launch_console — a decimal console hwnd, or the `wt:<pid>:<startMs>` form for a Windows Terminal tab. Targets THIS pane for the whole run+wait+read: the pane title is re-resolved before every read, so a mid-run retitle (e.g. a classic console renaming to `user@host` after an ssh login) is still tracked. Takes precedence over windowTitle. This is the paneId FIELD of launch_console's result — NOT its windowTitle. A Windows Terminal pane is tracked while its tab is the ACTIVE tab (switching away pauses the reads until you switch back)."
    • addedInput schema / properties / paneId / maxLength
      Added value: +48
    • addedInput schema / properties / pasteKey
      Added value: +{
      +  "default": "auto",
      +  "description": "Paste key combo. 'auto' picks ctrl+shift+v for WSL/bash/mintty/wezterm/alacritty, ctrl+v elsewhere. Only used when preferClipboard=true.",
      +  "enum": [
      +    "auto",
      +    "ctrl+v",
      +    "ctrl+shift+v"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / preferClipboard
      Added value: +{
      +  "default": true,
      +  "description": "Paste the input from the clipboard instead of typing it — safe for long text and not run through IME conversion (does not help while an IME composition is already in progress: the paste keystroke is consumed by the IME and nothing arrives, though the call still answers ok; hints.clipboard.imeOpen says when the IME was on at the paste). Your clipboard is replaced for the duration of the call and put back afterwards, but the restore is skipped when another process wrote to the clipboard first, when its contents are too large for an addon-less build to carry back, or when saving it failed; hints.clipboard reports which backend served the paste and whether the restore ran. Default true.",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / pressEnter
      Added value: +{
      +  "default": true,
      +  "description": "Press Enter after typing (default true).",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / readOptions / additionalProperties
      Added value: +{}
    • addedInput schema / properties / readOptions / propertyNames
      Added value: +{
      +  "type": "string"
      +}
    • addedInput schema / properties / restoreFocus
      Added value: +{
      +  "default": true,
      +  "description": "Restore the previously-focused window after sending (default true).",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / sendOptions / additionalProperties
      Added value: +{}
    • addedInput schema / properties / sendOptions / propertyNames
      Added value: +{
      +  "type": "string"
      +}
    • addedInput schema / properties / settleMs
      Added value: +{
      +  "default": 300,
      +  "description": "Milliseconds to wait after sending before checking foreground window (default 300).",
      +  "maximum": 2000,
      +  "minimum": 0,
      +  "type": "integer"
      +}
    • addedInput schema / properties / sinceMarker
      Added value: +{
      +  "description": "Marker returned from a previous call. If found in current text, only the diff is returned.",
      +  "maxLength": 64,
      +  "type": "string"
      +}
    • addedInput schema / properties / source
      Added value: +{
      +  "default": "auto",
      +  "description": "'auto' = UIA TextPattern then OCR fallback; 'uia' = TextPattern only (fail on miss); 'ocr' = OCR only.",
      +  "enum": [
      +    "auto",
      +    "uia",
      +    "ocr"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / stripAnsi
      Added value: +{
      +  "default": true,
      +  "description": "Strip ANSI escape sequences (default true).",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / trackFocus
      Added value: +{
      +  "default": true,
      +  "description": "When true (default), detect if focus was stolen after sending. Reports focusLost in the response.",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / until / oneOf
      Added value: +[
      +  {
      +    "properties": {
      +      "mode": {
      +        "const": "quiet",
      +        "type": "string"
      +      },
      +      "quietMs": {
      +        "default": 1500,
      +        "description": "Stop when output is silent for this many ms (default 1500).",
      +        "maximum": 30000,
      +        "minimum": 50,
      +        "type": "integer"
      +      }
      +    },
      +    "required": [
      +      "mode"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "mode": {
      +        "const": "pattern",
      +        "type": "string"
      +      },
      +      "pattern": {
      +        "description": "Stop when output matches this string (or regex if regex:true)",
      +        "type": "string"
      +      },
      +      "quietMs": {
      +        "description": "Optional settle fallback. When set, also completes with completion.reason:'quiet' (completion.matchedPattern stays absent — check it to tell a match from a settle) if output stays stable for this many ms WITHOUT the pattern matching, instead of waiting for the hard timeout. Use for commands that may finish without ever printing the pattern — e.g. a final line with no trailing newline that an end-anchored pattern (\\n / $) can't bind (issue #384). Omit to keep waiting for the pattern until timeoutMs.",
      +        "maximum": 30000,
      +        "minimum": 50,
      +        "type": "integer"
      +      },
      +      "regex": {
      +        "default": false,
      +        "description": "If true, treat pattern as a regex",
      +        "type": "boolean"
      +      }
      +    },
      +    "required": [
      +      "mode",
      +      "pattern"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "mode": {
      +        "const": "exit",
      +        "type": "string"
      +      },
      +      "shell": {
      +        "default": "auto",
      +        "description": "Shell the terminal runs, used to build the completion epilogue. 'bash' and 'powershell' are first-class. 'cmd' is not supported yet (returns ExitModeShellUnsupported). 'auto' (default) detects from the window process: a conhost-hosted shell resolves, but a nested/remote shell is invisible (an SSH/WSL session reports its OUTER process, so auto picks the outer shell and warns — pass shell explicitly for remote sessions); auto fails loudly (ExitModeShellAmbiguous) only for unknown hosts such as Windows Terminal. Inputs ending in an open construct (here-doc, unbalanced quote, unterminated $(…), here-string, trailing \\/backtick) are rejected with ExitModeUnsafeInput.",
      +        "enum": [
      +          "bash",
      +          "powershell",
      +          "cmd",
      +          "auto"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "mode"
      +    ],
      +    "type": "object"
      +  }
      +]
    • removedInput schema / properties / until / type
      Removed value: -"object"
    • changedInput schema / properties / windowTitle / description
      Previous value: -"Partial title of the terminal window (e.g. 'PowerShell', 'pwsh', 'WindowsTerminal'). Provide windowTitle OR paneId (paneId takes precedence)."New value: +"'read' / 'run': Partial title of the terminal window (e.g. 'PowerShell', 'pwsh', 'WindowsTerminal'). Provide windowTitle OR paneId (paneId takes precedence).\n'send': Partial title of the terminal window. Provide windowTitle OR paneId (paneId takes precedence)."
  2. Changed2 schema fields changedv1.13.0
    • addedInput schema / properties / paneId
      Added value: +{
      +  "type": "string"
      +}
    • changedInput schema / properties / windowTitle / description
      Previous value: -"Partial title of the terminal window (e.g. 'PowerShell', 'pwsh', 'WindowsTerminal')."New value: +"Partial title of the terminal window (e.g. 'PowerShell', 'pwsh', 'WindowsTerminal'). Provide windowTitle OR paneId (paneId takes precedence)."
  3. Addedv1.9.2
  4. Removedv1.8.0
  5. Addedv1.6.0
  6. Removedv1.5.1
  7. Addedv1.5.0
  8. Removedv1.4.3
  9. Addedv1.4.2
  10. Removedv1.4.0
  11. Changed1 schema field changedv1.2.1
    • changedInput schema / oneOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "action": {
      -        "const": "read"
      -      }
      -    },
      -    "required": [
      -      "action"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "action": {
      -        "const": "send"
      -      }
      -    },
      -    "required": [
      -      "action"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "action": {
      -        "const": "run"
      -      },
      -      "input": {
      -        "description": "Command to send (Enter is appended automatically)",
      -        "maxLength": 10000,
      -        "type": "string"
      -      },
      -      "readOptions": {
      -        "description": "Extra options forwarded to terminal read (lines, source, ocrLanguage, etc.)",
      -        "type": "object"
      -      },
      -      "sendOptions": {
      -        "description": "Extra options forwarded to terminal send (method, chunkSize, etc.)",
      -        "type": "object"
      -      },
      -      "timeoutMs": {
      -        "default": 30000,
      -        "description": "Hard timeout in ms (default 30s)",
      -        "maximum": 600000,
      -        "minimum": 500,
      -        "type": "integer"
      -      },
      -      "until": {
      -        "type": "object"
      -      },
      -      "windowTitle": {
      -        "description": "Partial title of the terminal window (e.g. 'PowerShell', 'pwsh', 'WindowsTerminal').",
      -        "maxLength": 200,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "action",
      -      "windowTitle",
      -      "input"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "action": {
      +        "const": "read"
      +      },
      +      "include": {
      +        "description": "Optional response-shape opt-in. `['envelope']` returns the self-documenting envelope (`_version` / `data` / `as_of` / `confidence`). `['raw']` forces raw shape (overrides DESKTOP_TOUCH_ENVELOPE=1 server default). Default behaviour is raw shape (compat with existing clients).",
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      }
      +    },
      +    "required": [
      +      "action"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "action": {
      +        "const": "send"
      +      },
      +      "include": {
      +        "description": "Optional response-shape opt-in. `['envelope']` returns the self-documenting envelope (`_version` / `data` / `as_of` / `confidence`). `['raw']` forces raw shape (overrides DESKTOP_TOUCH_ENVELOPE=1 server default). Default behaviour is raw shape (compat with existing clients).",
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      }
      +    },
      +    "required": [
      +      "action"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "action": {
      +        "const": "run"
      +      },
      +      "include": {
      +        "description": "Optional response-shape opt-in. `['envelope']` returns the self-documenting envelope (`_version` / `data` / `as_of` / `confidence`). `['raw']` forces raw shape (overrides DESKTOP_TOUCH_ENVELOPE=1 server default). Default behaviour is raw shape (compat with existing clients).",
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      },
      +      "input": {
      +        "description": "Command to send (Enter is appended automatically)",
      +        "maxLength": 10000,
      +        "type": "string"
      +      },
      +      "readOptions": {
      +        "description": "Extra options forwarded to terminal read (lines, source, ocrLanguage, etc.)",
      +        "type": "object"
      +      },
      +      "sendOptions": {
      +        "description": "Extra options forwarded to terminal send (method, chunkSize, etc.)",
      +        "type": "object"
      +      },
      +      "timeoutMs": {
      +        "default": 30000,
      +        "description": "Hard timeout in ms (default 30s)",
      +        "maximum": 600000,
      +        "minimum": 500,
      +        "type": "integer"
      +      },
      +      "until": {
      +        "type": "object"
      +      },
      +      "windowTitle": {
      +        "description": "Partial title of the terminal window (e.g. 'PowerShell', 'pwsh', 'WindowsTerminal').",
      +        "maxLength": 200,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "action",
      +      "windowTitle",
      +      "input"
      +    ],
      +    "type": "object"
      +  }
      +]
  12. Addedv1.1.1
  13. Removedv1.1.0
  14. Addedv1.0.3

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does so: it enumerates completion reasons (quiet | pattern_matched | exited | timeout | window_closed | window_not_found | send_failed), documents outputIntegrity:'baseline_lost' and the forced empty output plus readError.code, the FileLockCollision warning, clipboard replacement by preferClipboard, the Windows Terminal exclusion from the BG path, and the foreground-refusal/other-desktop failure modes. Side effects (clipboard replaced, foreground stolen) and auth/routing constraints are surfaced up front.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded and cleanly sectioned with Purpose/Details/Prefer/Caveats/Examples, and the examples are useful. However, it is extremely dense and repeats material already carried by the 96%-coverage schema (paneId behavior is restated three times in the schema and again here, as is the clipboard-replacement caveat), so several sentences do not earn their place relative to structured fields.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, yet the description documents the response surface directly — completion={reason, elapsedMs}, outputIntegrity, warnings, hints (verifyDelivery.unverifiable, hints.clipboard, hints.terminalMarker.previousMatched) — along with recovery actions for each. For a 25-parameter, three-mode, multi-failure-mode tool, nothing operationally necessary is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 96%, so the baseline is 3, but the description adds genuinely non-redundant semantics: it explains the paneId-vs-windowTitle precedence ('pass the paneId field, NOT windowTitle'), the deprecated `command` alias for `input`, and when to choose pattern vs exit mode. It stops short of a full walkthrough of secondary parameters (settleMs, chunkSize, focusFirst), which the schema already covers.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a concrete verb+resource+scope: 'Interact with a terminal window: read output, send input, or run+wait+read in one call,' then splits the three action modes explicitly and notes that read/send absorb formerly-standalone tools. An agent can distinguish this from siblings like screenshot, keyboard, and window_dock without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit routing: prefer action='run' for execution+result, switch to until:{mode:'pattern'} for long-running builds/test runners because quiet mode can complete prematurely, and use read/send only for fine-grained interleaving. It also names the alternative to avoid ('Do not screenshot the terminal — action='read' is cheaper and structured'), which is exactly the when-not guidance the dimension asks for.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.