npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@hyuga/tokenlint

v0.5.0

Published

Count hardcoded colors, measure design-token coverage, and gate PRs — a zero-config, zero-dependency GitHub Action + CLI. Understands CSS custom properties and Tailwind arbitrary values.

Downloads

682

Readme

tokenlint

npm version license zero dependencies

Part of a set of zero-dependency CI tools for AI-agent repos — start with reflint.

Count hardcoded colors, measure design-token coverage, and gate PRs. A zero-config, zero-dependency GitHub Action + CLI that understands both CSS custom properties and Tailwind arbitrary values (text-[#3b82f6]).

デザイントークンを使わずベタ書きされた色を毎PRで数え、トークン網羅率をスコアカード+動的バッジにする。設定ファイル不要・依存ゼロ。


Why

Your design system has tokens. Colors still get hardcoded anyway — in a rushed PR, in a pasted component, in a text-[#3b82f6]. Existing linters (stylelint-declaration-strict-value) only pass/fail; they don't give you a number you can watch.

tokenlint makes the debt visible:

  • a coverage badge on your README that moves every time someone touches styling,
  • a scorecard (color-chip grid) you can paste into a PR,
  • and a nearest-token suggestion for every hardcoded color.

Zero-config: it reads your --color-* custom properties as the token palette. No config file, no token file, no Figma. Point it at a folder and get a number in 3 seconds.

Install & use

npx @hyuga/tokenlint            # scan ./ and print a scorecard
npx @hyuga/tokenlint src        # scan a folder
npx @hyuga/tokenlint --report   # write tokenlint-report.html (the shareable scorecard)

As a GitHub Action (the PR gate)

Gate on new debt only — don't punish the whole team for the colors that were already there, just fail when a PR adds hardcoded colors:

# .github/workflows/tokenlint.yml
name: tokenlint
on: [pull_request]
jobs:
  tokens:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0        # tokenlint diffs against the PR base
      - uses: hyuga611/tokenlint@v0
        with:
          paths: src
          max-new: 0            # fail only if this PR ADDS hardcoded colors

--since/base defaults to the PR base commit, so "new in this PR" works with zero extra config. Prefer max-new (net new) over max (total) unless you're at zero and want to stay there.

paths: src is a promise that src exists. From 0.3.0, if it does not — renamed, moved, a typo — tokenlint exits 2 instead of passing. Before that it scanned nothing, counted zero, found zero ≤ max, and printed a green ✓ pass; the gate went on reporting success for as long as the path stayed wrong. Exit 2 means could not evaluate, as distinct from 1 for the gate failed.

As a README badge

npx @hyuga/tokenlint --badge > coverage.json   # shields.io endpoint JSON

Publish coverage.json (e.g. via a Gist with Schneegans/dynamic-badges-action) and point a shields endpoint badge at it:

![token coverage](https://img.shields.io/endpoint?url=<raw-url-of-coverage.json>)

What it detects

| | | | --- | --- | | Hardcoded | #hex, rgb()/rgba(), hsl()/hsla() in CSS color properties · Tailwind arbitrary colors (text-[#..], bg-[rgb(..)]) | | Tokens | --color-* (any custom property whose value is a color) | | Tokenized usage | var(--token) in a color property | | Coverage | tokenized / (tokenized + hardcoded) | | Suggestion | nearest defined token by perceptual color distance |

Honest v0 scope

tokenlint is dependency-zero and regex-based on purpose. Not yet handled (planned):

  • named colors (red, white) are not flagged;
  • SCSS $variables are not treated as tokens (only CSS custom properties);
  • Tailwind semantic classes (text-primary) are not yet counted as tokenized — only arbitrary values are flagged.

The "new in this PR" delta (--since / --max-new) uses the net count change (base → head), like size-limit's byte delta: robust and hard to game.

Options

tokenlint [paths...] [options]

  --max <n>          fail (exit 1) if TOTAL hardcoded colors > n
  --since <ref>      diff against a git ref (e.g. the PR base) for "new this PR"
  --max-new <n>      fail (exit 1) if this PR ADDS more than n hardcoded colors
  --report[=file]    write an HTML scorecard (default: tokenlint-report.html)
  --badge[=kind]     shields.io endpoint JSON (kind: coverage | hardcoded | new)
  --format <fmt>     text (default) | json
  --no-color         disable ANSI color
  -h, --help / -v, --version

Related tools

Zero-dependency CI linters for repos where AI agents do the work. Each one fails the PR on something that breaks quietly.

| | Catches | | --- | --- | | reflint | AGENTS.md / llms.txt / CLAUDE.md pointing at commands, scripts, or paths that no longer exist | | skills-lint | SKILL.md broken references + name/trigger collisions between skills | | carrylint | Skills with the author's machine or model baked in — absolute paths, undeclared CLIs, unresolved placeholders | | genchi | Agents reporting "done" without re-fetching real-world state | | tracklint | Forms and CTAs that quietly stopped being wired for conversion tracking | | tokenlint ← you are here | Hardcoded colors that bypass your design tokens | | reflint for VS Code | The same reflint checks, inline in the editor as you save | | orogami | Not a linter — natural Japanese/CJK line breaking for OGP images (BudouX + font subsetting) |

MIT © hyuga611