A terminal UI for managing a Mender robot/device fleet —
think lazygit/lazydocker, but for Mender. Browse devices, accept new ones,
upload .mender artifacts, create deployments, and run a one-keypress
sequential deploy (configure → deploy) for freshly provisioned robots.
Talks to the Mender Management API using a Personal Access Token. Works against hosted Mender by default and any self-hosted server via a configurable base URL.
- Devices — list/filter devices, view inventory + configuration, accept /
reject / dismiss pending devices (with a
y/nconfirmation before each action). - Artifacts — list releases/artifacts, upload a
.menderfile, delete. - Deployments — list deployments with live status and drill into per-device status (auto-refreshing). Create deployments through a guided form: pick the artifact from a list (no typing), then target all accepted devices or a specific multi-selected set. Abort running deployments.
- Sequential Deploy — the headline feature: pick an already-accepted device and a profile, and lazymender will push the device configuration, wait for it to be applied, then deploy the profile's artifact and wait for completion — with confirmation between each step. Profiles are created, edited and deleted right inside the Sequential tab — no hand-editing files required.
- Theme-aware UI — colors follow your terminal's color scheme (ANSI palette) and automatically adapt to light vs. dark backgrounds.
go build -o lazymender .or install the binary from the releases in this repo
lazymender keeps two files side by side in
$XDG_CONFIG_HOME/lazymender/ (~/.config/lazymender/):
| File | Holds |
|---|---|
config.toml |
server URL + Personal Access Token |
profiles.toml |
provisioning profiles for the Sequential Deploy wizard |
The repo ships a ready-to-edit
config.example.toml — copy it and fill in your token:
mkdir -p ~/.config/lazymender
cp config.example.toml ~/.config/lazymender/config.tomlOr generate a minimal starter file:
lazymender -print-config-example > ~/.config/lazymender/config.tomlserver_url = "https://hosted.mender.io" # change for self-hosted
pat = "your-personal-access-token"The PAT and server URL can also be supplied via the MENDER_PAT and
MENDER_SERVER_URL environment variables (which override the file).
Create a Personal Access Token in the Mender UI under Settings → My organization → Personal access tokens.
Profiles power the Sequential Deploy wizard. You normally don't edit this file
by hand — create, edit and delete profiles from the Sequential tab
(n new, e edit, x delete). The artifact is picked from a list of your real
releases, so it always matches. If you prefer a file to start from, copy
profiles.example.toml:
cp profiles.example.toml ~/.config/lazymender/profiles.toml# A full bootstrap: set device configuration, then deploy the docker app.
[[profiles]]
name = "robot-bootstrap"
artifact_name = "docker-app-v1.4" # must match a release/artifact name
[profiles.config] # desired device configuration
timezone = "Europe/Amsterdam"
fleet_id = "north-1"
# Deploy only, no config step (empty config table):
[[profiles]]
name = "os-only"
artifact_name = "robot-os-v2.3"
[profiles.config]Migration: profiles used to live in
config.toml. Any legacy[[profiles]]blocks still present there are moved intoprofiles.tomlautomatically on first launch.
lazymender # uses the default config path
lazymender -config ./my.toml
lazymender -mock # explore with a built-in fake server (no PAT needed)lazymender -mock starts an in-process fake Mender Management API with seeded
devices, artifacts and deployments, and points the UI at it. It needs no PAT and
no network. Deployments and configuration pushes progress over time, so the
live-refreshing deployment view and the Sequential Deploy wizard behave like the
real thing. Demo provisioning profiles are injected automatically (so the
Sequential tab works immediately), unless your config already defines some.
This is the fastest way to develop and try features end-to-end.
| Scope | Keys |
|---|---|
| Global | tab/shift+tab cycle • 1–4 jump • ? help • q quit |
| Devices | ↑/↓ move • enter detail • a accept • r reject • d dismiss (y/n to confirm) • s sequential • / filter • R refresh |
| Artifacts | u upload • x delete • R refresh |
| Deployments | n new • enter detail (live) • b abort • R refresh |
| — new form | ←/→ pick artifact • toggle target all/specific • space select devices • ctrl+a all • enter create • esc cancel |
| Sequential | tab switch device/profile pane • ↑/↓ select • enter start • R refresh |
| — profiles | n new • e edit • x delete |
| — profile form | ←/→ pick artifact • ctrl+a add config row • ctrl+d remove row • enter save • esc cancel |
- On the Devices screen, highlight a device and press
s. - lazymender switches to the Sequential tab with that device selected.
- Pick a profile and press
enter. It then runs:- Precheck — the device must already be accepted (accept it on the Devices screen first; lazymender will not auto-accept here).
- Apply configuration — sets the profile's config, triggers a config deployment, and waits for it to finish.
- Deploy artifact — creates a single-device deployment of the profile's
artifact and waits for
success.
Each step waits for confirmation before the next begins; a failure stops the run and is reported with the error.
- Deployments use the v1 static device-list API, available on all plans. v2 filter-based ("dynamic") deployments are Enterprise-only and out of scope.
- The new deployment form can target all accepted devices or a hand-picked subset; full provisioning (config → deploy) is covered by the sequential workflow.
- Artifact building is out of scope — upload pre-built
.menderfiles. - The Deployments screen uses a split list/detail layout; on very narrow terminals (width < 62) the detail panel — where the new-deployment form renders — is hidden, though the form keys still work.
go build ./...
go vet ./...
go test ./...Layout:
internal/config configuration + profiles (config.toml / profiles.toml)
internal/mender Management API client (no TUI deps, unit-tested)
internal/workflow sequential deploy engine (UI-agnostic, unit-tested)
internal/mock in-memory fake Management API for `-mock` and tests
internal/tui Bubble Tea screens (devices, artifacts, deployments, sequential)
The internal/mock server is exercised by internal/mock/server_test.go using
the real client and workflow engine, so it doubles as an end-to-end test of
the whole stack.