# run_program

Source: https://libtmux.org/en/ts/latest/mcp/tools/run_program/

> Run a program in a new pane of its own with your user's permissions. Run a program in a pane of its own and wait for it; returns its output and exit status. No shell parses argv and nothing is typed into its pane, so the output holds no command line or echo. Check outcome and outputComplete before trusting output. The pane is removed before this returns unless keep is set. A program still running at the timeout, capped by the server's wait ceiling, is ended: run longer ones with start_program. Commands come from this MCP server's PATH, and one not found or not executable fails the call before anything runs. stdin is input when given, else the terminal. PAGER and GIT_PAGER are cat. Use startDirectory in place of cd, ["sh", "-c", ...] for pipes, and run_shell_command for a command that needs an existing shell's state. Requires tmux 3.8 or newer.

tool MCPlatest

MCP concept example

A working example of the core library. It can change without notice.

[What concept means](https://libtmux.org/en/meta/support/#concept-and-alpha)

* **run_program**( [argv](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.input%2Fproperties%2Fargv): [Array](https://json-schema.org/understanding-json-schema/reference/array "array (JSON Schema)")<[string](https://json-schema.org/understanding-json-schema/reference/string "string (JSON Schema)")>, [fromPaneId](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.input%2Fproperties%2FfromPaneId)?: [string](https://json-schema.org/understanding-json-schema/reference/string "string (JSON Schema)"), [height](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.input%2Fproperties%2Fheight)?: [integer](https://json-schema.org/understanding-json-schema/reference/numeric "numeric (JSON Schema)"), [inheritShell](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.input%2Fproperties%2FinheritShell)?: [boolean](https://json-schema.org/understanding-json-schema/reference/boolean "boolean (JSON Schema)") | [Array](https://json-schema.org/understanding-json-schema/reference/array "array (JSON Schema)")<[string](https://json-schema.org/understanding-json-schema/reference/string "string (JSON Schema)")>, [input](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.input%2Fproperties%2Finput)?: [string](https://json-schema.org/understanding-json-schema/reference/string "string (JSON Schema)"), [keep](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.input%2Fproperties%2Fkeep)?: [boolean](https://json-schema.org/understanding-json-schema/reference/boolean "boolean (JSON Schema)"), [maxLines](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.input%2Fproperties%2FmaxLines)?: [integer](https://json-schema.org/understanding-json-schema/reference/numeric "numeric (JSON Schema)"), [placement](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.input%2Fproperties%2Fplacement)?: "window" | "split", [separateStderr](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.input%2Fproperties%2FseparateStderr)?: [boolean](https://json-schema.org/understanding-json-schema/reference/boolean "boolean (JSON Schema)"), [startDirectory](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.input%2Fproperties%2FstartDirectory)?: [string](https://json-schema.org/understanding-json-schema/reference/string "string (JSON Schema)"), [timeoutMs](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.input%2Fproperties%2FtimeoutMs)?: [integer](https://json-schema.org/understanding-json-schema/reference/numeric "numeric (JSON Schema)"), [width](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.input%2Fproperties%2Fwidth)?: [integer](https://json-schema.org/understanding-json-schema/reference/numeric "numeric (JSON Schema)"), )

  tool \[[source](https://github.com/libtmux/libtmux-ts/blob/f7b03a361f7c97677406b4ab937b2772ddb5f7dd/packages/mcp/src/tools/input.ts#L670)][¶](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program)

  Run a program in a new pane of its own with your user’s permissions. Run a program in a pane of its own and wait for it; returns its output and exit status. No shell parses argv and nothing is typed into its pane, so the output holds no command line or echo. Check outcome and outputComplete before trusting output. The pane is removed before this returns unless keep is set. A program still running at the timeout, capped by the server’s wait ceiling, is ended: run longer ones with [start_program](https://libtmux.org/en/ts/latest/mcp/tools/start_program/). Commands come from this MCP server’s PATH, and one not found or not executable fails the call before anything runs. stdin is input when given, else the terminal. PAGER and GIT_PAGER are cat. Use startDirectory in place of cd, \[“sh”, “-c”, …] for pipes, and [run_shell_command](https://libtmux.org/en/ts/latest/mcp/tools/run_shell_command/) for a command that needs an existing shell’s state. Requires tmux 3.8 or newer.

  * MCP request method

    `tools/call` Send `run_program` as the tool name, with the arguments below.

  ## Arguments[#](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.parameters)

  * **[`argv`](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.input%2Fproperties%2Fargv)** ([Array](https://json-schema.org/understanding-json-schema/reference/array "array (JSON Schema)")<[string](https://json-schema.org/understanding-json-schema/reference/string "string (JSON Schema)")>)

    The program and its arguments, as given: \[“git”, “status”, “—short”]. Put variables first with env: \[“env”, “CI=1”, “make”, “test”].

    * minItems

      `1`

    * maxItems

      `256`

  * **[`fromPaneId`](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.input%2Fproperties%2FfromPaneId)**? ([string](https://json-schema.org/understanding-json-schema/reference/string "string (JSON Schema)"))

    Run beside this pane, in its directory and session, with that session’s tmux environment. Variables the pane’s shell exported come only with inheritShell.

    * pattern

      `"^%\\d+$"`

  * **[`height`](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.input%2Fproperties%2Fheight)**? ([integer](https://json-schema.org/understanding-json-schema/reference/numeric "numeric (JSON Schema)"))

    Rows of the program’s terminal. Defaults to tmux’s default-size.

    * maximum

      `10000`

    * exclusiveMinimum

      `0`

  * **[`inheritShell`](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.input%2Fproperties%2FinheritShell)**? ([boolean](https://json-schema.org/understanding-json-schema/reference/boolean "boolean (JSON Schema)") | [Array](https://json-schema.org/understanding-json-schema/reference/array "array (JSON Schema)")<[string](https://json-schema.org/understanding-json-schema/reference/string "string (JSON Schema)")>)

    With fromPaneId, first read the variables that pane’s idle shell exported, by typing one env command into it, and run the program with them: true for all, or a list of names, such as \[“PATH”, “VIRTUAL_ENV”], for only those. The shell must be a POSIX one at its prompt, as [run_shell_command](https://libtmux.org/en/ts/latest/mcp/tools/run_shell_command/) requires. argv\[0] is then found on the shell’s PATH, and one missing exits 127.

    Matches one or more variants.

    * **[Variant 2](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.input%2Fproperties%2FinheritShell%2FanyOf%2F1)** ([Array](https://json-schema.org/understanding-json-schema/reference/array "array (JSON Schema)")<[string](https://json-schema.org/understanding-json-schema/reference/string "string (JSON Schema)")>)

      * minItems

        `1`

      * maxItems

        `256`

      - **[Items](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.input%2Fproperties%2FinheritShell%2FanyOf%2F1%2Fitems)** ([string](https://json-schema.org/understanding-json-schema/reference/string "string (JSON Schema)"))

        * pattern

          `"^[A-Za-z_][A-Za-z0-9_]*$"`

  * **[`input`](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.input%2Fproperties%2Finput)**? ([string](https://json-schema.org/understanding-json-schema/reference/string "string (JSON Schema)"))

    Text the program reads as its stdin, from a private file, so no shell quotes it and the pane never shows it. Needs the tmux server on this machine.

  * **[`keep`](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.input%2Fproperties%2Fkeep)**? ([boolean](https://json-schema.org/understanding-json-schema/reference/boolean "boolean (JSON Schema)"))

    Leave the pane, dead and showing the output, for a person to read and close. Set it only when a person asked to see the run.

  * **[`maxLines`](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.input%2Fproperties%2FmaxLines)**? ([integer](https://json-schema.org/understanding-json-schema/reference/numeric "numeric (JSON Schema)"))

    Keep at most this many lines, from the end. Defaults to the server limit.

    * maximum

      `9007199254740991`

    * exclusiveMinimum

      `0`

  * **[`placement`](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.input%2Fproperties%2Fplacement)**? ("window" | "split")

    With fromPaneId: “window”, the default, is a background window of its session; “split” splits that pane, so a person watching it sees the run. Focus stays put.

  * **[`separateStderr`](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.input%2Fproperties%2FseparateStderr)**? ([boolean](https://json-schema.org/understanding-json-schema/reference/boolean "boolean (JSON Schema)"))

    Return what the program writes to stderr apart, as stderr, so output holds stdout alone. Its stderr is then no terminal. Needs the tmux server on this machine, as input does.

  * **[`startDirectory`](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.input%2Fproperties%2FstartDirectory)**? ([string](https://json-schema.org/understanding-json-schema/reference/string "string (JSON Schema)"))

    Directory the program starts in, taken literally. Defaults to the directory this MCP server was started in, or the fromPaneId pane’s. One that cannot be entered fails the call, with the reason, before the program starts.

  * **[`timeoutMs`](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.input%2Fproperties%2FtimeoutMs)**? ([integer](https://json-schema.org/understanding-json-schema/reference/numeric "numeric (JSON Schema)"))

    How long to let it run; 30 s by default and clamped by the server ceiling. The result says what was used.

    * maximum

      `9007199254740991`

    * exclusiveMinimum

      `0`

  * **[`width`](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.input%2Fproperties%2Fwidth)**? ([integer](https://json-schema.org/understanding-json-schema/reference/numeric "numeric (JSON Schema)"))

    Columns of the program’s terminal. A program that formats to its width — ls, ps, git log —graph — lays out to this at the source.

    * maximum

      `10000`

    * exclusiveMinimum

      `0`

  ## Result[#](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.result)

  Returns [object](https://json-schema.org/understanding-json-schema/reference/object "object (JSON Schema)")

  * **[`droppedLines`](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.output%2Fproperties%2FdroppedLines)** ([integer](https://json-schema.org/understanding-json-schema/reference/numeric "numeric (JSON Schema)"))

    Lines of output withheld by maxLines.

    * minimum

      `-9007199254740991`

    * maximum

      `9007199254740991`

  * **[`effectiveTimeoutMs`](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.output%2Fproperties%2FeffectiveTimeoutMs)** ([integer](https://json-schema.org/understanding-json-schema/reference/numeric "numeric (JSON Schema)"))

    The timeout enforced.

    * minimum

      `-9007199254740991`

    * maximum

      `9007199254740991`

  * **[`exitStatus`](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.output%2Fproperties%2FexitStatus)** ([integer](https://json-schema.org/understanding-json-schema/reference/numeric "numeric (JSON Schema)") | [null](https://json-schema.org/understanding-json-schema/reference/null "null (JSON Schema)"))

    The exit status; null when a signal ended the program (see signal) or the timeout ended it (outcome timed_out).

    Matches one or more variants.

    * **[Variant 1](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.output%2Fproperties%2FexitStatus%2FanyOf%2F0)** ([integer](https://json-schema.org/understanding-json-schema/reference/numeric "numeric (JSON Schema)"))

      * minimum

        `-9007199254740991`

      * maximum

        `9007199254740991`

  * **[`lostEnd`](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.output%2Fproperties%2FlostEnd)** ([boolean](https://json-schema.org/understanding-json-schema/reference/boolean "boolean (JSON Schema)"))

    True when the end may be missing: tmux closed the pane before reading it. Running it again repeats what it did; for one with effects, have it write its output to a file with \[“sh”, “-c”, ”… > file”] and read the file.

  * **[`lostStart`](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.output%2Fproperties%2FlostStart)** ([boolean](https://json-schema.org/understanding-json-schema/reference/boolean "boolean (JSON Schema)"))

    True when the start scrolled past the scrollback limit; pipe a long output into a file, or read it with [start_program](https://libtmux.org/en/ts/latest/mcp/tools/start_program/).

  * **[`omittedBytes`](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.output%2Fproperties%2FomittedBytes)** ([integer](https://json-schema.org/understanding-json-schema/reference/numeric "numeric (JSON Schema)"))

    Output bytes omitted by the result ceiling.

    * minimum

      `-9007199254740991`

    * maximum

      `9007199254740991`

  * **[`outcome`](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.output%2Fproperties%2Foutcome)** ("completed" | "timed_out")

    completed: it ended on its own, or by the signal reported, whatever exitStatus says. timed_out: it was ended at the timeout, possibly part way through its work; running it again repeats what it did, so use [start_program](https://libtmux.org/en/ts/latest/mcp/tools/start_program/) for one that needs longer.

  * **[`output`](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.output%2Fproperties%2Foutput)** ([string](https://json-schema.org/understanding-json-schema/reference/string "string (JSON Schema)"))

    The bounded tail of what the program printed, as its terminal shows it; stderr and stdout share it.

  * **[`outputComplete`](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.output%2Fproperties%2FoutputComplete)** ([boolean](https://json-schema.org/understanding-json-schema/reference/boolean "boolean (JSON Schema)"))

    False when outcome is timed_out, lostStart or lostEnd is true, or maxLines or the result limit cut the output or stderr.

  * **[`returnedBytes`](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.output%2Fproperties%2FreturnedBytes)** ([integer](https://json-schema.org/understanding-json-schema/reference/numeric "numeric (JSON Schema)"))

    UTF-8 output bytes returned.

    * minimum

      `-9007199254740991`

    * maximum

      `9007199254740991`

  * **[`signal`](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.output%2Fproperties%2Fsignal)** ([string](https://json-schema.org/understanding-json-schema/reference/string "string (JSON Schema)") | [null](https://json-schema.org/understanding-json-schema/reference/null "null (JSON Schema)"))

    The signal that ended the program, such as “SIGTERM”; otherwise null. A program that exits 130 on its own reads as SIGINT, as that status means.

  * **[`stderr`](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.output%2Fproperties%2Fstderr)** ([string](https://json-schema.org/understanding-json-schema/reference/string "string (JSON Schema)") | [null](https://json-schema.org/understanding-json-schema/reference/null "null (JSON Schema)"))

    The bounded tail of what the program wrote to stderr, with separateStderr; otherwise null, and stderr is in output.

  No other properties are accepted.

  ## Annotations[#](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.annotations)

  * [`destructiveHint`](https://libtmux.org/en/ts/latest/mcp/reference/glossary/#destructiveHint)

    `true`

  * [`idempotentHint`](https://libtmux.org/en/ts/latest/mcp/reference/glossary/#idempotentHint)

    `false`

  * [`openWorldHint`](https://libtmux.org/en/ts/latest/mcp/reference/glossary/#openWorldHint)

    `true`

  * [`readOnlyHint`](https://libtmux.org/en/ts/latest/mcp/reference/glossary/#readOnlyHint)

    `false`

  ## Protocol data[#](https://libtmux.org/en/ts/latest/mcp/tools/run_program/#mcp.tool.run_program.schemas)

  Use the complete advertised contract for validation and client integration.

  Input schema

  ```json
  {
    "$schema": "http://json-schema.org/draft-07/schema#",
    "properties": {
      "argv": {
        "description": "The program and its arguments, as given: [\"git\", \"status\", \"--short\"]. Put variables first with env: [\"env\", \"CI=1\", \"make\", \"test\"].",
        "items": {
          "type": "string"
        },
        "maxItems": 256,
        "minItems": 1,
        "type": "array"
      },
      "fromPaneId": {
        "description": "Run beside this pane, in its directory and session, with that session's tmux environment. Variables the pane's shell exported come only with inheritShell.",
        "pattern": "^%\\d+$",
        "type": "string"
      },
      "height": {
        "description": "Rows of the program's terminal. Defaults to tmux's default-size.",
        "exclusiveMinimum": 0,
        "maximum": 10000,
        "type": "integer"
      },
      "inheritShell": {
        "anyOf": [
          {
            "type": "boolean"
          },
          {
            "items": {
              "pattern": "^[A-Za-z_][A-Za-z0-9_]*$",
              "type": "string"
            },
            "maxItems": 256,
            "minItems": 1,
            "type": "array"
          }
        ],
        "description": "With fromPaneId, first read the variables that pane's idle shell exported, by typing one env command into it, and run the program with them: true for all, or a list of names, such as [\"PATH\", \"VIRTUAL_ENV\"], for only those. The shell must be a POSIX one at its prompt, as run_shell_command requires. argv[0] is then found on the shell's PATH, and one missing exits 127."
      },
      "input": {
        "description": "Text the program reads as its stdin, from a private file, so no shell quotes it and the pane never shows it. Needs the tmux server on this machine.",
        "type": "string"
      },
      "keep": {
        "description": "Leave the pane, dead and showing the output, for a person to read and close. Set it only when a person asked to see the run.",
        "type": "boolean"
      },
      "maxLines": {
        "description": "Keep at most this many lines, from the end. Defaults to the server limit.",
        "exclusiveMinimum": 0,
        "maximum": 9007199254740991,
        "type": "integer"
      },
      "placement": {
        "description": "With fromPaneId: \"window\", the default, is a background window of its session; \"split\" splits that pane, so a person watching it sees the run. Focus stays put.",
        "enum": [
          "window",
          "split"
        ],
        "type": "string"
      },
      "separateStderr": {
        "description": "Return what the program writes to stderr apart, as stderr, so output holds stdout alone. Its stderr is then no terminal. Needs the tmux server on this machine, as input does.",
        "type": "boolean"
      },
      "startDirectory": {
        "description": "Directory the program starts in, taken literally. Defaults to the directory this MCP server was started in, or the fromPaneId pane's. One that cannot be entered fails the call, with the reason, before the program starts.",
        "type": "string"
      },
      "timeoutMs": {
        "description": "How long to let it run; 30 s by default and clamped by the server ceiling. The result says what was used.",
        "exclusiveMinimum": 0,
        "maximum": 9007199254740991,
        "type": "integer"
      },
      "width": {
        "description": "Columns of the program's terminal. A program that formats to its width — ls, ps, git log --graph — lays out to this at the source.",
        "exclusiveMinimum": 0,
        "maximum": 10000,
        "type": "integer"
      }
    },
    "required": [
      "argv"
    ],
    "type": "object"
  }
  ```

  Output schema

  ```json
  {
    "$schema": "http://json-schema.org/draft-07/schema#",
    "additionalProperties": false,
    "properties": {
      "droppedLines": {
        "description": "Lines of output withheld by maxLines.",
        "maximum": 9007199254740991,
        "minimum": -9007199254740991,
        "type": "integer"
      },
      "effectiveTimeoutMs": {
        "description": "The timeout enforced.",
        "maximum": 9007199254740991,
        "minimum": -9007199254740991,
        "type": "integer"
      },
      "exitStatus": {
        "anyOf": [
          {
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          },
          {
            "type": "null"
          }
        ],
        "description": "The exit status; null when a signal ended the program (see signal) or the timeout ended it (outcome timed_out)."
      },
      "lostEnd": {
        "description": "True when the end may be missing: tmux closed the pane before reading it. Running it again repeats what it did; for one with effects, have it write its output to a file with [\"sh\", \"-c\", \"... > file\"] and read the file.",
        "type": "boolean"
      },
      "lostStart": {
        "description": "True when the start scrolled past the scrollback limit; pipe a long output into a file, or read it with start_program.",
        "type": "boolean"
      },
      "omittedBytes": {
        "description": "Output bytes omitted by the result ceiling.",
        "maximum": 9007199254740991,
        "minimum": -9007199254740991,
        "type": "integer"
      },
      "outcome": {
        "description": "completed: it ended on its own, or by the signal reported, whatever exitStatus says. timed_out: it was ended at the timeout, possibly part way through its work; running it again repeats what it did, so use start_program for one that needs longer.",
        "enum": [
          "completed",
          "timed_out"
        ],
        "type": "string"
      },
      "output": {
        "description": "The bounded tail of what the program printed, as its terminal shows it; stderr and stdout share it.",
        "type": "string"
      },
      "outputComplete": {
        "description": "False when outcome is timed_out, lostStart or lostEnd is true, or maxLines or the result limit cut the output or stderr.",
        "type": "boolean"
      },
      "returnedBytes": {
        "description": "UTF-8 output bytes returned.",
        "maximum": 9007199254740991,
        "minimum": -9007199254740991,
        "type": "integer"
      },
      "signal": {
        "description": "The signal that ended the program, such as \"SIGTERM\"; otherwise null. A program that exits 130 on its own reads as SIGINT, as that status means.",
        "type": [
          "string",
          "null"
        ]
      },
      "stderr": {
        "description": "The bounded tail of what the program wrote to stderr, with separateStderr; otherwise null, and stderr is in output.",
        "type": [
          "string",
          "null"
        ]
      }
    },
    "required": [
      "droppedLines",
      "effectiveTimeoutMs",
      "exitStatus",
      "omittedBytes",
      "outcome",
      "output",
      "lostEnd",
      "lostStart",
      "outputComplete",
      "returnedBytes",
      "signal",
      "stderr"
    ],
    "type": "object"
  }
  ```
