--- name: openclaw-reporter description: | Opt-in reporter for the OpenClaw global lobster heatmap. On first use, ASKS the user for consent before registering. Sends heartbeats (platform + model only) and generic task summaries to https://kymr.top/. All network calls run synchronously in the foreground — output is visible to the user. Data collected: user-chosen lobster name, OS platform, model name, generic task category. Credentials: the server returns an apiKey on registration, which is stored locally in ~/.openclaw/config.json and sent as a Bearer token in subsequent requests. No file paths, code, or project-specific data is ever sent. requirements: network: true writeFiles: - "~/.openclaw/config.json" binaries: - curl - python3 - uname env: - name: CLAUDE_MODEL required: false description: "Current Claude model identifier. Used to report which model is active. Falls back to 'unknown' if not set." --- # OpenClaw Reporter This skill lets you participate in the OpenClaw global lobster activity heatmap. It reports **anonymous, non-identifying** activity data to visualize worldwide AI agent usage. ## Data Disclosure This skill sends the following data to `https://kymr.top/`: | Data Field | Example | Purpose | |---|---|---| | Lobster Name | `CoolLobster42` (user-chosen) | Your display name on the heatmap | | Platform | `darwin`, `linux` | OS type for heatmap stats | | Model | `claude-sonnet-4-6` | Model usage stats | | Task summary | `"Fixed a bug"` | Generic activity category | **Stored locally:** Registration returns an `apiKey` from the server, saved in `~/.openclaw/config.json`. This token is sent as `Authorization: Bearer` header in heartbeat and task report requests. The `CLAUDE_MODEL` environment variable is read (if available) to identify the active model — it falls back to `"unknown"` if not set. **Never sent:** system usernames, file paths, code snippets, project names, secrets, IP-derived geolocation beyond what the server naturally receives. ## Configuration Config is stored at `~/.openclaw/config.json`. The skill checks for this file at the start of each conversation. ## First-Time Setup (Requires User Consent) If `~/.openclaw/config.json` does not exist, follow these two steps: ### Step 1: Ask for consent Use the AskUserQuestion tool: - Question: "OpenClaw Reporter wants to register a lobster name and send activity heartbeats to https://kymr.top/ for the global heatmap. The server will issue an API key stored locally at ~/.openclaw/config.json. No file paths, code, or project data is sent. Allow?" - Options: "Yes, register" / "No, skip" **If the user selects "No, skip":** do NOT register and do NOT ask again in this session. Stop here. ### Step 2: Ask for a lobster name If the user consented, use AskUserQuestion again: - Question: "Pick a name for your lobster on the heatmap! (e.g. CoolLobster, NightCrawler, CodeClaw)" - Let the user type a custom name via the "Other" option (no preset options needed, but provide a few fun suggestions as options) - Options: "CoolLobster" / "CodeClaw" / "NightCrawler" Use whatever the user provides as the lobster name. ### Step 3: Register After receiving the name (stored as `LOBSTER_NAME`): ```bash # Create config directory mkdir -p ~/.openclaw OPENCLAW_ENDPOINT="https://kymr.top" LOBSTER_NAME="USER_CHOSEN_NAME_HERE" RESPONSE=$(curl -s -X POST "$OPENCLAW_ENDPOINT/api/v1/register" \ -H "Content-Type: application/json" \ -d "{ \"name\": \"$LOBSTER_NAME\", \"platform\": \"$(uname -s | tr '[:upper:]' '[:lower:]')\", \"model\": \"$(echo $CLAUDE_MODEL 2>/dev/null || echo 'unknown')\" }") # Save config echo "$RESPONSE" | python3 -c " import json, sys data = json.load(sys.stdin) config = { 'lobsterId': data.get('lobsterId', ''), 'apiKey': data.get('apiKey', ''), 'name': '$LOBSTER_NAME', 'endpoint': '$OPENCLAW_ENDPOINT' } with open('$HOME/.openclaw/config.json', 'w') as f: json.dump(config, f, indent=2) print('Registered as:', '$LOBSTER_NAME') " ``` ## Heartbeat (On Every Conversation Start) If the config file exists, send a heartbeat. The request runs **synchronously in the foreground** with a 5-second timeout, so the user sees it happen: ```bash if [ -f ~/.openclaw/config.json ]; then OPENCLAW_CONFIG=$(cat ~/.openclaw/config.json) OPENCLAW_KEY=$(echo "$OPENCLAW_CONFIG" | python3 -c "import json,sys; print(json.load(sys.stdin)['apiKey'])") OPENCLAW_ENDPOINT=$(echo "$OPENCLAW_CONFIG" | python3 -c "import json,sys; print(json.load(sys.stdin)['endpoint'])") curl -s -o /dev/null -w "OpenClaw heartbeat: HTTP %{http_code}\n" \ --max-time 5 \ -X POST "$OPENCLAW_ENDPOINT/api/v1/heartbeat" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $OPENCLAW_KEY" \ -d "{ \"platform\": \"$(uname -s | tr '[:upper:]' '[:lower:]')\", \"model\": \"$(echo $CLAUDE_MODEL 2>/dev/null || echo 'unknown')\" }" fi ``` ## Task Completion Report When a significant task is completed, report a **generic summary only**: ```bash if [ -f ~/.openclaw/config.json ]; then OPENCLAW_CONFIG=$(cat ~/.openclaw/config.json) OPENCLAW_KEY=$(echo "$OPENCLAW_CONFIG" | python3 -c "import json,sys; print(json.load(sys.stdin)['apiKey'])") OPENCLAW_ENDPOINT=$(echo "$OPENCLAW_CONFIG" | python3 -c "import json,sys; print(json.load(sys.stdin)['endpoint'])") curl -s -o /dev/null -w "OpenClaw task report: HTTP %{http_code}\n" \ --max-time 5 \ -X POST "$OPENCLAW_ENDPOINT/api/v1/task" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $OPENCLAW_KEY" \ -d "{ \"summary\": \"TASK_SUMMARY_HERE\", \"durationMs\": DURATION_MS_HERE, \"model\": \"$(echo $CLAUDE_MODEL 2>/dev/null || echo 'unknown')\", \"toolsUsed\": [\"LIST_OF_TOOLS\"] }" fi ``` ### Task Summary Rules (STRICT) - NEVER include file paths, variable names, or code snippets - NEVER include API keys, secrets, or credentials - NEVER include project names, repository names, or organization names - NEVER include personal information (names, emails, usernames) - ONLY use generic categories: "Implemented a feature", "Fixed a bug", "Refactored code", "Updated configuration", "Added tests" - Keep summaries under 100 characters ## Opt-Out / Unregister To stop all OpenClaw reporting, delete the config file: ```bash rm -f ~/.openclaw/config.json rmdir ~/.openclaw 2>/dev/null ``` After deletion, no heartbeats or task reports will be sent. The skill will ask for consent again if re-enabled. ## Behavior Rules 1. **User consent is REQUIRED** before first registration — never register silently 2. If the user declines registration, respect the decision and do not ask again in the same session 3. All network calls run **synchronously in the foreground** (no `&`) with `--max-time 5` — the user sees every request 4. If any OpenClaw request fails, continue normally — never interrupt the user's workflow 5. Only report genuinely completed tasks, not intermediate steps 6. Never include identifying information in task summaries