Skip to main content

Overview

ClawControl provides a secrets management system to securely store and reuse API keys across multiple deployments. Instead of entering the same API key every time you create a deployment, you can save it once and select it from a list. Secrets are stored locally in ~/.clawcontrol/secrets/ and organized by service type.

How Secrets Work

Secrets are managed by the service in src/services/secrets.ts. Each secret:
  • Has a unique ID generated from its name
  • Belongs to a specific service (e.g., hetzner, anthropic, telegram)
  • Stores the actual API key/token value
  • Includes a creation timestamp

Storage Location

Secrets are stored in JSON files organized by service:
~/.clawcontrol/secrets/
├── hetzner.json
├── digitalocean.json
├── anthropic.json
├── openrouter.json
└── telegram.json
Each file contains an array of saved secrets for that service (see src/types/index.ts:244-247):
{
  "keys": [
    {
      "id": "production-key",
      "name": "Production Key",
      "value": "sk-ant-...",
      "createdAt": "2026-02-28T10:00:00.000Z"
    },
    {
      "id": "development-key",
      "name": "Development Key",
      "value": "sk-ant-...",
      "createdAt": "2026-02-28T11:00:00.000Z"
    }
  ]
}

Secret Schema

Secrets follow the SavedSecretSchema defined in src/types/index.ts:236-242:
id
string
required
Unique identifier for the secret. Auto-generated from the name using lowercase letters, numbers, and hyphens.If a secret with the same ID already exists, a numeric suffix is added (e.g., my-key-1, my-key-2).
name
string
required
Human-readable name for the secret. Displayed in the UI when selecting secrets.
value
string
required
The actual API key or token value. This is what gets used in your deployments.
createdAt
string
required
ISO 8601 timestamp of when the secret was saved.

Using Secrets

When creating a new deployment, ClawControl prompts you to either:
  1. Select a saved secret from your existing secrets for that service
  2. Enter a new API key and optionally save it for future use
This happens for each credential required:
  • Cloud provider API keys (Hetzner, DigitalOcean)
  • AI provider API keys (Anthropic, OpenAI, OpenRouter)
  • Telegram bot tokens

Saving Secrets

Secrets are saved using the saveSecret() function in src/services/secrets.ts:41-53:
export function saveSecret(
  service: string,
  name: string,
  value: string
): SavedSecret {
  const keys = readSecretFile(service);
  const id = generateSecretId(service, name);
  const secret: SavedSecret = {
    id,
    name,
    value,
    createdAt: new Date().toISOString(),
  };
  keys.push(secret);
  writeSecretFile(service, keys);
  return secret;
}

Retrieving Secrets

Retrieve all secrets for a service using getSecretsForService() in src/services/secrets.ts:37-39:
export function getSecretsForService(service: string): SavedSecret[] {
  return readSecretFile(service);
}

Secret ID Generation

Secret IDs are auto-generated from the name to create URL-safe, filesystem-friendly identifiers. The logic in src/services/secrets.ts:68-81:
  1. Convert name to lowercase
  2. Replace non-alphanumeric characters with hyphens
  3. Remove leading/trailing hyphens
  4. Add numeric suffix if ID already exists
Examples:
  • "Production Key""production-key"
  • "My API Key""my-api-key"
  • "Production Key" (duplicate) → "production-key-1"

Deleting Secrets

Delete a secret by service and ID using deleteSecret() in src/services/secrets.ts:55-62:
export function deleteSecret(service: string, id: string): boolean {
  const keys = readSecretFile(service);
  const idx = keys.findIndex((k) => k.id === id);
  if (idx < 0) return false;
  keys.splice(idx, 1);
  writeSecretFile(service, keys);
  return true;
}
Returns true if the secret was found and deleted, false otherwise.

Supported Services

ClawControl supports saving secrets for:

Cloud Providers

  • hetzner - Hetzner Cloud API keys
  • digitalocean - DigitalOcean API tokens
  • vultr - Vultr API keys (when supported)

AI Providers

  • anthropic - Anthropic API keys (Claude)
  • openai - OpenAI API keys (GPT)
  • openrouter - OpenRouter API keys (multi-provider gateway)

Communication Channels

  • telegram - Telegram Bot API tokens

Security Considerations

Secrets are stored unencrypted in plain text JSON files in ~/.clawcontrol/secrets/.Ensure this directory has appropriate filesystem permissions (readable only by your user).
Best Practices:
  • Use appropriate filesystem permissions on ~/.clawcontrol/ (default: user-only access)
  • Don’t commit secrets to version control
  • Rotate API keys regularly
  • Delete unused secrets to minimize exposure

Example: Managing Secrets

Example Secret File

~/.clawcontrol/secrets/anthropic.json:
{
  "keys": [
    {
      "id": "production",
      "name": "Production",
      "value": "sk-ant-api03-abc123...",
      "createdAt": "2026-01-15T10:00:00.000Z"
    },
    {
      "id": "development",
      "name": "Development",
      "value": "sk-ant-api03-xyz789...",
      "createdAt": "2026-01-20T14:30:00.000Z"
    },
    {
      "id": "testing",
      "name": "Testing",
      "value": "sk-ant-api03-test456...",
      "createdAt": "2026-02-01T09:15:00.000Z"
    }
  ]
}

Programmatic Access

If you need to access secrets programmatically:
import { getSecretsForService, saveSecret, deleteSecret } from './services/secrets.js';

// Get all Anthropic API keys
const anthropicKeys = getSecretsForService('anthropic');

// Save a new key
const newSecret = saveSecret(
  'anthropic',
  'My New Key',
  'sk-ant-api03-...',
);

// Delete a key
const deleted = deleteSecret('anthropic', 'old-key-id');
  • Type Definition: src/types/index.ts:236-247 - SavedSecretSchema and SecretFileSchema
  • Secrets Service: src/services/secrets.ts - All secret management functions
  • Config Service: src/services/config.ts:253-257 - Secret storage paths

Build docs developers (and LLMs) love