PTY-based terminal emulator with web backend for running TUI applications via HTTP/WebSocket APIs
Project description
Term Wrapper
A full-featured terminal emulator with web backend that can run any TUI (Text User Interface) application and control it via HTTP/WebSocket APIs.
Features
- PTY-based Terminal Emulation: Full pseudo-terminal support for running terminal applications
- FastAPI Backend: RESTful API and WebSocket endpoints for terminal control
- Session Management: Create, manage, and control multiple terminal sessions
- CLI Subcommands: Scriptable terminal control from bash/shell without writing Python
- Python Client Library: High-level primitives (wait_for_text, wait_for_quiet, get_text)
- Comprehensive Tests: 118 tests covering unit, integration, and e2e scenarios
What's Supported
โ Fully Working
- Simple commands:
ls,cat,echo, shell scripts - Interactive programs: Python REPL, bash, interactive shells
- Text editors:
vim(fully tested with comprehensive test suite) - System monitors:
htop(fully tested with screen buffer parsing) - AI CLI tools:
claudeCLI (tested with both print and interactive modes) - Full-screen TUI apps: Complete support for any terminal application
- ANSI colors & formatting: Complete support for escape sequences
- Terminal resize: Dynamic window resizing with SIGWINCH
- Multiple sessions: Concurrent terminal sessions with session management
๐ Optional Web Frontend
The included web frontend (frontend/) serves as a universal web mirror for any TUI application:
- Access any terminal app through your browser with full rendering
- Built with xterm.js for complete ANSI escape sequence support
- Mobile-friendly interface for running TUI apps on phones/tablets
- Not required - the REST/CLI API works standalone for programmatic control
Architecture
โโโโโโโโโโโโโโโโโโโ
โ CLI Client โ โ Python client for interactive control
โโโโโโโโโโฌโโโโโโโโโ
โ HTTP/WebSocket
โ
โโโโโโโโโโโโโโโโโโโ
โ FastAPI Server โ โ Web backend with REST + WebSocket
โโโโโโโโโโฌโโโโโโโโโ
โ
โ
โโโโโโโโโโโโโโโโโโโ
โ Session Manager โ โ Manages multiple terminal sessions
โโโโโโโโโโฌโโโโโโโโโ
โ
โ
โโโโโโโโโโโโโโโโโโโ
โ PTY Terminal โ โ Pseudo-terminal for running TUI apps
โโโโโโโโโโฌโโโโโโโโโ
โ
โ
โโโโโโโโโโโโโโโโโโโ
โ TUI App โ โ Any terminal application (vim, htop, etc.)
โโโโโโโโโโโโโโโโโโโ
Installation
From PyPI (Recommended for Users)
pip install term-wrapper
This installs the term-wrapper command:
term-wrapper --help
term-wrapper create htop
The server starts automatically! When you run a term-wrapper command, it automatically starts the backend server if it's not already running. The server picks an available port and saves it to ~/.term-wrapper/port for future commands.
From Source (For Development)
git clone https://github.com/rom1504/term-wrapper.git
cd term-wrapper
uv sync
When developing with uv, prefix commands with uv run:
uv run term-wrapper --help
uv run term-wrapper create htop
Quick Start
Run a TUI App
The server starts automatically when you use the CLI!
Option A: Using CLI Subcommands (Recommended)
# Create a session
SESSION=$(term-wrapper create bash -c "cd /tmp && claude" | python3 -c "import sys, json; print(json.load(sys.stdin)['session_id'])")
# Wait for text to appear
term-wrapper wait-text $SESSION "Welcome" --timeout 10
# Send input (supports \n, \r, \t, \x1b escape sequences)
term-wrapper send $SESSION "create hello.py\r"
# Get clean text output (ANSI codes stripped)
term-wrapper get-text $SESSION
# Wait for output to stabilize
term-wrapper wait-quiet $SESSION --duration 2
# Delete session
term-wrapper delete $SESSION
See all available subcommands:
term-wrapper --help
Note: In development with uv, prefix commands with uv run, e.g., `uv run term-wrapper --help
#### Option B: Using Python Client Library
```python
from term_wrapper.cli import TerminalClient
client = TerminalClient()
session_id = client.create_session(command=["bash"], rows=40, cols=120)
# High-level primitives
client.wait_for_text(session_id, "Welcome", timeout=10)
client.write_input(session_id, "ls -la\r")
text = client.get_text(session_id) # Clean text, ANSI stripped
client.wait_for_quiet(session_id, duration=2) # Wait for stability
client.delete_session(session_id)
client.close()
Option C: Using HTTP API Directly
# Create a session
curl -X POST http://localhost:8000/sessions \
-H "Content-Type: application/json" \
-d '{"command": ["python3", "examples/simple_tui.py"], "rows": 24, "cols": 80}'
# Returns: {"session_id": "xxx-xxx-xxx"}
# Get output
curl http://localhost:8000/sessions/{session_id}/output
# Send input
curl -X POST http://localhost:8000/sessions/{session_id}/input \
-H "Content-Type: application/json" \
-d '{"data": "+"}'
# Delete session
curl -X DELETE http://localhost:8000/sessions/{session_id}
CLI Subcommands
The term-wrapper CLI command is installed automatically when you install the package via pip. It provides scriptable terminal control without writing Python code. All commands output JSON for easy parsing.
Installation: The CLI entry point is defined in pyproject.toml as:
[project.scripts]
term-wrapper = "term_wrapper.cli:sync_main"
After pip install term-wrapper, the term-wrapper command will be available in your PATH. During development with uv, use uv run term-wrapper.
Available Subcommands
# Session Management
term-wrapper create [--rows N] [--cols N] [--env JSON] COMMAND...
term-wrapper list
term-wrapper info SESSION_ID
term-wrapper delete SESSION_ID
# Input/Output
term-wrapper send SESSION_ID TEXT # Supports \n, \r, \t, \x1b
term-wrapper get-output SESSION_ID # Raw output with ANSI codes
term-wrapper get-text SESSION_ID # Clean text (ANSI stripped)
term-wrapper get-screen SESSION_ID # Parsed 2D screen buffer
# Waiting Primitives
term-wrapper wait-text SESSION_ID TEXT [--timeout SECS]
term-wrapper wait-quiet SESSION_ID [--duration SECS] [--timeout SECS]
# Interactive
term-wrapper attach SESSION_ID # WebSocket interactive mode
term-wrapper web SESSION_ID # Open session in browser
# Server Management
term-wrapper stop # Stop the background server
Quick Example: Open Session in Browser
# Create a session
SESSION=$(term-wrapper create htop | python3 -c "import sys, json; print(json.load(sys.stdin)['session_id'])")
# Open it in your browser - that's it!
term-wrapper web $SESSION
Shell Script Example
#!/bin/bash
# Automate vim file editing
SESSION=$(term-wrapper create vim myfile.txt | \
python3 -c "import sys, json; print(json.load(sys.stdin)['session_id'])")
# Enter insert mode
term-wrapper send $SESSION "i"
sleep 0.3
# Type content
term-wrapper send $SESSION "Hello World\nLine 2"
sleep 0.5
# Save and quit (ESC + :wq)
term-wrapper send $SESSION "\x1b"
term-wrapper send $SESSION ":wq\r"
sleep 0.5
# Cleanup
term-wrapper delete $SESSION
See examples/ directory for more examples with vim, htop, and Claude Code.
Python Client Library
The TerminalClient class provides high-level primitives for terminal control:
from term_wrapper.cli import TerminalClient
client = TerminalClient(base_url="http://localhost:8000")
# Session management
session_id = client.create_session(command=["bash"], rows=40, cols=120)
sessions = client.list_sessions()
info = client.get_session_info(session_id)
client.delete_session(session_id)
# Input/Output
client.write_input(session_id, "ls -la\r")
output = client.get_output(session_id, clear=True)
text = client.get_text(session_id, strip_ansi_codes=True)
screen = client.get_screen(session_id) # 2D screen buffer
# Waiting primitives
client.wait_for_text(session_id, "username:", timeout=10)
client.wait_for_condition(session_id, lambda text: "done" in text, timeout=30)
client.wait_for_quiet(session_id, duration=2.0, timeout=30)
# Incremental reading
new_lines = client.get_new_lines(session_id)
client.mark_read(session_id)
client.close()
API Reference
REST Endpoints
POST /sessions- Create a new terminal sessionGET /sessions- List all active sessionsGET /sessions/{id}- Get session informationDELETE /sessions/{id}- Delete a sessionPOST /sessions/{id}/input- Send input to terminalPOST /sessions/{id}/resize- Resize terminal windowGET /sessions/{id}/output- Get raw terminal outputGET /sessions/{id}/screen- Get parsed 2D screen buffer (clean text)
WebSocket Endpoint
WS /sessions/{id}/ws- Real-time bidirectional terminal I/O
Testing
Run all tests:
uv run pytest tests/ -v
Run specific test suites:
# Unit tests
uv run pytest tests/test_terminal.py tests/test_api.py -v
# End-to-end tests
uv run pytest tests/test_e2e.py -v
# Integration tests with TUI apps
uv run pytest tests/test_ink_integration.py -v
# Vim tests
uv run pytest tests/test_vim.py -v
Application Reports
We've tested various TUI applications with detailed reports:
| Application | Status | Report | Tests |
|---|---|---|---|
| vim | โ Fully Functional | reports/vim_report.md | tests/test_vim.py |
| htop | โ Fully Functional | reports/htop_report.md | tests/test_htop.py |
| Claude CLI | โ Fully Functional | reports/claude_report.md | tests/test_claude.py |
Each report includes:
- Test methodology and results
- Usage examples (HTTP & WebSocket)
- Technical details (escape sequences, commands)
- Performance metrics
- Best practices
Want to add a new application? See reports/TESTING_GUIDE.md for a comprehensive step-by-step guide on testing and documenting new TUI applications.
Claude Code Skill
Want to use term-wrapper with Claude Code? Check out the Term Wrapper skill!
The skill enables Claude to control any terminal application programmatically. See skill/SKILL.md for complete instructions on using term-wrapper with CLI commands, Python, or HTTP APIs.
Web Frontend
Access any terminal application through your browser with the included web frontend.
Quick Start
The server starts automatically when you use the CLI. To access the web frontend:
# Option 1: Use any term-wrapper command (auto-starts server)
term-wrapper create bash
# Find the port (saved in ~/.term-wrapper/port)
PORT=$(cat ~/.term-wrapper/port)
# Open in browser
http://localhost:$PORT/
Or start the server manually for development:
# Start server on fixed port
uv run python main.py
# Open in browser
http://localhost:8000/
Launch Any Application
Use URL parameters to launch specific apps:
# Launch htop
http://localhost:8000/?cmd=htop
# Launch vim with a file
http://localhost:8000/?cmd=vim&args=/tmp/myfile.txt
# Launch Python REPL
http://localhost:8000/?cmd=python3
One-Command Launch
Shell function to start server and open browser automatically:
# Add to ~/.bashrc or ~/.zshrc
tweb() {
local cmd="${1:-bash}"
if ! curl -s http://localhost:8000/health > /dev/null 2>&1; then
cd /path/to/term_wrapper && uv run python main.py > /tmp/term-wrapper.log 2>&1 &
sleep 2
fi
open "http://localhost:8000/?cmd=${cmd}" # or xdg-open on Linux
}
# Usage
tweb htop # Launch htop in browser
tweb vim /tmp/test.txt # Launch vim in browser
Full documentation: See frontend/README.md for complete guide including mobile support, customization, and troubleshooting.
Example TUI Apps
Interactive htop Demo (examples/htop_demo.py)
Demonstrates full interaction with htop system monitor:
uv run python examples/htop_demo.py
Features:
- Navigate process list with arrow keys
- Toggle tree view
- Change sort order
- Interactive command mode
- Live system monitoring through the API
Python TUI App (examples/simple_tui.py)
A simple counter application demonstrating:
- Terminal control codes
- Raw mode input handling
- Interactive key bindings
Controls:
+: Increment counter-: Decrement counterr: Reset counterq: Quit
Project Structure
term_wrapper/
โโโ term_wrapper/ # Main package
โ โโโ terminal.py # PTY-based terminal emulator
โ โโโ session_manager.py # Session management
โ โโโ api.py # FastAPI backend
โ โโโ cli.py # CLI client
โโโ tests/ # Test suite
โ โโโ test_terminal.py # Terminal emulator tests
โ โโโ test_api.py # API tests
โ โโโ test_e2e.py # End-to-end tests
โ โโโ test_ink_integration.py # TUI app tests
โโโ examples/ # Example applications
โ โโโ simple_example.py # Simple HTTP API usage
โ โโโ vim_example.py # Vim automation example
โ โโโ htop_demo.py # Interactive htop demonstration
โ โโโ simple_tui.py # Python TUI demo
โโโ skill/ # Claude Code skill
โ โโโ SKILL.md # Term Wrapper skill for AI agents
โโโ frontend/ # Web frontend with xterm.js
โ โโโ README.md # Frontend documentation and usage guide
โ โโโ index.html # Main web interface
โ โโโ app.js # Frontend application logic
โ โโโ style.css # Styles and responsive design
โโโ docs/ # Documentation
โโโ scripts/ # Utility scripts
โโโ main.py # Server entry point
โโโ pyproject.toml # Project configuration
Development
Built with:
- uv - Fast Python package manager
- FastAPI - Modern web framework
- uvicorn - ASGI server
- pytest - Testing framework
- websockets - WebSocket support
License
ISC
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file term_wrapper-0.5.1.tar.gz.
File metadata
- Download URL: term_wrapper-0.5.1.tar.gz
- Upload date:
- Size: 106.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7c5db53afc9e8cd8cfb002adab6983ef8a7dd18d879b96e7279673c2125d1f0c
|
|
| MD5 |
705136e43cd31153ff9558e40505766e
|
|
| BLAKE2b-256 |
eb5a888db56c3448e2c1bc0e3bc10d175f8e8d340af6585044457154daa40775
|
File details
Details for the file term_wrapper-0.5.1-py3-none-any.whl.
File metadata
- Download URL: term_wrapper-0.5.1-py3-none-any.whl
- Upload date:
- Size: 30.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aa3383b460c3cb3b59320c725bc0a1563b731fbe6ed816a3e0d612fa1052656c
|
|
| MD5 |
3d0ac0b19e5ab5c234f23e225d6fc6df
|
|
| BLAKE2b-256 |
6358d46fd421d3adc6da4d3da74aac3195b980082071fb360b70f44bb317b262
|