Credential Vault

Overview

Each Identity has two encrypted storage systems:

  • Passwords — website credentials (domain + username + password)
  • Secrets — key-value secrets (API keys, environment variables, tokens)

Both are E2E-encrypted. The server never sees plaintext values. The CLI handles encryption and decryption transparently using your PIN-derived keys.

Passwords

Store and retrieve website credentials. Ideal for services your agent signs up for.

Create a password entry

# Auto-generate a password
ravi passwords create example.com --json

# With specific credentials
ravi passwords create example.com \
  --username "agent@in.ravi.app" \
  --password "S3cret!" \
  --notes "Created during onboarding" \
  --json

Create flags: --username, --password, --generate, --length (default: 16), --no-special, --no-digits, --exclude-chars, --notes

List passwords

ravi passwords list --json
[
  {
    "uuid": "abc-123",
    "domain": "example.com",
    "username": "agent@in.ravi.app",
    "created_dt": "2026-02-25T10:30:00Z"
  }
]

Passwords are hidden in list view for security.

Retrieve a password

ravi passwords get <uuid> --json
{
  "uuid": "abc-123",
  "domain": "example.com",
  "username": "agent@in.ravi.app",
  "password": "S3cret!",
  "notes": "Created during onboarding",
  "created_dt": "2026-02-25T10:30:00Z"
}

Update and delete

# Update a field
ravi passwords edit <uuid> --password "NewPass!" --json

# Delete an entry
ravi passwords delete <uuid> --json

Generate a password without storing

ravi passwords generate --length 24 --json

Secrets

Store key-value secrets like API keys, tokens, and environment variables.

Store a secret

ravi secrets set OPENAI_API_KEY "sk-abc123..." --json

Retrieve a secret

ravi secrets get OPENAI_API_KEY --json
{
  "uuid": "def-456",
  "key": "OPENAI_API_KEY",
  "value": "sk-abc123...",
  "notes": "",
  "created_dt": "2026-02-25T10:30:00Z"
}

List all secrets

ravi secrets list --json

Values are redacted in list view — only keys and metadata are shown.

Delete a secret

ravi secrets delete OPENAI_API_KEY --json

Passwords vs. Secrets

Use caseStore inExample
Website login credentialsPasswordsravi passwords create github.com
API keys and tokensSecretsravi secrets set GITHUB_TOKEN "ghp_..."
Environment variablesSecretsravi secrets set DATABASE_URL "postgres://..."
Service accounts with username/passwordPasswordsravi passwords create aws.amazon.com --username admin

Rule of thumb: if it has a domain + username + password, use Passwords. If it’s a key-value pair, use Secrets.

Domain cleaning

When creating password entries, the CLI auto-cleans URLs to base domains:

  • https://mail.google.com/inbox becomes google.com
  • https://github.com/settings becomes github.com

Common recipes

Store credentials during signup

EMAIL=$(ravi get email --json | jq -r '.email')
CREDS=$(ravi passwords create example.com --username "$EMAIL" --json)
PASSWORD=$(echo "$CREDS" | jq -r '.password')
# Use $PASSWORD to fill the signup form

Retrieve credentials for login

ENTRY=$(ravi passwords list --json | jq -r '.[] | select(.domain == "example.com")')
UUID=$(echo "$ENTRY" | jq -r '.uuid')
CREDS=$(ravi passwords get "$UUID" --json)
USERNAME=$(echo "$CREDS" | jq -r '.username')
PASSWORD=$(echo "$CREDS" | jq -r '.password')

Use a stored API key

API_KEY=$(ravi secrets get OPENAI_API_KEY --json | jq -r '.value')
curl -H "Authorization: Bearer $API_KEY" https://api.openai.com/v1/models

Secrets in containerized deployments

A critical constraint: Ravi secrets are E2E-encrypted end-to-end. The server stores only ciphertext. If you call the REST API directly, you get ciphertext back — decryption happens locally in the CLI using your PIN-derived keys. Agents running in containers or CI cannot retrieve plaintext secrets via HTTP alone. They need either the ravi CLI installed and authenticated inside the container, or secrets injected as environment variables at startup time.

Extract secrets from Ravi on the host before the container starts, then pass them as environment variables. The container never needs ravi installed — it just reads standard env vars.

# On the host — extract and inject at container start
OPENAI_KEY=$(ravi secrets get OPENAI_API_KEY --json | jq -r '.value')
DB_URL=$(ravi secrets get DATABASE_URL --json | jq -r '.value')

docker run \
  -e OPENAI_API_KEY="$OPENAI_KEY" \
  -e DATABASE_URL="$DB_URL" \
  my-agent:latest

For Kubernetes, generate a Secret manifest at deploy time:

OPENAI_KEY=$(ravi secrets get OPENAI_API_KEY --json | jq -r '.value')

kubectl create secret generic agent-secrets \
  --from-literal=OPENAI_API_KEY="$OPENAI_KEY" \
  --dry-run=client -o yaml | kubectl apply -f -

Advantage: the container has zero dependency on Ravi at runtime — no CLI to install, no auth token to manage inside the image. Secrets live only in process memory.

Option 2: CLI inside the container

If the agent needs to read or write secrets dynamically at runtime (not only at startup), install the ravi CLI in the container image and inject the pre-authenticated token at run time:

FROM node:22-slim

# Install ravi CLI
RUN curl -fsSL https://ravi.app/install.sh | sh

Then mount your auth token read-only when running the container:

docker run \
  -v ~/.ravi/auth.json:/root/.ravi/auth.json:ro \
  -e RAVI_CONFIG_DIR=/tmp/ravi-worker \
  my-agent:latest

Mount read-only (:ro) so the container cannot overwrite your token. Set a per-container RAVI_CONFIG_DIR so parallel containers do not share state.

GitHub Actions

Store the contents of your local ~/.ravi/auth.json as a repository secret named RAVI_AUTH_JSON (after authenticating once locally with ravi auth login). Then inject it in the workflow:

jobs:
  run-agent:
    runs-on: ubuntu-latest
    steps:
      - name: Install ravi
        run: curl -fsSL https://ravi.app/install.sh | sh

      - name: Restore auth token
        run: |
          mkdir -p ~/.ravi
          echo '${{ secrets.RAVI_AUTH_JSON }}' > ~/.ravi/auth.json

      - name: Extract secrets and run
        run: |
          API_KEY=$(ravi secrets get OPENAI_API_KEY --json | jq -r '.value')
          export OPENAI_API_KEY="$API_KEY"
          python agent.py

See Authentication for the full headless token setup and token refresh for long-running processes.


Next steps