WhatTheDock is a terminal app for working with Docker containers and Compose stacks.
It is meant for the stuff you do all the time:
- see what is running
- check logs and problems
- start, stop, restart, edit, clone, delete, or recreate containers
- manage local and remote Docker hosts
- keep a small library of Compose files you can edit, save, and make live
- yank a container's configuration on one host, switch hosts, and paste it onto another (the Container Clipboard — see below)
- gracefully shut down or reboot a host, right from the app
It uses Docker's normal defaults. If docker ps works on your machine,
whatthedock should have a decent shot at working too.
This is still an early project, but the main workflow is usable.
Install the latest release:
curl -fsSL https://raw.githubusercontent.com/allisonhere/whatthedock/main/scripts/install.sh | shThe installer downloads the latest release binary, checks that it runs, and
puts it in /usr/local/bin. If that is not writable, it uses ~/.local/bin.
Set INSTALL_DIR if you want another location.
Build from source:
go install github.com/allisonhere/whatthedock/cmd/whatthedock@latestRun it:
whatthedockRun the demo if you do not have Docker handy:
whatthedock --demoThere are two search helpers:
- Press
Ctrl+Kfor the command palette. Type what you want, then pressEnter. - Press
?for Help. Inside Help, press/and type a word likecatalog,logs,delete, orsystems.
That is usually faster than remembering every key.
| Key | What it does |
|---|---|
j / k or Up / Down |
Move around |
Tab / Shift+Tab |
Move between panes |
Left / Right |
Move between panes |
Enter |
Open/select the focused item |
Space |
Expand/collapse a stack row; pause/resume logs in Logs |
/ |
Filter containers and stacks; in Logs, filter log lines |
r |
Refresh Docker state |
s |
Start/stop the selected container |
Alt+r |
Restart the selected container |
n |
Create a container or Compose service |
m |
Edit the selected service; on a stack row, edit the whole stack |
C |
Clone the selected container/service |
y |
Yank the selected container's configuration (Container Clipboard) |
P |
Paste the yanked container onto the current host |
D |
Delete the selected container/service; on a stack row, delete the whole stack |
u |
Pull latest image and recreate in place |
e |
Open a shell in the selected running container |
c |
Copy selected details |
o |
Open a selected port, mount, or Compose path |
q / Ctrl+C |
Quit |
| Key | What it does |
|---|---|
l |
Show logs |
L |
Expand logs across most of the screen |
e / w / i / a in Logs |
Show errors, warnings, info, or all log lines |
f / End in Logs |
Jump to the end and follow live output |
Home / PgUp / PgDn in Logs |
Move through log history |
c in Logs |
Copy all currently visible (filtered) log lines to the clipboard |
Esc in Logs |
Clear the active log filter |
p |
Show problems |
a in Problems |
Ask the configured AI provider to analyze the selected problem |
g |
Show stats graphs |
AI analysis is opt-in. It only runs when you press a in Problems, and only
after you configure a provider in Settings.
Press n to create something new. Press m to edit what is selected.
Useful keys in the create/edit form:
| Key | What it does |
|---|---|
[ / ] |
Switch between standalone, Compose service, and Compose stack modes |
Up / Down / Tab |
Move between fields |
h / l or Left / Right |
Change choices or move the cursor in text fields |
Enter |
Move to the next field; on the Compose file field, browse |
Ctrl+O |
Browse for a Compose file |
Ctrl+Y |
Edit the Compose YAML directly |
Ctrl+P |
Open the small create/edit Compose catalog picker |
Ctrl+S |
Validate or save changes |
Ctrl+Enter / Alt+Enter |
Show the final confirmation |
Esc / q |
Cancel/close |
Compose support is practical, not magical:
- A single-service Compose file can be edited as a service.
- A multi-service Compose file is treated as a stack.
- Editing a stack row edits the whole Compose file.
- Editing one service in a stack asks whether you mean that service or the whole stack.
- Local and SSH systems both work for Compose reads, writes, and
docker composeruns.
Writing to a Compose file is treated as something you may want to undo:
- Before every apply, WhatTheDock snapshots the target file to a timestamped
sibling (
compose.yaml.whatthedock-YYYYMMDD-HHMMSS.bak) and keeps the newest ten. - The confirmation screen shows a real diff of the file that will be written — the added and removed lines exactly as the merge will produce them — not just a generated preview.
- Only the fields you actually changed are merged in. Keys the form doesn't
manage (
build,container_name,network_mode, depends-on, comments, ...) are left untouched. Restore last compose backup(fromCtrl+K) puts the newest backup back, snapshotting the current file first so the restore is itself reversible. Runu(Replicate) afterwards to bring the running service up to match. Works on local and SSH systems.whatthedock doctor(see below) also flags any Compose file that is missing unmanaged keys its last backup still had.
The Compose catalog is a library of Compose files.
Use it when you want to keep a Compose file around, edit it safely, add notes, or later make it live on a local or remote Docker host.
Open it from the command palette:
Ctrl+K -> Curate Compose files
Catalog keys:
| Key | What it does |
|---|---|
Tab |
Switch between Library, Live, and Unused views |
j / k |
Move selection |
f |
Filter entries |
A |
Add a draft from a URL or path |
B |
Browse for a Compose file and add it as a draft |
N |
Start a blank draft |
Enter / l |
Preview an entry |
e |
Edit an entry |
c |
Create a runnable draft from a live stack |
S |
Save a live stack as a draft |
M / p |
Make the selected entry live |
s |
Change status: draft, live, or archived |
m |
Toggle missing/unused review |
n / t |
Edit note or tags |
a |
Archive or unarchive |
D |
Delete the catalog entry |
Notes are saved in catalog metadata and mirrored into a WhatTheDock comment block at the top of the Compose file. That way the note travels with the YAML instead of only living in the app.
Make Live asks for a destination path, shows conflicts, writes the Compose file
to the active local or SSH system, then runs docker compose up -d.
Open these from Ctrl+K:
Curate Docker imagesCurate Docker networksCurate Docker volumes
The keys are the same in each one:
| Key | What it does |
|---|---|
j / k |
Move through the list |
Space |
Select a removable item |
r |
Reload |
d |
Delete selected items |
y / Enter |
Confirm deletion |
n / Esc |
Cancel |
In-use items are shown, but they cannot be selected for removal.
Open from Ctrl+K:
Shut down host machineReboot host machine
Both gracefully stop every running container on the current host first, then run the actual OS-level shutdown/reboot — locally or over SSH, matching whatever system you're currently connected to. An itemized confirm screen lists exactly which containers will be stopped before anything happens.
Confirmation is deliberately not a single keypress. Because the same actions
are reachable from the command palette, the confirm screen requires you to
type the host's own name before the action is armed, so a mis-highlighted row
can't power off a machine by accident. Esc cancels.
The OS command runs non-interactively (sudo -n ...) so it never hangs
waiting for a password on a terminal that isn't there. If the host needs
one, WhatTheDock asks for it in-app — a masked prompt, never a terminal
handoff — and retries with it piped to sudo -S. Wrong password just
reopens the prompt; Esc always cancels. If you'd rather never be asked,
configure passwordless sudo for shutdown on the host once and this
never comes up again.
Not available in demo mode — there's no real host behind it.
Press S to manage Docker systems.
You can:
- switch between systems
- test a connection
- add a local or SSH system
- edit a system
- delete an inactive system
System keys:
| Key | What it does |
|---|---|
Enter |
Switch to the selected system |
t |
Test the selected system |
a |
Add a system |
e |
Edit a system |
d |
Delete an inactive system |
Ctrl+S while editing |
Save |
Esc |
Cancel/close |
Supported system types:
local: Docker on this machine, using normal Docker defaults unless you set a host.ssh: a tunnel to a remote Docker socket.
SSH auth modes:
config/agent: use your normal SSH config, keys, and agent.keychain: store the SSH password in the OS keychain, not insettings.json.password prompt: letsshask for the password each time.
To add one: install Docker on the remote host and confirm your user can reach
its socket there (ssh user@host docker ps), then give the system a name and
the SSH host (either user@host or a host alias from ~/.ssh/config).
WhatTheDock opens a local unix socket and forwards the remote Docker socket
over SSH, so nothing Docker-related needs to listen on the network. Key-based
auth (or an agent) is the smoothest choice; if you use a password, the
keychain mode keeps it in the OS keychain rather than settings.json.
Settings live in your platform config directory. On Linux that is usually:
~/.config/whatthedock/settings.json
Yank a container's configuration on one Docker host, switch hosts, paste it
on another — the vim-flavored y / P workflow:
select container
y
switch host
P
review conflicts
deploy
y captures a container's full configuration (image, command, entrypoint,
env, ports, mounts, networks, restart policy, healthcheck, resource limits,
and more) into an in-session clipboard — shown as [YANK: name] in the
status bar. It persists while you switch between systems, and keeps a
short history of your last few yanks.
P checks the yanked container against whatever host you're currently on
— name/port collisions, whether the image needs pulling, whether a network
needs creating, bind-mount paths that don't exist there, secret-like env
vars — and shows a review screen before anything happens:
| Key | What it does |
|---|---|
Enter |
Open the paste for editing (name, ports, mounts, env, networks) before deploying |
d |
Deploy as-is (refused if there's a blocking conflict, e.g. a name collision) |
t |
Redirect any missing bind-mount source(s) to a placeholder directory, so a deploy isn't blocked on them |
Esc |
Cancel — the clipboard item is kept, so you can try again |
This is a configuration clone, not a data migration: named volumes are created if needed, but volume and bind-mount contents are never copied between hosts, and the source container is never touched. Env vars that look like secrets (passwords, tokens, keys, ...) are flagged and their values are never shown in the review screen.
A bind mount whose source directory doesn't exist on the destination is a
blocking conflict by default — Docker refuses to create a container with a
missing bind source. Press t to redirect it instead: WhatTheDock creates
an empty placeholder directory under
~/.local/share/whatthedock/paste-placeholders/<container>/<mount> on the
destination, points the mount at it so the deploy can proceed, and records
the original path as a label on the created container
(com.whatthedock.paste.original-bind-source:<path-in-container>) — visible
later via docker inspect or the Inspector, not just a one-time message.
The placeholder is empty: no data is migrated into it, and the confirm
screen says so again right before you deploy.
Open Settings with , or Ctrl+,.
Settings include:
- theme and graph style
- refresh interval
- default activity pane
- whether to start in Dashboard
- editor mode
- AI provider/model/API key/base URL
- app activity log options
- update checks
Press Ctrl+S to save.
If you export a provider's normal API key environment variable, that wins over a stored key:
ANTHROPIC_API_KEYOPENAI_API_KEYGEMINI_API_KEY
Press d for the Dashboard.
It shows a quick view of the host, running containers, CPU, memory, network activity, and problems.
| Key | What it does |
|---|---|
j / k |
Move through rows |
Enter |
Open the highlighted container |
p |
Jump to Problems |
Esc / q / d |
Close Dashboard |
Mouse wheel and click work where the terminal supports them.
WhatTheDock can check GitHub releases for updates.
When an update is available, it asks before installing. If you say yes, it downloads the matching release asset, verifies its signature, replaces the running binary, and restarts.
The release signing key is baked into the app. Unsigned or invalid updates are rejected.
Because the verifying key lives in the binary you are already running, rotating the release signing key needs one manual reinstall (for example with the install command above). An old binary cannot verify a release signed with the new key, so it refuses the very update that would move you onto it; after that one-time reinstall, self-updates resume. The release tool checks that the configured signing key matches the baked verifier before it will run.
whatthedock doctordoctor prints a read-only health report: app environment and config, Docker
connectivity for the active system, config/log file permissions, remote system
config and tunnel sockets, and every Compose file WhatTheDock has backed up
(flagging one that has lost keys its last backup still had). It never changes
anything — no tunnels started, no files written, no credentials read beyond a
yes/no "is one stored" check.
Add --json for machine-readable output. Exit codes are 0 (clean), 1
(warnings), and 2 (failures).
Run the normal checks:
make checkThat runs:
gofmt -l .go test ./...go test -race ./...go vet ./...go build -buildvcs=false ./...
Run locally from source:
go run -buildvcs=false ./cmd/whatthedockRun the demo from source:
go run -buildvcs=false ./cmd/whatthedock --demoBuild a binary:
go build -buildvcs=false -o whatthedock ./cmd/whatthedock
./whatthedockPrint the version:
whatthedock --versionMore detail:
The release helper is a small TUI:
go run ./cmd/releaseIt shows the branch, latest tag, commit log, and diff since the last tag. It can build, sign, tag, push the tag, and create the GitHub release.
Use a dry run first:
go run ./cmd/release -dry-runRelease binaries are signed with an ed25519 signature. Generate the signing key once with:
go run ./cmd/release -genkeyKeep the private key in WHATTHEDOCK_SIGNING_KEY, or save it to the
gitignored .whatthedock-signing-key so you don't have to export it each time
(the environment variable wins if both are set). Do not commit it.
The release tool refuses to run when the configured key doesn't match the
public key baked into internal/update/verify.go, since a release signed that
way would be rejected by every installed app. Update the two together when
rotating.
WhatTheDock uses TideUI for the shared terminal UI pieces: panes, borders, rows, overlays, themes, and status bars.
Docker behavior, Compose behavior, settings, actions, and app state live here in WhatTheDock.





