Concepts
Widgets
The app’s Home is a canvas of widgets: a clock, a summary of your sessions, your machines, the usage of each coding harness. You move them, resize them, minimize them, and add or remove them. Where each one sits is kept in a plain file, so the app, the CLI and your coding agent can all change it.
What a widget is
A widget is a small file, widget.yml, that says two things: where the
data comes from, and how the app draws it. It holds no code. The app does
the work; the file only picks from what the app offers.
devmachine widgets list
lists every widget you can use. devmachine widgets help claude-code/usage
says what one widget takes.
Widgets come in packages
Every widget ships inside a package, next to the recipe
that installs the tool behind it. claude-code/usage is the usage
widget of the claude-code package. The app’s own widgets, such as the
clock, are in the devmachine-app package.
A widget that only shows what the app already knows — the clock, your
machines, harness usage — works without adding its package anywhere. A
widget that reads something a package installs needs that package added
to a machine and synced first; widgets list says so, and names the
command. See why widgets come from packages.
From engine 1.1 a widget can also show the output of a command, a web address, an answer from a coding harness, or a live copy of a session — on your computer, a machine or a workspace. A command, prompt or session widget runs what its package installs, so it needs the package added and synced; a web address needs nothing. See the widget format.
Your own packages can ship widgets too. Write a widgets: folder in the
package (see the widget format), then
check it:
devmachine widgets validate ~/.config/devmachine/packages/my-package
A widget in your own package replaces the release’s package of the same name, the same way your packages always do.
A package can also feed its widgets with one of its own commands — a
package provider, such as devmachine-app/stats — run on a machine
through the CLI. And anybody can publish a package with widgets:
devmachine packages install <git-address> brings it in, and its widgets
that run code ask before they run. See where a public widget comes
from.
Areas and boards
An area is a place in the app that holds widgets. There are five:
- Home, a free canvas: each widget has a place and a size. A widget that
has a natural height (a summary, a list, some text) can follow its content
with
size: auto. - The sidebar, on the left: a list, top to bottom. The workspace list is one widget there, so you can put others above or below it.
- The context sidebar, the Context tab next to a session: a list too. Each of its sections (shortcuts, publish a port, monitors, shells, sub-agents, to-do, pull requests, links) is one widget.
- The menu bar title, at the top of the screen: up to three short widgets in a row, ”❯_” and the number of open pull requests unless you change it.
- The menu bar popover, what opens when you click it: each widget is a tab, Pull Requests and Usage unless you change it.
The sidebar’s top bar and footer, and the context panel’s other tabs (Preview, Files, Git), stay as they are: they are not widgets. Neither is the popover’s footer (Open, Stats, Subdomains, the color picker, Quit).
Each area has a board in <config>/boards/: home.yml, sidebar.yml,
context-sidebar.yml, menubar.yml and menubar-panel.yml. Home’s board
says where each widget is and how big:
format: 1
surface: home
widgets:
- id: clock
type: devmachine-app/clock
frame: {x: 24, y: 24, w: 320, h: 160}
size: medium
minimized: false
z: 1
- id: machines
type: devmachine-app/machines
frame: {x: 352, y: 24, w: 320}
size: auto
minimized: false
z: 2
size: auto has no h: the app draws the widget as tall as what it shows,
so it is never taller than its content. If you resize it shorter, the
height you chose stays, up to the content. See why a widget is as tall as
what it shows.
A sidebar’s board is just the list, in order:
format: 1
surface: sidebar
widgets:
- id: workspaces
type: devmachine-app/workspaces
size: auto
When a sidebar or menu bar board is missing, the app writes the board that draws that area as it always looked, and the CLI reads a missing one the same way. Settings → Appearance can reset each one.
The context sidebar hands its widgets the selected session’s context:
machine, session, workspace, path (the session’s folder), repo
and branch (from Git), and harness. Switching sessions runs each
widget again with the new values. A widget written in place that uses
them, such as a command reading {{context.path}}, asks you to allow it
again for each new set of values.
The menu bar title runs its widgets whenever the app runs, at most every 30 seconds; the popover runs its own only while it is open. See what runs in the menu bar.
Edit a board by hand, from the app, or with the CLI:
devmachine widgets add claude-code/usage --set harness=codex
devmachine widgets add claude-code/usage --board context-sidebar --after todo
devmachine widgets move usage --before shortcuts --board context-sidebar
devmachine widgets move usage-panel --before pull-requests-panel --board menubar-panel
devmachine widgets remove usage
The app sees a change to the file within a second. A board with a mistake is never written over: the app keeps the last good layout and says which line is wrong, and the CLI refuses to change it until it is fixed.
A board can also hold a widget written in place, with a title, a source
and a view and no package — a quick df on a workspace, say. One that
runs something waits until you press Allow. See the widget
format.
Changing one copy
The same widget can sit on a board twice and look different: each entry
may give it its own title, its own every (how often it runs) and its
own input values in with. In the app, ⋯ → Edit… changes them, and
⋯ → Choose … picks from a widget’s lists, such as which machines it
shows. A widget written in the board is edited the same way, and changing
what it runs asks for your approval again.