tuiw
![]()
TUI applications wrapper with tmux for headless operation.
Overview
rust-tuiw enables headless interaction with TUI (Terminal User Interface) applications by wrapping them with tmux. This allows for programmatic control and automation of interactive terminal applications.
Architecture
Daemon/Client Model
The application operates in two modes:
- Daemon: GraphQL server that manages tmux sessions and TUI applications
- Client: CLI interface that communicates with the daemon via GraphQL
On first invocation, if no daemon is running, the process automatically starts as a daemon. Subsequent invocations act as clients.
Components
┌─────────────────────────────────────────────────────────┐
│ Client │
│ (GraphQL Client) │
└──────────────────────┬──────────────────────────────────┘
│ GraphQL over HTTP
│ SSE for subscriptions
┌──────────────────────▼──────────────────────────────────┐
│ Daemon │
│ (GraphQL Server) │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Session Management (in-memory) │ │
│ │ - Session ID generation │ │
│ │ - CWD tracking │ │
│ │ - Multiple session support │ │
│ └─────────────────────┬───────────────────────────┘ │
│ │ │
│ ┌─────────────────────▼───────────────────────────┐ │
│ │ Tmux Wrapper │ │
│ │ - Session creation │ │
│ │ - Key input injection │ │
│ │ - Output capture (capture-pane) │ │
│ │ - Change detection for SSE │ │
│ └─────────────────────┬───────────────────────────┘ │
└────────────────────────┼───────────────────────────────┘
│
┌────────▼────────┐
│ Tmux Sessions │
│ ┌──────────┐ │
│ │ TUI │ │
│ │ App │ │
│ └──────────┘ │
└─────────────────┘
GraphQL API
Mutations
createSession(command: String!, cwd: String!): SessionIDsendKeys(sessionId: SessionID!, keys: String!): BooleancloseSession(sessionId: SessionID!): Boolean
Queries
listSessions: [Session!]!getOutput(sessionId: SessionID!): String!getSessionStatus(sessionId: SessionID!): SessionStatus!
Subscriptions
screenChanges(sessionId: SessionID!): String!(via SSE)
Session Management
Each session maintains:
- Unique session ID
- Working directory (cwd) from client invocation location
- Tmux session reference
- Output buffer and change detection state
Multiple TUI applications can run simultaneously, each in its own session.
Use Cases
Primary: Claude Code Automation
Claude Code currently lacks a headless interaction mode. By wrapping Claude Code with rust-tuiw, you can:
- Programmatically send commands
- Monitor output changes
- Automate coding workflows
General TUI Automation
Since rust-tuiw works with any TUI application, it enables automation for:
- All coding agents (not just Claude Code)
- Interactive CLI tools
- Terminal-based development environments
- Any ncurses/TUI application
Technology Stack
- Language: Rust (edition 2024)
- Async Runtime: tokio
- GraphQL: async-graphql
- HTTP Server: axum
- CLI Parsing: clap
- Process Management: tmux
Getting Started
Prerequisites
- Rust toolchain (1.91.1 or later)
- tmux
- NixOS users: Use
nix developfor development environment
Installation
The binary will be available at target/release/tuiw.
Alternatively, install via cargo:
Basic Usage
1. Create a Session
Create a new TUI session by specifying the command to run:
This will output a session ID (UUID format):
Session created: a1b2c3d4-e5f6-7890-abcd-ef1234567890
You can also specify a working directory:
2. List Sessions
View all active sessions:
Output:
Sessions:
a1b2c3d4-e5f6-7890-abcd-ef1234567890 - bash (/home/user)
3. Send Keys
Send keyboard input to a session:
4. Get Output
Capture the current screen content:
5. Check Status
Check if a session is running:
6. Close Session
Terminate a session:
Example: Automating vim
# Create a vim session
SESSION_ID=
# Open a file
# Enter insert mode and type
# Save and quit
# Close session
SSE for Real-time Monitoring
Subscribe to screen changes via Server-Sent Events:
This streams output whenever the screen content changes.
GraphQL API
The daemon exposes a GraphQL API at http://127.0.0.1:50051/graphql:
Troubleshooting
Daemon not starting:
- Check if port 50051 is available
- Ensure tmux is installed and in PATH
Session not found:
- The daemon is stateless and sessions are lost on restart
- Verify the session ID is correct using
rust-tuiw list
Keys not being sent:
- Ensure the session is still running with
rust-tuiw status - Special keys like Enter, Escape, Tab should be sent as separate commands
Development
See Makefile for available commands:
make build- Build the projectmake run- Run the applicationmake test- Run testsmake check- Run cargo checkmake clippy- Run clippy lintsmake fmt- Format code
License
Apache-2.0