17 KiB
ACTIVE.md - Syntax Library & Pre-Flight Checklist
Read the relevant section BEFORE using any tool. This is your syntax reference.
Core Philosophy: Quality over speed. Thorough and correct beats fast and half-baked.
📖 How to Use This File
- Identify the tool you need to use
- Read that section completely before writing any code
- Check the checklist items one by one
- Verify against examples - correct and wrong
- Execute only after validation
🔧 read - Read File Contents
Purpose
Read contents of text files or view images (jpg, png, gif, webp).
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
file_path |
string | YES | Path to the file (absolute or relative) |
offset |
integer | No | Line number to start from (1-indexed) |
limit |
integer | No | Maximum lines to read |
Instructions
- ALWAYS use
file_path, neverpath - ALWAYS provide the full path
- Use
offset+limitfor files >100 lines - Images are sent as attachments automatically
- Output truncated at 2000 lines or 50KB
Correct Examples
# Basic read
read({ file_path: "/root/.openclaw/workspace/ACTIVE.md" })
# Read with pagination
read({
file_path: "/root/.openclaw/workspace/large_file.txt",
offset: 1,
limit: 50
})
# Read from specific line
read({
file_path: "/var/log/syslog",
offset: 100,
limit: 25
})
Wrong Examples
# ❌ WRONG - 'path' is incorrect parameter name
read({ path: "/path/to/file" })
# ❌ WRONG - missing required file_path
read({ offset: 1, limit: 50 })
# ❌ WRONG - empty call
read({})
Checklist
- Using
file_path(notpath) - File path is complete
- Using
offset/limitfor large files if needed
✏️ edit - Precise Text Replacement
Purpose
Edit a file by replacing exact text. The old_string must match exactly (including whitespace).
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
file_path |
string | YES | Path to the file |
old_string |
string | YES | Exact text to find and replace |
new_string |
string | YES | Replacement text |
Critical Rules
- old_string must match EXACTLY - including whitespace, newlines, indentation
- Parameter names are
old_stringandnew_string- NOToldText/newText - Both parameters required - never provide only one
- Surgical edits only - for precise changes, not large rewrites
- If edit fails 2+ times - switch to
writetool instead
Instructions
- Read the file first to see exact content
- Copy the exact text you want to replace (including whitespace)
- Provide both
old_stringandnew_string - If edit fails, verify the exact match - or switch to
write
Correct Examples
# Simple replacement
edit({
file_path: "/root/.openclaw/workspace/config.txt",
old_string: "DEBUG = false",
new_string: "DEBUG = true"
})
# Multi-line replacement (preserve exact whitespace)
edit({
file_path: "/root/.openclaw/workspace/script.py",
old_string: """def old_function():
return 42""",
new_string: """def new_function():
return 100"""
})
# Adding to a list
edit({
file_path: "/root/.openclaw/workspace/ACTIVE.md",
old_string: "- Item 3",
new_string: """- Item 3
- Item 4"""
})
Wrong Examples
# ❌ WRONG - missing new_string
edit({
file_path: "/path/file",
old_string: "text to replace"
})
# ❌ WRONG - missing old_string
edit({
file_path: "/path/file",
new_string: "replacement text"
})
# ❌ WRONG - wrong parameter names (newText/oldText)
edit({
file_path: "/path/file",
oldText: "old",
newText: "new"
})
# ❌ WRONG - whitespace mismatch (will fail)
edit({
file_path: "/path/file",
old_string: " indented", # two spaces
new_string: " new" # four spaces - but old didn't match exactly
})
Recovery Strategy
# If edit fails twice, use write instead:
# 1. Read the full file
content = read({ file_path: "/path/to/file" })
# 2. Modify content in your mind/code
new_content = content.replace("old", "new")
# 3. Rewrite entire file
write({
file_path: "/path/to/file",
content: new_content
})
Checklist
- Using
old_stringandnew_string(not newText/oldText) - Both parameters provided
- old_string matches EXACTLY (copy-paste from read output)
- Considered if
writewould be better - Plan to switch to
writeif this fails twice
📝 write - Create or Overwrite File
Purpose
Write content to a file. Creates if doesn't exist, overwrites if it does.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
file_path |
string | YES* | Path to the file |
path |
string | YES* | Alternative parameter name (skills legacy) |
content |
string | YES | Content to write |
*Use file_path for standard operations, path for skill files
Critical Rules
- Overwrites entire file - no partial writes
- Creates parent directories automatically
- Must have complete content ready before calling
- Use after 2-3 failed
editattempts instead of continuing to fail
When to Use
- Creating new files
- Rewriting entire file after failed edits
- Major refactors where most content changes
- When exact text matching for
editis too difficult
Instructions
- Have the COMPLETE file content ready
- Double-check the file path
- For skills: use
pathparameter (legacy support) - Verify content includes everything needed
Correct Examples
# Create new file
write({
file_path: "/root/.openclaw/workspace/new_file.txt",
content: "This is the complete content of the new file."
})
# Overwrite existing (after failed edits)
write({
file_path: "/root/.openclaw/workspace/ACTIVE.md",
content: """# ACTIVE.md - New Content
Complete file content here...
All sections included...
"""
})
# For skill files (uses 'path' instead of 'file_path')
write({
path: "/root/.openclaw/workspace/skills/my-skill/SKILL.md",
content: "# Skill Documentation..."
})
Wrong Examples
# ❌ WRONG - missing content
write({ file_path: "/path/file" })
# ❌ WRONG - missing path
write({ content: "text" })
# ❌ WRONG - partial content thinking it will append
write({
file_path: "/path/file",
content: "new line" # This REPLACES entire file, not appends!
})
Checklist
- Have COMPLETE content ready
- Using
file_path(orpathfor skills) - Aware this OVERWRITES entire file
- All content included in the call
⚡ exec - Execute Shell Commands
Purpose
Execute shell commands with background continuation support.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
command |
string | YES | Shell command to execute |
workdir |
string | No | Working directory (defaults to cwd) |
timeout |
integer | No | Timeout in seconds |
env |
object | No | Environment variables |
pty |
boolean | No | Run in pseudo-terminal (for TTY UIs) |
host |
string | No | Host: sandbox, gateway, or node |
node |
string | No | Node name when host=node |
elevated |
boolean | No | Run with elevated permissions |
Critical Rules for Cron Scripts
- ALWAYS exit with code 0 -
sys.exit(0) - Never use exit codes 1 or 2 - these log as "exec failed"
- Use output to signal significance - print for notifications, silent for nothing
- For Python scripts: use
sys.exit(0)not bareexit()
Instructions
- For cron jobs: Script must ALWAYS return exit code 0
- Use
sys.exit(0)explicitly at end of Python scripts - Use stdout presence/absence to signal significance
- Check
timeoutfor long-running commands
Correct Examples
# Simple command
exec({ command: "ls -la /root/.openclaw/workspace" })
# With working directory
exec({
command: "python3 script.py",
workdir: "/root/.openclaw/workspace/skills/my-skill"
})
# With timeout
exec({
command: "long_running_task",
timeout: 300
})
# Cron script example (MUST exit 0)
# In your Python script:
import sys
if significant_update:
print("Notification: Important update found!")
sys.exit(0) # ✅ Output present = notification sent
else:
sys.exit(0) # ✅ No output = silent success
Wrong Examples
# ❌ WRONG - missing command
exec({ workdir: "/tmp" })
# ❌ WRONG - cron script with non-zero exit
# In Python script:
if no_updates:
sys.exit(1) # ❌ Logs as "exec failed" error!
if not important:
sys.exit(2) # ❌ Also logs as error, even if intentional!
Python Cron Script Template
#!/usr/bin/env python3
import sys
def main():
# Do work here
result = check_something()
if result["significant"]:
print("📊 Significant Update Found")
print(result["details"])
# Output will trigger notification
# ALWAYS exit 0
sys.exit(0)
if __name__ == "__main__":
main()
Checklist
commandprovided- If cron script: MUST
sys.exit(0)always - Using output presence for significance (not exit codes)
- Appropriate
timeoutset if needed workdirspecified if not using cwd
🌐 browser - Browser Control
Purpose
Control browser via OpenClaw's browser control server.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
action |
string | YES | Action: status, start, stop, profiles, tabs, open, snapshot, screenshot, navigate, act, etc. |
profile |
string | No | "chrome" for extension relay, "openclaw" for isolated |
targetUrl |
string | No | URL to navigate to |
targetId |
string | No | Tab target ID from snapshot |
request |
object | No | Action request details (for act) |
refs |
string | No | "role" or "aria" for snapshot refs |
Critical Rules
- Chrome extension must be attached - User clicks OpenClaw toolbar icon
- Use
profile: "chrome"for extension relay - Check gateway status first if unsure
- Fallback to curl if browser unavailable
Instructions
- Verify gateway is running:
openclaw gateway status - Ensure Chrome extension is attached (badge ON)
- Use
profile: "chrome"for existing tabs - Use
snapshotto get current page state - Use
actwith refs from snapshot for interactions
Correct Examples
# Check status first
exec({ command: "openclaw gateway status" })
# Open a URL
browser({
action: "open",
targetUrl: "https://example.com",
profile: "chrome"
})
# Get page snapshot
browser({
action: "snapshot",
profile: "chrome",
refs: "aria"
})
# Click an element (using ref from snapshot)
browser({
action: "act",
profile: "chrome",
request: {
kind: "click",
ref: "e12" # ref from snapshot
}
})
# Type text
browser({
action: "act",
profile: "chrome",
request: {
kind: "type",
ref: "e5",
text: "Hello world"
}
})
# Screenshot
browser({
action: "screenshot",
profile: "chrome",
fullPage: true
})
Fallback When Browser Unavailable
# If browser not available, use curl instead
exec({ command: "curl -s https://example.com" })
# For POST requests
exec({
command: 'curl -s -X POST -H "Content-Type: application/json" -d \'{"key":"value"}\' https://api.example.com'
})
Checklist
- Gateway running (
openclaw gateway status) - Chrome extension attached (user clicked icon)
- Using
profile: "chrome"for relay - Using refs from snapshot for interactions
- Fallback plan (curl) if browser fails
⏰ openclaw cron - Scheduled Tasks
Purpose
Manage scheduled tasks via OpenClaw's cron system.
CLI Commands
| Command | Purpose |
|---|---|
openclaw cron list |
List all cron jobs |
openclaw cron add |
Add a new job |
openclaw cron remove <name> |
Remove a job |
openclaw cron enable <name> |
Enable a job |
openclaw cron disable <name> |
Disable a job |
Critical Rules
- Use
--cronfor the schedule expression (NOT--schedule) - No
--enabledflag - jobs enabled by default - Use
--disabledif you need job disabled initially - Scripts MUST always exit with code 0
Parameters for cron add
| Parameter | Description |
|---|---|
--name |
Job identifier (required) |
--cron |
Cron expression like "0 11 * * *" (required) |
--message |
Task description |
--model |
Model to use for this job |
--channel |
Channel for output (e.g., "telegram:12345") |
--system-event |
For main session background jobs |
--disabled |
Create as disabled |
Instructions
- Always check
openclaw cron listfirst when user asks about cron - Use
--cronfor the time expression - Ensure scripts exit with code 0
- Use appropriate channel for notifications
Correct Examples
# Add daily monitoring job
openclaw cron add \
--name "monitor-openclaw" \
--cron "0 11 * * *" \
--message "Check OpenClaw repo for updates" \
--channel "telegram:1544075739"
# List all jobs
openclaw cron list
# Remove a job
openclaw cron remove "monitor-openclaw"
# Disable temporarily
openclaw cron disable "monitor-openclaw"
Wrong Examples
# ❌ WRONG - using --schedule instead of --cron
openclaw cron add --name "job" --schedule "0 11 * * *"
# ❌ WRONG - using --enabled (not a valid flag)
openclaw cron add --name "job" --cron "0 11 * * *" --enabled
# ❌ WRONG - script with exit code 1
# (In the script being called)
if error_occurred:
sys.exit(1) # This will log as "exec failed"
Checklist
- Using
--cron(not--schedule) - No
--enabledflag used - Script being called exits with code 0
- Checked
openclaw cron listfirst
🔍 General Workflow Rules
1. Discuss Before Building
- Confirmed approach with user?
- User said "yes do it" or equivalent?
- Wait for explicit confirmation, even if straightforward
2. Search-First Error Handling
Error encountered:
↓
Check knowledge base first (memory files, TOOLS.md)
↓
Still stuck? → Web search for solutions
↓
Simple syntax error? → Fix immediately (no search needed)
3. Verify Tools Exist
Before using any tool, ensure it exists:
openclaw tools list # Check available tools
Known undocumented: searx_search is documented in skills but NOT enabled. Use curl to SearXNG instead.
4. Memory Updates
After completing work:
memory/YYYY-MM-DD.md- Daily log of what happenedMEMORY.md- Key learnings (main session only)SKILL.md- Tool/usage patterns for skillsACTIVE.md- If new mistake pattern discovered
5. Take Your Time
- Quality over speed
- Thorough and correct beats fast and half-baked
- Verify parameters before executing
- Check examples in this file
🚨 My Common Mistakes Reference
| Tool | My Common Error | Correct Approach |
|---|---|---|
read |
Using path instead of file_path |
Always file_path |
edit |
Using newText/oldText instead of new_string/old_string |
Use _string suffix |
edit |
Partial edit, missing one param | Always provide BOTH |
edit |
Retrying 3+ times on failure | Switch to write after 2 failures |
exec |
Non-zero exit codes for cron | Always sys.exit(0) |
cron |
Using --schedule |
Use --cron |
cron |
Using --enabled flag |
Not needed (default enabled) |
| General | Acting without confirmation | Wait for explicit "yes" |
| General | Writing before discussing | Confirm approach first |
| General | Rushing for speed | Take time, verify |
| Tools | Using tools not in openclaw tools list |
Verify availability first |
📋 Quick Reference: All Parameter Names
| Tool | Required Parameters | Optional Parameters |
|---|---|---|
read |
file_path |
offset, limit |
edit |
file_path, old_string, new_string |
- |
write |
file_path (or path), content |
- |
exec |
command |
workdir, timeout, env, pty, host, node |
browser |
action |
profile, targetUrl, targetId, request, refs |
📚 Reference Files Guide
| File | Purpose | When to Read |
|---|---|---|
SOUL.md |
Who I am | Every session start |
USER.md |
Who I'm helping | Every session start |
AGENTS.md |
Workspace rules | Every session start |
ACTIVE.md |
This file - tool syntax | BEFORE every tool use |
TOOLS.md |
Tool patterns, SSH hosts, preferences | When tool errors occur |
SKILL.md |
Skill-specific documentation | Before using a skill |
MEMORY.md |
Long-term memory | Main session only |
🆘 Emergency Recovery
When edit keeps failing
# 1. Read full file
file_content = read({ file_path: "/path/to/file" })
# 2. Calculate changes mentally or with code
new_content = file_content.replace("old_text", "new_text")
# 3. Write complete file
write({
file_path: "/path/to/file",
content: new_content
})
When tool parameters are unclear
- Check this ACTIVE.md section for that tool
- Check
openclaw tools listfor available tools - Search knowledge base for previous usage
- Read the file you need to modify first
Last Updated: 2026-02-05
Check the relevant section BEFORE every tool use
Remember: Quality over speed. Verify before executing. Get it right.