
Powered by Runta. The essential safety harness for OpenClaw/Hermes Agent's PII & Sensitive Credentials.
ClawShell is a security-privileged process for the OpenClaw/Hermes Agent ecosystem. It sits between OpenClaw/Hermes Agent and upstream LLM API providers (OpenAI, Anthropic, OpenRouter), performing virtual-to-real API key mapping and DLP (Data Loss Prevention) scanning on request and response bodies. It can also expose an Email read endpoint with sender allowlist/denylist filtering.
OpenClaw/Hermes Agent never holds real API keys, only virtual keys that ClawShell swaps for real ones before forwarding requests upstream. Real keys are stored in a privileged config directory (/etc/clawshell) protected by Unix file system permissions.
ClawShell maps virtual API keys to real provider keys so that OpenClaw/Hermes Agent never has direct access to real credentials.
/etc/clawshell/clawshell.toml, readable only by the clawshell system user. OpenClaw/Hermes Agent holds only virtual keys.Authorization: Bearer for OpenAI, x-api-key for Anthropic).ClawShell scans HTTP request and response bodies for sensitive data using configurable regex patterns.
block or redact action.ClawShell supports sender-based email filtering so each virtual key only sees mailbox content based on sender rules.
/etc/clawshell/clawshell.toml, readable only by the clawshell system user. OpenClaw/Hermes Agent holds only virtual keys.ClawShell supports OAuth-based authentication as an alternative to static API keys.
ClawShell exposes running counters at GET /admin/stats so operators can audit proxy activity since startup and across restarts.
prompt_tokens / completion_tokens / total_tokens (parsed from non-streaming JSON responses — SSE streams are not counted), number of emails hidden by the sender policy, and a per-address breakdown of filtered senders.127.0.0.1 / ::1 peers; non-loopback clients receive 403.[stats] persist_path = "..." in clawshell.toml (typically /var/lib/clawshell/stats.json under the hardened systemd unit, since /etc/clawshell is read-only there).<overflow> bucket so memory stays bounded.clawshell onboard wizard configures exactly one downstream LLM client per run — either OpenClaw or Hermes Agent — to route all requests through ClawShell's proxy. See Agent Target (pick one). ║ security boundary (Unix File System Permissions)
║
║ ┌───────────────────────────┐
║ │ /etc/clawshell │
║ │ ┄ real API keys │
║ │ ┄ DLP patterns │
║ │ ┄ email sender rules │
║ │ ┄ IMAP account creds │
║ └──────────┬────────────────┘
║ reads │
║ ┌──────────┴────────────────┐
┌──────────────┐ REQUEST ║ │ │ REQUEST ┌────────────┐
│ ├──(virtual───╫─►│ ClawShell ├──-(real key,───►│ │
│ OpenClaw or │ key) ║ │ │ PII redacted) │ OpenAI / │
│ Hermes Agent │ ║ │ DLP scan │ │ Anthropic/ │
│ holds only │ RESPONSE ║ │ real-key mapping │ RESPONSE │ OpenRouter │
│ virtual keys │◄────────────║◄─┤ email sender filtering │◄────────────────┤ │
│ │ ║ │ │ └────────────┘
│ │ EMAIL GET ║ │ │ IMAP fetch ┌────────────┐
│ ├───(virtual──║ | |───(real key)───►| |
│ │ key) ║ │ │ │ IMAP │
│ │ ║ │ │ | Provider │
│ │ ║ │ │ RESPONSE │ Gmail / │
│ │ filtered ║ │ │◄────────────────│ Outlook / │
│ │◄────────────║◄─| | │ custom │
└──────────────┘ ║ | | └────────────┘
║ └───────────────────────────┘
OpenClaw/Hermes Agent only holds virtual keys and cannot access the real API keys stored in the privileged config.
ClawShell swaps virtual keys for real ones and scans for PII before forwarding requests upstream.
ClawShell also enforces sender-based filtering before returning email data.
cargo install clawshell --locked
# Requires privilege to set up the security boundary
sudo clawshell onboard
npm install -g @clawshell/clawshell
# Requires privilege to set up the security boundary
sudo clawshell onboard
RUSTFLAGS="--remap-path-prefix=$(pwd)=. --remap-path-prefix=$HOME=/" cargo build --release
ls -al target/release/clawshell
wget https://musl.cc/x86_64-linux-musl-cross.tgz -O /tmp/musl-cross.tgz
tar -xzf /tmp/musl-cross.tgz -C /tmp
CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER="/tmp/x86_64-linux-musl-cross/bin/x86_64-linux-musl-gcc" \
RUSTFLAGS="--remap-path-prefix=$(pwd)=. --remap-path-prefix=$HOME=/" \
cargo build --release --target x86_64-unknown-linux-musl
The onboard command is an interactive setup wizard that must be run with sudo. It:
clawshell system user./etc/clawshell (mode 700) and /var/log/clawshell./etc/clawshell/clawshell.toml.~/.openclaw/openclaw.json for OpenClaw, or runs hermes config set for Hermes).sudo clawshell onboard
# Start (daemonizes by default)
sudo clawshell start
# Start in the foreground
sudo clawshell start --foreground
# Start with a custom config file
sudo clawshell start -c /path/to/clawshell.toml
# Check status
clawshell status
# View logs
clawshell logs
clawshell logs --level error
clawshell logs --follow
# Restart / Stop
sudo clawshell restart
sudo clawshell stop
# Migrate config schema to current version
sudo clawshell migrate-config
By default ClawShell listens on 127.0.0.1:18790.
You can override the bind address at runtime with environment variables:
CLAWSHELL_SERVER_HOST=0.0.0.0 CLAWSHELL_SERVER_PORT=17890 clawshell start --foreground
ClawShell reads its config from /etc/clawshell/clawshell.toml. You can view or edit it with:
sudo clawshell config # print current config
sudo clawshell config --edit # open in $EDITOR
A minimal config looks like this:
version = "0.2.1"
log_level = "info"
[server]
host = "127.0.0.1"
port = 18790
[upstream]
openai_base_url = "https://api.openai.com"
anthropic_base_url = "https://api.anthropic.com"
# Virtual-to-real API key mappings
[[keys]]
virtual_key = "vk-alice-001"
real_key = "sk-your-real-openai-key-here"
provider = "openai"
[[keys]]
virtual_key = "vk-claude-001"
real_key = "sk-ant-your-real-anthropic-key-here"
provider = "anthropic"
# Data Loss Prevention (DLP)
# action = "block" -> reject the request with 400
# action = "redact" -> replace matches with [REDACTED:<name>] and forward
[dlp]
scan_responses = false
patterns = [
{ name = "ssn", regex = '\b\d{3}-\d{2}-\d{4}\b', action = "redact" },
{ name = "visa_card", regex = '\b4[0-9]{12}(?:[0-9]{3})?\b', action = "redact" },
{ name = "amex_card", regex = '\b3[47][0-9]{13}\b', action = "redact" },
]
# Email secure endpoint
[email]
enabled = true
mode = "allowlist"
allow_senders = ["alice@example.com", "@trusted.org"]
deny_senders = []
default_max_results = 50
[[email.accounts]]
virtual_key = "vk-email-001"
email = "bot@gmail.com"
app_password = "abcd efgh ijkl mnop"
imap_host = "imap.gmail.com"
imap_port = 993
# Outlook preset example:
# imap_host = "imap-mail.outlook.com"
Instead of a static API key, you can authenticate via OAuth using your ChatGPT / Codex account.
During sudo clawshell onboard, select "Codex / ChatGPT (OAuth)" as the provider. The wizard will start a device code flow:
/etc/clawshell/oauth/.No browser is required on the server.
To configure OAuth manually in clawshell.toml:
# OAuth-backed key — no real_key needed
[[keys]]
virtual_key = "vk-codex-001"
auth = "oauth"
oauth_provider = "codex"
provider = "openai"
# OAuth provider definition
[[oauth_providers]]
provider = "codex"
# Optional overrides (defaults work for ChatGPT):
# client_id = "app_EMoamEEZ73f0CkXaXp7hrann"
# auth_url = "https://auth.openai.com/authorize"
# token_url = "https://auth.openai.com/oauth/token"
ClawShell handles token refresh automatically. When using Codex OAuth, requests to /v1/chat/completions are translated to the ChatGPT Responses API format and routed to chatgpt.com/backend-api/codex.
If start, restart, stop, config --edit, onboard, or uninstall reports that migration is required, run:
sudo clawshell migrate-config --config /etc/clawshell/clawshell.toml
See clawshell.example.toml for a full example.
sudo clawshell onboard begins with a single, mandatory choice:
=== Agent Target ===
? Which downstream agent should ClawShell wire through?
> OpenClaw
Hermes Agent
Each onboard run configures exactly one downstream client. There's no "also configure the other one" path — switching later means re-running sudo clawshell onboard and picking the other target. The prompt has no default preselection, so you pick explicitly every time.
When you pick OpenClaw, the wizard:
~/.openclaw/openclaw.json (numbered .bak files, mode 000).openclaw config set to patch three paths: env.CLAWSHELL_API_KEY, agents.defaults.models.clawshell/<model>, and models.providers.clawshell.get-email-messages skill bundle to <openclaw_root>/skills/ when email integration is enabled.openclaw models set clawshell and openclaw gateway restart at the end.This is the historical onboarding flow and is unchanged by the
$ claude mcp add clawshell \
-- python -m otcore.mcp_server <graph>