Skip to content

credentials

mytool credentials <list | add <NAME> | remove <NAME> | test <NAME> | doctor>

Feature: Credentials. Passthrough subtree — --output must appear after the word credentials. Unlike config, there is no default subcommand: bare mytool credentials is a usage error.

Every subcommand works from the tool's declared credentials, which come from App::credentials() — populated by ApplicationBuilder::credentials_from(...). A tool that never wires a provider has an empty credential set: list prints an empty table, doctor succeeds trivially, and everything taking a <NAME> fails with no credential named `<NAME>` and the help text no credentials are configured for this tool.

The four layers a credential can declare

A CredentialRef may declare any combination of env, keychain, literal and fallback_env. The resolver tries them in that order and stops at the first hit.

credentials list

Prints one row per declared credential.

$ mytool credentials list
 name      | service   | account | mode | status
-----------+-----------+---------+------+--------
 api-token | mytool    | default | env  | -
Column Value
name The credential's declared name
service / account From the keychain layer, or - when there is none
mode The first configured layer: env, keychain, literal, fallback-env, or unconfigured
status Always -

mode is read off the config shape, not from a probe — list performs no I/O and never touches the keychain. status is a placeholder column that is always -; test and doctor are the subcommands that report real resolution status.

Honours --output json.

credentials test <NAME>

Probes one credential and prints where it resolved.

status Meaning
resolved The resolver found a value; source names the layer
missing No layer produced a value
refused-in-ci Only a literal was available and the environment is CI
error The keychain backend failed — locked store, OS-level error
unknown A resolution outcome this version does not recognise

Anything other than resolved prints the row and then fails the command with credential `<NAME>` did not resolve. Honours --output json.

credentials doctor

test for every declared credential at once. Prints all rows, then fails with one or more credentials did not resolve if any row is not resolved. Honours --output json.

credentials add <NAME>

Prompts for a secret without echoing it, then stores it — if there is somewhere to store it.

The credential declares What add does
A keychain layer Prompts, writes to the OS keychain under the declared service/account, prints a confirmation
No keychain, but an env layer Prompts, discards the secret, and prints the export line you should run yourself
Only a literal Refuses (see below)
Nothing settable Fails with credential `<NAME>` has no env layer to populate

add cannot set an environment variable for you

For an env-layer credential the wizard collects the secret and then throws it away:

set the secret in your shell:
    export <the env var the credential declares>=...
(rtb-cli does not write to the calling shell's environment.)

A process cannot modify its parent shell's environment, and putting the secret into the running process's own environment would leak it to every child process. The prompt is still shown, which reads as if something was stored — nothing was.

add refuses a literal-only credential

credential `<NAME>` declares only a literal layer; refusing to add an undeclared override

with help edit your config to add an env or keychain layer first. Storing into a layer the config does not declare would create a value the resolver never reaches.

credentials remove <NAME>

Deletes the credential from the OS keychain.

Removing a credential that is not in the keychain is not an error:

credential `<NAME>` not present in keychain (nothing to remove)

remove refuses to half-remove a literal

A credential with a literal and no keychain layer fails:

credential `<NAME>` is a literal in config; rtb-cli refuses to silently leave it in place

with help edit your config file to remove the literal value. Reporting success while the secret stayed in the config file would be worse than refusing.

A credential with both a literal and a keychain layer is removed from the keychain only — the literal stays in the config file, and the resolver will keep finding it.

Ignores --output

add and remove are interactive and print prose, not rows. They accept --output and ignore it.