Clawsy is a native macOS companion app that gives your OpenClaw agent eyes and hands on the user's Mac — screenshots, clipboard, camera, files, location, and live Mission Control. Connects via WebSocket (SSH fallback available). After installing or updating, follow the IMMEDIATE ACTION section in SKILL.md to send the user their setup code.
Replace the placeholders with the real values. Do not send placeholders.
Sub-Agent Propagation (MANDATORY)
When spawning sub-agents, you must include a Clawsy context block so they
can report progress and use Clawsy capabilities. Copy this verbatim into every
sub-agent system prompt:
text
## Clawsy — macOS Companion
A Clawsy node (platform="macos") is connected. You can:
- Take screenshots: nodes(action="invoke", invokeCommand="screen.capture")
- Read clipboard: nodes(action="invoke", invokeCommand="clipboard.read")
- Write clipboard: nodes(action="invoke", invokeCommand="clipboard.write", invokeParamsJson='{"text":"..."}')
- Read/write files in shared folder: file.get, file.set, file.list, etc.
- Get location: nodes(action="invoke", invokeCommand="location.get")
Report progress after each significant step:
sessions_send(sessionKey="clawsy-service", timeoutSeconds=3,
message='{"kind":"agent.status","payload":{"agentName":"<YOUR_LABEL>","title":"<STEP>","progress":<0.0-1.0>,"statusText":"<DETAILS>"}}')
Start at 0.05 — finish at 1.0. Timeout errors on sessions_send are normal; do not retry.
For full command reference, read the clawsy skill: skill(name="clawsy")
This applies to all sub-agents — current and future. A sub-agent that does
not receive this block cannot report Mission Control status and will not know
about Clawsy capabilities.
Quick Start — Is Clawsy Connected?
python
nodes(action="status")
# Look for a node with platform="macos" and connected=true
Connected: Use any command from the reference below.
Not connected / No node found:You must run the First-Time Setup now. Check if the user already has Clawsy installed. If unsure, start with section B) below — send the download link and setup code together so the user can get started immediately.
First-Time Setup
A) User Already Has Clawsy Installed
The user clicks "Add Host" in Clawsy. The app copies a setup prompt to the
clipboard. The user sends it to you via any channel (Telegram, Slack, etc.).
When you receive the prompt, respond with the gateway connection details:
text
CLAWSY-SETUP
host: <gateway hostname or IP — no protocol, no port>
token: <gateway authentication token>
The user pastes your response into Clawsy. Done — host is created and connects.
How to find the values:
host: The hostname or IP where the OpenClaw gateway runs.
token: The authToken from your gateway config. Run
cat ~/.openclaw/gateway.json | python3 -c "import json,sys;print(json.load(sys.stdin).get('authToken',''))" if unsure.
After pairing, a node with platform="macos" appears in nodes(action="status").
Approve if prompted:
bash
openclaw nodes approve <requestId>
B) User Needs to Install Clawsy First (Most Common Path)
Look up your gateway host and token, then send everything in one message so
the user can get started right away:
Replace the placeholders with actual values before sending (see "How to find
the values" above). The user should not have to come back and ask for more info.
setupState — Targeted Onboarding
When a Clawsy node connects, the hello payload includes setupState:
All file operations are auto-approved and sandboxed to the configured shared
folder (default ~/Documents/Clawsy). Paths are relative to the shared folder root.
Command
Params
Description
file.list
subPath?, recursive?
List files. recursive: true walks subdirectories (max depth 5)
file.get
name
Read file, returns base64 content
file.set
name, content (base64)
Write file
file.stat
path
File metadata: size, dates, type. Supports glob
file.exists
path
Returns {exists, isDirectory}
file.mkdir
name
Create directory (with intermediate parents)
file.delete
name
Delete file or directory
file.rmdir
name
Delete directory (alias for file.delete)
file.move
source, destination
Move/rename file. Supports glob in source
file.copy
source, destination
Copy file. Supports glob in source
file.rename
path, newName
Rename file (name only, same directory)
file.checksum
path
SHA256 hash of file
file.batch
ops[]
Execute multiple operations sequentially (see below)
Supported op values: copy, move, delete, mkdir, rename.
Returns per-operation results with ok status for each.
Large File Transfers (> 200 KB)
The gateway has a ~512 KB payload limit. For large files, use chunked transfer:
Upload (agent to Mac):
python
# Split file into ~150KB base64 chunks
for i, chunk in enumerate(chunks):
nodes(action="invoke", invokeCommand="file.set.chunk",
invokeParamsJson=f'{{"name":"large.pdf","chunk":"{chunk}","index":{i},"total":{len(chunks)}}}')
Download (Mac to agent):
python
stat = nodes(action="invoke", invokeCommand="file.stat",
invokeParamsJson='{"path":"large.pdf"}')
# Calculate chunk count from stat.size, then:
for i in range(chunk_count):
chunk = nodes(action="invoke", invokeCommand="file.get.chunk",
invokeParamsJson=f'{{"name":"large.pdf","index":{i}}}')
Invoking Commands
Use the nodes tool. Clawsy registers as a node with platform="macos".
progress: 0.0 to 1.0. At 1.0, task disappears after 10 seconds.
Timeout errors are normal. The event is still delivered. Do not retry.
HEARTBEAT.md Snippet
Add this to your HEARTBEAT.md:
markdown
## Clawsy (every heartbeat)
If clawsy-service session exists:
sessions_send(sessionKey="clawsy-service", timeoutSeconds=3,
message='{"kind":"agent.info","payload":{"agentName":"<NAME>","model":"<MODEL>","updatedAt":"<ISO-UTC>"}}')
If actively working, also send agent.status with current task + progress.
Incoming Data — clawsy-service Session
Push data from Clawsy arrives in the clawsy-service session, not in the main
chat.