3.6 KiB
knecht
CLI + TUI for managing Portainer stacks from the local services/ directory.
Installation
cd knecht
go build -o knecht .
# move to somewhere on your PATH, e.g.:
mv knecht /usr/local/bin/knecht
Configuration
~/.config/knecht/config.toml:
url = "https://portainer.example.com"
token = "ptr_..."
ignore = ["portainer"] # stack names to hide (e.g. self-managed containers)
# Optional
endpoint = "local" # Portainer environment name, auto-detected if omitted
services_path = "/path/to/services" # defaults to git root / services
The API token is generated in Portainer under Account → Access tokens.
Commands
| Command | Description |
|---|---|
knecht |
Launch the TUI |
knecht list |
Print all stacks with status and drift summary |
knecht deploy <stack> |
Deploy a new stack from services/<stack>/docker-compose.yml |
knecht update <stack> |
Update an existing stack, preserving Portainer env vars |
knecht restart <stack> |
Stop then start a stack |
knecht diff <stack> |
Print compose and env key drift |
knecht logs [container] |
Open Dozzle in the browser; deep-links to a specific container if given |
<stack> always maps to a folder name under services/.
TUI
Run knecht with no arguments to launch the interactive TUI.
┌─ stacks ──────────────┐ ┌─ detail ──────────────────────────────┐
│ ● traefik live │ │ rrr │
│ ● rrr live ~ │ │ │
│ ● jellyfin live │ │ status: running │
│ dummy not deploy │ │ drift: compose ~3 lines │
│ │ │ │
│ │ │ [u] update [d] diff [r] refresh │
└───────────────────────┘ └──────────────────────────────────────┘
Keybinds
| Key | Action |
|---|---|
↑ / ↓ |
Navigate stacks |
u |
Update selected stack (preserves Portainer env vars) |
D |
Deploy selected stack (only available when not deployed) |
d |
Toggle diff view |
e |
Generate or append .env.example from Portainer env keys |
r |
Refresh all stacks |
esc |
Return to summary view |
q / ctrl+c |
Quit |
Drift Detection
knecht compares the local services/<stack>/docker-compose.yml against what is deployed in Portainer, and the keys in services/<stack>/.env.example against the env vars set in Portainer.
| Indicator | Meaning |
|---|---|
~ next to stack name |
Drift detected |
! missing: KEY |
Key is in .env.example but not set in Portainer |
? unknown: KEY |
Key is in Portainer but not in .env.example — press e to append |
no .env.example |
Portainer has env vars but no example file exists — press e to generate |
Stacks with no .env.example file are not penalised for env drift — absence of the file means "no opinion".
Stack Convention
Each stack is a directory under services/ containing:
services/<name>/
├── docker-compose.yml # required
└── .env.example # optional — documents required Portainer env vars
knecht deploy <name> / knecht update <name> read these files directly. Env var values are never stored locally — only the keys in .env.example, as documentation.