- Introduced `workspace_root` configuration in global and MagicForm settings to enforce path security. - Updated CLI commands to require relative paths for `--workspace` and `--config-dir` when `workspace_root` is set. - Added detailed validation rules for workspace paths to prevent directory traversal and absolute paths. - Enhanced agent processing to track execution metrics, including token usage and tool calls, and included these metrics in outbound messages. - Updated callback payloads for MagicForm to support progress and escalation messages, including detailed metrics for final responses. - Refactored agent loop to accumulate metrics across LLM iterations and publish progress updates during tool execution. - Added tests to ensure proper handling of new metrics and workspace path validations.
14 KiB
PicoClaw CLI Reference
Install
go install github.com/nuestra-ai/picoclaw/cmd/picoclaw@latest
Global Config
Create ~/.picoclaw/config.json (or set PICOCLAW_CONFIG env var):
{
"model_list": [
{
"model_name": "main",
"model": "anthropic/claude-sonnet-4.6",
"api_key": "sk-ant-...",
"api_base": "https://api.anthropic.com/v1"
}
],
"agents": {
"defaults": {
"workspace_root": "/data/workspaces",
"model_name": "main",
"max_tokens": 4096,
"max_tool_iterations": 20
}
}
}
The global config is the base. Per-workspace configs overlay it (see Workspace Config).
workspace_root defines the security boundary for all workspace and config-dir paths. When set, --workspace and --config-dir must be relative subdirectories within it. See Path Security for details.
Subcommands
| Command | Alias | Description |
|---|---|---|
picoclaw agent |
Interact with the agent (interactive REPL or one-shot) | |
picoclaw gateway |
g |
Start the HTTP gateway server |
picoclaw auth |
Manage authentication (login, logout, status, models) | |
picoclaw cron |
c |
Manage scheduled tasks |
picoclaw skills |
Manage skills (list, install, remove, search) | |
picoclaw status |
Show current status | |
picoclaw migrate |
Migrate config/workspace from another installation | |
picoclaw onboard |
Interactive first-run setup | |
picoclaw version |
Print version |
picoclaw agent
Interact with the agent directly. Without -m, starts an interactive REPL. With -m, sends a single message and exits.
Flags
| Flag | Short | Default | Description |
|---|---|---|---|
--message |
-m |
Single message (non-interactive). Omit for interactive REPL. | |
--session |
-s |
"" (→ agent:main:cli:default) |
Session key for conversation isolation (e.g. stackId:conversationId). |
--model |
Override model name from config. | ||
--workspace |
Agent workspace directory, relative to workspace_root. Resolved to an absolute path before use. |
||
--config-dir |
Config directory (relative to workspace_root) containing config.json and bootstrap files (AGENTS.md, IDENTITY.md, SOUL.md, USER.md). |
||
--tools |
Comma-separated tool allowlist (e.g. read_file,web_fetch). Only these tools are enabled. |
||
--skills |
Comma-separated skill filter (e.g. summarize,translate). Only these skills are loaded. |
||
--debug |
-d |
false |
Enable debug logging. |
Config Precedence (highest wins)
CLI flags (--model, --tools, --skills, --workspace)
> config-dir/config.json
> ~/.picoclaw/config.json
> defaults
Session Key Formatting
The --session value is automatically prefixed:
| Input | Resulting key |
|---|---|
| (empty) | agent:main:cli:default |
s1:c1 |
agent:main:cli:s1:c1 |
my-project |
agent:main:cli:my-project |
agent:custom:key |
agent:custom:key (used as-is) |
Session files are stored at {workspace}/sessions/{sanitized_key}.json.
Examples
# Interactive mode with default session
picoclaw agent
# One-shot message
picoclaw agent -m "Hello, world"
# With workspace isolation (paths relative to workspace_root)
picoclaw agent -m "Summarize the report" \
-s tenant1:conv42 \
--workspace tenant1/conv42 \
--config-dir tenant1/config
# Restricted tools, custom model
picoclaw agent -m "Search the web for recent news" \
--tools web,web_fetch \
--model gpt-5.2
# Debug mode to see session key, model, and iteration details
picoclaw agent -d -m "Hello" -s test
Note
: When
workspace_rootis set in the global config,--workspaceand--config-dirmust be relative paths (e.g.tenant1/conv42, not/data/workspaces/tenant1/conv42). Whenworkspace_rootis not set, paths fall back tofilepath.Absresolution for backward compatibility.
picoclaw gateway
Start the HTTP gateway server. Channels (Telegram, Discord, MagicForm, etc.) receive messages via webhooks and respond asynchronously.
| Flag | Short | Default | Description |
|---|---|---|---|
--debug |
-d |
false |
Enable debug logging. |
picoclaw gateway
# or with debug logging:
picoclaw gateway -d
Listens on {gateway.host}:{gateway.port} from the config (default 127.0.0.1:18790).
picoclaw auth
Manage provider authentication.
picoclaw auth login
picoclaw auth login -p <provider>
| Flag | Short | Default | Description |
|---|---|---|---|
--provider |
-p |
(required) | Provider: openai, anthropic, google-antigravity |
--device-code |
false |
Use device code flow for headless environments (OpenAI) | |
--setup-token |
false |
Use setup-token flow for Anthropic (from claude setup-token) |
Anthropic login prompts to choose between:
- Setup token (recommended) — paste a token from
claude setup-token - API key — paste an
sk-ant-...key from console.anthropic.com
Use --setup-token to skip the prompt and go directly to option 1.
OpenAI login uses browser-based OAuth by default, or --device-code for headless environments.
Google Antigravity login uses browser-based OAuth with PKCE. Also fetches user email and Cloud Code Assist project ID.
picoclaw auth logout
picoclaw auth logout [-p <provider>]
| Flag | Short | Default | Description |
|---|---|---|---|
--provider |
-p |
"" (all) |
Provider to logout from. Empty = logout from all. |
picoclaw auth status
picoclaw auth status
Shows all authenticated providers with method, status, account info, and expiry. For Anthropic OAuth credentials, also displays 5-hour and 7-day usage percentages.
picoclaw auth models
picoclaw auth models
Lists available models for Google Antigravity (requires prior login). Shows model ID, display name, and quota status.
picoclaw cron
Manage scheduled tasks.
picoclaw cron list
picoclaw cron list
picoclaw cron add
picoclaw cron add -n <name> -m <message> (--every <seconds> | --cron <expr>)
| Flag | Short | Default | Description |
|---|---|---|---|
--name |
-n |
(required) | Job name |
--message |
-m |
(required) | Message for the agent |
--every |
-e |
Run every N seconds | |
--cron |
-c |
Cron expression (e.g. 0 9 * * *) |
|
--deliver |
-d |
false |
Deliver response to a channel |
--channel |
Channel for delivery | ||
--to |
Recipient for delivery |
--every and --cron are mutually exclusive; one is required.
picoclaw cron remove / enable / disable
picoclaw cron remove <job-id>
picoclaw cron enable <job-id>
picoclaw cron disable <job-id>
picoclaw skills
Manage skills (install, remove, list, search).
picoclaw skills list # List installed skills
picoclaw skills list-builtin # List built-in skills
picoclaw skills install <url> # Install from URL or local path
picoclaw skills install-builtin # Install built-in skills to workspace
picoclaw skills remove <name> # Remove an installed skill
picoclaw skills search <query> # Search skill registries
picoclaw skills show <name> # Show skill details
The install command also supports --registry <name> <slug> to install from a named registry.
picoclaw migrate
Migrate config and workspace from another installation (e.g. OpenClaw).
| Flag | Default | Description |
|---|---|---|
--from |
openclaw |
Source to migrate from |
--dry-run |
false |
Preview changes without applying |
--refresh |
false |
Re-run migration (overwrite existing) |
--config-only |
false |
Migrate config only |
--workspace-only |
false |
Migrate workspace only |
--force |
false |
Overwrite existing files |
--source-home |
Custom source home directory | |
--target-home |
Custom target home directory |
Workspace Config
A workspace-level config.json (placed in the config directory) overlays the global config. Only these fields are honored:
| Field | Behavior | Required? |
|---|---|---|
model_list |
Replaces global model_list | Yes, if using a different API key |
agents.defaults |
Merges non-zero fields (model_name, max_tokens, temperature, etc.) | No |
agents.list |
Replaces global agents list | No |
tools |
Merges only keys present in the file (unmentioned tools are not affected) | No |
session |
Merges non-zero fields (dm_scope, identity_links) | No |
bindings |
Replaces global bindings | No |
Not honored (infrastructure-level): gateway, heartbeat, devices, providers, channels.
Protected fields: workspace_root cannot be overridden by a workspace config overlay — the boundary is always set by the base (global) config. If a workspace overlay sets a workspace value, it is validated against the base config's workspace_root; traversal attempts (e.g. ../../escape) cause a hard error.
Example config.json:
{
"model_list": [
{
"model_name": "main",
"model": "anthropic/claude-sonnet-4.6",
"api_key": "sk-ant-tenant-key",
"api_base": "https://api.anthropic.com/v1"
}
],
"agents": {
"defaults": {
"model_name": "main",
"max_tokens": 4096,
"temperature": 0.7
}
},
"tools": {
"exec": { "enabled": false }
}
}
Directory Layout
PicoClaw uses the following workspace directory structure for per-tenant/per-conversation isolation:
{workspace_root}/
{stackId}/
config/ # configDir -- shared per-stack
config.json # API key, model, agent settings
AGENTS.md # Agent instructions (optional)
IDENTITY.md # Agent identity (optional)
SOUL.md # Agent personality (optional)
USER.md # User context (optional)
{conversationId}/ # workspace -- per-conversation
sessions/ # Conversation history (managed by PicoClaw)
memory/ # Persistent agent memory (managed by PicoClaw)
skills/ # Workspace-local skills (optional)
The config directory contains shared settings (API keys, bootstrap files) for all conversations in a stack. Each conversation gets its own workspace directory with isolated sessions and memory.
Tool Names Reference
For --tools (CLI) or allowedTools (webhook API):
| Tool name | Description |
|---|---|
read_file |
Read files from workspace |
write_file |
Write files to workspace |
edit_file |
Edit files in workspace |
append_file |
Append to files in workspace |
list_dir |
List directory contents |
exec |
Execute shell commands |
spawn |
Spawn background processes |
cron |
Schedule recurring tasks |
web |
Web search (DuckDuckGo, Brave, etc.) |
web_fetch |
Fetch and parse web pages |
skills |
Run installed skills |
find_skills |
Search skill registries |
install_skill |
Install skills from registry |
subagent |
Spawn sub-agents |
message |
Send messages to channels |
mcp |
Model Context Protocol tools |
i2c |
I2C hardware bus (Linux only) |
spi |
SPI hardware bus (Linux only) |
Path Security
When workspace_root is set in agents.defaults, all workspace and config-dir paths are validated as relative subdirectories of that root. This applies uniformly across the CLI (--workspace, --config-dir), the gateway (webhook workspace/configDir fields), and workspace config overlays.
Validation rules (when workspace_root is set):
- Absolute paths are rejected — use
tenant1/conv42, not/data/workspaces/tenant1/conv42. - Directory traversal is rejected —
../escape,a/../../etc,foo/..all fail. - Empty string and bare
.are rejected — the path must pick a subdirectory, not root itself. - Relative paths are joined to
workspace_root—tenant1/conv42becomes/data/workspaces/tenant1/conv42. - A post-join boundary check confirms the resolved path stays within
workspace_root.
Without workspace_root: paths fall back to filepath.Abs resolution for backward compatibility, but traversal (..) is still rejected.
Enforcement points:
- CLI —
--workspaceand--config-dirare validated before any workspace config overlay is loaded. - Gateway — webhook
workspaceandconfigDirfields are validated by each channel handler (e.g. MagicForm). - Agent loop — defense-in-depth re-validation of metadata-driven workspace overrides.
- Config overlay —
workspace_rootcannot be overridden;workspacevalues from overlays are validated against the base config boundary.
Troubleshooting
--workspace or --config-dir rejected
- When
workspace_rootis set, paths must be relative subdirectories (e.g.s1/c1). Absolute paths,..traversal, and empty/.paths are rejected. - If
workspace_rootis not set and you get a traversal error, the path contains..which is always blocked.
Workspace config overlay rejected
- A workspace
config.jsonthat setsagents.defaults.workspaceto a path escapingworkspace_rootwill cause a hard error during config merge. Fix the overlay'sworkspacevalue.
Workspace config ignored
- Verify
config.jsonexists in the--config-dirpath. - Check that the JSON is valid (
picoclaw agent -dshows parse errors). - Only allowed fields are merged.
gateway,heartbeat,devices,providersare ignored.
Tools unexpectedly disabled
- Workspace
config.jsononly affects tools explicitly mentioned. If you set{"tools": {"exec": {"enabled": false}}}, onlyexecis disabled; all other tools keep their global config values.
Session not persisting
- Ensure the same
--workspacepath is used for the same conversation. - Sessions are stored at
{workspace}/sessions/. Different workspace paths = different sessions.