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

flowtrace-cli

v0.4.1

Published

Trace an API route through the code that serves it, overlay the test evidence that covers it, and turn a diff into the specs that must run.

Readme

flowtrace

Trace an HTTP route through the code that serves it, put the test evidence that covers it next to the result, and turn a diff into the specs that must run.

It reads source with regular expressions rather than a compiler, so it needs no build, no toolchain and no language server — and it works across repository boundaries, which is where the question usually lives: a request leaves a client in one checkout and is served in another.

Today it understands ASP.NET Core (C#), Ionic/Angular and React + Redux (TypeScript), Playwright and Cypress.

Install · Quickstart · Your own repositories · For AI agents · Commands · Documentation · Benchmarks · Limitations · Contributing · License

Install

npm i -g flowtrace-cli

The npm package is flowtrace-cli — the bare name belongs to an unrelated flow-based-programming tool — and the binary it installs is flowtrace. Zero runtime dependencies; Node 20 or newer.

Or download a single-file executable for Linux, macOS or Windows from the releases page — no Node install required. Or run from a checkout with node bin/flowtrace.js.

Quickstart

The repository ships a worked example under examples/demo-shop: a small ASP.NET Core service with a catalog and an orders controller, a second service that reserves stock, a web client with a Cypress suite, and a Playwright suite that covers some of it. Nothing to set up:

cd examples/demo-shop
flowtrace extract
flowtrace join
flowtrace trace "POST orders/v1/checkout" --seeds
POST orders/v1/checkout  api  src/Controllers/OrdersController.cs:36  [start]
└─ OrdersController.Checkout  api  src/Controllers/OrdersController.cs:36  [literal]
   ├─ ◇ 39-42  if (request == null || string.IsNullOrEmpty(request.PaymentToken))  → 400 BadRequest  [branch:error_return]
   ├─ ◇ 45-48  if (!placed)  → 403 Forbidden  [branch:error_return]
   └─ IOrderService  api  src/Controllers/OrdersController.cs:14  [ctor]
      └─ OrderService  api  src/Services/OrderService.cs:21  [di]
         └─ OrderService.PlaceOrder  api  src/Services/OrderService.cs:35  [body]
            ├─ ◇ 38-41  if (!accepted)  [branch:if]
            ├─ IOrderRepository  api  src/Services/OrderService.cs:21  [ctor]
            │  └─ ■ OrderRepository  api  src/DataAccess/OrderRepository.cs:18  [db·write]
            ├─ IPublishEndpoint  api  src/Services/OrderService.cs:22  [ctor]
            │  └─ InMemoryPublishEndpoint  api  src/Messaging/InMemoryPublishEndpoint.cs:7  [di]
            │     └─ InMemoryPublishEndpoint.Publish  api  src/Messaging/InMemoryPublishEndpoint.cs:7  [body]  graph: unavailable
            └─ OrderPlacedEvent  bus  src/Services/OrderService.cs:43  [publish]
               └─ OrderPlacedConsumer  api  src/Messaging/OrderPlacedConsumer.cs:13  [message·fqn]
                  └─ OrderPlacedConsumer.Consume  api  src/Messaging/OrderPlacedConsumer.cs:16  [body]
                     ├─ ILogger<OrderPlacedConsumer>  api  src/Messaging/OrderPlacedConsumer.cs:13  [ctor]  unresolved
                     ├─ IOrderRepository  api  src/Messaging/OrderPlacedConsumer.cs:13  [ctor]
                     │  └─ ↑ OrderRepository (see above, ×3)
                     └─ FulfilOrderJob  bus  src/Messaging/OrderPlacedConsumer.cs:20  [publish]
                        ├─ FulfilOrderJobConsumer  api  src/Messaging/FulfilOrderJobConsumer.cs:13  [message·fqn]
                        │  └─ FulfilOrderJobConsumer.Run  api  src/Messaging/FulfilOrderJobConsumer.cs:18  [body]
                        │     └─ IFulfilmentHandler  api  src/Messaging/FulfilOrderJobConsumer.cs:13  [ctor]
                        │        └─ FulfilmentHandler  api  src/Services/FulfilmentHandler.cs:18  [di]
                        │           └─ FulfilmentHandler.Fulfil  api  src/Services/FulfilmentHandler.cs:21  [body]
                        │              ├─ ◇ 24-27  if (order == null)  → throw InvalidOperationException (500)  [branch:error_return]  (async)
                        │              └─ IOrderRepository  api  src/Services/FulfilmentHandler.cs:18  [ctor]
                        │                 └─ ↑ OrderRepository (see above, ×3)
                        └─ OrderFulfilmentConsumer  api  src/Messaging/OrderFulfilmentConsumer.cs:11  [message·fqn]
                           └─ OrderFulfilmentConsumer.Consume  api  src/Messaging/OrderFulfilmentConsumer.cs:14  [body]
                              ├─ IProductRepository  api  src/Messaging/OrderFulfilmentConsumer.cs:11  [ctor]
                              │  └─ ■ ProductRepository  api  src/DataAccess/ProductRepository.cs:13  [db·read]
                              └─ ILogger<OrderFulfilmentConsumer>  api  src/Messaging/OrderFulfilmentConsumer.cs:11  [ctor]  unresolved

use-case seeds (3):
U1  error_return@39=taken  → 400 BadRequest  #5a6423a0
U2  error_return@39=not-taken, error_return@45=taken  → 403 Forbidden  #ca37457e  [unknown: placed ← unresolved]
U3  error_return@39=not-taken, error_return@45=not-taken  → ■ db OrderRepository.SaveOrder, ⇝ OrderPlacedEvent → OrderPlacedConsumer [api] → ■ db OrderRepository.MarkPlaced → ■ db OrderRepository.FindOrder → ■ db ProductRepository.GetById  #31ba2067
    also on path: [email protected]:38
    also on path (infrastructure): [email protected]:24

4 sinks · 4 branch points (3 primary) · 1 repo (api) · via: body 10, ctor 9, di 7, literal 1, message 3, publish 2 · 1 graph hop unavailable

graph: unavailable marks a hop the walk could not extend without a code index configured; it stops there rather than guessing. [unknown: placed ← unresolved] marks a branch condition that could not be traced back to something a caller controls; it is reported as unknown rather than assumed reachable.

Then flowtrace cover --area checkout puts the existing tests next to those seeds, and span, cases and scaffold turn the gaps into a tester's page, case sheets and starting specs. The full tour, with every command's output, is docs/getting-started.md.

Your own repositories

Put flowtrace.config.json in the directory that holds your checkouts and name them:

workspace/
  flowtrace.config.json
  shop-api/       an ASP.NET Core checkout
  shop-e2e/       a Playwright checkout
{
  "out": "out",
  "repos": [
    { "id": "api", "kind": "backend", "root": "shop-api", "role": ["api"] },
    { "id": "e2e", "kind": "playwright", "root": "shop-e2e" }
  ]
}

kind is one of backend (ASP.NET Core), contracts (message and DTO definitions), mobile (Ionic/Angular), web (React + Redux) or playwright (a spec suite). Paths resolve relative to the configuration file. Then flowtrace extract, flowtrace join, and trace a route. Step by step, with the expected output at each step and a table of what to do when something is off: docs/getting-started.md. Every key: docs/configuration.md; every key at its built-in value: flowtrace.config.example.json.

For AI agents

The output is deterministic, every line carries a file:line, and a gap in what the tool knows prints as a gap. That makes it a good tool to hand to an agent, and docs/agent-guide.md says how: the setup an agent can run unassisted, a block to paste into the agent's instructions, which command answers which question, and the reading rules that keep the tool's honesty intact in the agent's answer.

Commands

| command | question | |---|---| | extract | what does each repository state about itself? | | join | which client calls reach which server routes, and which do not? | | join --against | what changed on the joined boundary since a saved snapshot — paths, seeds, effects, evidence levels? | | join --export-edges | hand the joined cross-repo edges to a code index, in one versioned, provenance-tagged file — format documented in examples/demo-shop/exports/README.md. | | render | write the joined route report and one flow page per called route. | | trace | what actually runs when this route is called — branches, services, database writes, published messages, consumers? | | routes-of | I hold a grep hit, a stack frame or a message name — which entry routes run through it? | | cover | which distinguishable ways through this feature's routes does a test actually pin down? | | scope | before I touch this area: its whole route universe, which routes already have automated evidence, and which reach a server-side authorization check. | | affected | I changed these files — which specs must run, and which affected routes have no test at all? | | scaffold | write a starting spec for each gap. | | cases | write a plain-English case sheet for each gap, for a person to judge. | | readiness | per feature area: routes reached, sinks by class, seeds by reachability. | | split | how should this branch split into reviewable commits, and is each slice green on its own? | | check | has this area's coverage regressed against the baseline we committed? | | calibrate | does the reader whose verdicts move my coverage numbers still read the way it did? | | span | one self-contained page per route, outcome first — what can happen, which outcomes a test already pins, what to do about the rest. | | surface | where can the state this route writes be read back? | | skeleton | write the spec that calls the route and observes that read-back. | | all | run extract, join and render in sequence. |

The honesty rule underneath all of it: flowtrace never reports a number it cannot point at a fact for. An intercept proves a request reached a route; it does not prove which way through it. So a route's evidence never silently becomes a path's evidence, and a branch no black-box caller can force is reported as unreachable rather than counted as a gap.

Every flag: docs/cli.md, which is flowtrace --help verbatim.

Documentation

docs/README.md lists every document and when to read it. The short version: getting started, for agents, concepts, command reference, configuration, area files, fact schema, the optional code index.

Benchmarks

How this compares to the tools an agent could install instead — joern, ast-grep, semgrep, code-graph-rag, serena, aider's repo map, with ripgrep as the floor — on public, sha-pinned corpora, with the truth sealed before anything runs. Gaps are published in both directions and no best-everywhere claim is made: several peers read C# and TypeScript better than these regular expressions do.

The method, the peers, the agent-in-the-loop protocol, the scorecard so far and the results are under docs/benchmarks/; bench/ holds the pins and the commands. The first agentic run showed no advantage over the baseline, and is published as exactly that.

Limitations

  • Extraction is heuristic, not a parse. An idiom the patterns do not recognise is invisible; the fix is to widen a regular expression in lib/extract/, and the patterns are grouped at the top of each file for exactly that. Comments and string literals are blanked before the patterns run, so an idiom written in prose is not read as code. A repository may also name an external fact provider, whose facts extract validates, tags with their producer and merges under a mode the configuration states.
  • Language and framework support is what is listed above, no more. A second messaging idiom — handler interfaces, sagas, and sends through a bus variable — is read once its interface and verb names are given in the configuration; only one idiom is recognised without that.
  • affected reads diffs through git, so the repository it reads must be a git checkout.
  • Coverage is evidence overlay, not instrumentation. It reports what the tests say they touch, from their own source; it never runs them.
  • Two suites cover the tool: the public contract suite under selftest/, run by npm test and by CI as its first step, and the private regression suite against corpora that are not public, run before each release. The public verification is the worked example under examples/demo-shop, which CI runs end to end on every push.
  • span --from-component covers the web repository kind only. A mobile-kind name is refused with its reason rather than answered partially.
  • A minimal-API route is walked into its inline lambda, or into the method a method-group handler names. A handler held in a delegate variable, and a route filter, are not walked.
  • A consumer is entered through the method whose parameter carries the message it consumes, or failing that through a known entry verb. A consumer that matches neither is reported as unresolved rather than entered through a guessed method.
  • routes-of searches extracted facts only. Its literal mode is exact and allowlisted; it does not scan source, expand a concrete URL into a template, or use the optional code index.
  • A parameterised Playwright title is the expression as written unless that repository is configured "titles": true, which runs its own installed Playwright in list mode during extract and appends the titles the listing resolves. A title inside a configured case-id wrapper resolves the same way; a title whose text reads as a single identifier, a dotted path or a call rests on its declaration's ordinal rather than being compared verbatim; and a spec file whose two sides cannot be lined up resolves nothing at all — its titles stay raw and the file is counted under refused. See docs/configuration.md#playwright-titles. A checkout and the npm package can do that; the single-file executable reports the titles as unavailable and extracts the rest.

Contributing

Branch, pull request, green CI: CONTRIBUTING.md has the constraints a change must keep, the single-file build subset among them. Vulnerabilities go through SECURITY.md, never a public issue. Participation is covered by the Code of Conduct. GOVERNANCE.md describes how the project is run and how someone becomes a reviewer or maintainer; MAINTAINERS.md lists who holds that role today. ROADMAP.md lists capabilities under consideration.

Semantic versioning from 0.x — the CLI surface may still change between minor versions. What changed in each release is in CHANGELOG.md. The current release is 0.4.1.

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you, as defined in the Apache-2.0 license, shall be dual-licensed as above, without any additional terms or conditions.