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

@ykstormsorg/quickdraw

v1.0.4

Published

Benchmark LLM streaming — TTFT, TPS, p50/p95/p99, cost ceiling, and regression diffing across OpenAI and Anthropic.

Readme

Quickdraw

Benchmark LLM streaming — TTFT, TPS, $/1K tokens. Across providers, on your prompts, with a hard cost ceiling.

CI npm version License: Apache 2.0


The problem

LLM SDKs give you a latency number but not a streaming breakdown. "Total time to first token" vs "time after last token" vs "throughput in tokens/sec" are different numbers that tell you different things. Quickdraw splits the stream into phases and gives you each one.


How it works

flowchart LR
    P[prompts<br/>test-prompts.ts]
    B[BenchmarkRunner<br/>runBenchmark]
    O[openai provider<br/>gpt-4o-mini]
    A[anthropic provider<br/>claude-haiku-4-5]
    M[computeMetrics<br/>ttft / tps / cost]
    R[results.jsonl<br/>api_calls.jsonl]
    P --> B
    B --> O
    B --> A
    O --> M
    A --> M
    M --> R

runBenchmark() iterates over providers[], streams each prompt, measures TTFT and TPS, writes api_calls.jsonl with raw data, and computes summary stats.

Metrics captured per run:

| Metric | Description | |---|---| | ttft_ms | Milliseconds from request start to first token received | | tps | Tokens per second after first token | | total_duration_ms | Full end-to-end time | | cost_usd | Computed from token counts × provider pricing | | guardrail_overhead_ms | Time spent in per-chunk callbacks |


Quick start

# Install
npm install -g @ykstormsorg/quickdraw

# Run against both providers, 3 runs each, $2 hard cost cap
quickdraw bench --providers openai,anthropic --runs 3 --cost-cap 2

# Use your own prompt and save the full results JSON
quickdraw bench --providers openai --runs 5 --prompt-file ./bench/standard-prompt.md --json run.json

# Dry run (no API calls, prints the plan only)
DRY_RUN=true quickdraw bench --providers openai --runs 1

# Regression-diff two saved runs (exit code 2 if a regression is detected)
quickdraw diff baseline.json candidate.json

The benchmark table reports avg / p50 / p95 / p99 for both TTFT and TPS, plus per-provider cost. If a required API key is missing, the CLI exits with a clean Set OPENAI_API_KEY / Set ANTHROPIC_API_KEY message and makes no network call.

Try locally

git clone https://github.com/ykstorm/quickdraw.git
cd quickdraw
npm install
npm test                    # vitest suite
DRY_RUN=true npm run bench  # dry run against mock infra
# Then with real keys:
export OPENAI_API_KEY=sk-...
export ANTHROPIC_API_KEY=sk-ant-...
npm run bench               # live against OpenAI + Anthropic

Library mode

import { runBenchmark } from '@ykstormsorg/quickdraw'

const results = await runBenchmark({
  providers: ['openai', 'anthropic'],
  runs: 3,
  guardrails: false,
})
// results: BenchmarkResult[] with per-provider stream metrics

Stack

| Layer | Choice | |---|---| | Runtime | Node.js 18+ | | Types | TypeScript | | Build | tsup | | Tests | Vitest | | Providers | OpenAI + Anthropic REST streaming (raw fetch) | | License | Apache 2.0 |


Measured (live)

Quickdraw benchmarking itself against Claude Haiku, measured in CI on a GitHub runner (claude-haiku-4-5, 3 runs, the committed bench/standard-prompt.md, a ~230-token completion):

| Metric | avg | p50 | p95 / p99 | |---|---|---|---| | TTFT (ms) | 775 | 739 | 1143 | | TPS (tokens/sec) | 87.2 | 85.6 | 90.9 |

Cost for the whole 3-run sweep: $0.0037 (well under the default $2 cap). TPS is computed from the provider's usage output-token count — not a raw count of streamed SSE frames, which undercounts throughput badly when one frame carries several tokens. Reproduce by triggering the live-anthropic job in live-bench.yml (manual dispatch only, so fork PRs can't reach the key), or locally with ANTHROPIC_API_KEY=… npm run bench -- --providers anthropic.

What's here now

  • Percentile reporting. TTFT and TPS are reported as avg / p50 / p95 / p99 across runs.
  • Regression diffing. quickdraw diff <run1.json> <run2.json> compares two saved runs and flags TTFT/TPS/cost regressions and success/model changes (exit code 2 when a regression is found).
  • Exact token counts. Token counts come from each provider's usage field when available, falling back to a char/4 estimate.
  • API-key preflight. Missing keys produce a clean Set <ENV_VAR> message and exit 1 — never a Bearer undefined 401 dump.

What's NOT here

  • No Bedrock / Vertex / Gemini support. Only OpenAI and Anthropic. Azure and local models are not wired.
  • No hosted nightly dashboard. The nightly workflow runs the real CLI and publishes a results page to GitHub Pages, but there is no richer dashboard UI yet.
  • Guardrail overhead is a stub. guardrail_overhead_ms is measured with a no-op callback — it doesn't run real Tripwire patterns.

Contributing

Contributions are welcome! Please read CONTRIBUTING.md for details on how to get involved.


License

Apache 2.0 — see LICENSE.