Files
openclaw-market/skill/openclaw-reporter/SKILL.md
richarjiang e79d721615 feat: 用 react-map-gl + MapLibre 替换 react-simple-maps 实现 2D 地图
- 替换 react-simple-maps/d3-geo/topojson-client 为 react-map-gl + maplibre-gl
- 使用 CARTO dark-matter 免费暗色瓦片,自带国家/城市名标注
- 基于 locale 动态切换地图标注语言(name:zh / name_en)
- MapLibre 原生 heatmap + circle 双层渲染替代 SVG 热力图
- 提取 MapPopup 组件,配合 react-map-gl Popup 实现点击弹窗
- continent page 改为 dynamic import (ssr: false)
- dev 模式去掉 Turbopack 以兼容 maplibre-gl
- 删除 heatmap-layer.tsx 和 react-simple-maps 类型声明
2026-03-13 14:46:23 +08:00

241 lines
10 KiB
Markdown

---
name: openclaw-reporter
description: |
Opt-in reporter for the OpenClaw global claw heatmap.
On first use, ASKS the user for consent before registering.
Sends heartbeats (platform + model only) and generic task summaries to https://kymr.top/.
Heartbeats are sent at session start and renewed via a PostToolUse hook, rate-limited
to at most once per 3 minutes — most invocations exit immediately after a timestamp check.
The PostToolUse hook does NOT read or send any tool names, arguments, or results.
Task reports are sent automatically via a Stop hook when the agent stops responding.
Data collected: user-chosen claw 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, tool names, or project-specific data is ever sent.
requirements:
network: true
writeFiles:
- "~/.openclaw/config.json"
- "~/.openclaw/scripts/heartbeat.sh"
- "~/.openclaw/scripts/task-report.sh"
- "~/.openclaw/.last_heartbeat"
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."
hooks:
SessionStart:
- hooks:
- type: command
command: "bash $HOME/.openclaw/scripts/heartbeat.sh 2>/dev/null || true"
timeout: 10
PostToolUse:
- hooks:
- type: command
command: "bash $HOME/.openclaw/scripts/heartbeat.sh 2>/dev/null || true"
timeout: 5
Stop:
- hooks:
- type: command
command: "bash $HOME/.openclaw/scripts/task-report.sh 2>/dev/null || true"
timeout: 10
---
# OpenClaw Reporter
This skill lets you participate in the OpenClaw global claw activity heatmap. It reports **minimal, non-code** activity data to visualize worldwide AI agent usage. Note: as with any HTTPS request, the server can observe your IP address.
## How It Works
- **Heartbeat**: Sent at session start (`SessionStart` hook) and renewed periodically (`PostToolUse` hook, rate-limited to once per 3 minutes). The `PostToolUse` hook does **not** read tool names, arguments, or results — it only triggers the same timestamp-checked heartbeat script. Most invocations exit immediately after reading a single timestamp file.
- **Task report**: Sent automatically when the agent finishes responding via a `Stop` hook.
- **Registration**: One-time setup requiring explicit user consent (see below).
- **Hooks**: Hooks are registered in the skill frontmatter and activate when the skill is loaded. No system-level files are modified.
## Data Disclosure
This skill sends the following data to `https://kymr.top/` (the OpenClaw Market production server; server-side source code is in this repository under `app/api/v1/`):
| Data Field | Example | Purpose |
|---|---|---|
| Claw Name | `CoolClaw42` (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 | `"Completed a task"` | Generic activity indicator |
**Stored locally:** Registration returns an `apiKey` from the server, saved in `~/.openclaw/config.json` with `chmod 600` (owner-only access). This token is sent as `Authorization: Bearer` header in heartbeat and task report requests. The endpoint URL (`https://kymr.top/`) is hardcoded in hook scripts — not read from the config file — so a modified config cannot redirect telemetry. The `CLAUDE_MODEL` environment variable is read (if available) to identify the active model — it falls back to `"unknown"` if not set.
**Visible to the server:** Your IP address is visible on every HTTPS request (this is inherent to any network call and not specific to this skill). The server uses IP for approximate geolocation on the heatmap — no more precise than city-level.
**Never sent:** system usernames, file paths, code snippets, project names, tool names, tool arguments, tool results, or secrets.
## Configuration
Config is stored at `~/.openclaw/config.json` (permissions `600`). Hook scripts live at `~/.openclaw/scripts/`. The hooks check for the config file before sending any requests — if it doesn't exist, nothing is sent. The endpoint is hardcoded to `https://kymr.top/` in the scripts and is **not** configurable via the config file.
## First-Time Setup (Requires User Consent)
If `~/.openclaw/config.json` does not exist, follow these steps:
### Step 1: Ask for consent
Use the AskUserQuestion tool:
- Question: "OpenClaw Reporter wants to register a claw name and send periodic heartbeats (once per 3 min, platform + model only) 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, tool names, 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 claw name
If the user consented, use AskUserQuestion again:
- Question: "Pick a name for your claw on the heatmap! (e.g. CoolClaw, 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: "CoolClaw" / "CodeClaw" / "NightCrawler"
Use whatever the user provides as the claw name.
### Step 3: Register and install hooks
After receiving the name (stored as `CLAW_NAME`), run Step 3a and Step 3b in sequence.
#### Step 3a: Register and save config
```bash
# --- OpenClaw Registration ---
set -e
OPENCLAW_ENDPOINT="https://kymr.top"
export CLAW_NAME="USER_CHOSEN_NAME_HERE"
mkdir -p ~/.openclaw/scripts
# Register with the server
RESPONSE=$(curl -s -X POST "$OPENCLAW_ENDPOINT/api/v1/register" \
-H "Content-Type: application/json" \
-d "{
\"name\": \"$CLAW_NAME\",
\"platform\": \"$(uname -s | tr '[:upper:]' '[:lower:]')\",
\"model\": \"$(echo $CLAUDE_MODEL 2>/dev/null || echo 'unknown')\"
}")
# Save config — pipe response via stdin to avoid shell injection
# Creates ~/.openclaw/config.json with chmod 600 (owner-only access)
echo "$RESPONSE" | python3 -c "
import json, sys, os
data = json.loads(sys.stdin.read())
config = {
'clawId': data.get('clawId', ''),
'apiKey': data.get('apiKey', ''),
'name': os.environ.get('CLAW_NAME', '')
}
path = os.path.expanduser('~/.openclaw/config.json')
with open(path, 'w') as f:
json.dump(config, f, indent=2)
os.chmod(path, 0o600)
print('Registered as:', config['name'])
"
```
#### Step 3b: Deploy hook scripts
```bash
# --- Deploy heartbeat script (rate-limited to once per 180s) ---
cat > ~/.openclaw/scripts/heartbeat.sh << 'HOOKEOF'
#!/bin/bash
# OpenClaw heartbeat — rate-limited to once per 180 seconds.
# No tool names, arguments, or results are read or sent.
CONFIG="$HOME/.openclaw/config.json"
[ -f "$CONFIG" ] || exit 0
LAST_FILE="$HOME/.openclaw/.last_heartbeat"
NOW=$(date +%s)
if [ -f "$LAST_FILE" ]; then
LAST=$(cat "$LAST_FILE" 2>/dev/null || echo 0)
[ $((NOW - LAST)) -lt 180 ] && exit 0
fi
KEY=$(python3 -c "import json; print(json.load(open('$CONFIG'))['apiKey'])" 2>/dev/null) || exit 0
[ -z "$KEY" ] && exit 0
curl -s -o /dev/null --max-time 5 -X POST 'https://kymr.top/api/v1/heartbeat' \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $KEY" \
-d "{\"platform\":\"$(uname -s | tr '[:upper:]' '[:lower:]')\",\"model\":\"${CLAUDE_MODEL:-unknown}\"}" \
2>/dev/null && echo "$NOW" > "$LAST_FILE" || true
HOOKEOF
chmod +x ~/.openclaw/scripts/heartbeat.sh
# --- Deploy task report script ---
cat > ~/.openclaw/scripts/task-report.sh << 'HOOKEOF'
#!/bin/bash
CONFIG="$HOME/.openclaw/config.json"
[ -f "$CONFIG" ] || exit 0
KEY=$(python3 -c "import json; print(json.load(open('$CONFIG'))['apiKey'])" 2>/dev/null) || exit 0
[ -z "$KEY" ] && exit 0
curl -s -o /dev/null --max-time 5 -X POST 'https://kymr.top/api/v1/task' \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $KEY" \
-d "{\"summary\":\"Completed a task\",\"model\":\"${CLAUDE_MODEL:-unknown}\"}" 2>/dev/null || true
HOOKEOF
chmod +x ~/.openclaw/scripts/task-report.sh
echo "--- OpenClaw setup complete ---"
```
## Hook Verification (Auto-Repair)
**Every time this skill is loaded**, if `~/.openclaw/config.json` exists, verify that hook scripts are present. Run this check silently:
1. Check `~/.openclaw/scripts/heartbeat.sh` exists and is executable
2. Check `~/.openclaw/scripts/task-report.sh` exists and is executable
If **any** check fails, re-run Step 3b from the registration above to redeploy the scripts. Do this silently without asking the user.
Verification command (run silently on skill load when config exists):
```bash
# Quick hook health check — re-deploy scripts if missing
if [ -f ~/.openclaw/config.json ]; then
NEEDS_REPAIR=false
[ -x ~/.openclaw/scripts/heartbeat.sh ] || NEEDS_REPAIR=true
[ -x ~/.openclaw/scripts/task-report.sh ] || NEEDS_REPAIR=true
if [ "$NEEDS_REPAIR" = true ]; then
echo "OpenClaw hook scripts need repair — reinstalling..."
# (re-run Step 3b from registration above)
fi
fi
```
If repair is needed, re-run Step 3b (Deploy hook scripts) from the registration above.
## Opt-Out / Unregister
To stop all OpenClaw reporting and remove hooks:
```bash
# Remove scripts, config, and timestamp
rm -f ~/.openclaw/scripts/heartbeat.sh ~/.openclaw/scripts/task-report.sh
rmdir ~/.openclaw/scripts 2>/dev/null
rm -f ~/.openclaw/config.json ~/.openclaw/.last_heartbeat
rmdir ~/.openclaw 2>/dev/null
echo "OpenClaw fully uninstalled."
```
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. Hooks run automatically via skill frontmatter — do NOT manually execute heartbeat or task report commands
4. If any OpenClaw request fails, continue normally — never interrupt the user's workflow
5. Never include identifying information in task summaries
6. **On skill load**: if `~/.openclaw/config.json` exists, silently verify hook scripts are present and redeploy if missing
7. **Idempotent**: running script deployment multiple times is safe
8. **No system-level modifications**: never write to `~/.claude/settings.json` or any file outside `~/.openclaw/`