Skip to content

Capture skill path in skill_key + platform as text + skill_name rename - #66

Merged
knoxgraeme merged 3 commits into
mainfrom
claude/telemetry-skill-name-platform
May 3, 2026
Merged

knoxgraeme merged 3 commits into
mainfrom
claude/telemetry-skill-name-platform

Conversation

@knoxgraeme

Copy link
Copy Markdown
Owner

Summary

Three follow-up telemetry fixes after #65, driven by what's actually showing up (or not) in the telemetry_events table.

  • skill_key now includes the in-repo path for monorepo skills. Previously every skill in a multi-skill repo collapsed to owner/repo. Now team-attention/hoyeon/skills/council is distinct from team-attention/hoyeon/skills/marketing. Root-level skills still use plain owner/repo.
  • platform is sent as a comma-separated text string, not a JSON array, to match the text column on telemetry_events. One install still equals one row, so download-count semantics are unchanged. Agent names contain no commas, so this round-trips cleanly.
  • skillName field renamed to skill_name for snake_case consistency with the rest of the payload (event_type, skill_key). The earlier rename in fix: use snake_case field names to match telemetry_events table columns #36 missed this one.
  • Dropped the redundant path field — it's already encoded inside skill_key.

Wire payload after this change

// command event (one per CLI invocation)
{"event_type": "command", "command": "add"}

// install event for a monorepo sub-skill
{
  "event_type": "install",
  "command": "add",
  "skill_key": "team-attention/hoyeon/skills/council",
  "owner": "team-attention",
  "repo": "hoyeon",
  "skill_name": "council",
  "platform": "Claude Code, Cursor"
}

// install event for a root-level skill
{
  "event_type": "install",
  "command": "add",
  "skill_key": "testany-io/testany-agent-skills",
  "owner": "testany-io",
  "repo": "testany-agent-skills",
  "skill_name": "testany-agent-skills",
  "platform": "Claude Code"
}

Backend schema this expects

telemetry_events columns (all snake_case, all nullable except event_type):

Column Type Notes
event_type text 'command' or 'install' — required
command text always set
skill_key text install events only
owner text install events only
repo text install events only
skill_name text install events only — needs to be added
platform text install events only — comma-separated agent names

Test plan

  • npm run typecheck, npm run lint, npm run build clean
  • npm test — 235/235 pass
  • End-to-end wire capture against a local fake telemetry endpoint:
    • command event arrives as {event_type, command}
    • install event for team-attention/hoyeon with path skills/council produces skill_key=team-attention/hoyeon/skills/council, skill_name=council, platform="Claude Code, Cursor"
    • install event for a root skill produces skill_key=owner/repo (no path), skill_name=repo
    • Multi-agent install: platform is "Claude Code, Cursor"; single-agent: "Claude Code"; empty: ""
    • Slash normalization: /sub/path/ → sub/path in skill_key

https://claude.ai/code/session_01NNWdGxePTFy2h67N4bFjNy


Generated by Claude Code

claude added 3 commits May 3, 2026 21:48
Previously skill_key was always 'owner/repo', so every skill in a
monorepo (e.g. team-attention/hoyeon with skills/council, skills/foo,
skills/bar) collapsed to the same key. The download tracker uses the
full path; telemetry should match.

- trackInstall now accepts an optional 'path' arg (the path within the
  repo). skill_key is built as 'owner/repo' for root skills or
  'owner/repo/path' for sub-skills, matching the canonical format.
- Add 'path' to the payload as a separate field (null for root) so the
  backend can slice without re-parsing skill_key.
- add.ts: derive path from skillPath ('SKILL.md' = root, else the dir).
- install.ts: pass entry.path from the parsed manifest entry.
- Normalize leading/trailing slashes on the path so '/sub/path/'
  becomes 'sub/path' before it hits skill_key.

Smoke-tested against a local server:
  root:     skill_key="testany-io/testany-agent-skills"    path=null
  sub:      skill_key="team-attention/hoyeon/skills/council" path="skills/council"
  slashes:  "/sub/path/" normalized to "sub/path"
Backend stores platform in a single text column, not a text[]. Sending
a JSON array would either fail to insert or get serialized awkwardly.

- platform is now a comma-separated string (e.g. 'Claude Code, Cursor').
  De-duplicated. Empty string when no platforms are known. Agent names
  contain no commas, so this round-trips cleanly.
- Drop the separate 'path' field from the payload — it's already
  encoded in skill_key ('owner/repo/path'). The backend can split
  skill_key on '/' if it needs path-level slicing.

One install still equals one row, preserving the existing download
count increment semantics.

Wire format now:
  {"event_type":"install","command":"add",
   "skill_key":"team-attention/hoyeon/skills/council",
   "owner":"team-attention","repo":"hoyeon","skillName":"council",
   "platform":"Claude Code, Cursor"}
…ency

Every other field on telemetry_events uses snake_case (event_type,
skill_key). skillName was the lone camelCase outlier — fixing it now
so the DB column can be plain 'skill_name' without a translation layer.
@knoxgraeme
knoxgraeme merged commit 88fc1be into main May 3, 2026
6 checks passed
@knoxgraeme
knoxgraeme deleted the claude/telemetry-skill-name-platform branch May 3, 2026 21:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants