Singsight — Install Skill for AI Coding Agents


Step 1 — Identify the target agent

Determine which agent to instrument:

  1. If the user named one explicitly, use that.
  2. Else, auto-detect by the runtime you're answering from:
    • If
      ~/.claude/
      ~/.claude/
      exists → Claude Code
    • If
      ~/.hermes/hermes-agent/
      ~/.hermes/hermes-agent/
      exists → Hermes Agent
    • If
      ~/.openclaw/openclaw.json
      ~/.openclaw/openclaw.json
      exists → OpenClaw
    • If
      ~/.config/opencode/opencode.json
      ~/.config/opencode/opencode.json
      exists → Opencode
  3. Else ASK THE USER: "Which agent should I instrument — Claude Code, Hermes Agent, OpenClaw, or Opencode?"
TargetStatusSection
Claude CodeStep 3
Hermes AgentStep 4
OpenClawStep 5
OpencodeStep 6

Step 2 — Get Singsight endpoint and API Key

You need two values:

  • Endpoint — the OTel collector URL (typically
    http://<singsight-host>:4318
    http://<singsight-host>:4318
    )
  • API Key — created in the Singsight web UI (header name:
    x-singsight-apikey
    x-singsight-apikey
    )

2a. Probe for existing config

Check if already configured in another agent:

# Check Claude Code grep -o 'x-singsight-apikey=["]*' "$HOME/.claude/settings.json" 2>/dev/null | head -1 # Check Hermes grep 'x-singsight-apikey' "$HOME/.hermes/.env" 2>/dev/null | head -1 # Check OpenClaw python3 -c " import json try: cfg = json.load(open('$HOME/.openclaw/openclaw.json')) h = cfg.get('diagnostics',{}).get('otel',{}).get('headers',{}) if 'x-singsight-apikey' in h: print(f'FOUND endpoint={cfg[\"diagnostics\"][\"otel\"][\"endpoint\"]}') except: pass " 2>/dev/null # Check Opencode grep 'x-singsight-apikey' "$HOME/.config/opencode/.env" 2>/dev/null | head -1

If found, ASK THE USER: "I found existing Singsight config for

<agent>
<agent>
. Reuse the same endpoint and API Key for
<target>
<target>
?"

If reuse confirmed, store as

$ENDPOINT
$ENDPOINT
and
$API_KEY
$API_KEY
and skip to Step 3.

2b. If not found — proactively prompt the user

You MUST actively tell the user where to get the values. Say exactly this:

Wait for the user to respond. Do NOT proceed until you have both values.

2c. Validate

  • Endpoint: must start with
    http://
    http://
    or
    https://
    https://
    , typically ends with port
    4318
    4318
    (HTTP) or
    4317
    4317
    (gRPC)
  • API Key: non-empty string (Singsight keys are opaque UUIDs)

Store as

$ENDPOINT
$ENDPOINT
and
$API_KEY
$API_KEY
for the following steps.


Step 3 — Claude Code

Claude Code has built-in OpenTelemetry support. Configuration goes into

~/.claude/settings.json
~/.claude/settings.json
.

3a. Check if already configured

if grep -q 'CLAUDE_CODE_ENABLE_TELEMETRY' "$HOME/.claude/settings.json" 2>/dev/null; then echo "ALREADY_CONFIGURED" fi

If already configured, ASK THE USER: "Claude Code already has telemetry configured. Want me to update the endpoint/key, or skip?"

3b. Merge into settings.json

SETTINGS="$HOME/.claude/settings.json" mkdir -p "$(dirname "$SETTINGS")" [ -f "$SETTINGS" ] || echo '{}' > "$SETTINGS" cp "$SETTINGS" "$SETTINGS.bak.$(date +%Y%m%d-%H%M%S)" TMP=$(mktemp) jq --arg endpoint "$ENDPOINT" --arg key "$API_KEY" ' .env = (.env // {}) + { "CLAUDE_CODE_ENABLE_TELEMETRY": "1", "CLAUDE_CODE_ENHANCED_TELEMETRY_BETA": "1", "OTEL_METRICS_EXPORTER": "otlp", "OTEL_LOGS_EXPORTER": "otlp", "OTEL_TRACES_EXPORTER": "otlp", "OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf", "OTEL_EXPORTER_OTLP_ENDPOINT": $endpoint, "OTEL_EXPORTER_OTLP_HEADERS": ("x-singsight-apikey=" + $key), "OTEL_LOG_TOOL_DETAILS": "1" } ' "$SETTINGS" > "$TMP" && mv "$TMP" "$SETTINGS" chmod 600 "$SETTINGS"

If

jq
jq
is not installed, ASK THE USER how to proceed:
brew install jq
brew install jq
(macOS) or
apt install jq
apt install jq
(Linux).

3c. Set user identity (recommended)

For the Users and Retention dashboards to work, set

enduser.id
enduser.id
:

SETTINGS="$HOME/.claude/settings.json" TMP=$(mktemp) jq --arg uid "$(whoami)" ' .env["OTEL_RESOURCE_ATTRIBUTES"] = ("enduser.id=" + $uid) ' "$SETTINGS" > "$TMP" && mv "$TMP" "$SETTINGS"

3d. Verify

python3 -c " import json cfg = json.load(open('$HOME/.claude/settings.json')) env = cfg.get('env', {}) assert env.get('CLAUDE_CODE_ENABLE_TELEMETRY') == '1', 'telemetry not enabled' assert env.get('OTEL_TRACES_EXPORTER') == 'otlp', 'traces not enabled' assert 'x-singsight-apikey=' in env.get('OTEL_EXPORTER_OTLP_HEADERS', ''), 'API key missing' print('✅ Claude Code configured successfully') print(f' Endpoint: {env[\"OTEL_EXPORTER_OTLP_ENDPOINT\"]}') print(f' Traces: enabled (beta)') print(f' Metrics + Logs: enabled') "

Tell the user:

Skip to Step 7.


Step 4 — Hermes Agent

Hermes uses the

hermes-plugin-otel-tracing
hermes-plugin-otel-tracing
plugin which exports traces, metrics, and logs via OTLP.

4a. Verify Hermes is installed

command -v hermes >/dev/null 2>&1 || { echo "ERROR: hermes not found"; } ls -d "$HOME/.hermes/hermes-agent" >/dev/null 2>&1 && echo "HERMES_OK"

If not found, tell the user to install Hermes first and STOP.

4b. Install the OTel plugin

pip install hermes-plugin-otel-tracing

4c. Configure environment

ENVFILE="$HOME/.hermes/.env" touch "$ENVFILE" cp "$ENVFILE" "$ENVFILE.bak.$(date +%Y%m%d-%H%M%S)" python3 - "$ENVFILE" "$ENDPOINT" "$API_KEY" <<'PY' import sys path, endpoint, key = sys.argv[1:] lines = [l for l in open(path).read().splitlines() if not l.startswith(("HERMES_OTEL_", "OTEL_EXPORTER_OTLP_", "OTEL_SERVICE_NAME="))] if lines and lines[-1].strip(): lines.append("") lines.extend([ "# Singsight observability", "HERMES_OTEL_ENABLED=true", "HERMES_OTEL_EXPORTER=otlp", f"OTEL_EXPORTER_OTLP_ENDPOINT={endpoint}", f'OTEL_EXPORTER_OTLP_HEADERS=x-singsight-apikey={key}', "OTEL_SERVICE_NAME=hermes-agent", ]) open(path, "w").write("\n".join(lines) + "\n") print("✅ Hermes .env updated") PY chmod 600 "$ENVFILE"

4d. Restart gateway if running

if hermes gateway status 2>/dev/null | grep -q "loaded"; then hermes gateway restart echo "gateway restarted" fi

4e. Verify

hermes chat -q "say hello" 2>&1 | tail -3 echo "✅ Hermes Agent configured. Check Singsight dashboards in ~5 minutes."

Tell the user:

Skip to Step 7.


Step 5 — OpenClaw

OpenClaw has a built-in

diagnostics-otel
diagnostics-otel
plugin that exports traces, metrics, and logs over OTLP.

5a. Verify OpenClaw is installed

command -v openclaw >/dev/null 2>&1 || { echo "ERROR: openclaw not found"; }

If not found, tell the user to install OpenClaw first and STOP.

5b. Install and enable the diagnostics-otel plugin

The plugin must be installed before it can be enabled:

openclaw plugins install @openclaw/diagnostics-otel openclaw plugins enable diagnostics-otel

If

openclaw plugins install
openclaw plugins install
fails (e.g. network issue), tell the user and STOP.

5c. Prompt user for API Key

You MUST proactively ask the user to copy the API Key. Say exactly this:

Wait for the user to respond with the API Key. Do NOT proceed until you have it. Store as

$API_KEY
$API_KEY
.

5d. Prompt user for config snippet

Once you have the API Key, ask the user to copy the config snippet. Say exactly this:

Wait for the user to respond. They may paste the full config, or just give you the endpoint. Store endpoint as

$ENDPOINT
$ENDPOINT
.

5e. Write config

Merge OTel config into

~/.openclaw/openclaw.json
~/.openclaw/openclaw.json
:

CONFIG="$HOME/.openclaw/openclaw.json" mkdir -p "$(dirname "$CONFIG")" [ -f "$CONFIG" ] || echo '{}' > "$CONFIG" cp "$CONFIG" "$CONFIG.bak.$(date +%Y%m%d-%H%M%S)" TMP=$(mktemp) python3 - "$CONFIG" "$ENDPOINT" "$API_KEY" <<'PY' import json, sys path, endpoint, key = sys.argv[1:] cfg = json.load(open(path)) diag = cfg.setdefault("diagnostics", {}) diag["enabled"] = True otel = diag.setdefault("otel", {}) otel.update({ "enabled": True, "endpoint": endpoint, "protocol": "http/protobuf", "serviceName": "openclaw-gateway", "headers": {"x-singsight-apikey": key}, "traces": True, "metrics": True, "logs": True, "captureContent": { "enabled": True, "inputMessages": True, "outputMessages": True, "toolInputs": True, "toolOutputs": True, "systemPrompt": True, }, }) plugins = cfg.setdefault("plugins", {}) allow = plugins.setdefault("allow", []) if "diagnostics-otel" not in allow: allow.append("diagnostics-otel") entries = plugins.setdefault("entries", {}) entries.setdefault("diagnostics-otel", {})["enabled"] = True json.dump(cfg, open(path, "w"), indent=2) print("✅ OpenClaw config updated") PY chmod 600 "$CONFIG"

5f. Restart gateway

openclaw gateway restart 2>/dev/null || echo "gateway not running (will pick up config on next start)"

5g. Verify

openclaw status 2>&1 | grep -i "diagnostics-otel" openclaw health 2>&1 | head -3

If

openclaw status
openclaw status
shows
diagnostics-otel
diagnostics-otel
as not installed or not loaded, the install in 5b may have failed — re-run
openclaw plugins install @openclaw/diagnostics-otel
openclaw plugins install @openclaw/diagnostics-otel
and restart again.

Tell the user:

Skip to Step 7.


Step 6 — Opencode

Opencode uses the

@devtheops/opencode-plugin-otel
@devtheops/opencode-plugin-otel
plugin.

6a. Install the plugin

Add to

~/.config/opencode/opencode.json
~/.config/opencode/opencode.json
:

CONFIG="$HOME/.config/opencode/opencode.json" mkdir -p "$(dirname "$CONFIG")" [ -f "$CONFIG" ] || echo '{}' > "$CONFIG" cp "$CONFIG" "$CONFIG.bak.$(date +%Y%m%d-%H%M%S)" TMP=$(mktemp) jq '.plugin = (.plugin // []) | if (.plugin | index("@devtheops/opencode-plugin-otel")) then . else .plugin += ["@devtheops/opencode-plugin-otel"] end' "$CONFIG" > "$TMP" && mv "$TMP" "$CONFIG"

6b. Configure environment

Create or update

~/.config/opencode/.env
~/.config/opencode/.env
:

ENVFILE="$HOME/.config/opencode/.env" mkdir -p "$(dirname "$ENVFILE")" touch "$ENVFILE" python3 - "$ENVFILE" "$ENDPOINT" "$API_KEY" <<'PY' import sys path, endpoint, key = sys.argv[1:] lines = [l for l in open(path).read().splitlines() if not l.startswith(("OPENCODE_ENABLE_TELEMETRY=", "OPENCODE_OTLP_", "OTEL_EXPORTER_OTLP_HEADERS="))] if lines and lines[-1].strip(): lines.append("") lines.extend([ "# Singsight observability", "OPENCODE_ENABLE_TELEMETRY=1", f"OPENCODE_OTLP_ENDPOINT={endpoint}", f"OTEL_EXPORTER_OTLP_HEADERS=x-singsight-apikey={key}", ]) open(path, "w").write("\n".join(lines) + "\n") print("✅ Opencode env updated") PY chmod 600 "$ENVFILE"

6c. Verify

echo "✅ Opencode configured. Run 'opencode' and check Singsight dashboards in ~5 minutes."

Tell the user:


Step 7 — Verify data in Singsight

After the user runs their agent for at least one turn, verify data is flowing:

# Check if the endpoint is reachable curl -sS -o /dev/null -w "%{http_code}" "$ENDPOINT/actuator/health" # Expect: 200

Tell the user:


Step 8 — Report what changed

Summarize for the user (never echo the API key):

Claude Code:

  • ~/.claude/settings.json
    ~/.claude/settings.json
    : added
    env
    env
    block with OTel + telemetry variables
  • Signals: traces (beta) + metrics + logs
  • No restart needed

Hermes Agent:

  • ~/.hermes/.env
    ~/.hermes/.env
    : added OTLP exporter variables
  • Installed:
    hermes-plugin-otel-tracing
    hermes-plugin-otel-tracing
  • Signals: traces + metrics + logs
  • Gateway restarted if running

OpenClaw:

  • ~/.openclaw/openclaw.json
    ~/.openclaw/openclaw.json
    : enabled
    diagnostics-otel
    diagnostics-otel
    plugin with endpoint/key
  • Signals: traces + metrics + logs
  • Gateway restarted if running

Opencode:

  • ~/.config/opencode/opencode.json
    ~/.config/opencode/opencode.json
    : added OTel plugin
  • ~/.config/opencode/.env
    ~/.config/opencode/.env
    : added OTLP endpoint/key
  • Signals: traces + metrics + logs

End with: "Your API key is stored in the config file listed above. Keep it readable only by you (

chmod 600
chmod 600
)."

联系我们
预约咨询
微信咨询
电话咨询
邮件咨询