The keyring integration lets you keep sensitive values — API keys, passwords, tokens — out of your config files entirely. Instead of writing secrets to disk alongside your other settings, the plugin stores them in the platform’s native secret store: macOS Keychain, Windows Credential Manager, or Linux Secret Service / Keyutils. Your config file on disk holds only non-sensitive fields; the secrets live in the OS and are retrieved on demand.
Declaring keyring fields
Use keyring() in your schema to mark a field as keyring-protected. You must give each field a unique id string — this becomes part of the OS keyring entry identifier.
See the Schema page for the full rules governing keyring() ids.
KeyringOptions
Most keyring operations accept a KeyringOptions object that identifies which keyring entry to use:
Both service and account must be non-empty, non-whitespace strings without control characters. Use a consistent pair throughout your app so that all operations address the same keyring entries.
Writing with .lock()
When you create or save a config that contains keyring fields, chain .lock(keyringOpts) before .run(). The plugin separates the secret values from the rest of the data, stores them in the OS keyring under {account}/{id}, and writes only the non-secret fields to the config file.
Reading with .unlock()
When you load a config that has keyring fields, chain .unlock(keyringOpts) to retrieve the secrets from the OS keyring and merge them back into the data object. The result is an UnlockedConfig instance whose .data property has keyring fields populated with their real values.
.unlock() requires the configurate:allow-unlock permission, which is
not included in configurate:default. You must add it explicitly to your
capability file. See the Permissions page for
details.
Locked vs unlocked data
When you call .run() on a load (or skip .unlock()), you receive a LockedConfig instance. Keyring fields in LockedConfig.data are null — the secrets have not been retrieved from the OS.
The TypeScript types reflect this distinction automatically. InferLocked<S> gives keyring fields the type null; InferUnlocked<S> gives them their real types (e.g. string).
Unlocking a LockedConfig after the fact
If you already have a LockedConfig and want to retrieve secrets later, call .unlock() directly on it:
Revoking access with UnlockedConfig.lock()
UnlockedConfig exposes a .lock() method that revokes access to the decrypted data through that instance. After calling it, any access to .data throws an error. Use this to reduce the window during which secrets are accessible in memory.
UnlockedConfig.lock() is an API-level access guard, not a cryptographic
memory wipe. JavaScript’s garbage collector controls when the underlying
memory is actually reclaimed. Treat it as a structural safeguard to prevent
accidental use of stale secret data, not as a guarantee of immediate memory
clearing.
Complete example
Relationship to BinaryProvider encryption
The keyring integration and BinaryProvider encryption are independent features. Keyring fields are schema-level annotations that route specific values to the OS secret store. BinaryProvider’s encryptionKey encrypts the entire config file at rest. You can use both together, but the plugin never stores a BinaryProvider encryption key in the OS keyring automatically — managing that key is your responsibility.