Storage
How credentials are persisted to disk with the JSON file backend.
Storage
Credentials can be persisted to disk so they survive restarts. The credential store uses a pluggable backend interface — the built-in backend stores credentials as a JSON file.
JSON file backend
createJsonFileBackend reads and writes credentials to a single JSON file:
import { createJsonFileBackend, resolveCredentialsPath } from "@comma-agents/core";
const backend = createJsonFileBackend({
filePath: resolveCredentialsPath(),
});Behavior
- File permissions: Written with
0o600(owner read/write only). - Directory creation: Parent directories are created automatically on first write.
- Corrupt files: If the file contains invalid JSON or fails schema validation, the backend returns empty data rather than throwing. The next write overwrites the file with valid data.
- Missing files: Returns empty data (no error).
JsonFileBackendOptions
Prop
Type
Default file location
resolveCredentialsPath() returns the shared default path:
| Platform | Path |
|---|---|
| All platforms | ~/.comma/credentials.json |
import { resolveCredentialsPath, resolveDataDir } from "@comma-agents/core";
resolveCredentialsPath(); // Full path to credentials.json
resolveDataDir(); // Parent directory onlyFile format
The credentials file is a JSON object. Top-level keys are scopes ($global for credentials available to all strategies, or a strategy name for scoped overrides). Within each scope, keys are provider IDs mapped to credential objects.
{
"$global": {
"anthropic": { "type": "api", "key": "sk-ant-..." },
"openai": { "type": "api", "key": "sk-..." }
},
"my-strategy": {
"openai": { "type": "api", "key": "sk-project-specific-..." }
}
}In this example, a strategy named my-strategy would use its own OpenAI key, while all other strategies fall through to the global one. Anthropic would resolve from the global scope for all strategies.
Custom backends
Implement the CredentialBackend interface to store credentials in a different location (database, encrypted file, OS keychain, etc.):
Prop
Type
import { createCredentialStore } from "@comma-agents/core";
import type { CredentialBackend } from "@comma-agents/core";
const myBackend: CredentialBackend = {
async readAll() {
// Read from your storage...
return {};
},
async writeAll(data) {
// Write to your storage...
},
};
const store = createCredentialStore({ backend: myBackend });