One-script setup for OpenClaw in a hardened OrbStack Ubuntu VM on macOS.
- macOS with OrbStack installed
- An Anthropic API key
cp .env.example .env.local # fill in your keys
./setup.shThe dashboard opens at http://localhost:18789 when ready (~2 min).
Copy .env.example to .env.local and fill in the values:
| Variable | Required | Description |
|---|---|---|
ANTHROPIC_API_KEY |
One of these | Anthropic (Claude) — default provider |
OPENAI_API_KEY |
One of these | OpenAI (GPT) — alternative provider |
OPENCLAW_MODEL |
No | Default model in provider/model format (see below) |
GITHUB_TOKEN |
No | GitHub CLI (create token) |
TELEGRAM_BOT_TOKEN |
No | Telegram bot interface |
TELEGRAM_USER_ID |
No | Skip pairing (get yours from @userinfobot) |
SURGE_SMS_API_KEY |
No | SMS notifications via Surge |
At least one AI provider key is required. You can set both to have a fallback.
Set OPENCLAW_MODEL in .env.local to change the default model. If not set, it defaults to anthropic/claude-sonnet-4-20250514.
# Examples
OPENCLAW_MODEL=anthropic/claude-sonnet-4-20250514 # default, best tool-calling
OPENCLAW_MODEL=anthropic/claude-haiku-4-5-20251001 # faster, cheaper
OPENCLAW_MODEL=openai/gpt-4o # requires OPENAI_API_KEY
OPENCLAW_MODEL=openai/o3-mini # requires OPENAI_API_KEYNote: OpenClaw relies heavily on tool calling (skills, cron, browser automation, etc.). Smaller or cheaper models often produce worse tool calls — wrong arguments, skipped tools, or malformed JSON. If things feel flaky, try a stronger model before debugging.
Telegram setup
- Message @BotFather →
/newbot→ copy the bot token - Set
TELEGRAM_BOT_TOKENin.env.local - To skip pairing, message @userinfobot for your numeric user ID → set
TELEGRAM_USER_ID
Google Workspace setup
Gives the agent access to Gmail, Drive, Calendar, Sheets, and Docs.
- Google Cloud Console → create a project
- Enable APIs: Gmail, Drive, Calendar, Sheets, Docs
- Google Auth Platform → Branding: fill in app name and emails
- Google Auth Platform → Audience: click Make internal (Google Workspace) or add your email as a test user (personal Gmail)
- Google Auth Platform → Data Access: add scopes —
gmail.modify,drive,calendar,spreadsheets,documents, plusopenid,userinfo.email,userinfo.profile - Google Auth Platform → Clients: create a Desktop app client
- Download JSON → save as
client_secret.jsonnext tosetup.sh
During setup, a browser window opens for Google sign-in. On rebuilds, existing credentials are reused automatically.
# Dashboard (auto-authenticates)
open "http://localhost:18789/?token=$(orb -m openclaw -u root bash -c \
'cat /home/ocagent/.openclaw/openclaw.json' | jq -r '.gateway.auth.token')"
# Terminal chat UI
orb -m openclaw -u root su -l -s /bin/bash ocagent -c 'openclaw tui'
# Shell into the VM
orb -m openclaw -u root su -l -s /bin/bash ocagent # service user
orb -m openclaw -u root bash # root
# Open workspace in Cursor / VS Code
cursor --remote ssh-remote+orb /workspace/vm-openclaw
# Logs
orb -m openclaw -u root journalctl -u openclaw -f
# Rebuild from scratch
orb delete openclaw && ./setup.shCron jobs let the agent run tasks on a schedule — reminders, checks, reports, etc.
# List all cron jobs
orb -m openclaw -u root su -s /bin/bash ocagent -c "openclaw cron list"
# Add a job that runs every 5 minutes
orb -m openclaw -u root su -s /bin/bash ocagent -c \
'openclaw cron add --name "my-check" --every 5m --message "Check for new emails"'
# Add a daily job at 9am (Central time)
orb -m openclaw -u root su -s /bin/bash ocagent -c \
'openclaw cron add --name "morning-brief" --cron "0 9 * * *" --tz America/Chicago --message "Give me a morning briefing"'
# Run a job immediately (for testing)
orb -m openclaw -u root su -s /bin/bash ocagent -c "openclaw cron run <job-id>"
# Remove a job
orb -m openclaw -u root su -s /bin/bash ocagent -c "openclaw cron rm <job-id>"
# Check scheduler status
orb -m openclaw -u root su -s /bin/bash ocagent -c "openclaw cron status"You can also create cron jobs by chatting with the agent in the dashboard or Telegram — just ask it to set up a recurring task.
Cron not working? ("pairing required" error)
This means the CLI device doesn't have admin permissions. The setup script handles this automatically, but if it happens after an update or restart:
# Approve the pending device request
orb -m openclaw -u root su -s /bin/bash ocagent -c "openclaw devices approve --latest"
# Restart the gateway
orb -m openclaw -u root systemctl restart openclaw
# Verify cron works
orb -m openclaw -u root su -s /bin/bash ocagent -c "openclaw cron status"The VM workspace is bind-mounted to ./workspace/ on your Mac — instant, bidirectional, no daemon.
Mac ./workspace/
↕ bind-mount
VM /workspace/vm-openclaw/
The rest of the Mac filesystem is blocked. Only this folder is exposed to the VM.
Multiple VMs
Each VM gets its own subfolder. Add a bind-mount in mac-isolation.service for each:
workspace/
├── vm-openclaw/ ← VM 1
├── vm-research/ ← VM 2
└── vm-builder/ ← VM 3
Obsidian integration
Open ./workspace/ as an Obsidian vault to browse and edit agent files from your Mac or iPhone via Obsidian Sync.
Useful plugins: data-files-editor (JSON, TXT), obsidian-html-plugin (HTML dashboards).
If you close your MacBook lid, macOS sleeps and the VM stops. To prevent this while plugged in:
sudo pmset -c disablesleep 1To re-enable lid sleep:
sudo pmset -c disablesleep 0Note:
caffeinateonly prevents idle sleep — it does not prevent lid-close sleep.pmset disablesleepis required.
OpenClaw gateway is unreachable (port 18789 not listening)
The openclaw.service can die after a supervisor restart (SIGUSR1) without systemd detecting a failure, since the exit code is 0. Check and restart:
# Check service status
orb -m openclaw -u root systemctl status openclaw.service
# Restart the gateway
orb -m openclaw -u root systemctl restart openclaw.service
# Verify it's listening
orb -m openclaw -u root ss -tlnp | grep 18789mac-isolation.service failed (workspace mount broken on reboot)
If the Mac workspace directory doesn't exist when the VM boots, the bind-mount fails. Fix:
# Ensure the workspace directory exists on your Mac
mkdir -p ./workspace
# Reset and restart the mount service
orb -m openclaw -u root systemctl reset-failed mac-isolation.service
orb -m openclaw -u root systemctl start mac-isolation.service| Layer | Detail |
|---|---|
| Workspace mount | Only ./workspace/ is exposed; the rest of the Mac filesystem is blocked by a read-only tmpfs overlay |
| API keys | .env.local and client_secret.json are gitignored — rotate if the host is compromised |
| Gateway token | Grants full control; port 18789 is restricted to loopback and the OrbStack bridge |
| Agent user | ocagent has no sudo and no login shell, but retains outbound HTTPS access |
| VM isolation | Not a hard security boundary — OrbStack VMs share the host kernel |