Skip to Content
ConnectCredential resolver

Credential Resolver

Every cmdop connect call (and every connecttool agent operation) needs a credential to reach the relay. There is exactly one source for that credential: the OAuth access token you obtain by running cmdop login.

This page covers how that single source is resolved, what happens when no credential is available, and how to fix a “not signed in” error.

The resolution

workspace.Resolver.ResolveCtx() (in internal/connect/workspace/resolve.go) is short by design — there is no chain of flags, env vars, or config files to walk:

  1. An already-resolved token passed by the caller. Some internal call sites (for example the agent-to-agent remoteagent funnel) already hold a token and hand it in directly. This is an internal override, not a user-facing flag or env var.
  2. OAuth access token from cmdop login (AuthMgr.GetAccessToken). This is the source for everything you do from the CLI.

If neither yields a credential, the resolver returns “no source” and the caller decides whether to treat that as an error — for cmdop connect it surfaces as a “run cmdop login” prompt.

Sources are tagged with a Source constant so the result can record where the credential came from:

const ( SourceOAuth Source = "oauth" // resolved from cmdop login SourceNone Source = "none" // nothing available )

There is no --api-key flag, no CMDOP_API_KEY environment variable, no named-fleet credential file (ssh_workspaces.json), and no legacy cfg.Chat.GrpcAPIKey path. Earlier builds had a multi-source resolver chain; it was removed. OAuth via cmdop login is the only way to authenticate the CLI today.

Why OAuth-only

Collapsing to a single OAuth source removes the surprise of a stale key on disk silently winning over the identity you just signed in with. Short-lived OAuth tokens (with refresh) also expire on their own — there is no long-lived API key to leak from a config file or CI env.

Getting authenticated

cmdop login # browser device flow, stores the OAuth token cmdop connect --list # uses the stored token automatically

The token is stored in the OS keyring (macOS Keychain, Linux Secret Service, Windows Credential Manager), with an encrypted-file fallback on headless hosts. Every later cmdop connect call resolves it transparently.

When no credential is available

If you run a connect command without signing in, the resolver returns the “no source” tag and the CLI rewrites the server error into an actionable remedy:

auth_error: not signed in — run `cmdop login`

friendlyAuthError (in cmd/cmdop/cmds/connect/connect_auth.go) is the helper that turns a generic unauthenticated from the relay into this guidance.

What the resolver does not do

  • It does not fetch tokens from the server. cmdop login does that, on demand, and stores the result.
  • It does not validate the token. An expired token resolves cleanly, carries to the relay, and fails there with unauthenticated — at which point the auth manager attempts a refresh.
  • It does not care which machine you are targeting. The OAuth token gates the relay; per-machine identity is enforced separately.

Server override

A call can carry an optional gRPC Server address override (used by on-prem deployments and test environments). When set, the resolver returns it alongside the token and the dial uses that endpoint instead of the default cloud relay. Most users never touch this.

Last updated on