CodeHerderSearch⌘KRequest access →

Git tokens on a device

Give one device several scoped GitHub or GitLab tokens, and see exactly which one a repository gets.

A device usually authenticates to git with a single identity — whatever gh auth login or glab auth login set up. This page covers the git-token pool: a way to give one device several labelled tokens instead, each scoped to a host, an access class, and optionally a set of repositories.

This is a device-local feature: every command here talks directly to the ch device-server process running on the machine you run it from, not to CodeHerder’s API. Run these commands on the device itself, with its device server already running. With no device server running, a write prints a clear message, exits non-zero, and changes nothing.

Why add one

One gh auth login or glab auth login gives a device one identity, on one host. A pool lets that same device hold a write token for your own org and a read-only token for a vendor’s repos, or a GitHub token and a GitLab token side by side. That’s the case a single sign-in can’t cover: one device, more than one repository, not all under the same account.

It’s opt-in

A device that never adds a token behaves exactly as it does today: gh auth login and glab auth login still supply the credential, the same as if the pool didn’t exist. Adding your first token doesn’t change how any existing repository authenticates unless a token in the pool actually matches it — see Which token a repository gets, below.

Adding a token

ch device git-token create <label> --host <host> --access <write|read> [--scope <prefix> ...] --token-file <path|->

<label> is a short name you choose — lowercase letters, digits, and hyphens, the same rule as any other short identifier in CodeHerder. --host is the git host the token authenticates against, such as github.com or gitlab.com. --access is write (can push and open a pull or merge request) or read (can only clone and fetch). --token-file reads the token from a file, or from standard input when you pass - — the token is never accepted inline or as a positional argument, so it can’t end up in your shell history or show up in a process list.

ch device git-token create my-laptop --host github.com --access write --scope github.com/your-org --token-file ~/gh-token.txt
echo "$TOKEN" | ch device git-token create ci-reader --host github.com --access read --token-file -

The command validates the token, adds it as a new, enabled entry, and prints its fingerprint — never the token itself.

Scopes

--scope narrows a token to one or more repository-path prefixes, and is repeatable — up to 16 per token. Omit it entirely and the token applies to every repository on that host. A scope is matched on a whole path segment, so --scope github.com/your-org covers github.com/your-org/anything but not github.com/your-org-labs/foo. A scope can’t be empty, contain whitespace, or start or end with /.

Listing what’s added

ch device git-token list

Prints a row per entry: label, host, scopes, access, state, fingerprint, and when it was last used. The list never prints token material, and the CLI has no command to read one back. The pool is plain files on the device. In process mode and --docker mode, an agent running as the same user can read them. See Isolating agents on a device.

Which token a repository gets

When a session needs to authenticate to a repository, CodeHerder picks the best-matching token from the pool, in this order:

  1. A disabled token is never a candidate.
  2. The token’s host must match the repository’s host.
  3. The token’s access class must match exactly what’s needed — a read-only step never receives a write token, and a step that needs to push never receives a read-only one. There’s no “write is good enough for read” shortcut.
  4. Among what’s left, the token with the longest matching scope wins; a host-wide token (no --scope) is the fallback if nothing more specific matches.
  5. If it’s still a tie, the least recently used token wins, then alphabetically by label.

A host with no matching pool entry falls back to that host’s own gh auth login / glab auth login, so a partial pool — say, only a GitLab token added — is fine; GitHub repositories on that same device keep using the CLI sign-in.

Your git host shows the merge request as opened by the owner of the token the device used to push. The commits inside it carry different names. See Whose name is on a commit.

Read tokens apply on any device. Write tokens apply on a device that runs each stage in its own container (see Isolating agent runs on a device); elsewhere, a step that needs to push still uses the device’s own gh/glab sign-in.

Disabling, enabling, and removing a token

ch device git-token disable <label>
ch device git-token enable <label>
ch device git-token delete <label>

Disabling keeps the entry but takes it out of selection — useful if you know a token is about to expire, or you’re rotating it out. Deleting removes it outright.

Limits

A device holds at most 32 tokens. create refuses a duplicate label, and refuses once the pool is already full — delete or disable an entry to make room.

The Git tokens health check

Once a device holds at least one token, its Health panel grows a Git tokens row counting how many it has per host. This check only ever reports OK — it never warns or blocks work, and it doesn’t test whether a token actually works. See Managing your devices for the full list of readiness checks.

Last updated

CodeHerder

Round up your herd.

Bring every human and every agent onto one table. Watch the work move. Costs update as it happens.

Try "pricing", "connect a device", or "who reviews the code"

↑↓ move · ↵ open · esc close