CLAVITORBlack-box credential issuance
Sign in Use for free — 10 entries

Developers

One CLI call. Every secret.

No env vars. No config files. No secrets in logs. Every secret your infrastructure needs, resolved at runtime.


The pattern

Store it once. Retrieve it anywhere.

Each agent is initialized once with its own token, scopes, and rate limits. After that, the agent can fetch secrets at runtime. The key is stored encrypted in the vault, never in env vars or source code. If the key rotates, update it in the vault UI — every agent picks it up automatically.

# One-time setup
$ clavitor-cli init <token>
# Single value
$ clavitor-cli get "OpenRouter API" --field key
sk-or-v1-abc123...
# Whole config — secrets resolved, safe template committed to git
$ clavitor-cli render app.config.json | myapp --config -

Three ways to use it

Field

One value. Pipe it into any command or script.

Render

Whole config file. Resolve all clavitor:// references at startup. Template is safe to commit.

Proxy

HTTPS proxy. Credentials resolved from headers transparently — never in logs or agent output.

Which one should I use?

FieldRenderProxy
Secrets out of logs
Works with any language
Works with any tool (curl, SDK, browser)
Per-agent scoping & audit
Multiple secrets at once
No code changes needed
Config files safe to commit
SSH / non-HTTP use cases

Quick pick: Building a script or CLI tool? Use Field. Deploying a service with a config file? Use Render. Running AI agents that make API calls? Use Proxy.


Field — single value

API_KEY=$(clavitor-cli get "OpenRouter" --field key)
SSH_KEY=$(clavitor-cli get "Deploy Key" --field private_key)

Render — whole config

Write your config with clavitor://entry/field references:

{
  "db": "clavitor://Production DB/password",
  "stripe": "clavitor://Stripe API/key",
  "openrouter": "clavitor://OpenRouter/key"
}
clavitor-cli render app.config.json | myapp --config -

Proxy — transparent credential injection

See the zero-knowledge proxy section below.


Zero-knowledge proxy

Your credentials never leave your machine.

One line to enable. No routing tables. No configuration. The agent writes clavitor:// where the secret should go — the proxy resolves it locally before the request leaves your machine.

export HTTPS_PROXY=http://localhost:1983

curl -H "Authorization: Bearer clavitor://OpenRouter/key" \
  https://openrouter.ai/api/v1/chat/completions

Why this beats every other credential proxy.

Nothing to steal. Cloud-hosted proxies are high-value targets — breach one and you get every customer’s credentials. Local proxies store credentials in their own config, readable by any agent on the machine. Clavitor’s proxy holds only an encrypted config file. No plaintext secrets on disk, no credential store to raid. Compromised agents find nothing.

Agents can’t pry it open. A compromised agent can’t extract credentials from the proxy — the proxy doesn’t expose an API, serve a dashboard, or accept commands. It reads one header, resolves one reference, and injects the result into the outbound request. No attack surface.

Nothing in logs. The agent writes clavitor://Entry/field. That’s what appears in stdout, in logs, in conversation history. The real credential exists only inside the proxy process for the duration of one HTTP call. Log aggregators, crash dumps, CI artifacts — clean.

Zero config. No routing tables, no API mappings, no credential files to manage. The clavitor:// reference in the header is the only instruction. One init, one env var, done.


Languages

Works in every language. No SDK required.

Bash

# Single value, consumed inline — never written to disk
curl -H "Authorization: Bearer $(clavitor-cli get 'OpenRouter API' --field key)" \
  https://openrouter.ai/api/v1/models

Go

key, _ := exec.Command("clavitor-cli", "get", "OpenRouter API", "--field", "key").Output()
client := openai.NewClient(option.WithAPIKey(strings.TrimSpace(string(key))))

Python

import subprocess
api_key = subprocess.check_output(
    ["clavitor-cli", "get", "Stripe API", "--field", "key"]
).decode().strip()
stripe.api_key = api_key

Rust

let key = std::process::Command::new("clavitor-cli")
    .args(["get", "AWS Credentials", "--field", "secret_key"])
    .output()?.stdout;
let secret = String::from_utf8(key)?.trim().to_string();

TypeScript / Node

import { execSync } from 'child_process';
const apiKey = execSync('clavitor-cli get "Anthropic API" --field key').toString().trim();
const client = new Anthropic({ apiKey });

Infrastructure

Zero secrets in config. Zero secrets in logs.

Docker Compose

Use render to resolve secrets before starting the stack:

# docker-compose.template.yml (committed to git)
services:
  app:
    environment:
      - DB_PASSWORD=clavitor://Production DB/password
      - API_KEY=clavitor://Stripe API/key

# Start with resolved secrets (never written to disk)
clavitor-cli render docker-compose.template.yml | docker compose -f - up

Terraform

data "external" "vault" {
  program = ["clavitor-cli", "get", "AWS Root", "--json"]
}
provider "aws" {
  secret_key = data.external.vault.result.password
}

Kubernetes

kubectl create secret generic app-secrets \
  --from-literal=db-pass="$(clavitor-cli get 'Production DB' --field password)" \
  --from-literal=api-key="$(clavitor-cli get 'Stripe API' --field key)"

Ansible

- name: Get database password
  command: clavitor-cli get "Production DB" --field password
  register: db_pass
  no_log: true

- name: Configure app
  template:
    src: app.conf.j2
  vars:
    db_password: "{{ db_pass.stdout }}"

GitHub Actions

- name: Deploy
  run: |
    clavitor-cli init ${{ secrets.CLAVITOR_TOKEN }}
    kubectl set image deployment/app \
      app=myapp:${{ github.sha }}
    kubectl create secret generic app-secrets \
      --from-literal=api-key="$(clavitor-cli get 'Deploy Token' --field key)" \
      --dry-run=client -o yaml | kubectl apply -f -

SSH with vault-stored keys

clavitor-cli get "Deploy Key" --field private_key | ssh-add -
ssh deploy@production

AI agents

Every agent. Scoped access. Full audit trail.

Each agent gets its own token, its own scopes, its own rate limits. The vault logs every credential access. Agents that access too many distinct credentials are automatically locked.

Claude Code

# Skill auto-installed on init
clavitor-cli init <token>

# Claude Code can now:
#   "get me the AWS credentials"
#   "what's the GitHub deploy token?"
#   "store this API key as 'Stripe Prod'"

The installed skill enforces guardrails: one credential at a time, no bulk enumeration, secrets never echoed to conversation output.

OpenClaw

Replace hardcoded API keys in openclaw.json with vault references:

{
  "providers": {
    "openrouter": {
      "apiKey": "clavitor://OpenRouter API/key"
    },
    "fireworks": {
      "apiKey": "clavitor://Fireworks.ai/key"
    }
  },
  "channels": {
    "discord": {
      "accounts": {
        "main": { "token": "clavitor://Discord Bot/token" }
      }
    }
  }
}
# Start with resolved config
clavitor-cli render openclaw.json | openclaw start --config -

Codex (OpenAI)

CODEX_ENV_API_KEY=$(clavitor-cli get "OpenAI API" --field key) codex

Cursor / Windsurf / Aider

Any agent that runs shell commands. Add to project instructions:

# "Use clavitor-cli to retrieve secrets. Never ask the user for passwords."

CrewAI / LangChain / AutoGen

import subprocess

def get_secret(name, field="password"):
    return subprocess.check_output(
        ["clavitor-cli", "get", name, "--field", field]
    ).decode().strip()

# Use inline — don't store in a variable longer than needed
client = OpenAI(api_key=get_secret("OpenRouter API", "key"))

n8n / Make / Zapier

HTTP-based integration with the vault API directly:

curl -H "Authorization: Bearer $CVT_TOKEN" \
  https://vault.example.com/api/entries/search?q=Stripe

Config rendering

Commit your configs. Not your secrets.

clavitor-cli render scans any file for clavitor://entry/field references, resolves each against the vault, and outputs the result. The template lives in git. The resolved config lives in a pipe. Secrets never touch disk.

# Template (committed to git)
$ cat app.config.json
{"api_key": "clavitor://OpenRouter API/key", "db": "clavitor://Prod DB/password"}
# Resolved (piped to application, never on disk)
$ clavitor-cli render app.config.json
{"api_key": "sk-or-v1-abc123...", "db": "hunter2"}

Works with JSON, YAML, TOML, .env, or any text file. If it contains clavitor://, it gets resolved.


The pattern is always the same.

One CLI call, any context. The agent's scope determines what it can see. The tier determines what it can decrypt. The audit log records every access.