/loa-credentials — Credential Management
Overview
Manage API credentials for Loa's multi-model provider system. Three storage tiers:
- •Environment variables — highest priority, standard approach
- •Encrypted store —
~/.loa/credentials/store.json.enc(Fernet/AES-128) - •.env.local — project-level dotenv file (gitignored)
Subcommands
status (default)
Show credential status for all known providers.
Workflow:
- •Run:
python3 -c "from loa_cheval.credentials import get_credential_provider; from loa_cheval.credentials.health import HEALTH_CHECKS; p = get_credential_provider('.'); [print(f'{k}: {\"configured\" if p.get(k) else \"missing\"}') for k in HEALTH_CHECKS]" - •Format results as a table:
code
Credential Status ───────────────────────────────── OPENAI_API_KEY configured (env) ANTHROPIC_API_KEY missing MOONSHOT_API_KEY configured (.env.local)
- •If any credentials are missing, suggest:
Run /loa-credentials set <NAME> to configure
set <CREDENTIAL_ID>
Store a credential in the encrypted store.
Workflow:
- •Validate the credential ID is in the known list or matches the allowlist pattern
- •CRITICAL: Use
AskUserQuestionto prompt for the value — NEVER accept credentials as command arguments - •Run:
python3 -c "from loa_cheval.credentials.store import EncryptedStore; s = EncryptedStore(); s.set('CREDENTIAL_ID', 'VALUE')" - •Confirm: "Stored CREDENTIAL_ID in encrypted store (~/.loa/credentials/)"
- •Optionally offer to test the credential
Security Rules:
- •NEVER echo, print, or log the credential value
- •NEVER include the credential value in tool call descriptions
- •NEVER store credentials in .claude/ or grimoires/
- •The value MUST come from user input via AskUserQuestion, never from command args
test
Test all configured credentials against provider endpoints.
Workflow:
- •Run:
python3 -c "from loa_cheval.credentials import get_credential_provider; from loa_cheval.credentials.health import check_all; results = check_all(get_credential_provider('.')); [print(f'{r.credential_id}: {r.status} — {r.message}') for r in results]" - •Format results:
code
Credential Health ───────────────────────────────── OPENAI_API_KEY ok — OpenAI API: valid (HTTP 200) ANTHROPIC_API_KEY error — Anthropic API: invalid key (HTTP 401) MOONSHOT_API_KEY missing — MOONSHOT_API_KEY not configured
delete <CREDENTIAL_ID>
Remove a credential from the encrypted store.
Workflow:
- •Confirm with user before deletion
- •Run:
python3 -c "from loa_cheval.credentials.store import EncryptedStore; s = EncryptedStore(); print('deleted' if s.delete('CREDENTIAL_ID') else 'not found')"
Error Handling
| Error | Cause | Resolution |
|---|---|---|
| "cryptography package required" | Missing dependency | pip install cryptography |
| "No credentials configured" | Empty store + no env vars | Run /loa-credentials set |
| "Health check timeout" | Network issue | Check connectivity |
Integration
Credentials stored via this command are automatically discovered by:
- •Config interpolation (
{env:VAR}tokens in.loa.config.yaml) - •LazyValue resolution (provider auth fields)
- •All skills that use model-invoke
The credential chain is: env var → encrypted store → .env.local Environment variables always take priority.