Signing in

Launch labdash with no credential and it walks you through it. There is no command to run first and no file to write.

The first run

labdash

A welcome screen asks which GitLab, then how you want to sign in. It is a screen inside the application, not a prompt before it, so ? works, resizing works, and Esc goes back one step.

first-run

Three ways in are offered:

ChoiceWhen
a one-time codeThe default. Works over SSH, inside WSL and in containers, because nothing has to reach localhost
your browserInstances older than GitLab 17.9, which have no device grant. labdash falls back to this on its own when it has to
a personal access tokenAny instance, and the only path where no OAuth application is registered

Esc goes back one step. q leaves, and says how to sign in later:

Not signed in. Run `labdash auth login` when you are ready, or launch labdash again.

Nothing is stored until a login finishes, so leaving changes nothing.

The device flow on gitlab.com

Choosing a one-time code shows it in a box, opens your browser, and waits.

device-flow

Enter the code, approve it, and the terminal picks the token up by itself. Four keys are on the footer while it waits: y copies the code, o opens the approval page again, t switches to a pasted token, and Esc goes back.

The same flow is available from the command line, for scripts and for a second instance:

labdash auth login

GitLab's device page after you approve

GitLab shows "Device successfully authorized" and then re-renders its empty device-code form. That reads like a second prompt, and it looks like the login failed. It did not. The page belongs to GitLab, and RFC 8628 defines no redirect to request, so labdash says what will happen instead, both on the login screen and in the terminal once the token arrives:

  You can close the browser tab. GitLab redisplays its device
  form after authorizing, but nothing more is needed there.

The loopback flow

Instances older than GitLab 17.9 have no device authorization grant. labdash falls back to a loopback browser flow with PKCE on port 7171 automatically, and you can ask for it on any instance:

labdash auth login --web

Personal access tokens

The gitlab.com application id means nothing on gitlab.example.com. Unless an administrator has registered an application there, a personal access token is the way in, and it lasts a great deal longer than an OAuth token does.

Create one at https://<your-host>/-/user_settings/personal_access_tokens with the api scope, or read_api for read-only mode.

To paste it by hand, run labdash, choose a personal access token, and paste it there. Nothing is echoed, and Esc leaves the screen.

For a script or for CI, pipe it in:

echo "$TOKEN" | labdash auth login --hostname gitlab.example.com --with-token
Info

auth login --with-token never prompts Reading a secret at a terminal means putting that terminal into raw mode, and a raw-mode read swallows Ctrl+C. The command reads a pipe and nothing else. Interactive pasting belongs to the app, where Esc always works.

labdash validates the token against the instance before storing it, so a typo fails at login rather than on the first refresh of the dashboard. It also asks the instance what the token is allowed to do, so a read_api token lands in read-only mode rather than discovering it on the first merge.

An instance labdash has not seen before

Signing in to a host with no entry in the settings file offers to write one:

gitlab.example.com is not in your settings file.
Saving it gives caCert, clientCert, proxy and subfolder a home.

  →  Save it     writes the instance, never the credential
     Skip        everything works; there is nowhere to put transport settings

Only the instance is written. The credential goes to your keyring, or to a 0600 file, and never to the settings file. Declining still completes the login, and the file is not created at all — see self-managed GitLab for what an entry is worth.

There is no

--token <value> flag A flag value lands in your shell history and is visible in the process list to every other user on the machine. labdash reads a token from standard input only. Interactive input goes through a no-echo read, so the token does not reach your scrollback either.

The two token types

OAuth access tokenPersonal access token
Who creates itlabdash auth login, automaticallyyou, by hand, in GitLab's UI
Lifetime2 hoursup to 365 days
Renewalautomatic, from a refresh tokennone; you create a new one
Needs a registered OAuth applicationyesno
Looks like64 hex charactersglpat-…

A two-hour lifetime suits a dashboard you leave open all day. labdash renews the token five minutes before it expires, and persists the rotated refresh token before returning. GitLab invalidates the old refresh token the moment it issues a new one, which is why labdash owns the whole chain rather than borrowing a credential another tool is also renewing.

Checking a credential

labdash auth status

It prints who the credential belongs to, where it is stored, when it expires, and which settings file was read. It never prints the token. Add --offline to skip the network call.

You do not have to remember to run it. A personal access token expires at 00:00 UTC on its date, so labdash puts a quiet line in the context bar from fourteen days out and a prominent one from three days out. An OAuth credential renews itself and never reaches that state.

If a token does expire while the dashboard is open, the error names the instance and carries that instance's token page, and Ctrl+A restarts the login for it.

gitlab.example.com rejected the credential — it has expired or been revoked.
Press Ctrl+A to sign in again, or create a token at
https://gitlab.example.com/-/user_settings/personal_access_tokens?scopes=api
labdash auth logout      # removes ours, and says so when there was nothing to remove
labdash settings path    # where the settings file lives
labdash settings show    # the configured instances, never a credential

Where the credential is stored

OSStore
WindowsWindows Credential Manager
macOSKeychain
LinuxSecret Service, where one is running
No keyring (headless, most containers)<config dir>/credentials.json at mode 0600, written temp-file-and-rename so a crash cannot truncate it

The keyring entry lives under the namespaced service com.gitlab.labdash rather than a bare labdash. A keyring is one flat namespace shared by every program on the machine, so a generic name is a credential another program can silently overwrite.

The settings file holds no secrets. It records which instances exist and how to reach them, and against gitlab.com it does not need to exist at all. See what is a setting.

Scopes

labdash requests api and read_user. With --read-only it requests read_api and read_user.

read_user covers GET /api/v4/user, which is what names you in the greeting and in auth status. labdash never pushes to a repository, so it never asks for write_repository. More at security.