# Usage

An eval tells you whether a skill helps when it runs. `usage` tells you whether it runs at all, and whether the model chose it or a person had to name it.

## What it answers

```sh
npx -y terum-skills@latest usage [skill] [--since <iso>] [--all] [--json]
```

An eval measures a skill in a sandbox. `usage` looks at your real sessions and counts how often each skill fired, split by who chose it. The finding it is built for is a skill with `0 autonomous` and some `explicit` firings: people reach for it by name, and the model never chooses it from its description.

## What it reads

Claude Code's own session transcripts, at `~/.claude/projects/<project>/<session>.jsonl`. The scan is one level deep, so nested subagent and workflow transcripts are not counted. Only records from a person at a terminal count, which keeps eval sandboxes and subagent sessions out of the numbers.

It does not read the session hook, a log file, the team repository, or anything on the network. There is no fetch, no clone lock and no model call. Its only write is the archive described below, and nothing it records leaves your machine.

## What an event is

An event is four fields and nothing else: the detector that saw it, the skill name, the timestamp, and the entrypoint. Two detectors, because a skill invoked with a slash command writes no `Skill` record:

| Detector | Evidence in the transcript | Meaning |
| --- | --- | --- |
| Autonomous | The model called the `Skill` tool | The model chose it from the catalog |
| Explicit | A `/name` command in a user message | A person named it |

Claude Code's own built-in slash commands, such as `clear`, `compact` and `model`, are excluded by name.

::: figure usage-calendar
Each day's firings for a few skills, split into the model choosing a skill and a person naming it.
:::

## The 30-day window and the archive

The default window is the last 30 days, because Claude Code prunes transcripts at roughly that age. So that later runs can see further back, every run appends the events it scanned to `~/.terum/skills/run/usage-events.jsonl`. Appending the same event twice adds one line, and the file holds no session ids, paths or free text.

The default window is answered from transcripts alone. The archive is read only when `--since` reaches earlier than 30 days ago, so deleting it changes no number in today's default report. `--since` takes an ISO-8601 date such as `2026-09-01` or a full timestamp, and anything else is refused rather than read as an empty window.

## Reading the report

```text
handoff         0 autonomous    7 explicit  ·  never chosen from its description
decision-walk   2 autonomous    4 explicit
deploy-check    9 autonomous    0 explicit  (placed mid-window)
14 skills placed here and never fired in this window.
3 fired names had no placement here; pass --all to list them.

Counts are invocations, not outcome-changing uses; reopenings are not deduped.
30-day window: Claude Code prunes transcripts, so earlier use is visible only where this machine has already archived it.
```

- **A row is a placement:** a skill terum-skills installed on this machine. A team skill you never installed has no row, because the model could not have passed it over.
- **`never chosen from its description`** is printed when the autonomous count is 0. It is the annotation the verb exists for.
- **Sort order makes the argument.** Rows sort by ascending autonomy, then by explicit count, highest first, so skills people name and the model never picks come first.
- **`(placed mid-window)`** means the skill was installed after the window opened and was only available for part of it.
- **Placed skills that never fired** are counted in one line, not listed.
- **Fired names with no placement,** such as a folder you added by hand, are one hint line. `--all`, or naming a single skill, lists them in the table.
- **The two caveats print every time.** A count is an invocation, not evidence that the skill helped.

## When a skill never fires

For a skill that never fired, "nobody needed it" and "it was needed and missed" look the same. `misses` separates them. It takes the prompts you typed from the same transcripts, asks a model which installed skills each prompt should have selected, and keeps a pair only where that skill did not fire in that prompt's turn.

```sh
npx -y terum-skills@latest misses [skill] [--since <iso>] [--limit <n>] [--json]
```

It is a separate verb because it spends model calls, on `sonnet`, and `usage` promises none. It looks back 7 days by default, and its output is candidates for review, never a rate.

## In the app

The desktop app runs `usage --json` once per window and draws two surfaces from it, each with a 30-day, 90-day or 1-year window. The longer two reach into the archive, so a machine that has not run `usage` for long shows fewer days further back.

- **The Activation tile** in the Library shows how many of a root's skills fired, as in `4 of 15`, split into chosen by the model, by name only, and never fired. It never shows a percentage.
- **A skill's Activity tab** draws a calendar of its firings by day, the autonomous and explicit split, a one-sentence reading of what the counts mean, and the two caveats.
