Metadata-Version: 2.4
Name: docksurf
Version: 0.3.1
Summary: Live, keyboard-driven terminal UI for Docker: Compose-aware, real-time stats, zero polling — manage containers, images, volumes, and networks without leaving the terminal
Project-URL: Homepage, https://github.com/praneeth-etta/docksurf
Project-URL: Repository, https://github.com/praneeth-etta/docksurf
Project-URL: Issues, https://github.com/praneeth-etta/docksurf/issues
Project-URL: Changelog, https://github.com/praneeth-etta/docksurf/blob/main/CHANGELOG.md
Author-email: praneeth reddy etta <praneethetta@gmail.com>
Maintainer-email: praneeth reddy etta <praneethetta@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: containers,devtools,docker,terminal,textual,tui
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: User Interfaces
Classifier: Topic :: System :: Systems Administration
Classifier: Topic :: Terminals
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: docker>=7.1.0
Requires-Dist: platformdirs>=4.0.0
Requires-Dist: rich>=13.0.0
Requires-Dist: textual>=0.80.0
Description-Content-Type: text/markdown

# docksurf

A keyboard-driven terminal UI for visualising and managing Docker resources like containers, images, volumes, and networks. Compose-aware and live: it reacts to Docker events on its own and streams real time resource usage, so you're observing, not polling. No GUI, no browser tab.


![docksurf's container tab](https://raw.githubusercontent.com/praneeth-etta/docksurf/main/docksurf-container-tab.png)

**Docs:** [Quickstart](https://github.com/praneeth-etta/docksurf/blob/main/QUICKSTART.md) · [Full keybindings reference](https://github.com/praneeth-etta/docksurf/blob/main/KEYBINDINGS.md) · [Changelog](https://github.com/praneeth-etta/docksurf/blob/main/CHANGELOG.md)

## Highlights

- **Live by default** — the tables auto-refresh on `docker events` (container start/stop/die, image pull/delete, …); `r` is a manual reload.
- **Local or remote** — honours your active `docker context` on startup: local, Docker Desktop, Colima, or a remote host over SSH/TCP.
- **Docker Compose aware** — containers grouped by project into a collapsible tree, with project-wide up/down/stop/start/restart, colour-coded per-service logs, and `B` to rebuild + recreate a single service in place.
- **Live resource stats** — CPU %, memory, network and block I/O streamed into the detail pane for the selected running container.
- **Full lifecycle control** — pause/unpause and kill sit alongside stop/start/restart, so a `stop` that hangs on its 10s timeout never needs the CLI.
- **Multi-select + bulk actions** — mark rows on any tab and stop/start/remove them as a batch; ideal for cleaning up after a test run.
- **Inspect & prune** — the full raw `docker inspect` JSON for any resource in a searchable modal, plus a one-key menu to prune stopped containers, dangling images, unused volumes/networks, or everything at once.
- **Full image/volume/network CRUD** — pull, tag, and layer-history for images; create + size-on-disk for volumes; create + connect/disconnect for networks (see [Tabs](#tabs)).
- **Power-user exec & copy** — a custom exec command with a chosen user, `docker cp` in/out of a container, and an on-demand `docker top` process snapshot, all via quick prompts.
- **Full control log viewer** — live follow, in-log search, timestamps, configurable tail/`--since`, and mouse drag-to-select text to copy (`Ctrl+C`).
- **Operational signals at a glance** — colour-coded health, uptime and restart count, plus recent health-check probe output in the detail pane.
- **Disk usage** — a `docker system df` breakdown (per-type size + reclaimable) on demand.
- **In-app context switching** — list and switch Docker contexts from inside the TUI (`D`), remembered across restarts.
- **Auto-reconnect** — if the daemon goes down mid-session, DockSurf reconnects and refreshes on its own the moment it's back.

## Requirements

- A reachable Docker daemon (local, or a remote one via `docker context`)
- Python 3.11+ and [`uv`](https://github.com/astral-sh/uv) — not needed if you're using the [standalone binary](#install)
- The `docker` CLI on `PATH` — only needed for exec-shell (`e`/`E`), Compose project actions (`u`/`k`), and file copy (`C`); everything else uses the SDK. DockSurf degrades gracefully if it's absent.

## Install

See [QUICKSTART.md](https://github.com/praneeth-etta/docksurf/blob/main/QUICKSTART.md) for install + first steps in under 2 minutes.

**From [PyPI](https://pypi.org/project/docksurf/):**

```bash
pip install docksurf
docksurf
```

Or run it without installing, via [`uvx`](https://docs.astral.sh/uv/guides/tools/):

```bash
uvx docksurf
```

**Standalone binary** (no Python/pip/uv required) — download the file for your OS from the [latest release](https://github.com/praneeth-etta/docksurf/releases/latest):

- Linux: `docksurf-linux-x86_64`
- macOS (Apple Silicon): `docksurf-macos-arm64`
- Windows: `docksurf-windows-x86_64.exe`

```bash
chmod +x docksurf-linux-x86_64   # or the macOS binary you downloaded
sudo mv docksurf-linux-x86_64 /usr/local/bin/docksurf
docksurf
```

On Windows, just run the `.exe` directly — no `chmod`/`mv` step needed.

**From source** (for development, or to run an unreleased change):

```bash
git clone <repo>
cd docksurf

uv venv && source .venv/bin/activate
uv pip install -e .

docksurf
```

Or without installing:

```bash
uv run python -m docksurf_py.app
```

## Releases

Published to PyPI via a tag-triggered GitHub Actions workflow (`.github/workflows/publish.yml`): pushing a `vX.Y.Z` tag builds the package and publishes it using [PyPI Trusted Publishing](https://docs.pypi.org/trusted-publishers/) (OIDC — no stored credentials), gated behind a manual approval step. See [CHANGELOG.md](https://github.com/praneeth-etta/docksurf/blob/main/CHANGELOG.md) for what's in each release.

## Keybindings

The essentials — full reference (per-tab keys, log pane, Compose header behaviour) lives in [KEYBINDINGS.md](https://github.com/praneeth-etta/docksurf/blob/main/KEYBINDINGS.md).

| Key          | Action                                                 |
|--------------|----------------------------------------------------------|
| `?`          | Help screen — every keybinding, in-app                   |
| `r`          | Refresh all Docker data                                  |
| `/`          | Search / filter the active tab                           |
| `↑/↓`, `Tab` | Navigate rows / switch tabs                              |
| `1`-`4`      | Jump directly to Containers / Images / Volumes / Networks |
| `s`/`S`/`x`  | Stop / start / restart (Containers tab)                  |
| `e`          | Exec shell into the focused container                    |
| `l`          | Toggle log viewer                                        |
| `space`      | Mark for a bulk action                                   |
| `d`          | Delete the selected — or marked — resource(s)            |
| `i`          | Inspect (raw `docker inspect` JSON)                      |
| `P`          | Prune menu                                               |
| `D`          | Switch Docker context                                    |
| `q`          | Quit                                                     |

## Tabs

Every tab has a leading mark column (`space` to toggle) for multi-select + bulk actions — see [Keybindings](#keybindings).

**Containers** — all containers (running and stopped), **grouped by Compose project** into a collapsible tree, with standalone containers below. Columns: name (with a colour-coded status dot) and image. The detail pane adds status, health, uptime, restart count, ports, networks, env vars, health-probe history, live CPU/mem/net/block-IO stats, and an on-demand `docker top` snapshot (`t`). For a Compose service, `B` rebuilds and recreates just that container, streamed live.

**Images** — all images, tagged as *In Use*, *Unused*, or *Dangling*. Detail pane shows size, created date, architecture, and which containers reference the image. Pull new images with live progress (`+`), view per-layer history (`h`), retag (`y`), and one-key mark-all-dangling for bulk cleanup (`a`).

**Volumes** — all volumes, tagged as *In Use* or *Orphaned*. Detail pane shows mountpoint, driver, labels, and attached containers. Create volumes (`+`) and pull on-demand per-volume size on disk (`b`).

**Networks** — all networks with driver and scope. Detail pane shows driver, scope, subnet, gateway, and each attached container's IP/MAC within the network. Create networks (`+`) and connect/disconnect containers (`v`/`m`).

## Architecture

Strict layering: `models.py` and `constants.py` are leaf modules nothing imports into. All Docker I/O lives in `docker/` (via the [Docker SDK for Python](https://docker-py.readthedocs.io/)) behind a `DockerService` protocol, so it's swappable in tests. `widgets/` is presentation-only, with no Docker knowledge. `renderer/`, `actions/`, `search.py`, and `observability.py` compose into the app itself — table rendering, resource actions, search, and live stats/`docker top` — driven by a single per-tab resource registry rather than branching on resource type throughout.

## How data is fetched

DockSurf talks to Docker through the SDK (`docker-py`), not the CLI — with three sanctioned exceptions, all guarded on the `docker` CLI being present: interactive **exec-shell** (needs a real TTY), **Compose project actions** (docker-py has no Compose support), and **file copy** (`docker cp` semantics aren't worth reproducing over the SDK's raw tar archives).

Resource lists are fetched in parallel on every refresh and kept live via `docker events` (debounced, selection-preserving); stats and logs stream straight from the SDK, with a Compose project's logs merged and colour-coded per service.

## Docker contexts — local and remote

DockSurf connects to whatever daemon your active Docker context points at (matching the `docker` CLI's precedence: `DOCKER_HOST` → active context → default socket). That doesn't have to be your local machine, and — since context switching now happens in-app — it doesn't require restarting DockSurf either.

**Creating a context** is still a `docker` CLI step (DockSurf lists and switches contexts, it doesn't create them):

```bash
# A context pointing at a remote Linux host over SSH — any host with a
# reachable Docker daemon and SSH access works: a cloud VM, a bare-metal
# box, a Raspberry Pi, a home server.
docker context create prod --docker "host=ssh://user@prod.example.com"

# Or over plain TCP, if the daemon's API is exposed that way
docker context create staging --docker "host=tcp://staging.example.com:2375"
```

**Switching contexts from inside DockSurf** — press `D` to list every context `docker context ls` knows about and pick one. This is in-app only: it never runs `docker context use`, so it doesn't touch `~/.docker/config.json` or repoint any other terminal's `docker`/`docker compose` — DockSurf just opens its own connection to the chosen context's daemon. The choice is remembered across restarts (`~/.local/share/docksurf/state.json`).

**Auto-reconnect** — if the daemon your active context points at goes down mid-session (VM reboot, daemon restart, network blip), the status bar flags it immediately (`● <reason>`) and DockSurf retries on its own every couple of seconds, reconnecting and refreshing the moment it's back — no restart, no manual `r`.

Works with any endpoint that speaks the **Docker Engine API** — a plain Linux daemon, Docker Desktop, Colima, Rancher Desktop, or a remote host over SSH/TCP. Managed platforms without that API can't be reached this way even with a custom context.

## Logging

App logs are written to `~/.local/share/docksurf/docksurf.log` — never to stdout (which belongs to the TUI). Useful for debugging refresh errors, failed Docker API calls, container/Compose action results, and stream lifecycle events.

## Changelog

See [CHANGELOG.md](https://github.com/praneeth-etta/docksurf/blob/main/CHANGELOG.md) for release history.
