Requirements
- Target platform
- OpenClaw
- Install method
- Manual import
- Extraction
- Extract archive
- Prerequisites
- OpenClaw
- Primary doc
- SKILL.md
Vault-backed API Keys management for OpenClaw. Secure file-based secret storage with one-click migration from plaintext config, dynamic key discovery, and pl...
Vault-backed API Keys management for OpenClaw. Secure file-based secret storage with one-click migration from plaintext config, dynamic key discovery, and pl...
Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.
I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete.
I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run.
Vault-backed API key management for the OpenClaw Control dashboard. Keys are stored in a secure file (~/.openclaw/secrets.json, mode 0600) and referenced via OpenClaw's built-in Secrets System. The AI agent never sees your keys.
ComponentStatusVault File Storageβ WorkingSecret References (SecretRef)β WorkingDynamic Key Discoveryβ WorkingOne-Click Migrationβ WorkingPlugin-Registered Tabβ WorkingVault Status Bannerβ WorkingKey Status Badgesβ WorkingVault-Only Keys Sectionβ WorkingManual "+ Add Secret" Formβ WorkingRestart Notification Bannerβ WorkingSkills Vault Key Selectorβ WorkingSkills Inline Key Creationβ WorkingAuth Profiles Displayβ Working
Keys are stored in ~/.openclaw/secrets.json (file permissions 0600). When you save a key, the UI: Writes the value to the vault file Configures the file secret provider in openclaw.json (if not already present) Replaces the plaintext config value with a SecretRef object Shows a restart notification β user must restart gateway for changes to take effect Config before migration: { "env": { "OPENAI_API_KEY": "sk-proj-abc123..." } } Config after migration: { "env": { "OPENAI_API_KEY": { "source": "file", "provider": "default", "id": "/OPENAI_API_KEY" } }, "secrets": { "providers": { "default": { "source": "file", "path": "~/.openclaw/secrets.json", "mode": "json" } }, "defaults": { "file": "default" } } } Vault file (~/.openclaw/secrets.json): { "OPENAI_API_KEY": "sk-proj-abc123..." }
The "π Migrate to Vault" button appears when plaintext keys are detected. It: Scans openclaw.json for all plaintext API key values Moves each to the vault file Replaces with SecretRef objects in config Auto-configures the file provider if needed Reports what was migrated
The UI automatically scans the entire config for API keys β no hardcoded list. Detection patterns: apiKey, api_key, token, secret, *_KEY, *_TOKEN, *_SECRET Where it looks: env.* β Environment variables skills.entries.*.apiKey β Skill-specific keys messages.tts.*.apiKey β TTS provider keys Any nested config path Known providers get friendly names, descriptions, and "Get key β" links: ProviderEnv KeyAnthropicANTHROPIC_API_KEYOpenAIOPENAI_API_KEYGoogle / GeminiGOOGLE_API_KEY / GEMINI_API_KEYBrave SearchBRAVE_API_KEYElevenLabsELEVENLABS_API_KEYDeepgramDEEPGRAM_API_KEYOpenRouterOPENROUTER_API_KEYGroqGROQ_API_KEYFireworksFIREWORKS_API_KEYMistralMISTRAL_API_KEYxAI (Grok)XAI_API_KEYPerplexityPERPLEXITY_API_KEYGitHubGITHUB_TOKENHume AIHUME_API_KEY / HUME_SECRET_KEY
Top of the page shows: π Vault Active (green) β All keys in vault, provider configured β οΈ X Plaintext Keys Detected (yellow) β Migration recommended
Each key row shows: VAULT (green) β Stored in secure vault file PLAINTEXT (yellow) β Still in config as raw string NOT SET (grey) β Not configured
Keys stored in the vault that aren't referenced by any config path are displayed in a dedicated "Vault-Only Keys" card. These are keys created manually or by skills that don't have a corresponding env/config entry. Each shows: π icon with the key name (monospace) Masked value preview Delete button
The Vault tab header includes a "+ Add Secret" button that expands an inline form: KEY_NAME input (monospace, UPPER_SNAKE_CASE recommended) Secret value input (password field) Save / Cancel buttons Writes to vault with envEntry: false β no config entry created, no restart triggered Key appears immediately in the "Vault-Only Keys" section
When a vault write triggers a config change, a yellow warning banner appears: β New secrets require a gateway restart to take effect. [Restart Now] The banner persists until the user clicks "Restart Now" or refreshes. This replaces the previous auto-reload behavior that caused unexpected gateway restarts.
On the Skills tab, skills that declare a primaryEnv get a vault key selector instead of a raw password input: When unlinked: Dropdown shows all vault keys with π icons "Select vault key for ENV_NAMEβ¦" placeholder Selecting a key writes a SecretRef to skills.entries.<key>.apiKey in config "οΌ Add new vault keyβ¦" option opens inline creation form When linked: Shows π KEY_NAME with an "Unlink" button Unlink removes the SecretRef from config Inline key creation: KEY_NAME + Secret value fields "Save & Link" creates the vault key and links it to the skill in one step Key also appears in the Vault tab's vault-only keys section
All skill groups (workspace, built-in, managed) render expanded (<details open>) for better discoverability. Previously workspace and built-in were collapsed by default.
Auth profile keys (from auth-profiles.json) that are stored in the vault are listed with their status. Backend RPCs support listing, error reset, and deletion.
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β Browser β β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β β β Vault Tab β β β β ββββββββββββββββββββββββββββββββββββββββββββ β β β β β OpenAI: [β’β’β’β’β’β’β’β’β’β’] [Save] [β] π’VAULT β β β β β β Anthropic: [ ] [Save] βͺNOT SETβ β β β β β + Add Secret [KEY_NAME] [value] [Save] β β β β β ββββββββββββββββββββββββββββββββββββββββββββ β β β β β β β β Skills Tab β β β β ββββββββββββββββββββββββββββββββββββββββββββ β β β β β whisper-api: π OPENAI_API_KEY [Unlink] β β β β β β sag: [Select vault key βΎ] β β β β β ββββββββββββββββββββββββββββββββββββββββββββ β β β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β β β β β βΌ (direct RPC, not via agent) β βββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββ β βββββββββΌββββββββ β Gateway β β secrets.write β β skills.update β ββββ¬ββββββββββ¬βββ β β ββββββββββΌβββ ββββΌβββββββββββββ β secrets. β β openclaw.json β β json β β (SecretRef β β (0600) β β objects only) β ββββββββββββββ ββββββββββββββββββ
MethodDescriptionsecrets.statusVault file status, key count, plaintext countsecrets.listList secret IDs with masked valuessecrets.writeStore key in vault + optionally update config with SecretRef. envEntry param (default true) controls whether an env block entry is created. Returns restartNeeded flag instead of auto-reloading.secrets.deleteRemove from vault + configsecrets.migrateBatch-migrate all plaintext keys to vaultsecrets.authProfiles.listList auth profile keys with vault statussecrets.authProfiles.resetErrorsReset auth profile error statesecrets.authProfiles.deleteDelete an auth profileskills.updateUpdated with vaultKeyId param β writes a SecretRef to skills.entries.<key>.apiKey or unlinks (empty string)
SkillStatusEntry includes a vaultKeyId field that reads the raw config JSON (not the runtime-resolved config where SecretRefs are replaced with resolved strings). This is done via extractVaultKeyIdFromConfig() which reads and caches openclaw.json directly, checking for SecretRef objects in skills.entries.<key>.apiKey.
No auto-restart on vault save. Previously, secrets.write called reloadSecrets() which could trigger a gateway restart. Now: Vault-only saves (envEntry: false) don't touch config β no restart needed Config-touching saves return restartNeeded: true β UI shows a restart banner Skills vault linking writes to config via writeConfigFile() β triggers the config file watcher which causes a gateway restart (inherent to the config watcher system)
This skill uses OpenClaw's built-in Secrets System (src/secrets/): File provider: { source: "file", path: "~/.openclaw/secrets.json", mode: "json" } SecretRef format: { source: "file", provider: "default", id: "/<KEY_NAME>" } Runtime resolution: prepareSecretsRuntimeSnapshot() resolves all refs at gateway startup Security: File permissions checked (0600), ownership verified, path guards The secrets system also supports env and exec providers for advanced setups (e.g., environment variables, external vault commands). The file provider is the default for this UI.
FilePurposesrc/gateway/server-methods/secrets.tsVault RPCs (status, list, write, delete, migrate, authProfiles)src/gateway/server-methods/skills.tsSkills update with vaultKeyId paramsrc/gateway/server-methods/plugins-ui.tsPlugin view registrationsrc/gateway/protocol/schema/agents-models-skills.tsvaultKeyId in SkillsUpdateParamsSchemasrc/agents/skills-status.tsvaultKeyId field on SkillStatusEntry, raw config readerui/src/ui/controllers/apikeys.tsVault-aware state, addVaultSecret, loadVaultOnlyKeysui/src/ui/controllers/skills.tsVaultKeyEntry type, loadVaultKeys, linkSkillToVaultKey, addVaultKeyAndLinkui/src/ui/views/apikeys.tsVault UI (banners, badges, migration, add form, vault-only keys, restart banner)ui/src/ui/views/skills.tsVault key selector dropdown, inline creation, expanded groupsui/src/ui/app.tsState properties (vault, restart, skill key management)ui/src/ui/app-render.tsProp wiring for vault and skillsui/src/ui/app-settings.tsTab load triggers for vault keysui/src/ui/types.tsvaultKeyId on SkillStatusEntryui/src/ui/navigation.tsVault tab (lock icon), removed 1password/discord standalone tabs
apikeys-ui/ βββ SKILL.md # This file βββ INSTALL_INSTRUCTIONS.md # Step-by-step installation (legacy) βββ reference/ βββ apikeys-controller.ts # UI controller (vault tab) βββ apikeys-views.ts # UI view (vault tab) βββ secrets-rpc.ts # Backend vault RPCs βββ skills-controller.ts # UI controller (skills vault integration) βββ skills-views.ts # UI view (vault key selector) βββ skills-status.ts # Backend skill status with vaultKeyId βββ skills-rpc.ts # Backend skills update RPC
No auto-restart on save β secrets.write no longer calls reloadSecrets(). A restart banner with "Restart Now" button lets the user decide when to restart. Vault-only keys β Keys created with envEntry: false don't appear in config. A separate secrets.list call finds all vault entries and shows orphan keys in a dedicated section. Raw config reading for vaultKeyId β The runtime resolves SecretRefs to strings, so loadConfig() returns resolved values. extractVaultKeyIdFromConfig() reads the raw JSON file directly (with mtime caching) to detect SecretRef objects. Skills expanded by default β All <details> groups render open for better UX. Collapsed-by-default hid skills that needed configuration. Skills use vault references, not plaintext β Skills with primaryEnv get a vault key selector dropdown instead of a password input. Linking writes a SecretRef to skills.entries.<key>.apiKey in config. Inline key creation from skills β "οΌ Add new vault keyβ¦" in the skills dropdown creates a vault entry and links it in one step, reducing friction.
Manual "+ Add Secret" form in Vault tab header β create vault keys without config entries Vault-Only Keys section β shows keys in vault not referenced by config Restart notification banner β yellow warning with "Restart Now" button replaces auto-reload Skills vault key selector β dropdown replaces raw password input for skills with primaryEnv Skills inline key creation β "οΌ Add new vault keyβ¦" creates and links in one step Skills expanded by default β all groups open, no more collapsed-by-default vaultKeyId on SkillStatusEntry β reads raw config JSON to detect SecretRef objects envEntry param on secrets.write β controls whether an env block entry is created vaultKeyId param on skills.update β writes SecretRef or unlinks skill from vault key
Vault-backed storage: Keys stored in ~/.openclaw/secrets.json (mode 0600) instead of plaintext config SecretRef integration: Config values replaced with OpenClaw SecretRef objects pointing to vault One-click migration: "Migrate to Vault" batch-migrates all plaintext keys Vault status banner: Green (all secure) or yellow warning (plaintext detected) Key badges: VAULT / PLAINTEXT / NOT SET per key New RPCs: secrets.status, secrets.list, secrets.write, secrets.delete, secrets.migrate Plugin UI registration: Moved from old nav to plugin architecture (settings group, position 1) Auto-provider config: Saving a key auto-configures the file secret provider if not present
Dynamic key discovery β scans entire config instead of hardcoded list Auto-grouping by category (Environment / Skills / Other) Common env keys shown even if not configured
Initial release with hardcoded provider slots Save/Clear functionality via config.patch
Code helpers, APIs, CLIs, browser automation, testing, and developer operations.
Largest current source with strong distribution and engagement signals.