Machines & Identity
Every Connect operation — interactive attach, one-shot exec, share-link creation, agent-to-agent calls, remote filesystem reads — funnels through a single resolver that turns the string you type into a concrete machine in the active fleet. This page describes what that resolver knows about a machine and how it picks one.
The four identifiers
A machine carries four kinds of names. They are not interchangeable:
| Field | Source | Stable? |
|---|---|---|
ID | server-assigned UUID | Yes — survives renames, OS reinstalls, reboots. |
Hostname | os.Hostname() on the agent host | No — changes if the OS hostname changes; may include .local on macOS. |
Name | friendly label (defaults to Hostname) | Editable in the desktop app and dashboard. |
| Prefix | first unique characters of Hostname or Name | Convenience only — not a real identifier. |
The MachineInfo struct lives in internal/connect/machines/types.go:14–60
and is what every Connect tool sees:
type MachineInfo struct {
ID string // UUID, stable
Hostname string // OS-reported
Name string // friendly label
Online bool // cached, may lag
HeartbeatAgeSeconds int64 // freshness signal — preferred over Online
WorkspaceID string
WorkspaceName string
AgentVersion string
ActiveSession *ActiveTerminalSession
}Resolution priority
machines.Resolve() (in internal/connect/machines/filter.go) tries the
input string against the machine list in this order, stopping at the first
match:
- UUID short-circuit. If the input matches the canonical
8-4-4-4-12UUID shape (case-insensitive), it is matched againstMachineInfo.ID. No fall-through — if no UUID matches, you get an error, not a fuzzy guess. - Exact hostname. Equal to
Hostnameafter lowercasing. - Exact display name. Equal to
Nameafter lowercasing. Useful when the friendly label diverges from the OS hostname. - Unique fuzzy prefix. A substring or prefix match across both
HostnameandName. If exactly one machine matches, it wins. - Ambiguous. Two or more candidates → error with a candidate list.
- No match. Error with the input echoed.
All consumers — cmdop connect, cmdop connect exec, ask_machine,
ask_machines, remotefs.Open — funnel through one machines.Resolve().
You only need to learn the precedence once.
Online flag vs heartbeat age
MachineInfo.Online is a cached boolean populated by the relay. It
reflects what the dashboard saw at the last list refresh, which can lag
real state by seconds to minutes. For freshness-sensitive logic the
authoritative signal is HeartbeatAgeSeconds:
0–30s— recent heartbeat, machine is live.30–90s— possibly degraded; the daemon may be running but its relay link is flaky.>90s— server will mark the machine offline on the next sweep.
The agent tool surface uses Online as the gate (online_only=true is the
default for ask_machines, false for connect.list per tool.go:34), but
when you need to debug a flaky machine, HeartbeatAgeSeconds is the
number to look at.
The whoami operation
The connect agent tool exposes operation=whoami, which is the simplest
way to ask “where am I?” from inside an agent prompt:
{
"operation": "whoami"
}The implementation calls os.Hostname() and matches against the fleet’s
machine list (case-insensitive). The result is one of:
{ "matched": true, "hostname": "mac-studio", "machine_id": "8f23..." }
{ "matched": false, "hostname": "mac-studio", "reason": "not in workspace" }
{ "matched": false, "hostname": "mac-studio", "reason": "api unreachable" }If the API is unreachable, whoami degrades gracefully: it still returns
the local hostname so prompts can use it as context. See
internal/connect/CLAUDE.md §whoami.
Listing machines
The CLI surfaces three views of the machine list:
# All machines in the active fleet.
cmdop connect --list
# Only the ones currently online.
cmdop connect --list --online
# JSON for scripting.
cmdop connect --list --jsonA typical row in the human-readable output looks like:
NAME HOSTNAME ID ONLINE AGE SESSION
mac-studio mac-studio.local 8f23... yes 4s —
prod-api-1 prod-api-1 a142... yes 12s active (jane@bmw)
vps-audi vps-audi c9f8... no 4m12s —
vps-bmw vps-bmw f200... yes 3s —The SESSION column is populated from MachineInfo.ActiveSession. It
shows whether somebody else is currently attached.
Fuzzy matching pitfalls
Two patterns cause confusion:
-
Ambiguous prefixes. If you type
prodand the fleet containsprod-api-1,prod-api-2,prod-db-1, the resolver returns:ambiguous machine "prod" — matches: prod-api-1, prod-api-2, prod-db-1The fix is to type more characters until exactly one machine matches, or to use the UUID prefix instead.
-
macOS
.localsuffix. On macOS,os.Hostname()often returnsmac-studio.local. The resolver matches this permissively — bothmac-studioandmac-studio.localresolve to the same machine.
A single-character prefix is rejected outright to avoid surprises. Use at least two characters when matching by prefix.
Renaming a machine
The OS hostname and the friendly name can both change. MachineInfo.ID
cannot. Rename flow:
- Edit the friendly name from the desktop app’s machines tab or the dashboard.
- Or change the OS hostname; the agent re-registers under the new value on its next heartbeat.
For the duration of the legacy reconciliation window (server-side), the old hostname continues to resolve. Long-running scripts should switch to UUID before assuming the rename has propagated everywhere.
For unattended scripts (CI, scheduled jobs, fan-out automations), prefer the UUID. It is immune to renames and never ambiguous. Save hostnames and prefixes for interactive flows where a human is reading the output.
Active session info
When somebody is attached to a machine, MachineInfo.ActiveSession
carries enough information for the dashboard and TUI picker to show
“already in use” hints:
type ActiveTerminalSession struct {
SessionID string
StartedAt time.Time
Operator string // hostname of the client that opened the session
}This is purely informational — multiple clients can attach to the same session. The desktop app uses it to dim machines that already have an operator. See interactive-attach for the multi-client model.
Cross-fleet addressing
A machine belongs to exactly one fleet. To talk to a machine in a
different fleet, select it with the --workspace flag (it keeps its
legacy name):
cmdop connect --workspace staging exec vps-bmw -- uptimeThere is no syntax for “machine X in fleet Y” in a single call without the flag — that is by design, because the relay enforces fleet scoping at the auth layer.