A beautiful terminal UI for running Ansible playbooks — without memorizing a single flag.
curl -sL https://raw.githubusercontent.com/zidesm/ansible-tui/main/install.sh | bash
sudo mv ansible-tui /usr/local/bin/No Node.js. No Python runtime. No background services. Just one binary.
Running ansible-playbook precisely is harder than it looks:
# Which tags were in that play again?
ansible-playbook -i inventory.yml site.yml \
--limit "web01,web02" \
--tags "deploy,restart" \
--check --diffYou end up grepping YAML files, copy-pasting hostnames, and manually composing
--tags lists — every time.
Heavy orchestrators like AWX or Semaphore solve this at the cost of a Kubernetes cluster, a PostgreSQL database, and a background daemon.
Ansible TUI is the middle ground: a zero-dependency, single-file executable that gives you a visual interactive selector right in your terminal.
┌──────────────────────────────────────────────────────────────────────────┐
│ 🚀 Ansible TUI Runner ✓ Last run succeeded │
│ │
│ ┌──── Hosts (2/3) ─────┐ ┌──── Playbook (4/7 tasks) ─────────────────┐ │
│ │ ❯ [x] webservers(2/2)│ │ ❯ ▼ [x] Deploy Application │ │
│ │ [x] web01 │ │ ▼ [~] Install packages [apt] │ │
│ │ [x] web02 │ │ ❯ [x] Install nginx │ │
│ │ [ ] dbservers (0/1)│ │ [x] Install certbot │ │
│ │ [ ] db01 │ │ ▼ [x] Deploy code [deploy] │ │
│ └──────────────────────┘ │ [x] Sync files │ │
│ │ [x] Restart services │ │
│ ┌─ Command Preview ──────────────────────────────────────────────────┐ │
│ │ ansible-playbook -i inventory.yml playbook.yml --limit web01,web02 │ │
│ │ --tags apt,deploy --check ON --diff off │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ [Tab] Switch [Space] Toggle [a] All Hosts [e] Expand All [r] Run │
└──────────────────────────────────────────────────────────────────────────┘
| Ansible TUI | AWX / Semaphore | ansible-playbook CLI |
|
|---|---|---|---|
| Setup | Single binary | K8s + DB required | ✓ Already there |
| Visual host/task picker | ✓ | ✓ | ✗ |
| Live output streaming | ✓ | ✓ | ✓ |
| State saved across runs | ✓ | ✓ | ✗ |
| Works offline / in SSH | ✓ | ✗ | ✓ |
| Zero dependencies | ✓ | ✗ | ✓ |
| Tag-aware selection | ✓ | Partial | Manual |
all:
children:
webservers:
hosts:
web1.example.com:
web2.example.com:
dbservers:
hosts:
db1.example.com:
db2.example.com:[webservers]
web1.example.com
web2.example.com
web3.example.com ansible_host=10.0.1.3
[dbservers]
db1.example.com
db2.example.comSupports inline host variables (e.g., ansible_host=10.0.1.3) — the hostname is extracted as the first token.
You can also organize inventory as a directory where each subdirectory or file represents a host group:
inventory/
├── webservers/
│ └── hosts.yml
├── dbservers/
│ └── hosts.yml
├── management # extensionless INI file
└── cacheservers.ini # or .ini extension
Each group subdirectory should contain hosts.yml, hosts.yaml, main.yml, or main.yaml with one of these formats:
Map format:
hosts:
web1.example.com:
web2.example.com:List format:
hosts:
- web1.example.com
- web2.example.comDirect list format:
- web1.example.com
- web2.example.comINI files at the root level can also use standard INI group syntax.
Pass the folder path as the inventory argument:
ansible-tui inventory/ playbook.yml# Auto-discover inventory.yml and playbook.yml from CWD or parent dir
ansible-tui
# Explicit paths
ansible-tui /path/to/inventory.yml /path/to/playbook.yml
# Clean start — ignore saved state
ansible-tui --clean
ansible-tui -C
# Show version
ansible-tui --versionAuto-discovery checks both . and .. for:
- Inventory:
inventory.yml,inventory.yaml,hosts.yml,hosts.yaml,hosts,inventory(directory) - Playbook:
playbook.yml,playbook.yaml,site.yml,site.yaml
# From local clone
deno run --allow-read --allow-run --allow-write --allow-env app.tsx
# Directly from GitHub — zero local files required
deno run --allow-read --allow-run --allow-write --allow-env \
https://raw.githubusercontent.com/congzhangzh/ansible-tui/main/app.tsx| Key | Action |
|---|---|
Tab |
Switch between Hosts / Playbook panel |
↑ ↓ |
Move cursor |
PgUp PgDn |
Page up / down |
Space |
Toggle checkbox (play/block toggles all children) |
→ / Enter |
Expand play or block |
← |
Collapse (on task/block: jump to parent) |
a |
Select / deselect all hosts |
e |
Expand all / collapse all plays & blocks |
| Key | Action |
|---|---|
c |
Toggle --check (dry-run) |
d |
Toggle --diff (show changes) |
r |
Run ansible-playbook |
s |
Print command and exit (for piping/scripting) |
q |
Quit |
| Key | Action |
|---|---|
↑ ↓ / PgUp PgDn |
Scroll |
Enter |
Back to selection |
q |
Quit |
- Parse — Reads
inventory.ymlfor host groups andplaybook.ymlfor plays/tasks (recursively expandsblock:structures, respects inherited tags) - Select — Interactive split-pane TUI: left pane for host targeting
(
--limit), right pane for task/tag selection (--tags) - Run — Spawns
ansible-playbookas a child process; output streams live inside the TUI with ANSI color support - Iterate — Press
Enterafter a run to return to selection with all choices intact. Tweak and re-run instantly.
- Items tagged
neverare shown with a(never)indicator and their tag is never added to--tagsautomatically - If a play itself has
[never, some-tag], selecting any task in that play will includesome-tagin--tags - Tags are rendered in cyan for quick identification
Selections (hosts, tasks, expanded plays, --check/--diff flags) are saved to
.ansible-tui-state.json next to your inventory. Restored automatically on next
launch. Use --clean to start fresh.
Deno (recommended):
git clone https://github.com/congzhangzh/ansible-tui
cd ansible-tui
deno compile --allow-read --allow-run --allow-write --allow-env -o ansible-tui app.tsxNode.js / tsx:
npm install
npm start # runs via tsxIssues and PRs welcome. This is intentionally a single-file app — all logic
lives in app.tsx to keep it easy to audit, fork, and run without a build step.
