Configuration ​
Main config file: ~/.skimpyclaw/config.json
Top-Level Sections ​
| Section | Description |
|---|---|
gateway | HTTP port, host, and mode (local | remote) |
agents | Default agent + agent definitions with identity and model |
models | Provider credentials + model aliases + prompt caching |
channels | Telegram, Discord, active channel selection |
cron.jobs | Scheduled tasks (agentTurn or script) |
heartbeat | Interval, prompt, optional model + tools |
dashboard | Token for /api/dashboard/* auth |
subagents | Concurrency, retry limits, default code agent |
langfuse | Optional observability tracing |
voice | Optional TTS/STT configuration |
skills | Skills system configuration |
projects | Named project paths for code agents |
Environment Placeholders ​
JSON values support env var substitution:
"${ANTHROPIC_API_KEY}"
"${TELEGRAM_BOT_TOKEN}"
"${DISCORD_BOT_TOKEN}"
"${HOME}"
"${CLAUDE_CODE_OAUTH_TOKEN}"Gateway ​
"gateway": {
"port": 18790,
"host": "127.0.0.1",
"mode": "local"
}Agents ​
"agents": {
"default": "main",
"list": {
"main": {
"identity": {
"name": "SkimpyClaw",
"emoji": "👙🦞"
},
"model": "claude-fast",
"thinking": "medium"
}
}
}Thinking levels: none, low, medium, high (enables extended thinking for supported models).
Models ​
"models": {
"providers": {
"anthropic": { "apiKey": "${ANTHROPIC_API_KEY}" },
"openrouter": {
"apiKey": "${OPENROUTER_KEY}",
"baseURL": "https://openrouter.ai/api/v1"
},
"codex": {
"authToken": "codex",
"authPath": "${HOME}/.codex/auth.json"
},
"kimi": {
"apiKey": "${KIMI_API_KEY}",
"baseURL": "https://api.kimi.com/v1"
}
},
"aliases": {
"claude-fast": "anthropic/claude-haiku-4-5",
"claude-think": "anthropic/claude-sonnet-4-5",
"claude-opus": "anthropic/claude-opus-4",
"codex5.3": "codex/gpt-5.3-codex"
},
"promptCaching": true
}Provider is determined by the prefix before / in the model string (e.g., openrouter/google/gemini-2.0-flash).
Provider-Specific Notes ​
- Anthropic: Supports both API key and OAuth (Claude Code) authentication
- Codex: Uses ChatGPT backend via
~/.codex/auth.json(created bycodexCLI) - Kimi: Requires
User-Agentheader with version string (handled automatically)
Channels ​
Telegram ​
"channels": {
"active": "telegram",
"telegram": {
"enabled": true,
"token": "${TELEGRAM_BOT_TOKEN}",
"allowFrom": ["@username", "123456789"],
"tools": {
"enabled": true,
"allowedPaths": ["${HOME}/.skimpyclaw", "${HOME}/Projects"],
"maxIterations": 100,
"bashTimeout": 30000,
"browser": {
"enabled": true,
"type": "chromium",
"headless": true,
"profileDir": "${HOME}/.skimpyclaw/browser-profile"
},
"execApproval": {
"enabled": true,
"ttlMs": 300000,
"requireForTiers": [2, 3]
}
},
"dailyNotesDir": "${HOME}/Notes/Daily"
}
}Discord ​
"discord": {
"enabled": true,
"token": "${DISCORD_BOT_TOKEN}",
"allowFrom": ["username", "123456789"],
"defaultChannelId": "123456789",
"tools": {
"enabled": true,
"allowedPaths": ["${HOME}/.skimpyclaw"]
}
}Cron Jobs ​
Two payload types: agentTurn and script.
Agent Turn ​
{
"id": "morning",
"name": "Morning Briefing",
"schedule": {
"kind": "cron",
"expr": "0 8 * * *",
"tz": "America/New_York"
},
"payload": {
"kind": "agentTurn",
"message": "Good morning! What's on the agenda today?",
"sendAsVoice": false
},
"model": "claude-think"
}Script ​
{
"id": "backup",
"name": "Daily Backup",
"schedule": {
"kind": "cron",
"expr": "0 2 * * *",
"tz": "UTC"
},
"payload": {
"kind": "script",
"script": "rsync -av ~/Documents /Volumes/Backup/",
"cwd": "${HOME}",
"timeoutMs": 600000
}
}Message from File ​
The message field can reference a markdown file:
{
"payload": {
"kind": "agentTurn",
"message": "~/prompts/morning-brief.md"
}
}Files are resolved relative to ~/.skimpyclaw/prompts/ or as absolute paths.
Subagents ​
"subagents": {
"maxConcurrent": 5,
"maxRetries": 2,
"defaultCodeAgent": "claude"
}maxConcurrent: Maximum parallel subagent tasks (default: 5)maxRetries: Retry attempts on failure (default: 2)defaultCodeAgent: Default CLI forcode_with_agent(claude,codex, orkimi)
Heartbeat ​
"heartbeat": {
"intervalMs": 300000,
"prompt": "Check for anything urgent. If nothing needs attention, respond with 'HEARTBEAT_OK'.",
"model": "claude-fast",
"tools": {
"enabled": false
}
}Dashboard ​
"dashboard": {
"token": "auto-generated-uuid",
"frontend": "framework"
}The token is auto-generated on first startup if not present.
Langfuse (Optional) ​
"langfuse": {
"enabled": true,
"publicKey": "${LANGFUSE_PUBLIC_KEY}",
"secretKey": "${LANGFUSE_SECRET_KEY}",
"baseUrl": "https://cloud.langfuse.com",
"environment": "local",
"release": "dev",
"exportMode": "batched"
}Traces are created per agent turn. Tool calls appear as child observations. Token costs may be blank for OAuth/Codex unless Langfuse has model pricing configured.
Voice (Optional) ​
"voice": {
"enabled": true,
"defaultProvider": "elevenlabs",
"providers": {
"elevenlabs": {
"apiKey": "${ELEVENLABS_API_KEY}",
"tts": {
"voiceId": "your-voice-id",
"model": "eleven_multilingual_v2"
}
},
"openai": {
"apiKey": "${OPENAI_API_KEY}",
"tts": {
"model": "tts-1",
"voice": "nova"
},
"stt": {
"model": "whisper-1"
}
},
"macos": {
"tts": {
"voice": "Zoe"
}
}
},
"channels": {
"telegram": {
"acceptVoice": true,
"sendVoice": true
},
"discord": {
"acceptVoice": true,
"sendVoice": true
}
}
}Voice Providers ​
- ElevenLabs: High-quality voices, requires
voiceId - OpenAI:
tts-1/tts-1-hdmodels, supports multiple voices - macOS: Uses
saycommand + ffmpeg (local, free)
Transcription Priority ​
- Local whisper.cpp (
whisper-cli) — fastest, free - Local Python whisper (
whisper) — free - Configured API provider — fallback
Skills ​
"skills": {
"enabled": true,
"directory": "${HOME}/.skimpyclaw/skills",
"entries": {
"my-skill": true,
"another-skill": false
},
"maxPromptTokens": 4000
}enabled: Master switch for skills systemdirectory: Path to skills directoryentries: Per-skill enable/disable overridesmaxPromptTokens: Budget for injected skills content
Projects ​
Named project paths for use with code_with_agent:
"projects": {
"skimpyclaw": "${HOME}/Sites/skimpyclaw",
"my-app": "${HOME}/Projects/my-app"
}Projects are automatically added to tool allowedPaths and can be referenced by name in code_with_agent and code_with_team calls.
Complete Example ​
{
"gateway": {
"port": 18790,
"host": "127.0.0.1",
"mode": "local"
},
"agents": {
"default": "main",
"list": {
"main": {
"identity": {
"name": "SkimpyClaw",
"emoji": "👙🦞"
},
"model": "claude-fast"
}
}
},
"models": {
"providers": {
"anthropic": {
"apiKey": "${ANTHROPIC_API_KEY}"
}
},
"aliases": {
"claude-fast": "anthropic/claude-sonnet-4-5",
"claude-opus": "anthropic/claude-opus-4"
},
"promptCaching": true
},
"channels": {
"active": "telegram",
"telegram": {
"enabled": true,
"token": "${TELEGRAM_BOT_TOKEN}",
"allowFrom": ["@yourusername"],
"tools": {
"enabled": true,
"allowedPaths": ["${HOME}/.skimpyclaw"]
}
}
},
"cron": {
"jobs": []
},
"heartbeat": {
"intervalMs": 300000,
"prompt": "Check for anything urgent."
}
}