Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Authentication

Most public skills and rules pull anonymously, but a private registry wants to know who you are before it hands anything over. Grimoire does not invent its own login system for that — it reads and writes the same credential store Docker and oras already use, so a single docker login (or grim login) covers every tool on the machine.

This page covers how Grimoire finds credentials when it talks to a registry, how grim login and grim logout manage them, and where they are stored on disk.

How credentials are resolved

Every registry request starts the same way: Grimoire looks up a credential for the target registry and falls back to anonymous access when it finds none. A missing credential is never an error — public artifacts keep working with no setup.

The lookup reads ~/.docker/config.json (or $DOCKER_CONFIG/config.json), the Docker config file. If a credential helper is configured for the registry, Grimoire asks the helper; otherwise it reads the base64 entry under auths. The registry key is normalized first — the scheme and any /v2/ API suffix are stripped, and docker.io is mapped to its canonical https://index.docker.io/v1/ form — so a credential stored by docker login resolves the same way under grim.

Credentials can also come from the environment for GRIM_INSECURE_REGISTRIES and other CI setups; see Configuration.

grim login

grim login [registry] authenticates to a registry and stores the credential so later pulls and pushes reuse it. With no positional argument it resolves the registry the same way every command does — --registry, then the default_registry option, then GRIM_DEFAULT_REGISTRY.

The username comes from --username/-u, or an interactive prompt when omitted on a terminal. The password is read from a hidden terminal prompt, or from standard input with --password-stdin. There is intentionally no --password <value> flag: a secret on the command line leaks through the process list and shell history.

# Interactive: prompts for the password without echoing it.
grim login ghcr.io -u alice

# Non-interactive (CI): read the token from stdin.
echo "$GITHUB_TOKEN" | grim login ghcr.io -u alice --password-stdin

Where the credential lands depends on what is configured — see Where credentials are stored. When no credential helper is configured, Grimoire refuses to write a plaintext credential unless you opt in with --allow-insecure-store, which stores a base64 entry (not encryption) in config.json. The file is created with owner-only (0600) permissions.

Grimoire stores the credential without first contacting the registry, which matches docker login with a credential helper. A wrong password therefore surfaces on the next pull or push, not at login time.

grim logout

grim logout [registry] removes a stored credential. It resolves the registry exactly like grim login.

Logout is idempotent: removing a credential that was never stored exits 0, matching docker logout and oras logout so a CI cleanup step never fails on a fresh runner.

grim logout ghcr.io

Where credentials are stored

Grimoire writes to the Docker-compatible config at $DOCKER_CONFIG/config.json, defaulting to ~/.docker/config.json. Set DOCKER_CONFIG to point both Grimoire and Docker at an isolated directory — useful for tests and per-job CI credentials.

The destination follows the same precedence Docker uses, highest first:

TierConfig keyStorage
Per-registry helpercredHelpers[registry]The named OS keychain helper.
Default helpercredsStoreThe named OS keychain helper.
Plaintext fallbackauths[registry]base64-encoded, gated by --allow-insecure-store.

A credential helper is a small program named docker-credential-<name> on your PATH that stores secrets in the OS keychain — for example osxkeychain, wincred, or secretservice/pass on Linux. The docker-credential-helpers project ships the common ones. When a helper is configured, the secret never touches config.json; only the helper name does.

Unlike docker login, Grimoire does not auto-detect and silently enable a platform helper on first use. It writes only what is already configured, or the explicit plaintext fallback — so a shared machine never gains a sticky credsStore entry behind your back.

Credentials in CI

A headless runner usually has no terminal and no keychain. Pipe the token in and opt into the plaintext store scoped to a per-job DOCKER_CONFIG:

export DOCKER_CONFIG="$RUNNER_TEMP/docker"
echo "$REGISTRY_TOKEN" | grim login "$REGISTRY" -u "$REGISTRY_USER" \
  --password-stdin --allow-insecure-store
grim release ./code-review "$REGISTRY/acme/code-review:1.2.3"
grim logout "$REGISTRY"

Because Grimoire shares the Docker config, a prior docker login step in the same job is enough on its own — grim reuses whatever Docker stored.