---
name: aivault
description: End-to-end runbook for agents to install aivault and migrate installed skills from direct URL credential auth to capability-based aivault invoke flows, including custom capability creation and registry PR workflow.
homepage: https://aivault.moldable.sh
---

# aivault Skill Adapter (Detailed Agent Runbook)

This document is intentionally detailed for AI agents.
Execute these steps exactly.

## Objective

Perform this migration on behalf of a human:

1. Install `aivault`.
2. Audit installed skills for URL-based auth usage.
3. Rewrite eligible call sites to `aivault invoke`/`json`/`markdown`.
4. Create custom credentials/capabilities when needed.
5. Open a registry PR for missing built-in providers/capabilities when appropriate.

## Hard Constraints

1. Never ask the human to paste secret values into chat.
2. Human enters secret values; agent migrates code paths.
3. Migrate URL-style HTTP calls only.
4. Do not migrate provider CLI auth flows for now (`gh`, `aws`, `gcloud`, vendor CLIs).
5. Do not leave any direct credential injection in migrated code paths.
6. Preserve behavior (method/path/body semantics) when rewriting calls.

## Dry-Run Mode

When the user asks for dry run:

1. Do not edit skill/application files.
2. Run discovery, classification, and capability mapping commands only.
3. Write outputs to a temp directory:
   - `would-write-migration-report.md`
   - `would-write.patch`
4. Show exact commands run and exact proposed changes.

## Inputs and Defaults

Use these default skill roots unless user specifies others:

```bash
SKILL_ROOTS=("$HOME/.codex/skills" "$HOME/.agents/skills" "$HOME/.openclaw/skills")
```

## Phase 1: Install and Verify aivault

Run:

```bash
if ! command -v aivault >/dev/null 2>&1; then
  curl -fsSL https://aivault.moldable.sh/install.sh | sh
fi
command -v aivaultd >/dev/null 2>&1
aivault status
aivaultd --help >/dev/null
```

If `aivault` is not found:

```bash
export PATH="$HOME/.local/bin:$PATH"
```

## Phase 2: Enumerate Installed Skills

List existing roots:

```bash
for d in "${SKILL_ROOTS[@]}"; do
  [ -d "$d" ] && echo "$d"
done
```

Find candidate code files under each root:

```bash
for d in "${SKILL_ROOTS[@]}"; do
  [ -d "$d" ] || continue
  rg --files "$d" \
    -g '*.sh' -g '*.bash' -g '*.zsh' \
    -g '*.js' -g '*.mjs' -g '*.cjs' -g '*.ts' \
    -g '*.py' -g '*.rb' -g '*.go' -g '*.ps1'
done
```

## Phase 3: Detect Risky Auth Patterns (Generic)

Important: run detection only on executable/source files, not markdown/docs. This avoids large false-positive noise.

Create a scan output directory first:

```bash
RUN_DIR="${RUN_DIR:-$(mktemp -d /tmp/aivault-skill-scan.XXXXXX)}"
echo "scan output: $RUN_DIR"
```

### 3A) Detect secret indicators

```bash
for d in "${SKILL_ROOTS[@]}"; do
  [ -d "$d" ] || continue
  rg -n --hidden -S \
    -g '*.sh' -g '*.bash' -g '*.zsh' \
    -g '*.js' -g '*.mjs' -g '*.cjs' -g '*.ts' \
    -g '*.py' -g '*.rb' -g '*.go' -g '*.ps1' \
    -e 'Authorization:\s*(Bearer|Basic)\s+[^[:space:]]+' \
    -e '(api[_-]?key|token|access[_-]?token|client[_-]?secret)=' \
    -e '(x-api-key|x-auth-token|x-access-token)' \
    -e '\b[A-Z][A-Z0-9_]{2,}(API|ACCESS|AUTH|SECRET|TOKEN|KEY)[A-Z0-9_]*\b' \
    "$d" >> "$RUN_DIR/3A_secret_indicators.txt" || true
done
```

### 3B) Detect direct HTTP call primitives

```bash
for d in "${SKILL_ROOTS[@]}"; do
  [ -d "$d" ] || continue
  rg -n --hidden -S \
    -g '*.sh' -g '*.bash' -g '*.zsh' \
    -g '*.js' -g '*.mjs' -g '*.cjs' -g '*.ts' \
    -g '*.py' -g '*.rb' -g '*.go' -g '*.ps1' \
    -e '\bcurl\b' \
    -e '\bfetch\s*\(' \
    -e '\baxios\.' \
    -e '\brequests\.' \
    -e '\bhttpx\.' \
    -e '\bhttp\.NewRequest\b' \
    "$d" >> "$RUN_DIR/3B_http_primitives.txt" || true
done
```

### 3C) Detect CLI auth flows (exclude from migration)

```bash
for d in "${SKILL_ROOTS[@]}"; do
  [ -d "$d" ] || continue
  rg -n --hidden -S \
    -g '*.sh' -g '*.bash' -g '*.zsh' \
    -g '*.js' -g '*.mjs' -g '*.cjs' -g '*.ts' \
    -g '*.py' -g '*.rb' -g '*.go' -g '*.ps1' \
    -e '\bgh\b' \
    -e '\baws\b' \
    -e '\bgcloud\b' \
    -e '\baz\b' \
    -e '\bvercel\b' \
    -e '\bstripe\b' \
    "$d" >> "$RUN_DIR/3C_cli_auth_flows.txt" || true
done
```

### 3D) Reduce noise by intersecting 3A and 3B

Only classify files that appear in both the secret-indicator set and HTTP-primitive set:

```bash
cut -d: -f1 "$RUN_DIR/3A_secret_indicators.txt" | sort -u > "$RUN_DIR/3A_files.txt"
cut -d: -f1 "$RUN_DIR/3B_http_primitives.txt" | sort -u > "$RUN_DIR/3B_files.txt"
comm -12 "$RUN_DIR/3A_files.txt" "$RUN_DIR/3B_files.txt" > "$RUN_DIR/candidate_overlap_files.txt"

wc -l "$RUN_DIR"/3A_secret_indicators.txt "$RUN_DIR"/3B_http_primitives.txt "$RUN_DIR"/3C_cli_auth_flows.txt
cat "$RUN_DIR/candidate_overlap_files.txt"
```

Then manually inspect each overlap file before classification.

## Phase 4: Classify Each Finding

For each finding, classify into exactly one bucket:

1. `MIGRATE_URL_AUTH`
2. `SKIP_CLI_AUTH`
3. `NO_SECRET_EXPOSURE`
4. `BLOCKED_NEEDS_HUMAN_INPUT`

Decision rules:

1. If it calls provider CLI and auth is managed by that CLI, classify `SKIP_CLI_AUTH`.
2. If it builds HTTP requests and injects credentials in headers/query/body/env, classify `MIGRATE_URL_AUTH`.
3. If call already uses `aivault invoke/json/markdown`, classify `NO_SECRET_EXPOSURE`.
4. If endpoint/auth shape is unclear, classify `BLOCKED_NEEDS_HUMAN_INPUT`.

Additional rule:
5. If capability exists but required provider credential is missing in aivault (`Available (needs credential)`), classify `BLOCKED_NEEDS_HUMAN_INPUT` until human stores required secret(s).

## Phase 5: Map URL Calls to Existing Capabilities

Inspect capabilities:

```bash
aivault capability list
aivault capability describe <capability-id>
```

Mapping method:

1. Extract `host`, `method`, and `path prefix` from original call.
2. Find capability whose allowed host/method/path can represent the same operation.
3. If found, plan direct rewrite to that capability ID.
4. If not found, execute Phase 7 (custom capability).
5. If found but capability is not ready (missing credential), stop migration for that callsite and provide the exact `aivault secrets create ...` command shown by `aivault capability describe <capability-id>`.

Readiness check:

```bash
aivault capability list
aivault capability describe <capability-id>
```

Example blocker:
- `github/repos` exists, but is `Available (needs credential)` until:
  - `aivault secrets create --name GITHUB_TOKEN --value "<human-token>" --scope global`

## Phase 6: Rewrite Patterns (Direct Migration)

### Bash/curl rewrite

Before:

```bash
curl -sS https://api.openai.com/v1/chat/completions \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d "$BODY"
```

After:

```bash
aivault invoke openai/chat-completions \
  --method POST \
  --body "$BODY"
```

### Node/fetch rewrite

Before:

```js
await fetch("https://api.example.com/v1/users", {
  method: "GET",
  headers: { Authorization: `Bearer ${process.env.MY_API_KEY}` },
});
```

After:

```js
import { execFileSync } from "node:child_process";

const out = execFileSync(
  "aivault",
  ["json", "my-api/users", "--method", "GET"],
  { encoding: "utf8" },
);
const data = JSON.parse(out);
```

### Python/requests rewrite

Before:

```python
import os, requests
requests.get(
    "https://api.example.com/v1/users",
    headers={"Authorization": f"Bearer {os.environ['MY_API_KEY']}"}
)
```

After:

```python
import json, subprocess

out = subprocess.check_output([
    "aivault", "json", "my-api/users", "--method", "GET"
], text=True)
data = json.loads(out)
```

Rewrite rules:

1. Keep non-auth headers only when needed via `--header`.
2. If endpoint requires explicit path/method, include `--method` and `--path`.
3. Preserve request body semantics using `--body` or `--body-file-path`.
4. Remove env var reads that only existed for direct auth injection.

## Phase 7: Custom Capability Cookbook (Detailed)

Run this when no built-in capability can represent the original URL call.

### 7A) Extract original request contract

Capture:

1. `provider_slug` (for example `my-api`)
2. `credential_id` (for example `my-api`)
3. `capability_id` (for example `my-api/users`)
4. `host` (for example `api.example.com`)
5. `method` and `path prefix` (for example `GET` and `/v1/users`)
6. auth strategy in use: header/query/multi-header/oauth2/aws-sigv4

### 7B) Human enters secret

Human/operator runs:

```bash
aivault secrets create --name MY_CUSTOM_KEY --value "<human-secret>" --scope global
```

Get secret ID:

```bash
aivault secrets list -v
```

Copy the created secret ID from the JSON output.

### 7C) Create credential

Header auth:

```bash
aivault credential create my-api \
  --provider my-api \
  --secret-ref vault:secret:<secret-id> \
  --auth header \
  --header-name authorization \
  --value-template "Bearer {{secret}}" \
  --host api.example.com
```

Query auth:

```bash
aivault credential create my-api \
  --provider my-api \
  --secret-ref vault:secret:<secret-id> \
  --auth query \
  --query-param api_key \
  --host api.example.com
```

Multi-header auth:

```bash
aivault credential create my-api \
  --provider my-api \
  --secret-ref vault:secret:<secret-id> \
  --auth multi-header \
  --auth-header "X-API-KEY={{api_key}}" \
  --auth-header "X-APP-KEY={{app_key}}" \
  --host api.example.com
```

### 7D) Create capability

```bash
aivault capability create my-api/users \
  --provider my-api \
  --credential my-api \
  --method GET \
  --method POST \
  --path /v1/users \
  --host api.example.com
```

### 7E) Harden policy immediately

```bash
aivault capability policy set \
  --capability my-api/users \
  --rate-limit-per-minute 60 \
  --max-request-body-bytes 1048576 \
  --max-response-body-bytes 10485760 \
  --response-block "api_key" \
  --response-block "secret" \
  --response-block "token"
```

### 7F) Validate invocation

```bash
aivault invoke my-api/users --method GET
```

Or with explicit path:

```bash
aivault invoke my-api/users --method GET --path /v1/users?status=active
```

### 7G) Rewrite skill callsites

Replace direct URL auth call with:

```bash
aivault invoke my-api/users --method GET
```

Then remove all direct credential injection logic from that path.

### 7H) Verify audit trail

```bash
aivault audit
```

Confirm the invocation is recorded.

### 7I) Rollback (if migration fails)

```bash
aivault capability delete my-api/users
aivault credential delete my-api
# optional and human-approved only:
# aivault secrets delete --id <secret-id>
```

## Phase 8: Scope-Aware Migrations (Optional but Recommended)

When different workspaces/groups need different credentials:

Workspace-scoped secret:

```bash
aivault secrets create --name OPENAI_API_KEY --value "<human-secret>" \
  --scope workspace --workspace-id my-workspace
```

Group-scoped secret:

```bash
aivault secrets create --name OPENAI_API_KEY --value "<human-secret>" \
  --scope group --workspace-id my-workspace --group-id my-group
```

Invoke with context:

```bash
aivault invoke openai/chat-completions \
  --workspace-id my-workspace \
  --group-id my-group \
  --body '{"model":"gpt-5.2","messages":[{"role":"user","content":"hello"}]}'
```

Resolution order is: group -> workspace -> global.

## Phase 9: Registry PR Workflow (Missing Built-In Coverage)

When a custom provider/capability should become default for all users, open a PR in:

- https://github.com/moldable-ai/aivault

Reference examples:

- https://github.com/moldable-ai/skills

### 9A) Add registry entry

Create `registry/<provider>.json` using schema `registry/schemas/registry-provider.schema.json`.

Template:

```json
{
  "$schema": "./schemas/registry-provider.schema.json",
  "provider": "my-api",
  "vaultSecrets": {
    "MY_API_KEY": "secret"
  },
  "auth": {
    "header": {
      "header_name": "authorization",
      "value_template": "Bearer {{secret}}"
    }
  },
  "hosts": ["api.example.com"],
  "capabilities": [
    {
      "id": "my-api/users",
      "provider": "my-api",
      "allow": {
        "hosts": ["api.example.com"],
        "methods": ["GET", "POST"],
        "pathPrefixes": ["/v1/users"]
      }
    }
  ]
}
```

### 9B) Include migration evidence in PR

PR should include:

1. Original direct URL auth snippet (redacted).
2. New `aivault invoke <capability-id>` snippet.
3. Capability rationale (host/method/path limits).
4. Any policy constraints added.

### 9C) Run project checks before opening PR

From repo root:

```bash
pnpm lint
pnpm check-types
pnpm test
pnpm evidence
pnpm stories
```

If behavior work touched story coverage, follow:

- `prds/user-stories/how-to.md`

## Phase 10: Final Verification Checklist

Mark complete only when all pass:

- [ ] `aivault` installed and callable (`aivault status`)
- [ ] all URL-auth findings classified
- [ ] all `MIGRATE_URL_AUTH` callsites rewritten
- [ ] zero direct auth header/query/env injection remains in migrated paths
- [ ] custom capabilities created where required
- [ ] audit log confirms migrated invocations
- [ ] CLI-auth paths explicitly documented as skipped
- [ ] registry PR opened for missing default providers/capabilities (when applicable)

## Reference Links

- Install: https://aivault.moldable.sh/install
- Install script: https://aivault.moldable.sh/install.sh
- Getting started: https://aivault.moldable.sh/getting-started
- Security model: https://aivault.moldable.sh/core/security-model
- Scopes and isolation: https://aivault.moldable.sh/core/scopes-and-isolation
- Secrets CLI: https://aivault.moldable.sh/cli/secrets
- Credentials CLI: https://aivault.moldable.sh/cli/credentials
- Capabilities CLI: https://aivault.moldable.sh/cli/capabilities
- Invoke CLI: https://aivault.moldable.sh/cli/invoke
- Custom providers: https://aivault.moldable.sh/registry/custom-providers
- Linux setup: https://aivault.moldable.sh/linux-servers
- macOS setup: https://aivault.moldable.sh/macos
- Registry repo: https://github.com/moldable-ai/aivault
- Skills examples: https://github.com/moldable-ai/skills
