Credential injection (nono run --credential <service> -- ...) reads secrets from the system keystore, but nono gives users no way to put secrets there. To set this up, a user currently has to use platform-specific tooling and figuring out the nono json policy schema:
- macOS:
security add-generic-password -s nono -a openai -w …
- Linux:
secret-tool store --label=nono service nono account openai
This issue is for more new users, then enterprise - who want to get going, yet could easily get things wrong. The most common failure is a service/account mismatch: the account you write with security/secret-tool has to be exactly the account the proxy reads for that service at run time, and nothing tells you what that account is. A built-in service might read from an env var or an external manager (1Password, Bitwarden) ather than the keystore at all - so a hand-written keystore entry is silently ignored, with no feedback about why injection "isn't working."
There's also no way to inspect the situation: which services exist, where each one's credential comes from, and whether it's actually available.
Matters would be helped with a nono credential command for storing and inspecting keystore credentials directly, so setup is:
nono credential set openai # paste the key once (no echo)
nono run --credential openai -- claude
Subcommands:
set <service> — prompt securely (terminal echo disabled) and store the
secret under the account the proxy actually reads for that service. Falls back
to plain line-reading when stdin isn't a TTY, so it stays scriptable.
list — show built-in and (with --profile) profile custom services,
their source (keystore / env / external manager / oauth2), and
availability. --json supported.
rm <service> — remove a stored credential (with a confirmation prompt;
-y to skip).
check <service> — verify a service's credential loads, without ever
printing the value (exits non-zero if it can't).
Resolution: service names resolve against the same built-in network policy and profile custom credentials that --credential <service> uses, so the account written by set is the account injected at run time. Non-keystore sources are handled explicitly:
- An env-backed service (e.g.
anthropic → env://ANTHROPIC_API_KEY) declines set with guidance to export the variable, rather than writing an unused keystore entry. `--account forces a keystore entry when needed.
- External-manager-backed services (1Password/Bitwarden/Apple Passwords/file) are surfaced with a redacted display and similarly declined.
- OAuth2 client-credential services point you at storing each half under its own account.
Library/CLI boundary: the nono library gains the keystore primitives
(store_secret / delete_secret / secret_exists, gated on the system-keyring feature, alongside the existing load_secret_by_ref); all policy and UX live in the CLI.
Example list output:
SERVICE ORIGIN SOURCE STATUS
anthropic built-in env: ANTHROPIC_API_KEY ✗ not set
gemini built-in keystore: gemini ✓ available
github built-in env: GITHUB_TOKEN ✓ available
openai built-in keystore: openai ✗ not set
Credential injection (
nono run --credential <service> -- ...) reads secrets from the system keystore, but nono gives users no way to put secrets there. To set this up, a user currently has to use platform-specific tooling and figuring out the nono json policy schema:security add-generic-password -s nono -a openai -w …secret-tool store --label=nono service nono account openaiThis issue is for more new users, then enterprise - who want to get going, yet could easily get things wrong. The most common failure is a service/account mismatch: the account you write with
security/secret-toolhas to be exactly the account the proxy reads for that service at run time, and nothing tells you what that account is. A built-in service might read from an env var or an external manager (1Password, Bitwarden) ather than the keystore at all - so a hand-written keystore entry is silently ignored, with no feedback about why injection "isn't working."There's also no way to inspect the situation: which services exist, where each one's credential comes from, and whether it's actually available.
Matters would be helped with a
nono credentialcommand for storing and inspecting keystore credentials directly, so setup is:Subcommands:
set <service>— prompt securely (terminal echo disabled) and store thesecret under the account the proxy actually reads for that service. Falls back
to plain line-reading when stdin isn't a TTY, so it stays scriptable.
list— show built-in and (with--profile) profile custom services,their source (
keystore/env/ external manager /oauth2), andavailability.
--jsonsupported.rm <service>— remove a stored credential (with a confirmation prompt;-yto skip).check <service>— verify a service's credential loads, without everprinting the value (exits non-zero if it can't).
Resolution: service names resolve against the same built-in network policy and profile custom credentials that
--credential <service>uses, so the account written bysetis the account injected at run time. Non-keystore sources are handled explicitly:anthropic→env://ANTHROPIC_API_KEY) declinessetwith guidance to export the variable, rather than writing an unused keystore entry. `--account forces a keystore entry when needed.Library/CLI boundary: the
nonolibrary gains the keystore primitives(
store_secret/delete_secret/secret_exists, gated on thesystem-keyringfeature, alongside the existingload_secret_by_ref); all policy and UX live in the CLI.Example
listoutput: