quay-tui 0.3.0

A TUI port manager for local processes, SSH forwards, and Docker containers
quay-tui-0.3.0 is not a library.

Quay

CI Crates.io License: MIT

A TUI port manager for local processes, SSH forwards, and Docker containers.

Features

  • Unified View: See all ports in one place (local, SSH, Docker)
  • Remote Mode: Scan remote hosts via SSH and forward ports with one key (quay --remote user@server)
  • Docker Target Mode: Discover LISTEN ports inside a Docker container and forward them via SSH (quay --remote host --docker container)
  • Interactive TUI: Navigate with keyboard, filter by source, search by name/port
  • Quick Actions: Kill processes or create SSH forwards directly from the interface
  • SSH Presets: Save frequently used port forwards as presets for one-key launch
  • Mouse Support: Click and scroll navigation (configurable)
  • Configuration: Customize auto-refresh interval, default filter, and more via ~/.config/quay/config.toml
  • CLI Support: Non-interactive commands for scripting (quay list --json)
  • Fast: Written in Rust with ratatui

Installation

cargo install quay-tui

Usage

TUI Mode (default)

quay

Remote Mode

Scan remote host ports via SSH and forward them locally:

# TUI with remote port scanning
quay --remote user@server

# List remote ports
quay --remote user@server list
quay --remote user@server list --json

# Kill remote process
quay --remote user@server kill 3000

In remote TUI mode:

  • Header shows Quay [remote: user@server]
  • Press F on any port to Quick Forward (same port number, no form)
  • Press f to open the forward form (SSH Host is auto-filled and locked)

Docker Target Mode

Discover and forward ports from inside a Docker container on a remote host:

# TUI with container port scanning
quay --remote ailab --docker syntopic-dev

# List container ports
quay --remote ailab --docker syntopic-dev list
quay --remote ailab --docker syntopic-dev list --json

In docker target TUI mode:

  • Header shows Quay [remote: ailab] [docker: syntopic-dev]
  • Ports are discovered via ss -tln inside the container (including unmapped ports)
  • Press F on any port to Quick Forward through SSH to the container IP
  • Press f to open the forward form (Remote Host = container IP, SSH Host = remote host, both locked)
  • The tunnel path: localhost:port → SSH → container_ip:port

CLI Commands

# List all ports
quay list

# Output as JSON
quay list --json

# Filter by source
quay list --local
quay list --ssh
quay list --docker

# Kill process on port
quay kill 3000

# Kill by PID
quay kill 3000 --pid 12345

# Create SSH port forward
quay forward 8080:localhost:80 remote-host

# Create reverse SSH forward
quay forward 8080:localhost:80 remote-host -R

Keybindings

Key Action
j / Move down
k / Move up
g / Home Go to first
G / End Go to last
/ Search mode
Enter Show details
K Kill selected process
f Create SSH forward
F Quick forward (remote/docker mode, same port)
p Open presets
r Refresh
a Toggle auto-refresh
0 Show all
1 Local only
2 SSH only
3 Docker only
? Help
q / Esc Quit

Screenshots

┌─────────────────────────────────────────────────────────────┐
│ Quay - Port Manager                                         │
├─────────────────────────────────────────────────────────────┤
│ Filter: [0] All  [/] search  [?] help                       │
├─────────────────────────────────────────────────────────────┤
│ TYPE   │ LOCAL  │ REMOTE          │ PROCESS/CONTAINER       │
├────────┼────────┼─────────────────┼─────────────────────────┤
│ LOCAL  │ :3000  │                 │ node (pid:1234)         │
│ LOCAL  │ :8080  │                 │ python (pid:5678)       │
│ SSH    │ :9000  │ localhost:80    │ ssh (pid:2345)          │
│ DOCKER │ :5432  │ postgres:5432   │ postgres (abc123)       │
├─────────────────────────────────────────────────────────────┤
│ [j/k] Navigate  [Enter] Details  [K] Kill  [f] Forward  [p] Presets  [?] Help  [q] Quit│
└─────────────────────────────────────────────────────────────┘

Configuration

Configuration files are stored in ~/.config/quay/.

config.toml

[general]
auto_refresh = true
refresh_interval = 5
default_filter = "all"  # all, local, ssh, docker
remote_host = "user@server"  # optional: default remote host
docker_target = "my-container"  # optional: default docker container

[ui]
mouse_enabled = true

presets.toml

[[preset]]
name = "Production DB"
key = "1"
local_port = 5432
remote_host = "localhost"
remote_port = 5432
ssh_host = "prod-bastion"

[[preset]]
name = "Staging Redis"
local_port = 6379
remote_host = "localhost"
remote_port = 6379
ssh_host = "staging-bastion"

Requirements

  • Rust 1.85+ (for building from source)
  • macOS or Linux (lsof for port detection)
  • Docker (optional, for container port detection)

Developer Tools

Built-in tools for testing without real services running:

# Launch TUI with mock data
quay dev mock

# Run a scenario (spawns listeners + launches TUI)
quay dev scenario full    # 3 open + 2 closed ports
quay dev scenario web     # Web app + DB + Cache
quay dev scenario micro   # 5 microservices
quay dev scenario --list  # Show available scenarios

# Listen on specific ports
quay dev listen 4000 5000
quay dev listen 8080 --http

# Check if ports are open/closed
quay dev check 3000 8080

Scenarios launch the TUI with pre-built entries, so both open () and closed () ports are visible even if the underlying ports are already in use.

Development

# Run in development
cargo run

# Build release
cargo build --release

# Run tests
cargo test

# Lint (pedantic)
cargo clippy --all-targets -- -D warnings

See docs/DEVELOPMENT.md for more details.

License

MIT