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

@tmonier/argot

v0.2.75

Published

argot — voice linter CLI. Single statically-linked binary replacing the TS/Bun CLI and Python engine.

Readme


Type checkers ask "is this valid?" argot asks the question that used to live in code review: "is this how we do it here?" — and catches AI code that's flawless, type-correct, lint-clean, and still doesn't belong. It answers with statistics on your repo's own history — the statistical core deterministic and replayable, everything local — never a second LLM judging the first.

It also asks a second question no other tool asks: did the AI play fair? When an agent can't make a failing test pass, the cheapest path to "done" is to make the test stop looking. argot reads both sides of every diff and pairs a weakened, disabled, or deleted test with the production change it covers.

Five learned detectors — plus the rules only your repo could write

| | Rule | It catches | | | :-- | :-- | :-- | :-- | | 🚫 | foreign-import + friends | a dependency, API, or idiom your repo has never used | "we don't do it this way here" | | ♻️ | redundant | a new function that reinvents one you already have | "you already have this" | | 📍 | misplaced | the right code, filed in the wrong place | "this doesn't belong here" | | 🧱 | layering | an internal import that reverses your architecture | "we never cross this boundary" | | 🧪 | test-deleted + friends | a test quietly weakened, disabled, or removed alongside the prod change it covers | "don't game the tests" | | 📜 | your own rules | the conventions only your repo has — scripted, no recompile | "here's exactly how we do it" |

The first five are learned from your git history. The sixth is written by you — and it's the part of every linter config your team actually cares about.

Get started

# install (single static binary — no Python, no Node)
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/get-tmonier/argot/releases/latest/download/argot-installer.sh | sh

Windows: powershell -c "irm https://github.com/get-tmonier/argot/releases/latest/download/argot-installer.ps1 | iex" · npm: npm install -g @tmonier/argot

Sixty seconds of proof, zero setup, on your own history:

argot audit      # ⏪ what did AI sneak into your last 50 commits?

audit fits the voice as it was 50 commits ago (in a temp worktree — your tree stays untouched), rescores everything since, and attributes every finding to its introducing commit — ai-assisted / human / unknown, from concrete commit markers only:

━━ argot audit ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  last 50 commits · 52% carry AI markers · 1 finding would have met review

  Worst offender — commit cae8349 · ai-assisted
  ! landing/src/pages/llms-full.txt.ts:L1-32 · foreign-import
      ↳ astro (L1), astro:content (L2) — 0 of 49 module specifiers…
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

The terminal card ends with a copy-paste share caption, and argot audit --format html is a screenshot-ready card — post your score.

Then fit today's voice so check raises these before they merge:

argot init       # learn this repo's voice (~25 s on a 1,100-file repo)
argot check      # score your working changes against it

Accuracy is a function of setup — argot learns from what it's allowed to see. Best path: npx skills add get-tmonier/argot, then /argot-setup in your coding agent (Claude Code, Cursor, 70+ agents) reads your repo, excludes what shouldn't shape the voice, and verifies the catch. Full guide: Setup · Getting started.

argot also runs as an MCP server (argot mcp) your agent can consult while it writes, and ships as a Claude Code plugin — the five skills plus the MCP server in one install: /plugin marketplace add get-tmonier/argot.

Demo

A PR adds a Django-style view to an all-FastAPI codebase. mypy and ruff are silent — the framework it reaches for is one this repo has never imported:

argot check · 1 hunk above threshold (1 foreign)

fastapi/receipts.py
  !  L1-L10         1.00  foreign  · staged · foreign-import [94a92c256ea1]
     ↳ django (L1) — 0 of 74 module specifiers in repo
       common here: fastapi (357×), pydantic (129×), typing (129×) (+7 more)
  1 | from django.views import View
             ^^^^^^

redundant names the function you already have (↳ duplicates slugify (src/utils/text.py:14) — similarity 0.86), misplaced names where the code belongs, layering names the direction an import reverses, and every line is your repo's own evidence. Full anatomy: Reading the output · What it catches.

Your conventions, as rules

Every team has conventions no generic linter ships: "presentational components take props — they don't fetch", "files are parsed through our loader, never a raw JSON.parse", "one HTTP client per repo". They live in review comments and onboarding docs — until an AI agent, who read neither, merges around them. With argot they're repo-local rules: a TOML manifest + a small sandboxed script in .argot/rules/, versioned with your code, loaded at run time — no plugin build, no recompile, one rule format across all 11 languages.

And they can do what no classic linter structurally can. A linter sees one version of one file; argot hands your rule both sides of the diff — so you can write rules about what a change removed:

# .argot/rules/no-dropped-endpoints/rule.toml
[rule]
schema = 1
name = "no-dropped-endpoints"
description = "removing a public endpoint requires a deprecation cycle — catch the route that silently disappears in a diff"
severity = "error"
languages = ["typescript", "javascript"]
// check.rhai — a route that existed before this change, and is gone now
const ROUTES = "(call_expression function: (member_expression property: (property_identifier) @verb)
                arguments: (arguments (string (string_fragment) @path)))";
let now = [];
for m in ts_query(ROUTES) { if m.capture == "path" { now.push(m.text); } }
for m in ts_query_old(ROUTES) {
    if m.capture == "path" && !now.contains(m.text) {
        report(m.line, "endpoint '" + m.text + "' removed without a deprecation cycle — see docs/api-lifecycle.md");
    }
}

No ESLint plugin can express that rule — there is no "old side" in a linter. And because argot fits your history, a rule's allowlist can be your own git log: import_attested("moment") asks "has this repo ever used this date library?" — no list to hardcode, no list to maintain. Rules run on changed files only (adopting one creates zero backlog noise), and their findings are suppressed, configured, and rendered exactly like built-in rules. argot rules test is the red/green authoring loop. Full reference + worked examples: Custom rules.

Rules an agent can't game

An AI agent that can't satisfy a check will reach for the next-cheapest green: mute the rule, downgrade it in a local config, --rule it=off, or — for a custom rule — just rewrite the script that caught it. Lock the rule and every one of those doors closes:

[rules]
layering = { severity = "error", locked = true }
custom   = { severity = "error", locked = true }   # lock every repo-local rule

A locked rule (opt-in, from the committed argot.toml only):

  • freezes its severityargot.local.toml and --rule overrides are refused;
  • refuses every suppression surface for its findings — inline # argot: ignore, [[mute]], and [exclude].paths don't apply;
  • and — the teeth — weakening the lock is itself a finding. rule-tampered (group governance, pinned error, unsuppressable) reads both sides of the diff being checked and fires when the change removes a lock, downgrades a locked severity, adds a [[mute]] on a locked rule, or edits a locked custom rule's script — with a loud run-level warning your CI surfaces (a PR annotation under --format github).

Tamper-evidence, not tamper-proofing — the same philosophy as the test-integrity rules: an agent can touch the alarm, but touching the alarm is the alarm. The one quiet way to relax a locked rule is a committed argot.toml diff a human reviews. Guide: Locked rules.

Configure it like any linter

Every rule (built-in or yours) defaults through argot.toml [rules]error / warn / off, per rule or per group — or per run via --rule layering=warn. A [rules] entry can also scope a rule to paths (layering = { include = ["src/**"] }). Excludes are gitignore-style [exclude].paths; inline # argot: ignore-next-line rule=… — reason and argot mute <hash> give line-level and durable committed acceptances. Guides: Configure · The commands.

argot vs. the tools you already run

| | Type checker | Linter | Copilot · SAST | argot | |---|:---:|:---:|:---:|:---:| | Catches invalid code | ✅ | ✅ | ~ | — | | Flags what's foreign to this repo | ❌ | ❌ | ❌ | ✅ | | Flags a function you already have | ❌ | ❌ | ❌ | ✅ | | Flags code filed in the wrong place | ❌ | ❌ | ❌ | ✅ | | Flags an import that breaks your layering | ❌ | ❌ | ❌ | ✅ | | Flags a test quietly weakened to game a failing suite | ❌ | ❌ | ❌ | ✅ | | Enforces your team's own conventions, cross-language, on the diff | ❌ | ~ | ❌ | ✅ | | Locked rules an agent can't mute, override, or rewrite unnoticed | ❌ | ❌ | ❌ | ✅ | | Audits merged history · attributes findings AI vs human | ❌ | ❌ | ❌ | ✅ | | Learns from your history · runs 100% local | ❌ | ❌ | ❌ | ✅ |

argot is additive: it sits after your type checker and linter and catches the one thing they can't — code that's valid and lint-clean but unlike anything your team has written. It's the harness around AI output, built from the one thing that can't hallucinate: your repo's own history.

Benchmarks

Honest, leak-free numbers, measured by the real fit → check pipeline — foreign fixtures spliced into real host files; false alarms counted on a temporal holdout the model never saw:

  • Foreign catch — 595/605 (98%) when the foreign symbol is visible in the diff · false alarms 0.29% of 22,513 real hunks (worst corpus 1.46%)
  • Architecture — 244/252 (96.8%) caught · 0/140 controls flagged · ≤2.7% over-fire on replayed real history
  • Reinvention — median 89% at ≤4.5% false fires per hunk · Misplacement — 85–99% (median 96%) at ≤1.2%, where the repo has separable architecture
  • Test-integrity — 144/153 (94.1%) gaming tactics caught · 0/102 legitimate-refactor controls · 1.12% of 5,268 replayed accepted test-touching commits flagged at gating severity

One documented limit: masked foreign — a foreign symbol whose name collides with one you already use — is statistically invisible to a voice model. We publish that number rather than hide it. And the method, stated plainly: catch rates are measured on fixtures we authored under a pre-registered rubric frozen before scoring; false alarms are counted on real commits the model never saw. Independent validation is welcome — that's what the reproducible harness is for. Per-language and per-corpus tables, methodology, confidence intervals: benchmarks page (CI-fed, can't drift from what ships). Want a language validated? Open an issue.

CI

- uses: get-tmonier/argot@main   # non-blocking voice score on every PR

--format github prints inline PR annotations; --format sarif feeds code scanning; --format json is a stable schema. Add publish-badge: true (with contents: write) for a live README badge — argot · N% in-voice, updated on every push. Copy-paste setups incl. pre-commit: the CI guide.

How it works

Five learned detectors, one source of truth — your git history — plus the rules you script yourself. A statistical voice model (two frequency tables + a callee-cluster partition — no neural net) catches foreign imports, callees, and token shapes; a local code-embedding model (jina-code via statically-linked llama.cpp) catches reinvention and misplacement; a module-dependency graph catches layering reversals; a test-inventory diff catches gamed tests. Fit in seconds, check in milliseconds, nothing leaves your machine — and nothing generates: every verdict is a statistic you can replay. Full detail: How it works · The scoring model · Performance · experiment log in docs/research/.

Contributing

Issues and PRs welcome — start with CONTRIBUTING.md:

git clone https://github.com/get-tmonier/argot && cd argot
just build       # cargo build --release -p argot → target/release/argot
just verify      # cargo fmt --check + clippy -D warnings + cargo test

Acknowledgements

argot is benchmarked against real repositories used as read-only corpora — cloned at benchmark time, never redistributed, each under its own license, none affiliated with argot: FastAPI, rich, faker, Saleor, Wagtail, Dagster, Scrapy, Hono, Ink, faker-js, Excalidraw, Outline, Express, Commander.js, ESLint, GitHub CLI, Hugo, ripgrep, bat, Guava, JUnit 5, PowerShell, Jellyfin, redis, curl, RocksDB, fmt, Homebrew, RuboCop, Laravel, and Composer.

Built on tree-sitter (11 grammars), libgit2 via git2, HuggingFace tokenizers (UnixCoder BPE), Rhai (scripted rules), clap, Serde, and cargo-dist. The semantic layer links llama.cpp (MIT) statically via llama-cpp-2; its model is jina-embeddings-v2-base-code by Jina AI (Apache-2.0), fetched on first use as a Q4_K_M GGUF quantization (a derivative work under Apache-2.0 §4) from the semantic-model-v1 release. argot is not affiliated with, nor endorsed by, Jina AI.

License

MIT