# tmux-popup
Composable tmux popup system with gum UI components.
<p align="center">
<img src="https://raw.githubusercontent.com/angelsen/tap-tools/main/assets/recordings/processed/tmux-popup-demo.gif" width="640" alt="tmux-popup demo">
<br>
<em>Interactive popup components in action</em>
</p>
## ✨ Features
- 🎨 **Rich Components** - Styled text, inputs, selections, confirmations
- 🔧 **Composable API** - Chain commands for complex interactions
- 📦 **Zero Dependencies** - Pure Python, only needs tmux and gum
- 🎯 **Type-Safe** - Full type hints and result parsing
- 🚀 **Lightweight** - Simple, focused library
## 📋 Prerequisites
Required system tools:
- **tmux** - Terminal multiplexer for popups
- **gum** - Provides the UI components
```bash
# macOS
brew install tmux gum
# Arch Linux
sudo pacman -S tmux gum
# Ubuntu/Debian
sudo apt install tmux
# For gum: https://github.com/charmbracelet/gum#installation
```
## 📦 Installation
```bash
# Install from PyPI
uv add tmux-popup # Recommended
pip install tmux-popup # Alternative
# Install from source
uv add git+https://github.com/angelsen/tap-tools.git#subdirectory=packages/tmux-popup
# Or with pip:
pip install git+https://github.com/angelsen/tap-tools.git#subdirectory=packages/tmux-popup
```
## 🚀 Quick Start
```python
from tmux_popup import Popup
from tmux_popup.gum import GumStyle, GumInput, GumChoose
# Create a simple popup
popup = Popup(width="65", title="My App")
result = popup.add(
GumStyle("Welcome!", header=True),
GumInput(placeholder="Enter your name...")
).show()
print(f"Hello, {result}!")
```
## 🎮 Usage
### Basic Input
```python
popup = Popup(width="50")
name = popup.add(
GumStyle("User Setup", header=True),
"Please enter your details:",
GumInput(placeholder="Name...", value="")
).show()
```
### Confirmations
```python
popup = Popup()
confirmed = popup.add(
GumStyle("⚠️ Warning", warning=True),
"This will delete all data.",
GumConfirm("Are you sure?", default=False)
).show()
if confirmed:
# Proceed with deletion
pass
```
### Selections
```python
# Single choice
choice = popup.add(
GumStyle("Select Action", header=True),
GumChoose([
("new", "📝 New File"),
("open", "📂 Open File"),
("save", "💾 Save File"),
("quit", "❌ Quit")
])
).show()
# Multiple selection with fuzzy search
items = ["Python", "JavaScript", "Go", "Rust", "TypeScript"]
selected = popup.add(
GumStyle("Select Languages", info=True),
GumFilter(items, limit=0, fuzzy=True)
).show() # Returns list of selected items
```
### Tables
```python
data = [
["Active", "Server 1", "192.168.1.10"],
["Idle", "Server 2", "192.168.1.11"],
["Active", "Server 3", "192.168.1.12"],
]
selected_ip = popup.add(
GumStyle("Select Server", header=True),
GumTable(
data,
headers=["Status", "Name", "IP"],
return_column=2 # Return IP column
)
).show()
```
## 📚 Components
### Core
- `Popup` - Main popup runner with tmux display-popup
- `Command` - Base class for all UI commands
### Input Components
- `GumInput` - Single line text input
- `GumWrite` - Multi-line text editor
- `GumConfirm` - Yes/no confirmation
### Selection Components
- `GumChoose` - Single choice from list
- `GumFilter` - Fuzzy search with multi-select
- `GumFile` - File picker
- `GumTable` - Table with row selection
### Display Components
- `GumStyle` - Styled text with presets (header, info, warning, error)
- `GumFormat` - Markdown/template formatting
- `GumPager` - Scrollable text viewer
- `GumLog` - Formatted log display
### Utility Components
- `GumJoin` - Layout multiple elements
- `GumSpin` - Loading spinner for async operations
## 🏗️ Architecture
The library follows a simple pattern:
1. **Commands** render themselves to shell script
2. **Popup** combines commands and executes via tmux
3. **Results** are parsed and returned to Python
```python
# Commands know how to render
cmd = GumInput(value="default")
script_lines = cmd.render() # Returns list of shell commands
# Popup handles execution
popup = Popup()
result = popup.add(cmd).show() # Executes and returns parsed result
```
## 🛠️ Development
```bash
# Clone repository
git clone https://github.com/angelsen/tap-tools
cd tap-tools
# Install for development (recommended)
uv sync
uv run --package tmux-popup python examples/demo.py
# Or with pip:
cd packages/tmux-popup
pip install -e .
python examples/demo.py
```
## 📄 License
MIT - see [LICENSE](../../LICENSE) for details.
## 👤 Author
Fredrik Angelsen
## 🙏 Acknowledgments
Built on top of:
- [tmux](https://github.com/tmux/tmux) - Terminal multiplexer
- [gum](https://github.com/charmbracelet/gum) - Delightful CLI interactions
Raw data
{
"_id": null,
"home_page": null,
"name": "tmux-popup",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.12",
"maintainer_email": null,
"keywords": "tmux, terminal, popup, gum, tui, cli",
"author": "Fredrik Angelsen",
"author_email": "Fredrik Angelsen <fredrikangelsen@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/fe/b5/09675a9e0593b5d2b3f6fdce8c43a4d71ae1a3ae2aff0f6aa769877a2185/tmux_popup-0.1.1.tar.gz",
"platform": null,
"description": "# tmux-popup\n\nComposable tmux popup system with gum UI components.\n\n<p align=\"center\">\n <img src=\"https://raw.githubusercontent.com/angelsen/tap-tools/main/assets/recordings/processed/tmux-popup-demo.gif\" width=\"640\" alt=\"tmux-popup demo\">\n <br>\n <em>Interactive popup components in action</em>\n</p>\n\n## \u2728 Features\n\n- \ud83c\udfa8 **Rich Components** - Styled text, inputs, selections, confirmations\n- \ud83d\udd27 **Composable API** - Chain commands for complex interactions\n- \ud83d\udce6 **Zero Dependencies** - Pure Python, only needs tmux and gum\n- \ud83c\udfaf **Type-Safe** - Full type hints and result parsing\n- \ud83d\ude80 **Lightweight** - Simple, focused library\n\n## \ud83d\udccb Prerequisites\n\nRequired system tools:\n- **tmux** - Terminal multiplexer for popups\n- **gum** - Provides the UI components\n\n```bash\n# macOS\nbrew install tmux gum\n\n# Arch Linux\nsudo pacman -S tmux gum\n\n# Ubuntu/Debian\nsudo apt install tmux\n# For gum: https://github.com/charmbracelet/gum#installation\n```\n\n## \ud83d\udce6 Installation\n\n```bash\n# Install from PyPI\nuv add tmux-popup # Recommended\npip install tmux-popup # Alternative\n\n# Install from source\nuv add git+https://github.com/angelsen/tap-tools.git#subdirectory=packages/tmux-popup\n# Or with pip:\npip install git+https://github.com/angelsen/tap-tools.git#subdirectory=packages/tmux-popup\n```\n\n## \ud83d\ude80 Quick Start\n\n```python\nfrom tmux_popup import Popup\nfrom tmux_popup.gum import GumStyle, GumInput, GumChoose\n\n# Create a simple popup\npopup = Popup(width=\"65\", title=\"My App\")\nresult = popup.add(\n GumStyle(\"Welcome!\", header=True),\n GumInput(placeholder=\"Enter your name...\")\n).show()\n\nprint(f\"Hello, {result}!\")\n```\n\n## \ud83c\udfae Usage\n\n### Basic Input\n```python\npopup = Popup(width=\"50\")\nname = popup.add(\n GumStyle(\"User Setup\", header=True),\n \"Please enter your details:\",\n GumInput(placeholder=\"Name...\", value=\"\")\n).show()\n```\n\n### Confirmations\n```python\npopup = Popup()\nconfirmed = popup.add(\n GumStyle(\"\u26a0\ufe0f Warning\", warning=True),\n \"This will delete all data.\",\n GumConfirm(\"Are you sure?\", default=False)\n).show()\n\nif confirmed:\n # Proceed with deletion\n pass\n```\n\n### Selections\n```python\n# Single choice\nchoice = popup.add(\n GumStyle(\"Select Action\", header=True),\n GumChoose([\n (\"new\", \"\ud83d\udcdd New File\"),\n (\"open\", \"\ud83d\udcc2 Open File\"),\n (\"save\", \"\ud83d\udcbe Save File\"),\n (\"quit\", \"\u274c Quit\")\n ])\n).show()\n\n# Multiple selection with fuzzy search\nitems = [\"Python\", \"JavaScript\", \"Go\", \"Rust\", \"TypeScript\"]\nselected = popup.add(\n GumStyle(\"Select Languages\", info=True),\n GumFilter(items, limit=0, fuzzy=True)\n).show() # Returns list of selected items\n```\n\n### Tables\n```python\ndata = [\n [\"Active\", \"Server 1\", \"192.168.1.10\"],\n [\"Idle\", \"Server 2\", \"192.168.1.11\"],\n [\"Active\", \"Server 3\", \"192.168.1.12\"],\n]\n\nselected_ip = popup.add(\n GumStyle(\"Select Server\", header=True),\n GumTable(\n data,\n headers=[\"Status\", \"Name\", \"IP\"],\n return_column=2 # Return IP column\n )\n).show()\n```\n\n## \ud83d\udcda Components\n\n### Core\n- `Popup` - Main popup runner with tmux display-popup\n- `Command` - Base class for all UI commands\n\n### Input Components\n- `GumInput` - Single line text input\n- `GumWrite` - Multi-line text editor\n- `GumConfirm` - Yes/no confirmation\n\n### Selection Components\n- `GumChoose` - Single choice from list\n- `GumFilter` - Fuzzy search with multi-select\n- `GumFile` - File picker\n- `GumTable` - Table with row selection\n\n### Display Components\n- `GumStyle` - Styled text with presets (header, info, warning, error)\n- `GumFormat` - Markdown/template formatting\n- `GumPager` - Scrollable text viewer\n- `GumLog` - Formatted log display\n\n### Utility Components\n- `GumJoin` - Layout multiple elements\n- `GumSpin` - Loading spinner for async operations\n\n## \ud83c\udfd7\ufe0f Architecture\n\nThe library follows a simple pattern:\n1. **Commands** render themselves to shell script\n2. **Popup** combines commands and executes via tmux\n3. **Results** are parsed and returned to Python\n\n```python\n# Commands know how to render\ncmd = GumInput(value=\"default\")\nscript_lines = cmd.render() # Returns list of shell commands\n\n# Popup handles execution\npopup = Popup()\nresult = popup.add(cmd).show() # Executes and returns parsed result\n```\n\n## \ud83d\udee0\ufe0f Development\n\n```bash\n# Clone repository\ngit clone https://github.com/angelsen/tap-tools\ncd tap-tools\n\n# Install for development (recommended)\nuv sync\nuv run --package tmux-popup python examples/demo.py\n\n# Or with pip:\ncd packages/tmux-popup\npip install -e .\npython examples/demo.py\n```\n\n## \ud83d\udcc4 License\n\nMIT - see [LICENSE](../../LICENSE) for details.\n\n## \ud83d\udc64 Author\n\nFredrik Angelsen\n\n## \ud83d\ude4f Acknowledgments\n\nBuilt on top of:\n- [tmux](https://github.com/tmux/tmux) - Terminal multiplexer\n- [gum](https://github.com/charmbracelet/gum) - Delightful CLI interactions",
"bugtrack_url": null,
"license": "MIT",
"summary": "Composable tmux popup system with gum UI components",
"version": "0.1.1",
"project_urls": {
"Issues": "https://github.com/angelsen/tap-tools/issues",
"Repository": "https://github.com/angelsen/tap-tools"
},
"split_keywords": [
"tmux",
" terminal",
" popup",
" gum",
" tui",
" cli"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "b687a69fd7d5e76a48b75bfa5971f73cb13bb296da0f42b55bb4588f08be441b",
"md5": "3c0b8c4a8e641ce3a9f0091c3d2d4486",
"sha256": "5cabb9f8c0d10ed2377be7fcef8e2c3ccd4b3c48dca46dcb4540a8f13505b843"
},
"downloads": -1,
"filename": "tmux_popup-0.1.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "3c0b8c4a8e641ce3a9f0091c3d2d4486",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.12",
"size": 17908,
"upload_time": "2025-08-11T10:20:10",
"upload_time_iso_8601": "2025-08-11T10:20:10.990024Z",
"url": "https://files.pythonhosted.org/packages/b6/87/a69fd7d5e76a48b75bfa5971f73cb13bb296da0f42b55bb4588f08be441b/tmux_popup-0.1.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "feb509675a9e0593b5d2b3f6fdce8c43a4d71ae1a3ae2aff0f6aa769877a2185",
"md5": "6b13a16b5701b06b4235bb3c9ea59f40",
"sha256": "fa69c1164c3983020382b0588b74743beb609a2ac9e2b20b6cd286e90db2f718"
},
"downloads": -1,
"filename": "tmux_popup-0.1.1.tar.gz",
"has_sig": false,
"md5_digest": "6b13a16b5701b06b4235bb3c9ea59f40",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.12",
"size": 12460,
"upload_time": "2025-08-11T10:20:12",
"upload_time_iso_8601": "2025-08-11T10:20:12.188908Z",
"url": "https://files.pythonhosted.org/packages/fe/b5/09675a9e0593b5d2b3f6fdce8c43a4d71ae1a3ae2aff0f6aa769877a2185/tmux_popup-0.1.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-11 10:20:12",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "angelsen",
"github_project": "tap-tools",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "tmux-popup"
}