# Coverage

> Use when auditing i18n translation completeness across all target locales or identifying locales below a coverage threshold. Produces a per-locale and summary coverage report.

- **Type:** Skill
- **Install:** `agentstack add skill-ericfitz-skills-coverage`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [ericfitz](https://agentstack.voostack.com/s/ericfitz)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** Apache-2.0
- **Upstream author:** [ericfitz](https://github.com/ericfitz)
- **Source:** https://github.com/ericfitz/skills/tree/main/loc/skills/coverage

## Install

```sh
agentstack add skill-ericfitz-skills-coverage
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Validate Localization Coverage

Generate a coverage report for all locales by running the bundled `scripts/check-i18n.py` analyzer and computing per-locale completeness against the master file.

## Bundled tool

`scripts/check-i18n.py` — the same self-contained Python 3.8+ analyzer used by [[analyze]]. See that skill for the full description.

When you see `${CLAUDE_PLUGIN_ROOT}` below, it refers to this plugin's install root — typically `~/.claude/plugins/cache/efitz-skills/loc//`. The analyzer lives at the plugin root's `scripts/` directory, so the analyzer is at `${CLAUDE_PLUGIN_ROOT}/scripts/check-i18n.py` (plugin-root `scripts/`, NOT a `skills//scripts/` subpath). If Claude Code does not pre-substitute the variable when you read this file, resolve it yourself: locate the directory containing this SKILL.md, walk up to the plugin root, and use the absolute path to `scripts/check-i18n.py`. Do **NOT** fall back to the legacy `$SKILL_DIR` form.

## Configuration

Reads `.claude/i18n.config.json` (walked up from `pwd`). Required fields: `locales_dir`, `master_locale`, `file_extension`.

Optional:

```jsonc
{
  "coverage": {
    "needs_attention_threshold": 95.0
  }
}
```

Defaults to 95% if absent.

## Inputs

None beyond the config file.

## Output

```json
{
  "master_file": "src/assets/i18n/en-US.json",
  "total_keys": 450,
  "locales_checked": 15,
  "per_locale": {
    "ar-SA": {
      "file_path": "src/assets/i18n/ar-SA.json",
      "missing_keys": ["about.trademarks"],
      "missing_count": 1,
      "coverage_percent": 99.78,
      "extra_keys": []
    }
  },
  "summary": {
    "average_coverage": 98.5,
    "fully_covered_locales": ["es-ES", "de-DE"],
    "needs_attention": [
      {"locale": "th-TH", "coverage_percent": 85.2, "missing_count": 67}
    ],
    "total_missing_translations": 245
  }
}
```

## Process

### 1. Run the bundled analyzer

```bash
uv run "${CLAUDE_PLUGIN_ROOT}/scripts/check-i18n.py" -y
```

`${CLAUDE_PLUGIN_ROOT}/skills/coverage` is the absolute path to this skill's directory (provided by the harness at invocation). The script auto-discovers `.claude/i18n.config.json`.

### 2. Parse output

The script emits sections delimited by `=== Comparing  with  ===`. For each target:

- Lines after `Keys present in  but missing in :` are `missing_keys` (until a blank line or next section).
- Lines after `Keys present in  but missing in :` are `extra_keys`.
- `No keys missing in .` indicates the corresponding list is empty.

Derive locale codes from the target's basename (e.g. `ar-SA.json` → `ar-SA`).

### 3. Count total keys in master

Load `/.` and recursively count *leaf* keys (string values, not parent objects). `about.title` counts as 1.

### 4. Compute coverage

For each locale:

```
coverage_percent = round(((total_keys - missing_count) / total_keys) * 100, 2)
```

### 5. Summarize

- `average_coverage`: arithmetic mean across locales, rounded to 2 decimals.
- `fully_covered_locales`: locales with `coverage_percent === 100.0` and no extra keys.
- `needs_attention`: locales with `coverage_percent .coverage_percent` | number | 0-100, two decimal places. |
| `per_locale..extra_keys` | string[] | May indicate obsolete or accidentally-added keys. |
| `summary.average_coverage` | number | Mean of `coverage_percent`. |
| `summary.needs_attention` | object[] | Below threshold, sorted by `missing_count` desc. |

## Notes

1. The script sorts locale files in place and moves originals to `$TMPDIR/old-`. Pass `--dry-run` if this is undesirable.
2. The leaf-counting method here must match the script's: skip `.comment` keys, count only string-valued leaves.
3. Locale codes are BCP 47. Do not maintain a code-to-name map — let callers derive display names from `Intl.DisplayNames` if needed.
4. Extra keys can legitimately exist (locale-specific content) but usually indicate stale translations.
5. If the script fails, report stderr and exit code; do not produce a partial report unless the user asks for one.

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [ericfitz](https://github.com/ericfitz)
- **Source:** [ericfitz/skills](https://github.com/ericfitz/skills)
- **License:** Apache-2.0

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-ericfitz-skills-coverage
- Seller: https://agentstack.voostack.com/s/ericfitz
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
