Skip to Content
DocsRemote accessAuth & passwords

Authentication & Connection PINs

Connect’s auth model has two layers, and confusion between them is the single most common source of “Session requires password” errors. This page describes both layers and the cache that ties them together.

The per-machine attach secret is the connection PIN. The CLI verb (cmdop connect password …), the CMDOP_AGENT_PASSWORD env var, and the --password flag keep the historical password name on the wire, but the thing the user sets is a PIN.

The two layers

LayerWhat it authenticatesWhere it lives
Relay credential”Is this caller allowed to talk to the relay at all?”The CLI token from cmdop login, scoped to your active fleet. Held in the OS keyring.
Connection PIN”Once a session is opened on this machine, is the operator allowed to drive it?”Per-machine setting on the agent. Cached locally per machine.

A relay credential is mandatory. A connection PIN is optional — only machines that explicitly set one require it. Both must be satisfied before a streaming session opens.

The relay credential gets you to the relay. The connection PIN gets you into the session. They are two different gates, configured in two different places, even though Connect collapses them into one flow at attach time.

Streaming vs one-shot auth

The relay handles password auth differently for a live, interactive attach than for a one-shot call. Mixing them up is the canonical source of pain; the short version:

Streaming attach

Used by interactive PTY attach and by the one-shot recovery door-opener. The PIN challenge happens inline on the live stream: a challenge is raised, the client answers from its sources below, and on success a session token is handed back. The client caches that token for 24 hours.

The connection PIN is verified on the target agent, not by the relay — the relay never sees the PIN and only brokers the challenge/response frames. The PIN never leaves the agent boundary as a stored secret.

One-shot calls

A one-shot call (send input, resize, run a command) does not carry a password. It presents the cached session token instead, and the relay checks that token. If no valid token is attached, the call fails with:

UNAUTHENTICATED: Session requires password. Authenticate via ConnectTerminal first.

This is the canonical “I’m seeing the password error” trap. The fix is not to install another password somewhere — it is to make sure a streaming attach has authenticated that session before any one-shot call against it fires.

The session token cache

The session token cache is a small process-wide store that ties the two together:

  • The streaming attach writes a token into it on a successful login.
  • Each later one-shot call reads the token back out and presents it.
  • TTL is 24 hours. Expired entries are pruned on access.
  • Memory-only — nothing lands on disk.

Practical consequences:

  1. Inside one daemon process, the cache is shared across surfaces. A streaming attach by cmdop connect populates the token; subsequent one-shot calls from cmdop connect exec or the connect agent tool reuse it.
  2. Across daemon restarts, the cache is gone. First call after restart pays the streaming-open cost again.
  3. Across hosts, the cache is independent. Each machine’s daemon caches its own tokens.

Password sources, in order

When a streaming attach is asked for a password, the client tries password sources in this order:

  1. --password flag. Explicit per-call value.
  2. Local store. A per-machine password record cached locally, keyed by machine ID. Set via cmdop connect password set, cleared via cmdop connect password clear.
  3. CMDOP_AGENT_PASSWORD env var. Single value, same for every machine. Used by automation and CI.
  4. TTY prompt. If a human is at the terminal, the CLI prompts inline.

The agent-tool surface skips step 4 — bots cannot answer prompts. If steps 1–3 do not yield a value, the call fails with an auth_error.

# Set a password locally for one machine. cmdop connect password set vps-audi # Password: <typed in> # Inspect (only that a value is set; never prints the password). cmdop connect password get vps-audi # Remove. cmdop connect password clear vps-audi

The CMDOP_AGENT_PASSWORD env var applies to every password challenge in the same process. For multi-machine fan-outs where machines have different passwords, prefer the local store (per-machine) or pass --password explicitly per call.

One-shot exec recovery (no extra prompts)

cmdop connect exec is a one-shot call. Without help, it would fail immediately on a password-protected machine because no prior streaming attach has populated the cache. The CLI handles this transparently with a recovery path:

  1. Try the one-shot command.
  2. If it is rejected for a missing session token, open a brief streaming attach, answer the password challenge, and capture the resulting session token into the cache.
  3. Retry the one-shot command — this time it succeeds.

Non-password machines pay zero overhead (step 1 just works). Password machines pay one extra streaming open per process. After that, every one-shot call against the same machine is fast.

Relay credential failures

The other half of auth — the relay CLI token — fails earlier and with clearer errors. Common ones:

ErrorCauseFix
auth_error: not signed inNo CLI token resolved.Run cmdop login.
unauthenticated: token expiredThe CLI token expired and could not refresh.cmdop login again.
permission_denied: machine X not in workspace YYou switched fleets; machine belongs to the previous one.Select the correct fleet in the dashboard, then cmdop login.

For the single CLI-token credential source, see credential-resolver.

MFA and login

MFA lives on the login flow, not on Connect itself. When you run cmdop login, the browser-based flow handles whatever multi-factor your account requires. The CLI token that comes back is the relay credential — Connect never sees the PIN, TOTP, or webauthn assertion directly.

The CLI token refreshes silently while it can; if the refresh fails, you re-run cmdop login. There is no “MFA prompt” in cmdop connect itself.

Talking to a password-protected machine

Putting it together, here is what happens for a password-protected machine on its first call after daemon restart:

  1. cmdop connect exec prod-api-1 -- uptime
  2. Resolver picks prod-api-1 from the fleet.
  3. The relay credential resolves (the CLI token from cmdop login).
  4. The one-shot command fires. The relay rejects it for a missing session token.
  5. CLI opens a streaming attach. The relay asks for the password.
  6. CLI tries the four password sources. Finds the password in the local store.
  7. The relay accepts the password and returns a session token. CLI caches it.
  8. CLI retries the one-shot command, this time presenting the cached token. The relay accepts it.
  9. uptime runs and returns.

Subsequent calls in the same process skip steps 4–7 entirely.

Self-to-self machines

When the caller and target share the same identity, the permission gate is bypassed (see server-to-server). The PIN gate is not — even on self-to-self, a PIN-protected machine still demands its PIN. The two gates are independent.

Common errors

SymptomLayerCauseFix
Session requires password. Authenticate via ConnectTerminal first.One-shot callNo streaming attach has populated the cache for this session.The CLI’s one-shot recovery path handles this — if you see it from a custom integration, ensure you do a streaming attach first.
auth_error: no password sourceStreamingAll four password sources empty.Set the password locally or via env; or pass --password.
unauthenticated: invalid session tokenOne-shot callCached token expired (24h passed) or evicted.Just rerun the call — recovery re-primes the cache.
permission_deniedRelayCLI token valid, but its fleet doesn’t cover this machine.Switch to the correct fleet and re-run cmdop login.