{
  "schemaVersion": "1.0",
  "item": {
    "slug": "api-key-ui-tab",
    "name": "API Keys UI",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/maverick-software/api-key-ui-tab",
    "canonicalUrl": "https://clawhub.ai/maverick-software/api-key-ui-tab",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/api-key-ui-tab",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=api-key-ui-tab",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "INSTALL_INSTRUCTIONS.md",
      "SKILL.md",
      "reference/apikeys-controller.ts",
      "reference/apikeys-views.ts",
      "reference/secrets-rpc.ts",
      "reference/skills-controller.ts"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "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."
        },
        {
          "label": "Upgrade existing",
          "body": "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."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-23T16:43:11.935Z",
      "expiresAt": "2026-04-30T16:43:11.935Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=4claw-imageboard",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=4claw-imageboard",
        "contentDisposition": "attachment; filename=\"4claw-imageboard-1.0.1.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/api-key-ui-tab"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/api-key-ui-tab",
    "agentPageUrl": "https://openagent3.xyz/skills/api-key-ui-tab/agent",
    "manifestUrl": "https://openagent3.xyz/skills/api-key-ui-tab/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/api-key-ui-tab/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "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."
      },
      {
        "label": "Upgrade existing",
        "body": "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."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "Vault Enhancements w/ UI v3.0.0",
        "body": "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."
      },
      {
        "title": "Status: ✅ Active",
        "body": "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"
      },
      {
        "title": "1. Vault-Backed Storage",
        "body": "Keys are stored in ~/.openclaw/secrets.json (file permissions 0600). When you save a key, the UI:\n\nWrites the value to the vault file\nConfigures the file secret provider in openclaw.json (if not already present)\nReplaces the plaintext config value with a SecretRef object\nShows a restart notification — user must restart gateway for changes to take effect\n\nConfig before migration:\n\n{\n  \"env\": {\n    \"OPENAI_API_KEY\": \"sk-proj-abc123...\"\n  }\n}\n\nConfig after migration:\n\n{\n  \"env\": {\n    \"OPENAI_API_KEY\": { \"source\": \"file\", \"provider\": \"default\", \"id\": \"/OPENAI_API_KEY\" }\n  },\n  \"secrets\": {\n    \"providers\": {\n      \"default\": { \"source\": \"file\", \"path\": \"~/.openclaw/secrets.json\", \"mode\": \"json\" }\n    },\n    \"defaults\": { \"file\": \"default\" }\n  }\n}\n\nVault file (~/.openclaw/secrets.json):\n\n{\n  \"OPENAI_API_KEY\": \"sk-proj-abc123...\"\n}"
      },
      {
        "title": "2. One-Click Migration",
        "body": "The \"🔒 Migrate to Vault\" button appears when plaintext keys are detected. It:\n\nScans openclaw.json for all plaintext API key values\nMoves each to the vault file\nReplaces with SecretRef objects in config\nAuto-configures the file provider if needed\nReports what was migrated"
      },
      {
        "title": "3. Dynamic Key Discovery",
        "body": "The UI automatically scans the entire config for API keys — no hardcoded list.\n\nDetection patterns: apiKey, api_key, token, secret, *_KEY, *_TOKEN, *_SECRET\n\nWhere it looks:\n\nenv.* — Environment variables\nskills.entries.*.apiKey — Skill-specific keys\nmessages.tts.*.apiKey — TTS provider keys\nAny nested config path\n\nKnown providers get friendly names, descriptions, and \"Get key ↗\" links:\n\nProviderEnv 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"
      },
      {
        "title": "4. Vault Status Banner",
        "body": "Top of the page shows:\n\n🔒 Vault Active (green) — All keys in vault, provider configured\n⚠️ X Plaintext Keys Detected (yellow) — Migration recommended"
      },
      {
        "title": "5. Key Status Badges",
        "body": "Each key row shows:\n\nVAULT (green) — Stored in secure vault file\nPLAINTEXT (yellow) — Still in config as raw string\nNOT SET (grey) — Not configured"
      },
      {
        "title": "6. Vault-Only Keys Section",
        "body": "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:\n\n🔒 icon with the key name (monospace)\nMasked value preview\nDelete button"
      },
      {
        "title": "7. Manual \"+ Add Secret\" Form",
        "body": "The Vault tab header includes a \"+ Add Secret\" button that expands an inline form:\n\nKEY_NAME input (monospace, UPPER_SNAKE_CASE recommended)\nSecret value input (password field)\nSave / Cancel buttons\nWrites to vault with envEntry: false — no config entry created, no restart triggered\nKey appears immediately in the \"Vault-Only Keys\" section"
      },
      {
        "title": "8. Restart Notification Banner",
        "body": "When a vault write triggers a config change, a yellow warning banner appears:\n\n⚠ New secrets require a gateway restart to take effect.\n[Restart Now]\n\nThe banner persists until the user clicks \"Restart Now\" or refreshes. This replaces the previous auto-reload behavior that caused unexpected gateway restarts."
      },
      {
        "title": "9. Skills Vault Key Selector",
        "body": "On the Skills tab, skills that declare a primaryEnv get a vault key selector instead of a raw password input:\n\nWhen unlinked:\n\nDropdown shows all vault keys with 🔒 icons\n\"Select vault key for ENV_NAME…\" placeholder\nSelecting a key writes a SecretRef to skills.entries.<key>.apiKey in config\n\"＋ Add new vault key…\" option opens inline creation form\n\nWhen linked:\n\nShows 🔒 KEY_NAME with an \"Unlink\" button\nUnlink removes the SecretRef from config\n\nInline key creation:\n\nKEY_NAME + Secret value fields\n\"Save & Link\" creates the vault key and links it to the skill in one step\nKey also appears in the Vault tab's vault-only keys section"
      },
      {
        "title": "10. Skills Expanded by Default",
        "body": "All skill groups (workspace, built-in, managed) render expanded (<details open>) for better discoverability. Previously workspace and built-in were collapsed by default."
      },
      {
        "title": "11. Auth Profiles Display",
        "body": "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."
      },
      {
        "title": "Security Model",
        "body": "┌──────────────────────────────────────────────────────────┐\n│  Browser                                                  │\n│  ┌──────────────────────────────────────────────────┐    │\n│  │  Vault Tab                                        │    │\n│  │  ┌──────────────────────────────────────────┐    │    │\n│  │  │ OpenAI: [••••••••••] [Save] [✕]  🟢VAULT │    │    │\n│  │  │ Anthropic: [        ] [Save]     ⚪NOT SET│    │    │\n│  │  │ + Add Secret  [KEY_NAME] [value] [Save]   │    │    │\n│  │  └──────────────────────────────────────────┘    │    │\n│  │                                                   │    │\n│  │  Skills Tab                                       │    │\n│  │  ┌──────────────────────────────────────────┐    │    │\n│  │  │ whisper-api: 🔒 OPENAI_API_KEY  [Unlink] │    │    │\n│  │  │ sag:         [Select vault key ▾]         │    │    │\n│  │  └──────────────────────────────────────────┘    │    │\n│  └──────────────────────────────────────────────────┘    │\n│                           │                               │\n│                           ▼ (direct RPC, not via agent)   │\n└───────────────────────────┼───────────────────────────────┘\n                            │\n                    ┌───────▼───────┐\n                    │   Gateway     │\n                    │ secrets.write │\n                    │ skills.update │\n                    └──┬─────────┬──┘\n                       │         │\n              ┌────────▼──┐  ┌──▼────────────┐\n              │ secrets.   │  │ openclaw.json  │\n              │ json       │  │ (SecretRef     │\n              │ (0600)     │  │  objects only) │\n              └────────────┘  └────────────────┘"
      },
      {
        "title": "Backend RPCs",
        "body": "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)"
      },
      {
        "title": "Skills-Status Integration",
        "body": "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."
      },
      {
        "title": "Restart Behavior",
        "body": "No auto-restart on vault save. Previously, secrets.write called reloadSecrets() which could trigger a gateway restart. Now:\n\nVault-only saves (envEntry: false) don't touch config — no restart needed\nConfig-touching saves return restartNeeded: true — UI shows a restart banner\nSkills vault linking writes to config via writeConfigFile() — triggers the config file watcher which causes a gateway restart (inherent to the config watcher system)"
      },
      {
        "title": "OpenClaw Secrets System Integration",
        "body": "This skill uses OpenClaw's built-in Secrets System (src/secrets/):\n\nFile provider: { source: \"file\", path: \"~/.openclaw/secrets.json\", mode: \"json\" }\nSecretRef format: { source: \"file\", provider: \"default\", id: \"/<KEY_NAME>\" }\nRuntime resolution: prepareSecretsRuntimeSnapshot() resolves all refs at gateway startup\nSecurity: File permissions checked (0600), ownership verified, path guards\n\nThe 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."
      },
      {
        "title": "Files Modified (Source Locations in OpenClaw Repo)",
        "body": "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"
      },
      {
        "title": "Reference Files",
        "body": "apikeys-ui/\n├── SKILL.md                              # This file\n├── INSTALL_INSTRUCTIONS.md               # Step-by-step installation (legacy)\n└── reference/\n    ├── apikeys-controller.ts             # UI controller (vault tab)\n    ├── apikeys-views.ts                  # UI view (vault tab)\n    ├── secrets-rpc.ts                    # Backend vault RPCs\n    ├── skills-controller.ts              # UI controller (skills vault integration)\n    ├── skills-views.ts                   # UI view (vault key selector)\n    ├── skills-status.ts                  # Backend skill status with vaultKeyId\n    └── skills-rpc.ts                     # Backend skills update RPC"
      },
      {
        "title": "Key Design Decisions",
        "body": "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.\n\n\nVault-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.\n\n\nRaw 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.\n\n\nSkills expanded by default — All <details> groups render open for better UX. Collapsed-by-default hid skills that needed configuration.\n\n\nSkills 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.\n\n\nInline key creation from skills — \"＋ Add new vault key…\" in the skills dropdown creates a vault entry and links it in one step, reducing friction."
      },
      {
        "title": "v3.0.0",
        "body": "Manual \"+ Add Secret\" form in Vault tab header — create vault keys without config entries\nVault-Only Keys section — shows keys in vault not referenced by config\nRestart notification banner — yellow warning with \"Restart Now\" button replaces auto-reload\nSkills vault key selector — dropdown replaces raw password input for skills with primaryEnv\nSkills inline key creation — \"＋ Add new vault key…\" creates and links in one step\nSkills expanded by default — all groups open, no more collapsed-by-default\nvaultKeyId on SkillStatusEntry — reads raw config JSON to detect SecretRef objects\nenvEntry param on secrets.write — controls whether an env block entry is created\nvaultKeyId param on skills.update — writes SecretRef or unlinks skill from vault key"
      },
      {
        "title": "v2.0.0",
        "body": "Vault-backed storage: Keys stored in ~/.openclaw/secrets.json (mode 0600) instead of plaintext config\nSecretRef integration: Config values replaced with OpenClaw SecretRef objects pointing to vault\nOne-click migration: \"Migrate to Vault\" batch-migrates all plaintext keys\nVault status banner: Green (all secure) or yellow warning (plaintext detected)\nKey badges: VAULT / PLAINTEXT / NOT SET per key\nNew RPCs: secrets.status, secrets.list, secrets.write, secrets.delete, secrets.migrate\nPlugin UI registration: Moved from old nav to plugin architecture (settings group, position 1)\nAuto-provider config: Saving a key auto-configures the file secret provider if not present"
      },
      {
        "title": "v1.1.0",
        "body": "Dynamic key discovery — scans entire config instead of hardcoded list\nAuto-grouping by category (Environment / Skills / Other)\nCommon env keys shown even if not configured"
      },
      {
        "title": "v1.0.0",
        "body": "Initial release with hardcoded provider slots\nSave/Clear functionality via config.patch"
      }
    ],
    "body": "Vault Enhancements w/ UI v3.0.0\n\nVault-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.\n\nStatus: ✅ Active\nComponent\tStatus\nVault File Storage\t✅ Working\nSecret References (SecretRef)\t✅ Working\nDynamic Key Discovery\t✅ Working\nOne-Click Migration\t✅ Working\nPlugin-Registered Tab\t✅ Working\nVault Status Banner\t✅ Working\nKey Status Badges\t✅ Working\nVault-Only Keys Section\t✅ Working\nManual \"+ Add Secret\" Form\t✅ Working\nRestart Notification Banner\t✅ Working\nSkills Vault Key Selector\t✅ Working\nSkills Inline Key Creation\t✅ Working\nAuth Profiles Display\t✅ Working\nFeatures\n1. Vault-Backed Storage\n\nKeys are stored in ~/.openclaw/secrets.json (file permissions 0600). When you save a key, the UI:\n\nWrites the value to the vault file\nConfigures the file secret provider in openclaw.json (if not already present)\nReplaces the plaintext config value with a SecretRef object\nShows a restart notification — user must restart gateway for changes to take effect\n\nConfig before migration:\n\n{\n  \"env\": {\n    \"OPENAI_API_KEY\": \"sk-proj-abc123...\"\n  }\n}\n\n\nConfig after migration:\n\n{\n  \"env\": {\n    \"OPENAI_API_KEY\": { \"source\": \"file\", \"provider\": \"default\", \"id\": \"/OPENAI_API_KEY\" }\n  },\n  \"secrets\": {\n    \"providers\": {\n      \"default\": { \"source\": \"file\", \"path\": \"~/.openclaw/secrets.json\", \"mode\": \"json\" }\n    },\n    \"defaults\": { \"file\": \"default\" }\n  }\n}\n\n\nVault file (~/.openclaw/secrets.json):\n\n{\n  \"OPENAI_API_KEY\": \"sk-proj-abc123...\"\n}\n\n2. One-Click Migration\n\nThe \"🔒 Migrate to Vault\" button appears when plaintext keys are detected. It:\n\nScans openclaw.json for all plaintext API key values\nMoves each to the vault file\nReplaces with SecretRef objects in config\nAuto-configures the file provider if needed\nReports what was migrated\n3. Dynamic Key Discovery\n\nThe UI automatically scans the entire config for API keys — no hardcoded list.\n\nDetection patterns: apiKey, api_key, token, secret, *_KEY, *_TOKEN, *_SECRET\n\nWhere it looks:\n\nenv.* — Environment variables\nskills.entries.*.apiKey — Skill-specific keys\nmessages.tts.*.apiKey — TTS provider keys\nAny nested config path\n\nKnown providers get friendly names, descriptions, and \"Get key ↗\" links:\n\nProvider\tEnv Key\nAnthropic\tANTHROPIC_API_KEY\nOpenAI\tOPENAI_API_KEY\nGoogle / Gemini\tGOOGLE_API_KEY / GEMINI_API_KEY\nBrave Search\tBRAVE_API_KEY\nElevenLabs\tELEVENLABS_API_KEY\nDeepgram\tDEEPGRAM_API_KEY\nOpenRouter\tOPENROUTER_API_KEY\nGroq\tGROQ_API_KEY\nFireworks\tFIREWORKS_API_KEY\nMistral\tMISTRAL_API_KEY\nxAI (Grok)\tXAI_API_KEY\nPerplexity\tPERPLEXITY_API_KEY\nGitHub\tGITHUB_TOKEN\nHume AI\tHUME_API_KEY / HUME_SECRET_KEY\n4. Vault Status Banner\n\nTop of the page shows:\n\n🔒 Vault Active (green) — All keys in vault, provider configured\n⚠️ X Plaintext Keys Detected (yellow) — Migration recommended\n5. Key Status Badges\n\nEach key row shows:\n\nVAULT (green) — Stored in secure vault file\nPLAINTEXT (yellow) — Still in config as raw string\nNOT SET (grey) — Not configured\n6. Vault-Only Keys Section\n\nKeys 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:\n\n🔒 icon with the key name (monospace)\nMasked value preview\nDelete button\n7. Manual \"+ Add Secret\" Form\n\nThe Vault tab header includes a \"+ Add Secret\" button that expands an inline form:\n\nKEY_NAME input (monospace, UPPER_SNAKE_CASE recommended)\nSecret value input (password field)\nSave / Cancel buttons\nWrites to vault with envEntry: false — no config entry created, no restart triggered\nKey appears immediately in the \"Vault-Only Keys\" section\n8. Restart Notification Banner\n\nWhen a vault write triggers a config change, a yellow warning banner appears:\n\n⚠ New secrets require a gateway restart to take effect. [Restart Now]\n\nThe banner persists until the user clicks \"Restart Now\" or refreshes. This replaces the previous auto-reload behavior that caused unexpected gateway restarts.\n\n9. Skills Vault Key Selector\n\nOn the Skills tab, skills that declare a primaryEnv get a vault key selector instead of a raw password input:\n\nWhen unlinked:\n\nDropdown shows all vault keys with 🔒 icons\n\"Select vault key for ENV_NAME…\" placeholder\nSelecting a key writes a SecretRef to skills.entries.<key>.apiKey in config\n\"＋ Add new vault key…\" option opens inline creation form\n\nWhen linked:\n\nShows 🔒 KEY_NAME with an \"Unlink\" button\nUnlink removes the SecretRef from config\n\nInline key creation:\n\nKEY_NAME + Secret value fields\n\"Save & Link\" creates the vault key and links it to the skill in one step\nKey also appears in the Vault tab's vault-only keys section\n10. Skills Expanded by Default\n\nAll skill groups (workspace, built-in, managed) render expanded (<details open>) for better discoverability. Previously workspace and built-in were collapsed by default.\n\n11. Auth Profiles Display\n\nAuth 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.\n\nArchitecture\nSecurity Model\n┌──────────────────────────────────────────────────────────┐\n│  Browser                                                  │\n│  ┌──────────────────────────────────────────────────┐    │\n│  │  Vault Tab                                        │    │\n│  │  ┌──────────────────────────────────────────┐    │    │\n│  │  │ OpenAI: [••••••••••] [Save] [✕]  🟢VAULT │    │    │\n│  │  │ Anthropic: [        ] [Save]     ⚪NOT SET│    │    │\n│  │  │ + Add Secret  [KEY_NAME] [value] [Save]   │    │    │\n│  │  └──────────────────────────────────────────┘    │    │\n│  │                                                   │    │\n│  │  Skills Tab                                       │    │\n│  │  ┌──────────────────────────────────────────┐    │    │\n│  │  │ whisper-api: 🔒 OPENAI_API_KEY  [Unlink] │    │    │\n│  │  │ sag:         [Select vault key ▾]         │    │    │\n│  │  └──────────────────────────────────────────┘    │    │\n│  └──────────────────────────────────────────────────┘    │\n│                           │                               │\n│                           ▼ (direct RPC, not via agent)   │\n└───────────────────────────┼───────────────────────────────┘\n                            │\n                    ┌───────▼───────┐\n                    │   Gateway     │\n                    │ secrets.write │\n                    │ skills.update │\n                    └──┬─────────┬──┘\n                       │         │\n              ┌────────▼──┐  ┌──▼────────────┐\n              │ secrets.   │  │ openclaw.json  │\n              │ json       │  │ (SecretRef     │\n              │ (0600)     │  │  objects only) │\n              └────────────┘  └────────────────┘\n\nBackend RPCs\nMethod\tDescription\nsecrets.status\tVault file status, key count, plaintext count\nsecrets.list\tList secret IDs with masked values\nsecrets.write\tStore 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.\nsecrets.delete\tRemove from vault + config\nsecrets.migrate\tBatch-migrate all plaintext keys to vault\nsecrets.authProfiles.list\tList auth profile keys with vault status\nsecrets.authProfiles.resetErrors\tReset auth profile error state\nsecrets.authProfiles.delete\tDelete an auth profile\nskills.update\tUpdated with vaultKeyId param — writes a SecretRef to skills.entries.<key>.apiKey or unlinks (empty string)\nSkills-Status Integration\n\nSkillStatusEntry 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.\n\nRestart Behavior\n\nNo auto-restart on vault save. Previously, secrets.write called reloadSecrets() which could trigger a gateway restart. Now:\n\nVault-only saves (envEntry: false) don't touch config — no restart needed\nConfig-touching saves return restartNeeded: true — UI shows a restart banner\nSkills vault linking writes to config via writeConfigFile() — triggers the config file watcher which causes a gateway restart (inherent to the config watcher system)\nOpenClaw Secrets System Integration\n\nThis skill uses OpenClaw's built-in Secrets System (src/secrets/):\n\nFile provider: { source: \"file\", path: \"~/.openclaw/secrets.json\", mode: \"json\" }\nSecretRef format: { source: \"file\", provider: \"default\", id: \"/<KEY_NAME>\" }\nRuntime resolution: prepareSecretsRuntimeSnapshot() resolves all refs at gateway startup\nSecurity: File permissions checked (0600), ownership verified, path guards\n\nThe 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.\n\nFiles Modified (Source Locations in OpenClaw Repo)\nFile\tPurpose\nsrc/gateway/server-methods/secrets.ts\tVault RPCs (status, list, write, delete, migrate, authProfiles)\nsrc/gateway/server-methods/skills.ts\tSkills update with vaultKeyId param\nsrc/gateway/server-methods/plugins-ui.ts\tPlugin view registration\nsrc/gateway/protocol/schema/agents-models-skills.ts\tvaultKeyId in SkillsUpdateParamsSchema\nsrc/agents/skills-status.ts\tvaultKeyId field on SkillStatusEntry, raw config reader\nui/src/ui/controllers/apikeys.ts\tVault-aware state, addVaultSecret, loadVaultOnlyKeys\nui/src/ui/controllers/skills.ts\tVaultKeyEntry type, loadVaultKeys, linkSkillToVaultKey, addVaultKeyAndLink\nui/src/ui/views/apikeys.ts\tVault UI (banners, badges, migration, add form, vault-only keys, restart banner)\nui/src/ui/views/skills.ts\tVault key selector dropdown, inline creation, expanded groups\nui/src/ui/app.ts\tState properties (vault, restart, skill key management)\nui/src/ui/app-render.ts\tProp wiring for vault and skills\nui/src/ui/app-settings.ts\tTab load triggers for vault keys\nui/src/ui/types.ts\tvaultKeyId on SkillStatusEntry\nui/src/ui/navigation.ts\tVault tab (lock icon), removed 1password/discord standalone tabs\nReference Files\napikeys-ui/\n├── SKILL.md                              # This file\n├── INSTALL_INSTRUCTIONS.md               # Step-by-step installation (legacy)\n└── reference/\n    ├── apikeys-controller.ts             # UI controller (vault tab)\n    ├── apikeys-views.ts                  # UI view (vault tab)\n    ├── secrets-rpc.ts                    # Backend vault RPCs\n    ├── skills-controller.ts              # UI controller (skills vault integration)\n    ├── skills-views.ts                   # UI view (vault key selector)\n    ├── skills-status.ts                  # Backend skill status with vaultKeyId\n    └── skills-rpc.ts                     # Backend skills update RPC\n\nKey Design Decisions\n\nNo auto-restart on save — secrets.write no longer calls reloadSecrets(). A restart banner with \"Restart Now\" button lets the user decide when to restart.\n\nVault-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.\n\nRaw 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.\n\nSkills expanded by default — All <details> groups render open for better UX. Collapsed-by-default hid skills that needed configuration.\n\nSkills 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.\n\nInline key creation from skills — \"＋ Add new vault key…\" in the skills dropdown creates a vault entry and links it in one step, reducing friction.\n\nChangelog\nv3.0.0\nManual \"+ Add Secret\" form in Vault tab header — create vault keys without config entries\nVault-Only Keys section — shows keys in vault not referenced by config\nRestart notification banner — yellow warning with \"Restart Now\" button replaces auto-reload\nSkills vault key selector — dropdown replaces raw password input for skills with primaryEnv\nSkills inline key creation — \"＋ Add new vault key…\" creates and links in one step\nSkills expanded by default — all groups open, no more collapsed-by-default\nvaultKeyId on SkillStatusEntry — reads raw config JSON to detect SecretRef objects\nenvEntry param on secrets.write — controls whether an env block entry is created\nvaultKeyId param on skills.update — writes SecretRef or unlinks skill from vault key\nv2.0.0\nVault-backed storage: Keys stored in ~/.openclaw/secrets.json (mode 0600) instead of plaintext config\nSecretRef integration: Config values replaced with OpenClaw SecretRef objects pointing to vault\nOne-click migration: \"Migrate to Vault\" batch-migrates all plaintext keys\nVault status banner: Green (all secure) or yellow warning (plaintext detected)\nKey badges: VAULT / PLAINTEXT / NOT SET per key\nNew RPCs: secrets.status, secrets.list, secrets.write, secrets.delete, secrets.migrate\nPlugin UI registration: Moved from old nav to plugin architecture (settings group, position 1)\nAuto-provider config: Saving a key auto-configures the file secret provider if not present\nv1.1.0\nDynamic key discovery — scans entire config instead of hardcoded list\nAuto-grouping by category (Environment / Skills / Other)\nCommon env keys shown even if not configured\nv1.0.0\nInitial release with hardcoded provider slots\nSave/Clear functionality via config.patch"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/maverick-software/api-key-ui-tab",
    "publisherUrl": "https://clawhub.ai/maverick-software/api-key-ui-tab",
    "owner": "maverick-software",
    "version": "3.0.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/api-key-ui-tab",
    "downloadUrl": "https://openagent3.xyz/downloads/api-key-ui-tab",
    "agentUrl": "https://openagent3.xyz/skills/api-key-ui-tab/agent",
    "manifestUrl": "https://openagent3.xyz/skills/api-key-ui-tab/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/api-key-ui-tab/agent.md"
  }
}