14 KiB
TOOLS.md - Local Notes & Tool Syntax
🔧 read — Read File Contents
Syntax:
read({ file_path: "/path/to/file"[, offset: N, limit: N] })
When to use: Read text files or view images (jpg, png, gif, webp).
Required: file_path — NEVER use path
Correct:
await read({ file_path: "/path/to/file" })
await read({ file_path: "/path/to/file", offset: 1, limit: 50 })
Wrong:
await read({ path: "/path/to/file" }) // ❌ 'path' is wrong, use 'file_path'
await read({}) // ❌ missing file_path entirely
Notes:
- Output truncated at 2000 lines or 50KB
- Use
offset+limitfor files >100 lines - Images sent as attachments automatically
🔧 edit — Edit File Contents
Syntax:
edit({ file_path: "/path", old_string: "exact text", new_string: "replacement" })
When to use: Precise text replacement. Old text must match exactly (including whitespace).
Required: BOTH old_string AND new_string (not oldText/newText)
Correct:
await edit({
file_path: "/path/to/file",
old_string: "text to replace",
new_string: "replacement text"
})
Wrong:
await edit({ file_path: "/path/file", old_string: "text" }) // ❌ missing new_string
await edit({ file_path: "/path/file", new_string: "text" }) // ❌ missing old_string
await edit({ file_path: "/path/file", oldText: "x", newText: "y" }) // ❌ wrong param names
Recovery: After 2 failed edit attempts → use write to rewrite the file completely.
🔧 write — Write File Contents
Syntax:
write({ file_path: "/path", content: "complete file content" })
When to use: Creating new files or rewriting entire files after failed edits.
Required: file_path AND complete content (overwrites everything)
Correct:
await write({
file_path: "/path/to/file",
content: "complete file content here"
})
Wrong:
await write({ content: "text" }) // ❌ missing file_path
await write({ path: "/file", content: "text" }) // ❌ use file_path not path
⚠️ Caution: Overwrites entire file — make sure you have the full content.
🔧 exec — Execute Shell Commands
Syntax:
exec({ command: "shell command"[, timeout: 30, workdir: "/path"] })
When to use: Run shell commands, background processes, or TTY-required CLIs.
Required: command
Correct:
await exec({ command: "ls -la" })
await exec({ command: "python3 script.py", timeout: 60 })
await exec({ command: "./script.sh", workdir: "/path/to/dir" })
Cron Scripts — CRITICAL:
# Always exit 0 for cron jobs
import sys
sys.exit(0)
Why: OpenClaw logs non-zero exits as failures. Use stdout presence for signaling:
if significant_update:
print(notification) # Output triggers notification
# No output = silent success
🔧 browser — Browser Control
Syntax:
browser({ action: "navigate|snapshot|click|...", targetUrl: "..." })
When to use: Navigate, screenshot, or interact with web pages.
Required: action
Requirements:
- Gateway must be running
- Chrome extension must be attached (click extension icon on tab)
Correct:
await browser({ action: "navigate", targetUrl: "https://example.com" })
await browser({ action: "snapshot" })
await browser({ action: "click", ref: "button-name" })
Quick Reference Summary
| Tool | Required Parameters | Common Errors |
|---|---|---|
read |
file_path |
Using path |
edit |
file_path, old_string, new_string |
Using newText/oldText, missing one param |
write |
file_path, content |
Partial content, missing file_path |
exec |
command |
Non-zero exit codes for cron |
browser |
action |
Using without gateway check |
Critical rules: Use file_path not path. Use old_string/new_string not oldText/newText.
Quality over speed. Verify before executing. Get it right.
Unified Search — Perplexity Primary, SearXNG Fallback
Primary: Perplexity API (cloud, AI-curated, paid)
Fallback: SearXNG (local, raw results, free)
Usage
# Default: Perplexity primary, SearXNG fallback on error
search "your query"
# Perplexity only (p = perplexity)
search p "your query"
search perplexity "your query"
# SearXNG only (local = searxng)
search local "your query"
search searxng "your query"
# With citations (Perplexity)
search --citations "your query"
# Pro model for complex queries
search --model sonar-pro "your query"
search --model sonar-deep-research "comprehensive research"
Models
| Model | Best For | Search Context |
|---|---|---|
| sonar | Quick answers, simple queries | Low/Medium/High |
| sonar-pro | Complex queries, coding | Medium/High |
| sonar-reasoning | Step-by-step reasoning | Medium/High |
| sonar-deep-research | Comprehensive research | High |
When to Use Each
- Perplexity: Complex queries, research, current events, anything needing synthesis
- SearXNG: Privacy-sensitive searches, simple factual lookups, bulk operations, rate limit fallback
Scripts
- Unified:
skills/perplexity/scripts/search.py - Perplexity-only:
skills/perplexity/scripts/query.py
Perplexity API
- Location:
/root/.openclaw/workspace/skills/perplexity/ - Key:
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 - Endpoint:
https://api.perplexity.ai/chat/completions - Models: sonar, sonar-pro, sonar-reasoning, sonar-deep-research
- Format: OpenAI-compatible
- Cost: ~$0.005 per query (shown in output)
- Features: AI-synthesized answers, citations, real-time search
- Note: Sends queries to Perplexity servers (cloud)
Voice/Text Reply Rules
- Voice message received → Reply with voice (using Kimi-XXX.ogg filename)
- Transcribe internally for understanding
- DO NOT send transcript text to Telegram
- DO NOT include any text with voice messages — voice-only, completely silent text
- Reply with voice-only, no text
- Text message received → Reply with text
- Never send both voice + text for the same reply
- ENFORCED 2026-02-07: Voice messages must be sent alone without accompanying text
Voice Settings
- TTS Provider: Local Kokoro @
http://10.0.0.228:8880 - Voice:
af_bella(American Female) - Filename format:
Kimi-YYYYMMDD-HHMMSS.ogg - Mode: Voice-only (no text transcript when sending voice)
Web Search
- Primary: Perplexity API (unified search, AI-curated)
- Fallback: SearXNG (local instance at
http://10.0.0.8:8888/) - Manual fallback: Use
search local "query"for privacy-sensitive searches - Browser tool: Only when gateway running and extension attached
Core Values
- Best accuracy — No compromises on quality
- Best performance — Optimize for speed where possible
- Privacy first — Always prioritize privacy in all decisions
- Always research before install — Search web for details, docs, best practices
- Local docs exception — If docs are local (OpenClaw, ClawHub), use those first
Search Preferences
- Search first — Try SearXNG before asking clarifying questions
- Prioritize sites: (to be filled in)
- GitHub / GitLab — For code, repos, technical docs
- Stack Overflow — For programming Q&A
- Wikipedia — For general knowledge
- Arch Wiki — For Linux/system admin topics
- Official docs — project.readthedocs.io, docs.project.org
- Avoid/deprioritize: (to be filled in)
- SEO spam sites
- Outdated forums (pre-2020 unless historical)
- Search language: English preferred, unless query is non-English
- Time bias: Prefer recent results for tech topics, timeless for facts
Search-First Sites (Priority Order)
When searching, prefer results from:
- docs.openclaw.ai / OpenClaw docs — OpenClaw documentation
- clawhub.com / ClawHub — OpenClaw skills registry
- docs.*.org / readthedocs.io — Official documentation
- github.com / gitlab.com — Source code, issues, READMEs
- stackoverflow.com — Programming solutions
- wikipedia.org — General reference
- archlinux.org/wiki — Linux/system administration
- reddit.com/r/ —* Community discussions (for opinions/experiences)
- news.ycombinator.com — Tech news and discussions
- medium.com / dev.to — Developer blogs (verify date)
SSH Hosts
-
epyc-debian-SSH (deb) —
n8n@10.0.0.38- Auth: SSH key (no password)
- Key:
~/.ssh/id_ed25519 - Sudo password:
passw0rd - Usage:
ssh n8n@10.0.0.38 - Status: OpenClaw removed 2026-02-07
-
epyc-debian2-SSH (deb2) —
n8n@10.0.0.39- Auth: SSH key (same as deb)
- Key:
~/.ssh/id_ed25519 - Sudo password:
passw0rd - Usage:
ssh n8n@10.0.0.39
Existing Software Stack
⚠️ ALREADY INSTALLED — Do not recommend these:
- n8n — Workflow automation
- ollama — Local LLM runner
- openclaw — AI agent platform (this system)
- openwebui — LLM chat interface
- anythingllm — RAG/chat with documents
- searxng — Privacy-focused search engine
- flowise — Low-code LLM workflow builder
- plex — Media server
- radarr — Movie management
- sonarr — TV show management
- sabnzbd — Usenet downloader
- comfyui — Stable Diffusion UI
When recommending software, ALWAYS check this list first and omit any matches.
Skills
Local Whisper STT
- Location:
/root/.openclaw/workspace/skills/local-whisper-stt/ - Purpose: Transcribe inbound voice messages
- Model:
base(CPU-only) - Usage: Auto-transcribes when voice message received
- Correct path:
scripts/transcribe.py(not root level)
Kimi TTS Custom
- Location:
/root/.openclaw/workspace/skills/kimi-tts-custom/ - Purpose: Generate voice with custom filenames and send voice-only replies
- Scripts:
scripts/generate_voice.py— Generate voice file (returns path, does NOT send)scripts/voice_reply.py— Generate + send voice-only reply (USE THIS for voice replies)
- Usage:
python3 scripts/voice_reply.py <chat_id> "text" - ⚠️ CRITICAL: Text reference to voice file does NOT send audio. Must use
voice_reply.pyor proper Telegram API delivery. Generation ≠ Delivery.
Qdrant Memory
- Location:
/root/.openclaw/workspace/skills/qdrant-memory/ - Mode: MANUAL ONLY — No automatic storage
- Collections:
kimi_memories(personal) — Identity, rules, preferences, lessonskimi_kb(knowledge base) — Web data, documents, reference materials
- Vector size: 1024 (snowflake-arctic-embed2)
- Distance: Cosine
- Qdrant URL:
http://10.0.0.40:6333
Personal Memory Scripts (kimi_memories):
scripts/store_memory.py— Manual storage with metadatascripts/search_memories.py— Semantic searchscripts/hybrid_search.py— Search files + vectors
Knowledge Base Scripts (kimi_kb):
scripts/kb_store.py— Store web/docs to KBscripts/kb_search.py— Search knowledge base
Usage:
# Personal memories ("q remember", "q recall")
python3 store_memory.py "Memory" --importance high --tags "preference"
python3 search_memories.py "voice settings"
# Knowledge base (manual document/web storage)
python3 kb_store.py "Content" --title "X" --domain "Docker" --tags "container"
python3 kb_search.py "docker volumes" --domain "Docker"
⚠️ CRITICAL: Never auto-store. Only when user explicitly requests with "q" prefix.
Infrastructure
Container Limits
- No GPUs attached — All ML workloads run on CPU
- Whisper: Use
tinyorbasemodels for speed
Local Services
- Kokoro TTS:
http://10.0.0.228:8880(OpenAI-compatible) - Ollama:
http://10.0.0.10:11434 - SearXNG:
http://10.0.0.8:8888(web search via curl) - Qdrant:
http://10.0.0.40:6333(vector database for memory + KB)- Collections:
kimi_memories(personal),kimi_kb(knowledge base) - Vector size: 1024 (snowflake-arctic-embed2)
- Distance: Cosine similarity
- Collections:
- Redis:
10.0.0.36:6379(task queue, available for future use)
Cron Jobs
- Default: Always check
openclaw cron listfirst when asked about cron jobs - Rob's scheduled tasks live in OpenClaw's cron system, not system crontab
- Only check system crontab (
crontab -l,/etc/cron.d/) if specifically asked about system-level jobs
Lessons Learned & Workarounds
Embedded Session Tool Errors
Issue: read tool called without path errors occur in embedded sessions even when parameter syntax is correct in workspace scripts.
Workarounds:
- Double-check parameters manually — Don't trust the model to pass them correctly in embedded contexts
- Avoid embedded tool calls when possible — Use workspace scripts instead
- Edit fails twice → Use write immediately — Don't retry edit tool more than once
- Verify file exists before read — Prevents ENOENT errors
- No redis-cli in container — Use Python redis module instead
- Browser tool unreliable — Use curl/SearXNG as primary web access
Common Parameter Errors to Avoid
| Wrong | Right | Notes |
|---|---|---|
path |
file_path |
Most common error |
newText/oldText |
new_string/new_string |
Edit tool only |
Missing new_string |
Include both params | Edit requires both |
Using write for small edits |
Use edit first |
Edit is safer for small changes |
Environment-Specific Gotchas
- Qdrant Python module — Must use scripts with proper sys.path setup
- Playwright browsers — Not installed, use curl/SearXNG for web scraping
- Browser gateway — Requires Chrome extension attached; rarely available
- Redis CLI — Not available; use
python3 -c "import redis..."instead