---
title: Skill Overhead Alert (Skills Bloat checker)
---
# Skill Overhead Alert (Skills Bloat checker)

## What it is

Amber inbox card that fires when the **Claude Code skills you have installed** add up to too much always-on overhead. It is the skills analogue of the [MCP Overhead Alert](mcp-bloat-alert.md): same inbox-card + snooze + Settings-limit shape, but **global** (skills config is not per-project in Omniscio — every installed skill loads into every conversation, so there is exactly one rule) and with **two independent trip legs** instead of MCP's three (skills hold no RAM while idle, so the RAM leg is dropped).

## Where to find it

An amber card in your inbox, alongside your other alerts, with the single global rule at **Settings → Notifications → Skill Overhead**. (It does not live under the **Skills** sidebar entry — that panel is for browsing and installing skills, not for this alert.)

## How it behaves

### What it watches

Every skill you install — a personal skill under `~/.claude/skills` or one that arrived with a plugin (the plugin cache) — loads its **YAML frontmatter into the skill-discovery index of every conversation**. That is the always-on tax: even a skill you never invoke costs context on every single message, because its name + description have to be advertised so the agent knows the skill exists. A pile of unused or heavy skills is pure waste. The checker watches the global set of installed skills — user skills plus plugin skills — and fires when either of these crosses its limit:

1. **Estimated frontmatter tokens** — the summed always-on frontmatter tokens across ALL installed skills. **Always labeled an estimate** (a `chars / 4` heuristic): Omniscio counts only the frontmatter, because only the frontmatter loads into every conversation — the skill body is read on demand when the skill actually runs, so it does not crowd the live context the same way. Default limit **20,000 tokens**.
2. **Unused skills** — count of installed skills (user + plugin) with **no invocation in the last 30 days** (from the `tool_invocations` scanner). The most reliable "wasted weight" signal. Default limit **1** — the daily card reviews one unused skill a day until none are left (a clean slate). Set it higher to stop sooner, or `0` to turn the daily card off.

A limit of `0` disables that leg. The alert fires when **either** enabled leg trips (frontmatter OR unused).

### New-user warm-up (the "unused skills" nudge waits 30 days)

The **"unused skills"** part of this alert stays **silent until you've been using Omniscio for at least 30 days** (measured from your first session). This is on purpose: that leg asks "which skills haven't you touched in the last 30 days?" — and on a brand-new install the honest answer is "all of them," because there simply isn't 30 days of history to look back on yet. Firing then would nag a new user that every skill is "unused" the day they installed it. So Omniscio holds the unused-skills nudge during that warm-up window and only starts watching once the 30-day question can be answered truthfully. A fresh install with no sessions yet is treated as brand-new. (Same warm-up idea as the record-breaking-session alerts.)

The **"too many skills loaded" (token overhead)** part is **not** held — a heavy pile of installed skills costs context on every message whether or not you've ever used them, so that leg is meaningful from day one and can fire immediately, even during the warm-up window.

### The plugin-usage fix (why your plugin skills used to say "Never used")

This feature ships with a real bug fix. The tool-invocation scanner records a skill's usage under the exact name it was invoked with. A **user** skill is invoked by its bare folder slug (e.g. `audit-aggregation`), but a **plugin** skill is invoked namespaced by its plugin (e.g. `superpowers:systematic-debugging`). The Skills view used to look up usage by the bare folder name only — so **every used plugin skill matched nothing and rendered "Never used"**, even one you run constantly (verified against real data: 14/14 plugin skills matched `<plugin>:<skill>`, 0/14 matched the bare name).

The matching now goes through one shared helper, [`src/shared/skill-usage-match.ts`](../../src/shared/skill-usage-match.ts), used by **both** the Skills view and the new Skill Overhead scan — so a heavily-used plugin skill is counted correctly in both places and is never false-flagged as unused. (It also folds in throwaway `.worktrees/<path>:<slug>` usage keys that past worktree sessions left behind, so a skill only ever run inside a worktree isn't wrongly counted as unused either.)

### The card

The card is titled "Skill overhead — N unused · ~N always-on tokens", surfaces at most **once per day**, and lives in your inbox alongside your other alerts (not grouped under the Skills sidebar entry — see above). Opening it shows one compact review of a single unused skill:

- The card asks one question and names the skill in it — **Archive last30days?**, or **Remove …?** for a plugin skill, which is what the confirmation will say too.
- One sentence under it carries both facts: how long the skill has gone unused, and what it costs every conversation. The two figures are emphasised inside the sentence, and the token figure stays labelled an estimate. **No recorded use** means no matching invocation was found, not proof the skill has never been used.
- A smaller line under that states what archiving actually does for that kind of skill. For a skill of your own it reads "Archiving is reversible. Nothing is deleted."; for a plugin skill it says the removal deletes it from the plugin cache, because that one is not reversible.
- One **What this skill does** disclosure holds everything else — the skill's source (your skill or its plugin), its full description, and the remaining metadata. It starts collapsed, exactly as the decision should.
- **Archive skill** (or **Remove skill**) is the card's one prominent action, sitting above a quiet **Keep it**.
- Once you Keep or Archive today's skill, the review becomes **All caught up for today**, or **No unused skills left** when the list is clear. **Show more skills** opens the Skills manager for broader cleanup.

The card offers:

- **Keep it** opens **Keep for 60 days** or **Keep permanently**. It suppresses the unused-skill reminder, not the skill's token cost. Keep works on desktop and paired phones.
- **Archive skill** works on desktop **and on a paired phone** — the same operation the Skills manager's own Remove performs there. It always confirms first, and the confirmation distinguishes user skills (moved to skills trash) from plugin skills (permanently removed from the plugin cache; reinstall the plugin to restore).
- Skills bundled with Omniscio also move to trash, and stay archived across launches. Restore them from **Archived in the Skills manager**; the review card does not contain an Archived list.
- **omniscio-control is never offered.** The seven other Omniscio skills route into its pages, so archiving it would break all of them. The card skips it and it does not count toward the unused total, though its token cost still counts in the frontmatter total.
- **Show more skills** is a secondary control, alongside session help. Controls that compete with Keep or Archive are disabled while confirmation or saving is in progress, then become available again on failure.

Putting the whole card away is a separate action from archiving the flagged skill: the card's own **Archive** button (top of the card; also the keyboard `E` shortcut, middle-click, bulk archive, or an inbox rule) just acknowledges today's overhead — it never touches a skill file. The card also supports the universal inbox **Snooze**, and the **Start session** button every alert card carries. You can mute Skill Overhead alerts entirely from the card, or from Settings → Notifications → Alert types.

**One review per day.** Keep or Archive marks today's review done, quieting the card for the rest of the local day. The next unused skill arrives tomorrow. Snooze is your "not today" control; the card's own Archive button uses the existing size-growth and reminder-cadence rules. Use the Skills manager to review more skills manually. Clearing a Keep (Start flagging) re-flags the skill without marking today's review done.

## For agents

### Honesty contract

- **Estimate:** the frontmatter-token figure (shown with the `tokens` unit, and flagged as an estimate in the card's fine print) — a `chars / 4` heuristic, never an exact tokenizer count.
- **Measured:** the installed-skill count and per-skill usage (call counts, "never used").

A non-technical user never sees a guess dressed up as a fact.

### Settings

**Settings → Notifications → Skill Overhead** holds the single global rule: a master enable toggle plus tunable limits (estimated-frontmatter-token limit, unused-skill limit) and the two re-alert knobs (growth %, cadence days). The master switch is the `enabled` flag on the seeded `'global'` rule — there is no `AppSettings` field.

The whole feature also respects **`enableSkillsIntegration`**: when the Skills feature is turned off, Omniscio neither scans nor alerts — no point nagging about a disabled surface, and a stale scan can never fire once skills are off.

### Implementation notes

- **Decision logic** is one pure module: [`src/shared/alert-features/skills-bloat-alert.ts`](../../src/shared/alert-features/skills-bloat-alert.ts) — `shouldFireSkillsBloatAlert(scan, rule, now)` plus the per-leg `frontmatterLegTrips` / `unusedLegTrips` helpers, `isOverAnyLimit`, and `isSameLocalDay` (the **daily gate**: once today's skill is reviewed the alert stays quiet for the rest of the local calendar day, then resurfaces the next one). The clock is injected, so it is testable without faking time.
- **Scan engine** ([`src/main/services/skills/skills-bloat-scan.ts`](../../src/main/services/skills/skills-bloat-scan.ts)) resolves the global installed set (user + plugin), sums the frontmatter estimates, and joins the 30-day usage aggregate through the shared `skill-usage-match` helper for unused detection. It reuses existing data — no skill is ever executed to measure it.
- **Storage** is a single global rule + a single global scan row (no per-project rows) plus a per-skill **kept** table (`skills_bloat_kept` — one row per kept skill, `kept_until` NULL = forever), all via forward-only migrations on the frozen baseline. A kept skill is excluded from the unused count only — never from the token total.
- **The inbox card** is a central alert, not its own inbox source: [`src/main/services/skills/skills-bloat-alert-card.ts`](../../src/main/services/skills/skills-bloat-alert-card.ts) turns today's due item into one global card (dedup key `skills-bloat-alert:global`) via the shared `reconcileAlertFamily` / `registerAlertArchiveListener` building blocks every alert family uses — it follows the feature's own push AND `SETTINGS_CHANGED` (the scan stops pushing once Skills integration is off). Its custom body is [`src/renderer/src/features/skills-bloat-alert/SkillsBloatAlertCardBody.tsx`](../../src/renderer/src/features/skills-bloat-alert/SkillsBloatAlertCardBody.tsx), mounted inside the shared `AlertInboxViewer`. Triggers and IPC handlers otherwise mirror the MCP Overhead Alert feature, minus the RAM leg.

## Related

- [mcp-bloat-alert.md](mcp-bloat-alert.md) — the sibling checker for MCP servers; same inbox-card + snooze shape, one extra leg (measured active-session RAM)
- [doc-token-alert.md](doc-token-alert.md) — the same alert pattern for a project's always-loaded agent docs (`CLAUDE.md` / `AGENTS.md` / `MEMORY.md`); the tiered-re-alert design originates here
- [use-skills.md](use-skills.md) — the Skills view this alert links to: browse, install, edit, and update your Claude Code skills (and where the same plugin-usage fix now shows correct "used"/"never used" flags)
- [inbox-overview.md](inbox-overview.md) — how unified-inbox rows surface across all integrations; the skill-overhead row lives in this list

See the contract for the full invariant list: `.claude/memory/contracts/skills-bloat-alert-contract.md`.
