npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@hughescr/tmux-mcp-server

v3.0.2

Published

A simplified and elegant MCP server for persistent shell execution via tmux.

Downloads

22

Readme

This is experimental software intended for testing and development purposes only. Do not use in production environments or with sensitive data.

A Model Context Protocol (MCP) server that provides persistent shell execution through tmux sessions. This server enables AI assistants to execute commands in persistent shells that maintain state across multiple interactions.

Table of Contents

Fork Acknowledgment

This project is a fork of the original persistent-shell-mcp by TNTisdial. The fork has been enhanced with parent tmux session detection and other improvements.

Features

  • Persistent Shell Sessions: Execute commands in tmux sessions that persist across MCP client restarts
  • Multiple Workspaces: Create isolated workspaces for different projects or tasks
  • Flexible Window Management: Organize commands in named windows within workspaces
  • Interactive Process Support: Handle long-running processes, REPLs, and interactive commands
  • Output Search: Search through terminal output with regex patterns and context
  • Non-blocking Execution: All commands run asynchronously, allowing parallel operations
  • Parent Session Detection: When started from within tmux, automatically uses the parent session instead of creating new ones

Installation

🚨 SECURITY WARNING: This software allows AI assistants to execute arbitrary shell commands on your system. Only install and use in isolated testing environments. Never use on systems with sensitive data or in production environments.

Prerequisites

  • Node.js 18.0.0 or higher (I use bun myself)
  • tmux installed on your system
    • Ubuntu/Debian: sudo apt install tmux
    • macOS: brew install tmux
    • CentOS/RHEL: sudo yum install tmux

Security

⚠️ IMPORTANT SECURITY NOTICE ⚠️

This MCP server executes arbitrary shell commands with your user privileges. Please review the comprehensive security documentation before use:

📋 Read SECURITY.md - Complete security guide covering:

  • Security risks and threat model
  • Input validation and command injection prevention
  • Workspace isolation and access controls
  • Secure deployment practices
  • Monitoring and incident response
  • Best practices for safe usage

Key security considerations:

  • Commands run with full user privileges
  • No built-in sandboxing or command filtering
  • All command output is accessible
  • File system and network access available
  • Resource exhaustion possible

Recommended for security-conscious users:

  • Use dedicated user accounts with limited privileges
  • Deploy in containers or isolated environments
  • Implement monitoring and logging
  • Review all commands before execution
  • Avoid use with sensitive data or production systems

Usage

MCP Client Configuration

Add to your MCP client configuration:

{
  "mcpServers": {
    "tmux-shell": {
      "command": "bunx",
      "args": ["--bunx", "@hughescr/tmux-mcp-server"]
    }
  }
}

or if you prefer npm/npx:

{
  "mcpServers": {
    "tmux-shell": {
      "command": "npx",
      "args": ["@hughescr/tmux-mcp-server"]
    }
  }
}

Available Tools

Quick Reference

| Tool Name | Description | Link to Section | |-----------|-------------|-----------------| | run_command | Start a command in a tmux window and return immediately | run_command | | get_output | Capture terminal output with lines or search mode | get_output | | send_input | Send text to a window (automatically appends Enter) | send_input | | send_keys | Send special key sequences using tmux syntax | send_keys | | scrollback_size | Get or set scrollback buffer size for workspace/session | scrollback_size | | create_workspace | Create a new workspace with a "main" window | create_workspace | | destroy_workspace | Destroy a workspace and all its windows | destroy_workspace | | list_workspaces | List all active workspaces and their windows | list_workspaces |

run_command

Start a command in a tmux window and return immediately.

run_command({
  command: "npm run dev",
  workspace_id: "my-project",  // optional, defaults to "default" - workspace_id not available if MCP server running inside tmux already
  window_name: "server"        // optional, defaults to "main"
})

To stop a running command, use send_keys with ["C-c"].

get_output

Capture terminal output with two modes:

Lines mode - Get a specific number of lines:

get_output({
  workspace_id: "my-project", // workspace_id not available if MCP server running inside tmux already
  window_name: "server",
  lines: 50  // optional, defaults to all scrollback history
})

Search mode - Search for patterns in output:

get_output({
  workspace_id: "my-project", // workspace_id not available if MCP server running inside tmux already
  window_name: "server",
  search: {
    pattern: "error|warning",     // JavaScript regex (no delimiters)
    context_lines: 2,            // lines before/after matches (default: 2)
    include_line_numbers: true   // include absolute line numbers (default: true)
  }
})

send_input

Send text to a window (automatically appends Enter).

send_input({
  text: "print('Hello, World!')",
  workspace_id: "my-project", // workspace_id not available if MCP server running inside tmux already
  window_name: "python"
})

send_keys

Send special key sequences using tmux syntax.

send_keys({
  keys: ["C-c"],  // Ctrl+C to interrupt
  workspace_id: "my-project", // workspace_id not available if MCP server running inside tmux already
  window_name: "server"
})

Common keys: C-c (interrupt), C-d (EOF), Up/Down (history), Tab (completion)

create_workspace

Create a new workspace with a "main" window.

create_workspace({ // tool not available if MCP server running inside tmux already
  workspace_id: "new-project"
})

destroy_workspace

Destroy a workspace and all its windows.

destroy_workspace({ // tool not available if MCP server running inside tmux already
  workspace_id: "old-project"
})

list_workspaces

List all active workspaces and their windows.

list_workspaces() // If MCP server running inside tmux already, only lists the windows of the current session
// Returns: "project1: main, server, database\nproject2: main"

scrollback_size

Get or set the scrollback buffer size for the entire workspace/session. This setting only applies to NEW windows created AFTER the change - existing windows keep their original scrollback size.

// Get current scrollback size
scrollback_size({
  workspace_id: "my-project" // workspace_id not available if MCP server running inside tmux already
})

// Set new scrollback size for future windows
scrollback_size({
  workspace_id: "my-project", // workspace_id not available if MCP server running inside tmux already
  lines: 10000  // Set to 10,000 lines, or 0 for unlimited (use with caution)
})

Available Resources

The server provides two MCP resources with helpful reference information:

tmux://keys-reference

Common tmux key sequences and their meanings, including:

  • Control keys (C-c, C-d, C-z)
  • Navigation keys (arrows, page up/down)
  • Other special keys

tmux://common-patterns

Common usage patterns and examples for:

  • Running commands
  • Interactive sessions
  • Monitoring long-running processes
  • Searching output
  • Managing multiple tasks

Scrollback Buffer Management

Scrollback buffers store terminal history and are managed per-session in tmux. The scrollback_size tool sets the session-level history-limit option which controls the buffer size for NEW windows created after the setting is changed. Existing windows keep their original scrollback size and cannot be modified. The MCP server automatically sets workspaces to 50,000 lines of history (compared to tmux's default of 2,000 lines) to provide more context for AI assistants.

Memory Usage Estimates

| Buffer Size | Memory per 80-column window | Notes | |-------------|----------------------------|-------| | 2,000 lines | ~1 MB | tmux default | | 10,000 lines | ~5 MB | More limited memory consumption | | 50,000 lines | ~24 MB | MCP server default | | 250,000 lines | ~120 MB | Very long-running or verbose processes |

Important considerations:

  • The scrollback_size tool sets the session-level history-limit option
  • This setting only affects NEW windows created AFTER the change
  • Existing windows keep their original scrollback size and cannot be modified
  • You must set the scrollback size BEFORE creating windows that need larger buffers
  • Every window carries its own ring buffer in memory
  • Plain ASCII text uses approximately 0.5 kB per 80-column line
  • Rich content (colored Unicode, complex formatting) can use up to 4x more memory
  • Setting lines to 0 means unlimited scrollback (use with caution on long-running processes)

Practical Recommendations

For development work: 10,000-50,000 lines provides good context without excessive memory usage.

For log monitoring: Consider lower values (2,000-5,000 lines) if monitoring high-volume logs.

For interactive workspaces: Higher values (50,000+ lines) help maintain context across long sessions.

Examples

// Check current scrollback size for workspace
scrollback_size({ workspace_id: "my-project" })

// Set conservative size for future windows in workspace (do this BEFORE creating windows)
scrollback_size({
  workspace_id: "my-project",
  lines: 2000
})
// Now create windows that will use the 2000-line buffer
run_command({ command: "tail -f /var/log/nginx/access.log", workspace_id: "my-project", window_name: "logs" })

// Set larger buffer for development workspace (do this BEFORE creating windows)
scrollback_size({
  workspace_id: "dev-project",
  lines: 50000
})
// Now create windows that will use the 50000-line buffer
run_command({ command: "npm run dev", workspace_id: "dev-project", window_name: "server" })

// Set unlimited history for important workspace (use carefully, do this BEFORE creating windows)
scrollback_size({
  workspace_id: "important-project",
  lines: 0
})

Memory monitoring tip: Use get_output with the lines parameter to limit how much history you retrieve, even if the buffer is larger.

Examples

For comprehensive examples of using the tmux MCP server, see EXAMPLES.md. The examples cover:

  • Basic command execution
  • Interactive development workflows (Python, Node.js, etc.)
  • Server management (dev servers, databases)
  • Log monitoring
  • Testing and CI/CD
  • SSH and remote operations
  • Workspace organization
  • And more practical use cases

Common Workflows

Running a Development Server

// Start the server
run_command({ command: "bun run dev", workspace_id: "myapp", window_name: "server" })

// Check server output
get_output({ workspace_id: "myapp", window_name: "server" })

// Search for errors
get_output({
  workspace_id: "myapp",
  window_name: "server",
  search: { pattern: "error|failed", context_lines: 3 }
})

// Stop the server
send_keys({ keys: ["C-c"], workspace_id: "myapp", window_name: "server" })

Interactive Python Session

// Start Python REPL
run_command({ command: "python3", workspace_id: "data", window_name: "python" })

// Send Python commands
send_input({ text: "import pandas as pd", workspace_id: "data", window_name: "python" })
send_input({ text: "df = pd.read_csv('data.csv')", workspace_id: "data", window_name: "python" })

// Check output
get_output({ workspace_id: "data", window_name: "python" })

// Exit Python
send_keys({ keys: ["C-d"], workspace_id: "data", window_name: "python" })

Managing Multiple Projects

// Create workspaces for different projects
create_workspace({ workspace_id: "frontend" })
create_workspace({ workspace_id: "backend" })
create_workspace({ workspace_id: "database" })

// Run commands in each
run_command({ command: "npm run dev", workspace_id: "frontend" })
run_command({ command: "python app.py", workspace_id: "backend" })
run_command({ command: "docker compose up", workspace_id: "database" })

// Check what's running
list_workspaces()

Architecture

Each workspace is a tmux session that can contain multiple named windows. This allows you to:

  • Organize related commands together
  • Maintain separate environments for different projects
  • Keep processes running independently
  • Switch between tasks without losing state

Parent Session Detection

When the MCP server is launched from within an existing tmux session, it automatically detects and uses that session instead of creating new ones. This provides seamless integration when running Claude or other MCP clients inside tmux.

Behavior when parent session is detected:

  • All commands run in the parent tmux session
  • workspace_id parameter is removed from all tools
  • Workspace management tools (create_workspace, destroy_workspace) are disabled
  • The server prevents sending commands to its own window for safety
  • Windows created by the server appear alongside your existing tmux windows

Example usage in parent session mode:

// No workspace_id needed - uses parent session
run_command({ command: "bun test", window_name: "tests" })
get_output({ window_name: "tests" })
send_keys({ keys: ["C-c"], window_name: "tests" })

Running Claude Code in tmux with Control Mode

You can run Claude Code inside tmux with control mode enabled (-CC flag) to monitor the windows that the MCP server creates in your terminal application. This provides a visual way to see what commands are running:

# Start or attach to a tmux session with control mode
tmux -CC new -A -n Claude -s persistent-shell bunx --bun @anthropic-ai/claude-code@latest --mcp-config ~/.claude/mcp.json

This command:

  • -CC: Enables tmux control mode for terminal integration
  • new -A: Creates a new session or attaches to existing one
  • -n Claude: Names the initial window "Claude"
  • -s persistent-shell: Names the session "persistent-shell"
  • Runs Claude Code with your MCP configuration

When using this setup, the tmux MCP server will detect it's running inside the "persistent-shell" session and automatically use that session for all operations. New windows created by the MCP server will appear in your terminal's tab bar or window list (assuming you're using something like iTerm with tmux -CC support).

Troubleshooting

Tmux Not Found

Error: tmux command not found

Install tmux using your system's package manager.

Command Not Responding

Use get_output to check the current state, then send_keys(['C-c']) to interrupt if needed.

Checking Process State

Use get_output with search to look for specific patterns:

get_output({
  workspace_id: "myapp",
  search: { pattern: "listening on|started|ready" }
})

License

MIT