Metadata-Version: 2.4
Name: portui
Version: 0.1.9
Summary: A terminal UI for monitoring and managing local listening ports
Project-URL: Repository, https://github.com/lowtrak/PorTUI
License: MIT
Requires-Python: >=3.9
Requires-Dist: psutil>=5.9.0
Requires-Dist: textual>=8.0.0
Description-Content-Type: text/markdown

# porTUI

A terminal UI application for monitoring local listening ports and managing the processes that own them.

## Features

- Real-time display of listening TCP/UDP ports with process information
- Configurable columns (Port, IP, Protocol, Process, PID, User, State, Command)
- Sortable by Port, IP, Protocol, Process, PID, User, State, or Command (numerical IP sorting)
- Sort order maintained during auto-refresh
- Inline tree view with real process hierarchy (toggle with `t`) — parent processes are resolved from the OS even when they don't hold ports (e.g. Chrome → Chrome Helper)
- Protocol filter to show TCP only, UDP only, or both (cycle with `h`)
- Real-time text filtering across all fields
- Port detail overlay with full untruncated command line (press Enter, Escape to close)
- Auto-refresh with configurable interval (pauses during interaction)
- Prominent visual indicator when auto-refresh is paused
- Kill processes with choice of graceful (SIGTERM) or force (SIGKILL), with PID recycling guard
- Configuration persistence (`~/.config/portui/config.json`)
- Cross-platform (macOS, Linux, Windows)

## Installation & Usage

### Run without installing (recommended)

```bash
uvx portui
```

### Install globally

```bash
uv tool install portui
portui
```

### Install with pip

```bash
pip install portui
portui
```

### Run from source

```bash
git clone https://github.com/lowtrak/PorTUI
cd PorTUI
uv sync
uv run portui
```

### Run as a module

```bash
uv run python -m portui
```

## Keyboard Shortcuts

| Key | Action |
|-----|--------|
| `↑/↓` or `j/k` | Navigate rows |
| `Enter` | Show full port/process details |
| `/` | Focus filter input (Escape to clear and exit) |
| `h` | Cycle protocol filter (Both → TCP → UDP) |
| `c` | Toggle column configuration |
| `s` | Cycle sort column (Port → IP → Proto → Process → PID → User → State → Command); active sort shown in title bar |
| `t` | Toggle tree view (htop-style process hierarchy) |
| `x` | Kill selected process |
| `r` | Manual refresh |
| `p` | Pause/resume auto-refresh |
| `i` | Set refresh interval |
| `?` | Show help |
| `q` | Quit |

## Requirements

- Python 3.9+
- [uv](https://docs.astral.sh/uv/) (for `uvx` usage)

## Platform notes

### macOS

`psutil.net_connections()` requires root on macOS and will raise a permission error when called as a normal user. PorTUI works around this by iterating connections per-process instead, which only skips processes you don't have access to (typically kernel/system processes). No `sudo` required.

## Development

```bash
git clone https://github.com/lowtrak/PorTUI
cd PorTUI
uv sync --group dev
uv run pytest
```

### Project structure

```
portui/
├── __init__.py      # Public exports
├── __main__.py      # python -m portui entry point
├── app.py           # PortUIApp (main TUI application)
├── collector.py     # PortDataCollector (psutil, kill logic)
├── config.py        # ConfigManager (load/save/validate)
├── models.py        # PortInfo dataclass
├── screens.py       # All Screen subclasses
├── sort.py          # SortController
└── tree.py          # ProcessTreeBuilder (htop-style tree)

tests/
├── test_config.py   # ConfigManager validation (15 tests)
├── test_filter.py   # Filter mode UI (8 tests)
├── test_kill.py     # Kill + PID recycling guard (9 tests)
├── test_sort.py     # Sort all columns (21 tests)
└── test_tree.py     # Tree view (7 tests)
```
