Skip to main content

MCP server for interacting with a REPL running inside a tmux pane

Project description

tmux-repl-mcp

An MCP server for interacting with a REPL running inside a tmux pane.

With it running, you might say something like the following to your AI:

I have a Lisp REPL running in the other pane (pane 0) of the current window we're in (window 6). Please debug the function we're writing together using that REPL.

It works with way more than just Lisp -- Python shell, Ruby irb, and Goose itself are all supported. Additional types of REPLs may be specified via environment variable.

Use it with Goose, Cursor, or any other MCP client.

But Why

I was working with my AI to interact with another tmux pane, and it could do it via CLI commands, but it doesn't know how to just get the output of the last command it run. Indeed, tmux doesn't support this directly. You have to ask it for the last e.g. 5000 lines or whatever, hoping that window has your output. But this poisons the context with too many tokens, and it has no mechanism for waiting until the command is finished. You just have to keep sleeping and checking, sleeping and checking. With this tool, I can now send commands to a running REPL and read back the output with perfect timing — no more guessing how long to sleep, no more context poisoning, no more "wait, 1000 lines wasn't enough" nonsense.

Features

Tool Description
is_repl_ready Check whether the pane is showing a known REPL prompt
get_last_command Read the last command and its output from the pane history
execute_command Send a command, wait for the REPL to finish, return output

Quick start

uvx tmux-repl-mcp

Goose configuration

extensions:
  tmux-repl-mcp:
    type: stdio
    cmd: uvx
    args:
      - tmux-repl-mcp
    enabled: true

Tools

is_repl_ready

is_repl_ready(pane="0", max_lines=50)

Returns {"kind": "<kind>"} if a known REPL prompt is detected on the last non-empty line of the pane, or {"kind": null} if the pane is busy or shows an unrecognised prompt.

get_last_command

get_last_command(kind, pane="0", max_lines=200)

Looks back through up to max_lines lines of the pane history for a complete prompt→command→output→prompt block and returns:

{"last_command": "...", "output": "..."}

Both values are null when no complete block is found or the REPL is still running.

execute_command

execute_command(command, kind, pane="0", max_lines=200, check=2.0)
  1. Verifies the REPL is ready and of the expected kind.
  2. Sends command to the pane via tmux send-keys.
  3. Waits (polling every check seconds) until the REPL prompt reappears.
  4. Returns {"status": "ok", "last_command": "...", "output": "..."}.

REPL kinds

The following kinds are built-in:

Kind Prompt pattern
python ^>>>
ipython ^In \[\d+\]:
bash [\$\#]\s*$
zsh [\$\#%]\s*$
sh [\$\#]\s*$
lisp ^\*\s*$ / ^…>\s*$ / ^\d+\]\s*$
sbcl ^\*\s*$ / ^\d+\]\s*$
node ^>
irb ^irb\(.*\):\d+:\d+> $
iex ^iex\(\d+\)> $

Adding custom kinds

Set the TMUX_REPL_KINDS environment variable to a JSON object:

export TMUX_REPL_KINDS='{"myrepl": "^myrepl> "}'

Entries here are merged on top of the built-in defaults, so existing kinds can also be overridden.


Development

# Install dev dependencies
uv sync --dev

# Run tests
uv run pytest -v

Goose permission tips

Because is_repl_ready and get_last_command only read tmux state, they are safe to mark as Always Allow in Goose. Reserve Ask User for execute_command since it writes to your REPL.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tmux_repl_mcp-0.1.0.tar.gz (6.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tmux_repl_mcp-0.1.0-py3-none-any.whl (8.7 kB view details)

Uploaded Python 3

File details

Details for the file tmux_repl_mcp-0.1.0.tar.gz.

File metadata

  • Download URL: tmux_repl_mcp-0.1.0.tar.gz
  • Upload date:
  • Size: 6.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for tmux_repl_mcp-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3e06e4e8af9252c58b56b1ef9869612362cc147320fb35bdd1db875e24040de9
MD5 d8c5ae0b549bf855a217bd192505a0d7
BLAKE2b-256 ce293f3ec24ee7b972fb89d4a197a1796d82596c7052ebfdda932a9f48e76919

See more details on using hashes here.

Provenance

The following attestation bundles were made for tmux_repl_mcp-0.1.0.tar.gz:

Publisher: pypi.yaml on djha-skin/tmux-repl-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tmux_repl_mcp-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: tmux_repl_mcp-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 8.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for tmux_repl_mcp-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 77169ee095f74b43c4405fa4ed44e2564c94081f7f530d5a6cb9a3d27e8bdeb5
MD5 d3df47b545691c1c10aadb80ee8234a8
BLAKE2b-256 8e32086b42061d3bdfd562981553a8b659ce78af35c7d32b20d8b02e57c71145

See more details on using hashes here.

Provenance

The following attestation bundles were made for tmux_repl_mcp-0.1.0-py3-none-any.whl:

Publisher: pypi.yaml on djha-skin/tmux-repl-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page