Skip to main content

Configuration

Two files, by intent:

  • .env — secrets, tokens, channel-enable flags. Never committed.
  • data/config.json — non-secret runtime config (bot name, allow-lists, timezone, budgets, etc.). Generated by bun run setup, edited by bun run path and friends.

Precedence (lowest → highest):

  1. Defaults baked into src/lib/config.ts
  2. data/config.json
  3. process.env (MARSCLAW_* overrides)

Env wins because existing users have .env muscle-memory and a binary upgrade must not silently change behaviour. Setup writes both files for you; edit by hand only when you need to.

.env reference

Channel tokens

KeyRequiredNotes
TELEGRAM_BOT_TOKENper-channelFrom @BotFather
SLACK_BOT_TOKENper-channelxoxb-…
SLACK_APP_TOKENper-channelxapp-…, needs connections:write
MARSCLAW_WHATSAPPper-channelSet to 1; QR-scan auth on first run

Provider auth

KeyRequiredNotes
ANTHROPIC_API_KEYoptionalOnly needed if not using Claude CLI's OAuth login
GEMINI_API_KEYoptionalUse a paid key instead of OAuth (higher quota)
GOOGLE_OAUTH_CLIENT_IDoptionalFor Gmail/Drive/etc. via MCP — desktop OAuth client
GOOGLE_OAUTH_CLIENT_SECREToptionalPairs with GOOGLE_OAUTH_CLIENT_ID

Voice

KeyNotes
MARSCLAW_VOICESet to 1 to enable Whisper STT + Kokoro TTS
WHISPER_URLDefault http://127.0.0.1:9000
WHISPER_MODELtiny / base / small / medium / large (default base)
KOKORO_URLDefault http://127.0.0.1:9001
KOKORO_VOICEDefault voice (af_heart, af_bella, am_adam, …)
KOKORO_FORMATogg (voice note) / mp3 / wav

YouTube transcripts

KeyNotes
MARSCLAW_YTDLP_PATHAbsolute path to yt-dlp. Setup pins this; the runtime falls back to common install dirs + a login-shell lookup if unset. See youtube.md

Behavior overrides

Each shadows the same field in data/config.json.

KeyNotes
AGENT_PROVIDERgemini or claude
MARSCLAW_BOT_NAMEName the agent uses for itself
MARSCLAW_OWNER_NAMEWhat the agent calls you
MARSCLAW_OWNER_PHONEYour WhatsApp number, digits only
MARSCLAW_TIMEZONEIANA tz, e.g. Asia/Colombo
MARSCLAW_LOCATIONFree-text, e.g. Colombo, Sri Lanka
MARSCLAW_WHATSAPP_ALLOWED_JIDSComma-list; empty allows all
MARSCLAW_TELEGRAM_ALLOWED_CHATSComma-list of Telegram chat ids; empty allows all
MARSCLAW_SLACK_ALLOWED_USERSComma-list of Slack user ids; empty allows all
MARSCLAW_ALLOWED_PATHSComma-list; default = cwd
MARSCLAW_ALLOW_SHELL1 to expose the Bash tool to the agent (default 0) — see security.md
MARSCLAW_ALLOW_WEB1 to expose WebFetch/WebSearch (default 0)
MARSCLAW_ALLOWED_WEB_DOMAINSComma-list of hosts WebFetch may hit (e.g. wikipedia.org,*.gov)
MARSCLAW_ALLOW_MUTATING_TOOLS1 to let the agent send mail / write Sheets / etc. (default 0)
MARSCLAW_AUDIT_LOGPath to the append-only audit log (default logs/audit.log)
MARSCLAW_MAX_SESSIONSLRU cap on Claude SDK sessions
MARSCLAW_CLAUDE_IDLE_MSRecycle idle sessions after N ms (default 15 min)
MARSCLAW_CLAUDE_MAX_SESSION_AGE_MSHard cap on session lifetime (default 4 h)
MARSCLAW_AGENT_TIMEOUT_MSPer-message timeout (default 300000)
MARSCLAW_RATE_LIMIT_PER_MINUTEInbound per-sender (default 10; 0 disables)
MARSCLAW_RATE_LIMIT_PER_HOURInbound per-sender (default 60; 0 disables)
MARSCLAW_DAILY_USD_BUDGETAnthropic spend cap (0 disables; metered keys only)
MARSCLAW_TOOL_PERMISSIONSbypass = disable the canUseTool gate (escape hatch)
MARSCLAW_WHATSAPP_VERBOSESet to 1 for Baileys protocol logs
LOG_LEVELdebug / info / warn / error / fatal

Paths

KeyDefault
MARSCLAW_DBdata/marsclaw.db
MARSCLAW_CONFIGdata/config.json
MARSCLAW_WHATSAPP_AUTHdata/whatsapp-auth
GEMINI_BINgemini
CLAUDE_BINclaude

data/config.json reference

Generated by setup; safe to edit while the bot is stopped. Shape mirrors src/lib/config.ts.

{
"bot_name": "Mars",
"owner_name": "Dimuthu",
"owner_phone": "94701234567",

// One-shot WhatsApp pairing. Setup flips these.
"whatsapp_pair_owner": false,
"whatsapp_pair_code": "",

// Inbound allow-lists. Empty = allow all (with a per-sender warning).
"allowed_jids": ["94701234567@s.whatsapp.net"],
"allowed_telegram_chats": ["123456789"],
"allowed_slack_users": ["U01ABC23DEF"],

// Filesystem sandbox for the agent's Read/Write/Edit/Glob/Grep tools.
// Defaults to [cwd]. Anything outside is denied at the tool-gate layer.
// Sensitive files (.env, data/secrets, data/config.json, ~/.claude.json,
// ~/.gemini, data/whatsapp-auth, data/marsclaw.db) are blocked regardless
// of what's listed here. See docs/security.md.
"allowed_paths": ["/Users/you/marsclaw", "/Users/you/Documents/notes"],

// Capability flags — all off by default. See docs/security.md for the
// egress / threat model implications of each.
"allow_shell": false, // expose the Bash tool? (denylist is not airtight; default off)
"allow_web": false, // expose WebFetch/WebSearch?
"allowed_web_domains": [ // WebFetch host allow-list (bare = apex + subdomains)
"wikipedia.org",
"developer.mozilla.org",
"github.com"
],
"allow_mutating_tools": false, // gmail_send, sheets_write, calendar_create_event, *_raw writes

// Claude SDK session cap & lifetimes.
"max_sessions": 20,
"idle_ms": 900000,
"max_session_age_ms": 14400000,

"timezone": "Asia/Colombo",
"location": "Colombo, Sri Lanka",

"voice_enabled": true,
"agent_provider": "claude",

// Extra Bash patterns to deny, on top of the built-in destructive list.
"extra_bash_denylist": [],

// Inbound rate-limits (per sender). 0 disables.
"rate_limit_per_minute": 10,
"rate_limit_per_hour": 60,

// Anthropic spend cap in USD. 0 disables. Skipped under Claude Pro/Max OAuth.
"daily_usd_budget": 0
}

Allowed paths

The agent's Read, Write, Edit, Glob, Grep, MultiEdit, and NotebookEdit tools are gated against allowed_paths. Default is just the project root.

bun run path list
bun run path add /Users/you/Documents/notes
bun run path remove /Users/you/Documents/notes
bun run path reset # back to [cwd]

The same sandbox applies to MCP send_file — files outside allowed_paths cannot be delivered.

A separate sensitive-path list sits in front of allowed_paths and blocks .env, data/secrets/, data/config.json, data/whatsapp-auth/, data/marsclaw.db, ~/.claude.json, ~/.claude/, and ~/.gemini/ regardless of how allowed_paths is configured. Grep/Glob additionally refuse a search root that straddles any sensitive subtree. See security.md for the full list and rationale.

Escape hatch: MARSCLAW_TOOL_PERMISSIONS=bypass disables the gate entirely. Intended as a one-release migration aid; logs a warning on boot. Do not set this in a running deployment.

Capability flags (security defaults)

Four flags govern what the agent can do beyond reading approved files. All are off by default; turning each one on reopens a specific attack surface that security.md walks through in detail.

FlagDefaultWhat it gates
allow_shellfalseThe Bash tool. A denylist can't make shell safe; removal is the only sound posture.
allow_webfalseWebFetch and WebSearch. Web reads are delegated to a researcher subagent in an empty-room context.
allowed_web_domains[]Host allow-list for WebFetch. Bare entry covers apex + subdomains; *.example.com form is equivalent.
allow_mutating_toolsfalseOutbound/mutating MCP tools: gmail_send, sheets_write, calendar_create_event, write-style *_raw calls.

Bash denylist

extra_bash_denylist adds JavaScript regex source strings to the built-in destructive patterns (rm -rf /, chmod 000, dd of=, fork bombs, mkfs, shred, security find-generic-password, data/secrets). Only relevant when allow_shell is on — when shell is off, Bash isn't available regardless.

Persona & memory files

FilePurpose
GEMINI.mdPersona instructions read by the Gemini provider
CLAUDE.mdPersona instructions read by Claude (also project instructions for claude CLI in this repo)
skills/*.mdSub-instructions referenced from a persona via @skills/<name>.md
MEMORY.mdThe agent's own long-term notes. Local-only, gitignored
MEMORY.template.mdSeed copied to MEMORY.md on first run
wiki/*.mdOptional longer structured pages the agent can read on demand

Reset memory: rm MEMORY.md && bun run start.

Multiple Google accounts

Refresh tokens are stored in the macOS Keychain (service marsclaw) or a 0600 fallback file on Linux. Add additional accounts with bun run google login — give each one a short alias (personal, work). The MCP tools accept an account argument to pick which one to use; the default is the alias marked default.