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

fossilizer

v0.2.0

Published

Evidence-based code documentation. Every claim traceable to source.

Readme

fossilize

evidence-based code documentation. every claim traceable to source.

fossilize generates documentation from three sources of truth: what the AST says (function signatures, types, imports, exports), what the tests prove (behavioral contracts, error paths, edge cases), and what git says (who changed what, when, how often). every statement in the output is backed by evidence you can verify.

self-hosted: fossilize documents its own codebase -- 63 source files, 828 definitions, 2863 resolved cross-file links, 138 functions indexed, 47 with test evidence, medium confidence overall. 753 tests across 26 test suites.

install

published as fossilizer (the command it installs is fossilize):

npm install -g fossilizer

quick start

npx fossilizer .

after a global install the command is fossilize; the rest of this readme uses that form.

this parses your source and test files, builds a scope graph, maps tests to functions, loads coverage data, and generates evidence-backed documentation.

output goes to .fossilize/ by default:

  • docs.md -- markdown documentation
  • docs.json -- structured index (for agents, dashboards, tooling)
  • docs.html -- standalone HTML report with navigation and search
  • snapshot.json -- index snapshot for drift detection
  • architecture.mmd -- mermaid module dependency diagram

commands

fossilize [dir] -- generate documentation for a project

fossilize drift [dir] -- compare current code against the last snapshot, flag changes

fossilize arch [dir] -- show module dependency graph

fossilize init [dir] -- create a .fossilize.json config file (auto-detects directories)

fossilize index [dir] -- build and save the function index without generating docs

fossilize query <symbol> [dir] -- emit the evidence packs for symbols matching <symbol> as JSON on stdout (for agents and tooling)

flags

--output, -o -- output format: markdown, json, html, both (md+json), all

--coverage, -c -- path to coverage file (lcov or istanbul json)

--test-dir, -t -- additional test directory (repeatable)

--out-dir, -d -- output directory (default .fossilize)

--internal -- include non-exported functions

--watch, -w -- watch for changes and regenerate (debounced, incremental)

--quiet, -q -- suppress human-readable output, emit machine-readable JSON to stdout. useful for CI pipelines, scripting, and tooling integration

--ai -- generate short prose summaries per function using Claude Opus 4.8. opt-in and paid. requires ANTHROPIC_API_KEY in the environment

--ai-max <n> -- cap how many functions get an AI summary in a single run

config

create .fossilize.json in your project root (or run fossilize init):

{
  "sourceDirs": ["src"],
  "testDirs": ["tests"],
  "coveragePath": "coverage/lcov.info",
  "outDir": ".fossilize",
  "output": "both"
}

CLI flags override config file values. unknown fields in config produce warnings to stderr so typos are caught early.

what it generates

for each public function, fossilize produces:

  • signature with params, return type, async status
  • call graph -- who calls this function, what it calls
  • middleware -- decorators (NestJS, Flask, Django) and Express/Koa/Hono middleware chains detected from route registrations
  • test evidence -- which tests exercise it, what assertions they make, which describe block they belong to
  • behavioral contract -- synthesized from test names and assertions: what inputs are handled, what outputs are verified, what errors are tested
  • coverage -- runtime execution count, branch coverage
  • git history -- last author, modification date, commit count
  • confidence level -- high (signature + tests + coverage + git), medium (two evidence types), low (signature only)

ai summaries

by default fossilize generates zero prose. it aggregates evidence deterministically. pass --ai to add a 1 to 3 sentence narration per function, written by Claude Opus 4.8 and grounded strictly in the evidence fossilize already collected.

export ANTHROPIC_API_KEY=sk-ant-...
npx fossilize . --ai

the model only sees structured evidence (signature, call graph, test names and assertions, coverage, contract). it never sees raw source bodies, and the system prompt forbids inventing anything not in the evidence. so summaries stay traceable, same as every other claim.

guardrails, because this is a paid api:

  • opt-in only. no network call happens without --ai or ai.enabled in config. without a key it warns and skips, the rest of the pipeline runs unchanged.
  • hard monthly cap. a local ledger at .fossilize/ai-ledger.json tracks spend per month and aborts before exceeding maxMonthlyUsd (default $10). worst case math is documented in src/ai/ledger.ts.
  • content-hash cache. .fossilize/ai-cache.json keys each summary by a hash of its evidence. unchanged functions are never re-sent, so repeat runs are nearly free and a function can never re-trigger its own call.
  • per-run function cap via maxFunctions (default 200) or --ai-max.
  • the api key is read only from the environment, never logged, never written to any snapshot, cache, ledger, or doc.

privacy note: with --ai, function metadata (signatures, test names, assertions) is sent to Anthropic. source file bodies are not.

config block (all optional):

{
  "ai": {
    "enabled": false,
    "model": "claude-opus-4-8",
    "maxFunctions": 200,
    "maxMonthlyUsd": 10
  }
}

drift detection

npx fossilize drift .

compares the current index against the last saved snapshot. detects:

  • new functions added
  • functions removed
  • signature changes
  • file moves
  • coverage loss
  • middleware chain changes
  • export status changes

exits with code 1 if drift is detected. useful in CI to catch undocumented changes.

architecture graph

npx fossilize arch .

outputs a mermaid diagram showing module dependencies, entry points, leaf modules, circular dependencies, and max dependency depth.

behavioral contracts

derived entirely from test evidence. for each tested function, fossilize synthesizes:

  • accepts -- parameter types plus what input patterns are tested (null handling, empty input, boundary values, invalid input)
  • returns -- return type plus what output properties are asserted (exact values, truthiness, collection membership, numeric bounds)
  • errors -- what error conditions are tested (throws, rejects, graceful handling)
  • side effects -- what mutations are verified (writes, logs, event emissions, external calls)

contracts are scored by completeness: a function with signature + tests + error handling + input validation gets "high" confidence.

ci integration

use --quiet for machine-readable output in pipelines:

# fail CI if docs have drifted from code
npx fossilize drift . --quiet

# generate docs and capture summary
RESULT=$(npx fossilize . --quiet)
echo "$RESULT" | jq .totalFunctions

the drift command exits non-zero when changes are detected, making it a natural CI gate.

languages

typescript and python, via tree-sitter. the parser detects language from file extension and selects the appropriate grammar automatically.

how it works

  1. parse -- tree-sitter parses source and test files into concrete syntax trees
  2. extract -- language-specific extractors pull definitions, references, exports, decorators, middleware chains, and test cases from the CSTs
  3. scope graph -- cross-file resolution of imports, calls, re-exports through barrel files, and type references
  4. coverage -- lcov and istanbul/v8 JSON coverage files are parsed, normalized, and matched to functions by name or line range
  5. git -- blame and log commands extract historical evidence per file
  6. index -- all evidence is collected per function into a structured index with confidence scoring
  7. contracts -- test names and assertion patterns are synthesized into behavioral descriptions
  8. generate -- pluggable renderers produce markdown, JSON, or HTML output
  9. drift -- index snapshots are compared to detect undocumented changes

resolution and precision

a deterministic record is only useful if it is true, so resolution refuses to guess. a reference resolves in this order:

  1. same file -- a local definition shadows any import of the same name.
  2. import-scoped -- a name imported into the file resolves through that import's source module (so an imported format binds to the file it came from, not some other same-named export).
  3. unambiguous global -- a bare name resolves only when there is exactly one definition, or a single exported one. multiple equally-plausible candidates resolve to nothing rather than a wrong edge.

member calls are resolved by receiver type, and only when that type is statically known:

  • this.method() (and Python self.) binds to the enclosing class.
  • this.field.method() binds through the field's declared type, taken from field declarations, constructor parameter-properties, and this.field = param / this.field = new T() assignments.
  • param.method() binds through the parameter's declared type.

a receiver whose type needs deeper inference (a return value, a multi-hop chain like this.config.dep.method()) is left unresolved rather than matched to a random same-named method. the guiding rule holds: a missing edge is honest, a wrong edge is not.

fossilize also emits extends, implements, and type_reference edges for inheritance and type relationships.

measuring it. the TypeScript compiler's type checker is scope- and import-aware, so it serves as a ground-truth oracle. a harness (tests/oracle/) diffs fossilize's call edges against the checker and reports precision and recall. on fossilize's own source the call graph scores roughly 0.996 precision / 0.98 recall. on real external repos precision holds in the 0.90 to 0.94 band. recall depends on style: ~0.96 for import-and-function-heavy code, and ~0.83 for instance-method-heavy code after typed-receiver resolution recovers the dependency-injection pattern (an instance-heavy repo measured 0.62 -> 0.83 recall once this.field.method() resolved through field types, with precision unchanged). the remaining gap is multi-hop chains the resolver deliberately declines rather than guess: a missing edge over a wrong one. reproduce with FOSS_BASELINE=1 npx vitest run tests/oracle/baseline-src.test.ts (self-host) or FOSS_REPO=/path/to/repo npx vitest run tests/oracle/baseline-repo.test.ts (any repo with a tsconfig).

drift, beyond structure

fossilize drift reports four buckets: new, removed, changed, and stale. a node is stale when its signature is unchanged but its behavioral evidence moved -- the synthesized contract or the test assertions changed. that is the dangerous case: the function looks identical to callers and to docs while provably doing something different. stale nodes count toward the non-zero drift exit code.

agent context packs

pass --min-confidence high (or medium/low) to emit documentation containing only nodes at or above that confidence. this produces a high-signal, evidence-backed context pack for feeding an LLM, without the low-confidence noise. the saved drift snapshot stays complete regardless, so filtering never causes false "removed" drift.

for targeted lookups, fossilize query <symbol> returns just the matching evidence packs as JSON on stdout, ordered by confidence:

# what does fossilize actually know about createUser?
npx fossilize query createUser . --min-confidence medium

each result carries the signature, the proven call graph, mapped tests and assertions, coverage, git, the behavioral contract, and unresolvedCallCount (how many of the function's calls could not be resolved, so a consumer knows whether the call graph is complete). this is the read surface an agent queries instead of guessing from raw source.

programmatic API

import {
  SourceParser,
  ScopeGraphBuilder,
  buildIndex,
  generateMarkdown,
  generateHtml,
  synthesizeContracts,
  buildArchitectureGraph,
  detectDrift,
} from "fossilize";

all pipeline stages are independently importable and composable. types are exported for consumers building custom tooling on top of the index.

license

MIT