Configuration
keycmd is configured with TOML: a [keys] table naming the credentials to expose, and an optional [aliases] table exposing them again in another shape.
For the complete schema, see the configuration reference. If a configuration is not doing what you expect, keycmd --verbose prints every file it loaded and the result of merging them.
Where configuration lives
Configuration can be stored in three places, where ~ is your home folder and . is the working directory you call keycmd from:
~/.keycmd- all
.keycmdfiles found while walking up the file system from. - the first
pyproject.tomlfound while walking up the file system from.
They are loaded and merged in that order, and merged deeply: later sources win per field, so a project can override a single option without restating the whole entry.
The search stays inside your project
The search for .keycmd and pyproject.toml stops at the root of a git repository, and before your home folder, so that configuration applies to a subtree of your file system rather than leaking across projects.
This is what makes keycmd convenient for teams: a .keycmd file committed to a repository names the credentials the project needs, and each developer only has to have those credentials in their own keyring.
Keys
Every entry under [keys] becomes one environment variable, named after the entry:
credential and username together identify the credential in your keyring — they are exactly what is handed to keyring.get_password(). The password it returns becomes the value of MY_TOKEN.
Two optional fields change the value before it is exposed:
format— a format string, applied firstb64— base64 encoding, applied second
Format strings
A format string lets you preprocess the credential before it is exposed as an environment variable. It is processed with Python's built-in str.format, so everything that function supports is available to you.
Three variables can be used in the format string:
credentialusernamepassword
So a basic auth header, for example, is a format string and a base64 flag:
[keys]
MY_TOKEN = { credential = "MY_TOKEN", username = "azure", format = "{username}:{password}", b64 = true }
format is applied before b64, which is what makes that combination produce the value a basic auth header wants.
Aliases
Aliases expose the same secret in several forms, without a second lookup in your keyring.
For example, you may have a single Personal Access Token for Azure DevOps, and want to use the same token for pip, npm and the REST API. pip wants the token in plain text, npm prefers it base64-encoded, and the REST API expects a basic auth header. Aliases make this easy:
[keys]
MY_TOKEN = { credential = "azure_secret", username = "azure" }
[aliases]
MY_TOKEN_B64 = { key = "MY_TOKEN", b64 = true }
MY_TOKEN_BASICAUTH = { key = "MY_TOKEN", format = "{username}:{password}", b64 = true }
An alias names an existing key with key, and takes the same b64 and format options as a key does. The keyring is only consulted once, for MY_TOKEN; the aliases are derived from what it returned.
pyproject.toml
Configuration can equally well live in a project's pyproject.toml, under the tool.keycmd table. The previous example becomes:
[tool.keycmd.keys]
MY_TOKEN = { credential = "azure_secret", username = "azure" }
[tool.keycmd.aliases]
MY_TOKEN_B64 = { key = "MY_TOKEN", b64 = true }
MY_TOKEN_BASICAUTH = { key = "MY_TOKEN", format = "{username}:{password}", b64 = true }
Only the first pyproject.toml found on the way up is used, and it is merged last, so it wins over the .keycmd files below it.
Configuration holds names, not secrets
Nothing you write in a configuration file is a secret: it names a credential and a user, and the password itself stays in your keyring. That is what makes these files safe to commit — and it is worth keeping it that way.