Custom skill names live in local history. Org totals may call them other.

· Skilled project notes

A four-column check for skill authors after GitHub Copilot CLI started reporting skill totals that hide customer-defined names.

Published by the Skilled project. Skilled reports recognized skill calls from local coding-agent histories. This diagnostic works without installing it.

On 17 September 2026, GitHub added Copilot CLI skill totals to the usage metrics API. The report answers "which items are used most" with a top-five list. For privacy, customer-defined skill names are not shown. Those skills are grouped under other. Source: Agentic CLI customizations now in the usage metrics API.

That is useful for GitHub-provided skills. It is not a named-use signal for a skill you shipped yourself.

The same gap shows up elsewhere. Marketplace install counts record copies, not runs. Server-side MCP or API skills can close the loop on the author's infrastructure. A local SKILL.md playbook often cannot. Yesterday's Ask HN asked how to measure runtime use of shipped skills that never call home. This note is a local answer that a user can run and, if they choose, share without transcripts.

Four columns #

Keep one row per skill you care about:

1skill | public label | local named invocations | last used

A useful report is one completed row, especially public label=other / local named invocations=0 or public label=other / local named invocations>=1.

What counts as a named invocation #

These are the records Skilled's readers currently keep. They are not a complete inventory of installed skills, and they are not proof the workflow succeeded.

Harness Named invocation Not a named invocation
Claude Code Skill tool_use with input.skill, or a non-builtin /name in history.jsonl A file under ~/.claude/skills/ or ~/.claude/skills/synced/. A Read of SKILL.md. /skills.
Codex CLI <name> inside a skill block on a response_item A copied parent session_meta on a fork file. Built-ins such as skill-creator.
OpenCode completed part rows with tool=skill and state.input.name A folder listing. <available_skills> XML. A slash-typed command.
Grok CLI read_file of skills/<name>/SKILL.md, or a <command-name> slash grok inspect discovery. A read of a sibling file in the skill folder. tool_call_update repeats.
Droid CLI tool_result text matching Skill "name" is now active rg of the skill name in session JSONL. /skills Effective status. disabledSkills.

Skilled does not read GitHub Copilot CLI session-state or org reports. If Copilot CLI is the only harness on the machine, this local column is out of scope.

Synthetic check #

The example is synthetic. It reads no files, makes no network requests, and uses only Python's standard library. Save it as named_vs_other.py and run python3 named_vs_other.py.

 1def row(skill, github_provided, installed, named_events):
 2    public = skill if github_provided else "other"
 3    named = len(named_events)
 4    last = named_events[-1] if named_events else "none"
 5    return (skill, public, named, last)
 6
 7# Custom skill: one install, no retained Skill tool_use.
 8disk_only = row("release-notes", False, True, [])
 9# Custom skill: one install, one retained Skill tool_use.
10invoked = row("release-notes", False, True, ["2026-09-17"])
11# GitHub-provided skill: the org report can print the name.
12builtin = row("code-review", True, True, ["2026-09-17"])
13
14assert disk_only == ("release-notes", "other", 0, "none")
15assert invoked == ("release-notes", "other", 1, "2026-09-17")
16assert builtin == ("code-review", "code-review", 1, "2026-09-17")
17
18for label, result in [
19    ("custom, disk only", disk_only),
20    ("custom, one named call", invoked),
21    ("github-provided", builtin),
22]:
23    print(label, result)

Expected output:

1custom, disk only ('release-notes', 'other', 0, 'none')
2custom, one named call ('release-notes', 'other', 1, '2026-09-17')
3github-provided ('code-review', 'code-review', 1, '2026-09-17')

Install state is the same in the first two rows. The org label is other in both. Only the retained named event changes the third column. That is the gap marketplace install counts and Copilot CLI other totals cannot close.

A no-install Claude Code check for the named column, on a machine that already has session JSONL, is: look for assistant tool_use blocks with "name": "Skill" and read input.skill. Do not paste the files. Count the name. Zero is inconclusive if history was pruned, rotated, or stored in a format the check does not recognize.

What Skilled can fill #

Inspected implementation: Skilled v0.3.3, src/providers/claude-code.ts, codex.ts, opencode.ts, grok.ts, droid.ts, and src/cli.ts. An isolated Claude Code fixture with a disposable CLAUDE_CONFIG_DIR (no real histories) returned 0 calls from a SKILL.md on disk plus a Read of that path, and 1 release-notes call from a single Skill tool_use. That tests the reader on artificial records, not compatibility with every Claude Code release.

If Skilled is already installed and the machine has one of the five harnesses above:

1skilled calls --json --no-index

Filter to one name with skilled detail release-notes --json --no-index. Add --source claude-code (or codex, opencode, grok, droid) when several agents are present. The command does not talk to GitHub, does not read Copilot CLI, and does not judge whether the skill's steps were followed.

Limits #

If you run this on a custom skill that GitHub would group as other, a useful reply is one sanitized row. If you tried Skilled because of this page, say so separately. Running the Python example is not evidence of adoption.

last updated: