apikeys-ui

ClawSkills 作者 OpenClaw Community v3.0.0

Vault-backed API Keys management for OpenClaw. Secure file-based secret storage with one-click migration from plaintext config, dynamic key discovery, vault key selector for skills, manual secret creation, and plugin-registered settings tab.

安装 / 下载方式

TotalClaw CLI推荐
totalclaw install clawskills:clawskills~maverick-software-api-key-ui-tab
cURL直接下载,无需登录
curl -fsSL https://skills.taituai.com/api/skills/clawskills%3Aclawskills~maverick-software-api-key-ui-tab/file -o maverick-software-api-key-ui-tab.md
# Vault Enhancements w/ UI v3.0.0

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.

## Status: ✅ Active

| Component | Status |
|-----------|--------|
| Vault File Storage | ✅ Working |
| Secret References (SecretRef) | ✅ Working |
| Dynamic Key Discovery | ✅ Working |
| One-Click Migration | ✅ Working |
| Plugin-Registered Tab | ✅ Working |
| Vault Status Banner | ✅ Working |
| Key Status Badges | ✅ Working |
| Vault-Only Keys Section | ✅ Working |
| Manual "+ Add Secret" Form | ✅ Working |
| Restart Notification Banner | ✅ Working |
| Skills Vault Key Selector | ✅ Working |
| Skills Inline Key Creation | ✅ Working |
| Auth Profiles Display | ✅ Working |

## Features

### 1. Vault-Backed Storage

Keys are stored in `~/.openclaw/secrets.json` (file permissions `0600`). When you save a key, the UI:

1. Writes the value to the vault file
2. Configures the file secret provider in `openclaw.json` (if not already present)
3. Replaces the plaintext config value with a `SecretRef` object
4. Shows a restart notification — user must restart gateway for changes to take effect

**Config before migration:**
```json
{
  "env": {
    "OPENAI_API_KEY": "sk-proj-abc123..."
  }
}
```

**Config after migration:**
```json
{
  "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`):**
```json
{
  "OPENAI_API_KEY": "sk-proj-abc123..."
}
```

### 2. One-Click Migration

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

### 3. Dynamic Key Discovery

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:

| Provider | Env Key |
|----------|---------|
| Anthropic | `ANTHROPIC_API_KEY` |
| OpenAI | `OPENAI_API_KEY` |
| Google / Gemini | `GOOGLE_API_KEY` / `GEMINI_API_KEY` |
| Brave Search | `BRAVE_API_KEY` |
| ElevenLabs | `ELEVENLABS_API_KEY` |
| Deepgram | `DEEPGRAM_API_KEY` |
| OpenRouter | `OPENROUTER_API_KEY` |
| Groq | `GROQ_API_KEY` |
| Fireworks | `FIREWORKS_API_KEY` |
| Mistral | `MISTRAL_API_KEY` |
| xAI (Grok) | `XAI_API_KEY` |
| Perplexity | `PERPLEXITY_API_KEY` |
| GitHub | `GITHUB_TOKEN` |
| Hume AI | `HUME_API_KEY` / `HUME_SECRET_KEY` |

### 4. Vault Status Banner

Top of the page shows:
- **🔒 Vault Active** (green) — All keys in vault, provider configured
- **⚠️ X Plaintext Keys Detected** (yellow) — Migration recommended

### 5. Key Status Badges

Each key row shows:
- **VAULT** (green) — Stored in secure vault file
- **PLAINTEXT** (yellow) — Still in config as raw string
- **NOT SET** (grey) — Not configured

### 6. Vault-Only Keys Section

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

### 7. Manual "+ Add Secret" Form

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

### 8. Restart Notification Banner

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.

### 9. Skills Vault Key Selector

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

### 10. Skills Expanded by Default

All skill groups (workspace, built-in, managed) render expanded (`<details open>`) for better discoverability. Previously workspace and built-in were collapsed by default.

### 11. Auth Profiles Display

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.

## Architecture

### Security Model

```
┌──────────────────────────────────────────────────────────┐
│  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) │
              └────────────┘  └────────────────┘
```

### Backend RPCs

| Method | Description |
|--------|-------------|
| `secrets.status` | Vault file status, key count, plaintext count |
| `secrets.list` | List secret IDs with masked values |
| `secrets.write` | Store 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.delete` | Remove from vault + config |
| `secrets.migrate` | Batch-migrate all plaintext keys to vault |
| `secrets.authProfiles.list` | List auth pr