From Zero to ZeroClaw: Achieving OpenClaw Feature Parity in One Session
March 25, 2026
I just spent an evening getting ZeroClaw — the open-source, Rust-based AI assistant — to full feature parity with OpenClaw. The journey involved wrestling with AWS Bedrock authentication, unlocking 44 tools from a locked-down default config, wiring up Claude Code as a subprocess provider, and getting it all running as a persistent macOS service with Telegram integration.
Here's everything I learned, broke, and fixed.
Why ZeroClaw
ZeroClaw is a single-binary AI assistant written entirely in Rust. Sub-10ms startup, under 5MB RAM, runs on anything from a Raspberry Pi to a Mac. It supports 20+ messaging channels (Telegram, Slack, Discord, Signal, iMessage, Matrix, and more), integrates with multiple AI providers, and ships with 70+ tools.
The pitch: OpenClaw but faster, smaller, and fully self-hosted.
The reality out of the box: a locked-down config that makes it feel like a chatbot from 2023.
Step 1: Installation
The install itself was trivial:
brew install zeroclaw
Homebrew drops a single binary at /opt/homebrew/bin/zeroclaw. No runtime dependencies. No Docker. No Python virtualenv hell.
Then the onboarding wizard:
zeroclaw onboard
This walks you through provider selection, model choice, and generates a ~/.zeroclaw/config.toml — a 700-line TOML file that controls everything.
Step 2: The Bedrock Authentication Saga
I had an AWS Bedrock API key (ABSK format) that worked perfectly with OpenClaw. Getting it to work with ZeroClaw was the first real challenge.
What didn't work
Standard AWS IAM credentials format. My ABSK key isn't a traditional AKIA... access key pair. It's a base64-encoded Bedrock bearer token — a newer AWS feature for simplified Bedrock authentication.
Setting AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY with the ABSK values produced:
Bedrock API error (403 Forbidden): {"message":"The security token included in the request is invalid."}
What did work
ZeroClaw actually supports bearer token auth through two mechanisms:
api_keyin config.toml — set at the top level:
api_key = "ABSK..."
AWS_BEARER_TOKEN_BEDROCKenvironment variable — following the same convention OpenClaw uses.
The key insight: you need both. The config file api_key tells ZeroClaw to use bearer auth instead of SigV4 signing. The environment variable ensures it's available to the Bedrock provider at runtime.
# ~/.zshrc
export AWS_REGION="us-west-2"
export AWS_BEARER_TOKEN_BEDROCK="ABSK..."
The model ID trap
Even after auth worked, the model ID was wrong. The onboarding wizard set anthropic.claude-sonnet-4-6 — but Bedrock requires inference profile IDs for on-demand throughput:
Bedrock API error (400 Bad Request): {"message":"Invocation of model ID
anthropic.claude-sonnet-4-6 with on-demand throughput isn't supported."}
The fix was using the cross-region inference profile format:
default_model = "us.anthropic.claude-sonnet-4-6"
I found the correct IDs by fetching the AWS docs — not guessing. Lesson learned: always verify model IDs against the actual Bedrock inference profiles page.
Step 3: The Default Config Problem
Out of the box, ZeroClaw is aggressively locked down. Here's what the default [autonomy] section looks like:
[autonomy]
level = "supervised"
workspace_only = true
max_actions_per_hour = 20
require_approval_for_medium_risk = true
block_high_risk_commands = true
forbidden_paths = ["/etc", "/root", "/home", "/usr", "/bin", "/opt", ...]
allowed_commands = ["git", "npm", "cargo", "ls", "cat", "grep", ...]
This means the agent:
- Can only operate inside
~/.zeroclaw/workspace - Can't find
claude(it's at~/.local/bin/claude— blocked by forbidden paths) - Can't run
curl,wget,docker,brew, ormake - Needs approval for anything remotely interesting
- Caps at 20 actions per hour
When I asked zeroclaw what tools it had, it reported ~20. When I asked it to use web search or Claude Code, it said "not available in this build."
It wasn't a build issue. It was a config issue.
Step 4: Unlocking Everything
Here's every config change I made to achieve feature parity:
Autonomy
[autonomy]
level = "full" # was: "supervised"
workspace_only = false # was: true
max_actions_per_hour = 100 # was: 20
require_approval_for_medium_risk = false # was: true
block_high_risk_commands = false # was: true
forbidden_paths = ["~/.ssh", "~/.gnupg"] # was: 14 paths blocked
allowed_commands = [
"git", "npm", "cargo", "ls", "cat", "grep", "find",
"echo", "pwd", "wc", "head", "tail", "date",
"python", "python3", "pip", "node",
"claude", "brew", "curl", "wget", "docker", "make", # added
"which", "env", "printenv", # added
]
shell_env_passthrough = ["PATH", "HOME", "USER", "AWS_BEARER_TOKEN_BEDROCK", "AWS_REGION"]
Auto-approve expanded
auto_approve = [
"file_read", "file_write",
"memory_recall", "memory_save",
"web_search_tool", "web_fetch",
"calculator", "glob_search", "content_search",
"image_info", "weather",
"shell", "browser", "http_request", # added
]
Agent capabilities
[agent]
max_tool_iterations = 25 # was: 10
parallel_tools = true # was: false
[agent.thinking]
default_level = "high" # was: "medium"
Tools enabled
[skills]
open_skills_enabled = true # was: false
allow_scripts = true # was: false
[skills.skill_creation]
enabled = true # was: false
[browser_delegate]
enabled = true # was: false
[media_pipeline]
enabled = true # was: false
[link_enricher]
enabled = true # was: false
[text_browser]
enabled = true # was: false
[mcp]
enabled = true # was: false
Claude Code integration
[claude_code]
enabled = true # was: false
timeout_secs = 600
allowed_tools = [
"Read", "Edit", "Bash", "Write",
"Glob", "Grep", "Agent", "WebFetch", "WebSearch", # added
]
env_passthrough = ["PATH", "HOME", "USER", "AWS_BEARER_TOKEN_BEDROCK", "AWS_REGION"]
[claude_code_runner]
enabled = true # was: false
Result
Tools went from ~20 to 44. The "not available in this build" message was a lie — every tool was compiled in, just gated behind config flags.
Step 5: Installing Missing Dependencies
Even with config unlocked, two tools needed external binaries:
# text_browser needs lynx/links/w3m
brew install lynx
# browser tool needs agent-browser
npm install --prefix ~/.local/lib agent-browser
ln -sf ~/.local/lib/node_modules/.bin/agent-browser ~/.local/bin/agent-browser
Step 6: Telegram Bot
Setting up Telegram was straightforward:
- Message
@BotFatheron Telegram,/newbot, pick a name - Get the token
- Add to config:
[channels_config.telegram]
bot_token = "your-token-here"
allowed_users = ["*"]
Important: Don't add extra fields like message_timeout_secs or session_backend under the telegram section — those belong at the [channels_config] level and will generate warnings if placed under [channels_config.telegram].
I found this by running zeroclaw config schema and extracting the TelegramConfig JSON schema to see exactly which fields are valid.
Step 7: Persistent Service
Instead of using brew services, I went with a native launchd plist for more control:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.zeroclaw.daemon</string>
<key>ProgramArguments</key>
<array>
<string>/opt/homebrew/bin/zeroclaw</string>
<string>daemon</string>
</array>
<key>EnvironmentVariables</key>
<dict>
<key>AWS_BEARER_TOKEN_BEDROCK</key>
<string>your-token</string>
<key>AWS_REGION</key>
<string>us-west-2</string>
<key>PATH</key>
<string>/Users/you/.local/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
<key>HOME</key>
<string>/Users/you</string>
</dict>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/Users/you/.zeroclaw/daemon.stdout.log</string>
<key>StandardErrorPath</key>
<string>/Users/you/.zeroclaw/daemon.stderr.log</string>
</dict>
</plist>
Save to ~/Library/LaunchAgents/com.zeroclaw.daemon.plist, then:
launchctl load ~/Library/LaunchAgents/com.zeroclaw.daemon.plist
Critical detail: launchd doesn't source ~/.zshrc. You must include PATH and HOME in the plist's EnvironmentVariables, or zeroclaw won't find claude, lynx, agent-browser, or any tool outside /usr/bin.
Step 8: SOUL.md — Making It Actually Useful
ZeroClaw reads ~/.zeroclaw/workspace/SOUL.md as its system identity. The default is generic. I replaced it with tool-priority instructions:
# SOUL.md — Who You Are
You are ZeroClaw, an autonomous AI agent.
## Tools Priority
1. For coding tasks: use `claude_code` (delegates to Claude Code CLI)
2. For web research: use `web_search_tool` then `web_fetch` for details
3. For file operations: use `file_read`, `file_write`, `file_edit`
4. For shell commands: use `shell`
5. For browser tasks: use `browser` or `browser_delegate`
## Style
- Be concise and direct
- If you can solve it, solve it — don't list options unless asked
This made a noticeable difference. Before the update, zeroclaw would describe what it could do. After, it just does it.
Final Verification
I ran a comprehensive tool-by-tool test:
| Tool | Status |
|-----------------------|--------|
| claude_code | Pass — writes code, reads files, runs commands |
| web_search_tool | Pass — DuckDuckGo results |
| web_fetch | Pass — fetches full page content |
| http_request | Pass — HTTP 200 from httpbin.org |
| text_browser | Pass — lynx rendering |
| shell | Pass — full PATH access, finds claude/lynx/agent-browser |
| memory_store/recall | Pass |
| cron_add/list | Pass |
| calculator | Pass |
| weather | Pass |
| screenshot | Pass |
44 tools total. All operational.
What I'd Do Differently
-
Start with
zeroclaw config schema— pipe it through jq and read the JSON schema before guessing at config keys. Would have saved 30 minutes of trial and error. -
Check the inference profiles page first — Bedrock model IDs are not the same as Anthropic model IDs. The
us.prefix matters. -
Don't trust the agent's self-report — when zeroclaw said tools were "not available in this build," the real answer was config flags. The binary ships with everything compiled in.
-
Set up
shell_env_passthroughearly — withoutPATHpassthrough, the agent can't find any tool outside the workspace. This is the single most impactful config change.
The Bottom Line
ZeroClaw's defaults are paranoid. That's arguably the right call for a tool that runs autonomously on your machine. But the gap between "installed" and "useful" is about 20 config changes, 2 brew installs, and understanding that workspace_only = true is the reason half your tools don't work.
Once unlocked, it's genuinely impressive — an 8.8MB binary that runs Claude Sonnet 4.6 via Bedrock, delegates coding to Claude Code, searches the web, automates browsers, and responds to Telegram messages. All on a single process using less memory than a Chrome tab.
The OpenClaw parity claim is real. You just have to configure your way there.
Built with ZeroClaw 0.6.2, Claude Sonnet 4.6 on AWS Bedrock (us-west-2), running on macOS.