Metadata-Version: 2.4
Name: skillcost
Version: 1.1.0
Summary: Estimates the token cost of agent skills and their linked resources
Requires-Python: >=3.12
Requires-Dist: markdownify>=1.2.2
Requires-Dist: mistune>=3.0.0
Requires-Dist: pyyaml>=6.0.3
Requires-Dist: tiktoken>=0.12.0
Description-Content-Type: text/markdown

# skillcost

[![PyPI](https://img.shields.io/pypi/v/skillcost)](https://pypi.org/project/skillcost/)

Estimates the token cost of agent skills and their linked resources.

Given a target file (typically a `SKILL.md`), `skillcost` counts tokens and crawls all linked files
and URLs to produce three cost figures:

| Metric       | Description                                                         |
| ------------ | ------------------------------------------------------------------- |
| **Resident** | Tokens loaded on every prompt, just because the skill is installed. |
| **Baseline** | Tokens loaded when the skill is invoked — the skill file itself.    |
| **Maximum**  | Tokens loaded if the agent follows every link in the skill file.    |

This also works on `CLAUDE.md` or any other plain-text UTF-8 file.

## Installation

Requires Python 3.12+.

```sh
# Using pip
pip install skillcost
# Or, using uv
uv tool install skillcost
```

## Usage

```sh
skillcost <path/to/file>
```

Output defaults to human-readable text. Pass `--json` or `--yaml` for machine-readable output.

```sh
skillcost SKILL.md
skillcost --json SKILL.md
skillcost --yaml SKILL.md
```

### Example output

```
Token Cost Report
=================
  Resident : 97
  Baseline : 1,940
  Maximum  : 18,390

Files (24)
  /path/to/reference/conventions.md                                       926
  /path/to/reference/utilities.md                                       1,751
  ...

Links
  Local links  : 17
  HTTP links   : 0
```

## Token counting

Token counts are computed using OpenAI's [tiktoken](https://github.com/openai/tiktoken) library
with the `cl100k_base` encoding.

## How links are counted

`skillcost` recognizes standard Markdown links in `.md` files:

- **`[text](relative/path)`** — a local link; followed recursively and counted toward the
  **maximum** cost only.
- **`[text](https://...)`** — an HTTP link; fetched once and counted toward the **maximum** cost.
  If the response is HTML (`text/html` or `application/xhtml+xml`), it is converted to Markdown via
  [markdownify](https://github.com/matthewwithanm/python-markdownify) before tokenizing; other
  content types are tokenized as-is. The fetched content is **not** re-parsed for further links. ``

## Caveats on the maximum

The **maximum** is an upper bound on what an agent _could_ pull in, not what it typically will.
Real invocations are almost always lower. A few things to keep in mind:

- **It assumes every link is followed.** Agents usually read only the subset relevant to the task
  at hand, so actual usage is often much lower than the maximum.
- **HTTP links are fetched once, not crawled.** HTML responses are converted to Markdown before
  tokenizing, which approximates what an agent would actually read. Other content types (JSON,
  plain text, etc.) are tokenized as-is, so their counts may overstate the human-readable cost.
- **Network-dependent and time-sensitive.** HTTP fetches can fail (counted as 0) or return
  different content over time, so the maximum is not reproducible across runs.
- **Non-`.md` files are read but not parsed.** Their full contents are tokenized; any links inside
  them are not followed.
- **Cycles are handled.** Each file and URL is counted at most once per run.
- **Anchors (`#section`) are stripped** before resolving local paths; the whole file is counted.
- **The tokenizer is `cl100k_base`.** Counts are an approximation for Claude models, which use a
  different tokenizer — expect small differences in practice.

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md).
