Skip to main content

tmux-popup

Composable tmux popup system with gum UI components.

tmux-popup demo

Features

🎨 Rich Display - Canvas with Markdown and flexible layouts
🔧 Hybrid Approach - Python data handling + full gum passthrough
📦 Zero Dependencies - Pure Python, only needs tmux and gum
🎯 Type-Safe - Full type hints with proper base classes
🔍 Fuzzy Search - Multi-select filtering with dict support

Installation

# Prerequisites
sudo pacman -S tmux gum       # Arch
brew install tmux gum         # macOS

# Install package
uv add tmux-popup             # Recommended
pip install tmux-popup        # Alternative

Quick Start

from tmux_popup import Popup, Canvas, Text, Input, Choose

# Display text
popup = Popup(width="60%", height="30%")
canvas = Canvas(border="rounded", padding="1")
canvas.add(Text("Welcome to tmux-popup!"))
popup.add(canvas).show()

# Get input
name = Popup().add(Input(prompt="Name: ")).show()

# Display then choose
popup = Popup()
popup.add(Canvas().add(Text("Continue?")))
result = popup.add(Choose(options=["Yes", "No"])).show()

Core Concepts

Three Patterns

# 1. Display only
Popup().add(Canvas().add(content)).show()

# 2. Input only  
Popup().add(interactive_element).show()

# 3. Display + Input
popup = Popup()
popup.add(Canvas().add(content))
result = popup.add(interactive_element).show()

Content & Layout

from tmux_popup import Popup, Canvas, Markdown, Text, Row, Column

# Rich content with Markdown
canvas = Canvas(border="rounded", padding="1")
canvas.add(Markdown("""# Title

**Bold**, *italic*, `code`

\```python
def hello():
    print("Hi!")
\```
"""))

# Two-column layout
left = Column(width="50%", border="normal", padding="1")
left.add(Markdown("## Left"))

right = Column(width="50%", border="normal", padding="1")  
right.add(Text("Right content"))

canvas.add(Row(left, right))
popup.add(canvas).show()

Interactive Elements

from tmux_popup import Input, Choose, Filter, Confirm, Table

# Text input
email = Popup().add(
    Input(prompt="Email: ", placeholder="user@example.com")
).show()

# Single choice (dict shows labels, returns values)
actions = {
    "📝 New File": "new",
    "📂 Open": "open",
    "❌ Quit": "quit"
}
result = Popup().add(Choose(options=actions)).show()  # Returns: "new", "open", or "quit"

# Multi-select with fuzzy search
packages = ["numpy", "pandas", "fastapi", "django"]
selected = Popup().add(
    Filter(options=packages, no_limit=True, fuzzy=True)
).show()  # Returns: ["numpy", "pandas"]

# Confirmation
if Popup().add(Confirm(prompt="Delete all?")).show():
    print("Deleting...")

# Table selection
data = [
    {"name": "Alice", "role": "Admin"},
    {"name": "Bob", "role": "User"}
]
row = Popup().add(Table(data=data)).show()  # Returns selected row dict

Advanced Features

Complete Example

from tmux_popup import Popup, Canvas, Row, Column, Markdown, Text, Filter

# Build interface
popup = Popup(width="80%", height="60%")
canvas = Canvas(border="rounded", padding="1")

# Two columns
left = Column(width="50%", padding="1")
left.add(Markdown("## Instructions\n\n• Type to filter\n• Space to select"))

right = Column(width="50%", padding="1")
right.add(Markdown("## Example\n\n    packages = ['numpy', 'pandas']"))

canvas.add(Row(left, right))
popup.add(canvas)

# Add interactive filter
packages = {"NumPy": "numpy", "Pandas": "pandas"}
selected = popup.add(
    Filter(options=packages, no_limit=True, fuzzy=True)
).show()

Gum Passthrough

All gum flags work via kwargs:

Choose(
    options=["A", "B", "C"],
    cursor_foreground="212",   # gum styling
    height=10,                 # gum display option
    select_if_one=True,        # gum behavior
    header="Select:"           # gum text
)

Debug Mode

# See generated shell script
Popup(debug=True).add(Canvas().add("Test")).show()

Components Reference

Core

  • Popup - Main container (width, height, border, debug)
  • Canvas - Content area (border, padding, margin, align)

Content

  • Text - Plain text
  • Markdown - Formatted markdown with code blocks

Layout

  • Row - Horizontal container
  • Column - Vertical container (width, border, padding)

Interactive

  • Input - Single-line input (prompt, placeholder, header)
  • Write - Multi-line editor (width, height)
  • Confirm - Yes/no dialog (prompt, affirmative, negative)
  • Choose - Single/multi selection (options, limit, header)
  • Filter - Fuzzy search (options, no_limit, fuzzy)
  • Table - Tabular selection (data, border)
  • FilePicker - File browser (path, file, all)
  • Pager - Scrollable viewer (content)
  • Spin - Loading spinner (command, title)
  • Format - Text formatter (content, format_type)

Types

  • TimeoutResult, CancelledResult - Special return values

Development

git clone https://github.com/angelsen/tap-tools
cd tap-tools/packages/tmux-popup
uv sync

# Run examples
python examples/demo.py

📄 License

MIT - see LICENSE for details.

👤 Author

Fredrik Angelsen

🙏 Acknowledgments

Built on top of:

  • tmux - Terminal multiplexer
  • gum - Delightful CLI interactions

Metadata

Release files for tmux-popup 0.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tmux-popup 0.2.2
File Size Uploaded
tmux_popup-0.2.2.tar.gz 19.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for tmux-popup 0.2.2
File Interpreter ABI Platform
tmux_popup-0.2.2-py3-none-any.whl Python 3 none any Details

Total release size: 50.4 kB

Release files / tmux_popup-0.2.2.tar.gz

Download URL tmux_popup-0.2.2.tar.gz
Size 19.8 kB
Tags Source
SHA-256 checksum
How to use checksums
04bea0e764fea6c6d866df3a4a22e480a6d6959e93ef6ec13d801febfbfd5618
BLAKE2b-256 checksum
How to use checksums
cd5e2ffe459dcbd59b136be2c86c46585ab85ddc396a1352eb466c26d671b1d8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.18

Release files / tmux_popup-0.2.2-py3-none-any.whl

Download URL tmux_popup-0.2.2-py3-none-any.whl
Size 30.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
94f2a21e749c084f2c1413f25f3b2f48f77b1318d6c6334fb90e94b4b7c3600d
BLAKE2b-256 checksum
How to use checksums
38758e9cc591c4de8a9a8d1db64c42fa4e00bbb6f990c1e380c3b15f10459112
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.18

Release history Release notifications | RSS feed

This release

0.2.2 This release

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page