cais

command module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 11, 2026 License: MIT Imports: 10 Imported by: 0

README

Cais

Run your self-hosted stack from the terminal, without leaving your compose file behind.

CI Go Status

Cais readme banner

Demo

Cais is a keyboard-driven terminal UI for a self-hosted stack running on Docker Compose. It reads your compose.yml and groups services the way you think about them. Nothing extra to host and nothing listening on a port.

Your compose file stays the source of truth. Every change Cais makes is written back into that file, comments and key order intact, so docker compose on the command line and Cais never disagree about what your stack is.

What it does

Groups, not a flat list of containers. A group is a Compose profiles: tag. Start all services in a group with one key, tail all their logs with another, and see at a glance which are running, which are healthy, and on what ports.

Everything you need to check your services. Ports, restart policy, networks, volumes, depends_on, healthcheck, image reference and resource limits, beside live memory, CPU, network and disk I/O for the running container.

A working link to the thing you just started. The config details view shows a link to the live service. Ctrl-click it, or copy it with y. The app never opens a browser itself.

A healthcheck in one keypress. h on a selected service opens a picker of templates: Postgres, MariaDB, Redis and nginx, each using a probe tool that ships in the image it targets, plus a generic HTTP fallback. Enter writes a validated healthcheck: block straight into the compose file.

New services without leaving the terminal. n on the Services page asks for a name and an image reference, then writes a minimal image: fragment straight into the compose file and opens the inline editor on it. Ports, volumes and everything else get added in the same YAML you would have hand-written, with live validation the whole way.

The .env beside your compose file gets a page of its own. The Env tab lists every variable with values masked by default. v reveals a value, c copies it, add/edit/delete go through small modals with a confirm on delete, and o opens the whole file in an inline editor. Writes are line-preserving, so comments and the variables you did not touch survive.

Edit the compose file in place, as YAML. e opens the service's own fragment in an inline editor: real YAML, not a form, so every Compose field is reachable. It validates as you type, auto-indents on Enter, indents with tab/shift+tab, and refuses to write a fragment that would not parse as Compose.

The inline YAML editor open on a service, with live validation

Logs without leaving. l streams docker compose logs -f for a service or a whole group in an overlay, with follow mode and scrollback.

Streaming logs for a service

More features

The compose file itself, syntax-highlighted and scrollable. E opens it in your $EDITOR; b browses the other compose files in the same directory and switches which one the app is driving.

Three themes, previewed live as you move the cursor: cais-dark, cais-dusk and cais-day. Enter applies and persists your choice; Esc restores the one you started with. Plus Catppuccin Mocha, Gruvbox Dark, Tokyo Night, Nord, Dracula, Solarized Dark, One Dark, Everforest Dark, Rosé Pine and Kanagawa Wave for a total of thirteen.

The theme picker, previewing a theme live over the Files page

Also: create, rename, and delete groups; change which services belong to them; confirm-guarded removes; a status re-poll every five seconds so panels reflect changes made outside the app; and a ? overlay listing every key, with the ones that do nothing on the current screen dimmed.

Install

go install github.com/filipemolina/cais@latest

Or build from source:

git clone https://github.com/filipemolina/cais.git
cd cais
make build     # installs to $(go env GOPATH)/bin, usually ~/go/bin

There are no downloadable binaries yet. A v* tag builds them (Linux and macOS, amd64 and arm64), but the releases stay in draft until the launch work in the roadmap, so go install or a clone is the way in for now.

Requirements: Docker with the Compose plugin on your PATH, a terminal, and Go 1.26+ to build. If something is missing or the daemon is not running, the app says which one failed (missing Docker, missing Compose plugin, unreachable daemon, or permissions) and gives you the exact command to fix it.

Use

cais                                    # the compose file in this directory
cais --dir ~/homelab/media              # resolve one in that directory
cais --file ~/homelab/compose.prod.yml  # open exactly this file

With no flags it auto-detects compose.yaml, compose.yml, docker-compose.yaml, docker-compose.yml, the same order Docker uses. The file that wins is named in the footer, and it is passed as --file to every docker compose call, so the commands always act on the file the panels describe. In a directory with no compose file at all, the app offers to write one.

Keys

? lists every key in context. The ones worth knowing:

Key Action
1 2 3 4 Groups / Services / Files / Env ([ and ] step through them)
k j Move the cursor; the details panel follows it
Tab Move focus between the list and the details panel
s t r p x Start · Stop · Restart · Pull · Remove (x confirms first)
l Stream logs for the service, or for every service in the group
y Copy a service's URL (when it publishes one)
h Add a healthcheck from the template picker
e Edit: a service's YAML inline, or a group's membership
E Open the whole compose file in $EDITOR (the .env file on the Env page)
n New: a group on the Groups page, a service on the Services page (name and image, then the inline editor opens on it), a variable on the Env page
R d Rename group · Delete group (d confirms first)
/ Filter the list by name
u Docker disk and memory usage overlay
T ? a q Themes · Help · About · Quit

Start/Stop/Restart/Pull/Remove run docker compose underneath, scoped to every service in the group on the Groups page, to one service on the Services page.

Status

Early, and honest about it. Everything shown above works today; what follows is what does not, in the order it is being closed. The sequence and the reasoning live in docs/ROADMAP.md:

  • Write safety: a backup before every edit. Every compose and .env write is snapshotted into .cais/backups/ next to the compose file before it lands, so a bad edit can be undone. Each source gets its own folder (compose_yaml/, _env/), and a copy is kept per write, deduped when the content has not changed. Up to 500 past copies are kept per file; older ones are pruned. The .env file is backed up too, so its secrets rest in the store alongside the compose file, and a .cais/.gitignore keeps the store out of git status. This is the store only: a browse and restore UI to travel back through those copies is the next step (v0.4.0).
  • Blank lines between services are not preserved across a write. Comments, quoting and key order are. This is accepted rather than fixed: a blank line inside a block scalar (command: |) is part of the string, and silently rewriting your data is a worse failure than losing your spacing.
  • A narrow terminal shows less, not worse. Under roughly 130 columns the keybinding bar starts dropping hints, and a narrow details panel drops columns from the member table, widest and least important first, and never q quit, ? help or the service's own name.

Issues and ideas are welcome, and at this stage they still change the direction.

Built with

Go, Bubble Tea / Lip Gloss for the UI, and compose-go, the same parser Docker itself uses, for the file. Docker actions shell out to the docker compose CLI rather than binding the SDK, so what the app does is what you would have typed.

License

MIT. © 2026 Filipe Molina.

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
src
banner
Package banner renders the Cais ASCII art banner for use as the TUI title and CLI startup splash.
Package banner renders the Cais ASCII art banner for use as the TUI title and CLI startup splash.
components/healthcheckpickermodal
Package healthcheckpickermodal is the h entry point on the Services page: a list of healthcheck templates relevant to the selected service, with an inline port field that appears only while the generic HTTP template is highlighted.
Package healthcheckpickermodal is the h entry point on the Services page: a list of healthcheck templates relevant to the selected service, with an inline port field that appears only while the generic HTTP template is highlighted.
components/servicefieldsstep
Package servicefieldsstep is the two-field step every "make a service" flow needs: a name and an image, then out to the existing YAML editor rather than a form with a field for every compose key - docs/DESIGN.md §Editing services rejects that outright.
Package servicefieldsstep is the two-field step every "make a service" flow needs: a name and an image, then out to the existing YAML editor rather than a form with a field for every compose key - docs/DESIGN.md §Editing services rejects that outright.
config
Package config reads and writes the user's persistent preferences: ~/.config/cais/config.yaml (or $XDG_CONFIG_HOME if set).
Package config reads and writes the user's persistent preferences: ~/.config/cais/config.yaml (or $XDG_CONFIG_HOME if set).
highlight
Package highlight turns raw text into styled text for the Files page's read-only viewer.
Package highlight turns raw text into styled text for the Files page's read-only viewer.
keys
Package keys is the single source of truth for every keybinding in the app.
Package keys is the single source of truth for every keybinding in the app.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL