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

@trazum/core

v1.86.0

Published

Trazum core: priced advisories for LLM prompts (caching, model tier, batching, schemas), plus deterministic trimming, token counting and pricing.

Readme

@trazum/core

Prompt optimiser. Shortens what you send to a model without changing what you ask for, and tells you what that is worth per month.

Zero runtime dependencies, and that is asserted in CI rather than promised. This library reads your prompts; every dependency would be someone else's code reading them too.

Part of Trazum. For the terminal, see @trazum/cli.

npm install @trazum/core

Use

import { optimize } from '@trazum/core';

const result = optimize(prompt, {
  level: 'safe',                       // or 'aggressive' — read the diff
  usage: {
    model: 'claude-opus-5',
    callsPerMonth: 50_000,
    avgOutputTokens: 500,
    cacheHitRate: 0.9,
    batchEligible: false,
  },
});

result.optimized;                    // the shortened prompt
result.savings.monthlySavingsUsd;    // what that is worth
result.advisories;                   // usually where the real money is
result.rules;                        // what each rule changed, with samples

The optimisation is deterministic: same input, same output, no API key, no network call, nothing to pay.

What it does

Trims with deterministic rules — courtesy, filler, verbose phrasing, duplicated paragraphs, decorative separators, shouting in capitals.

Never touches what would break the prompt. Code fences, inline code, URLs, template placeholders ({{x}}, ${x}, {x}, {% %}) and XML/HTML tags are isolated before any rule runs. If a rule ever did make one of those disappear, that rule is discarded and the rest carry on.

Tells you where the money actually is. Trimming is usually not it. Read result.advisories first — they are sorted warnings-first, then by monthly saving:

| Advisory | What it finds | |---|---| | prompt-caching | Caching is a byte-for-byte prefix match, so a template only caches up to its first placeholder. The saving is computed over the real stable prefix. | | cache-prefix-reorder | Stable instructions stranded after the first placeholder never cache. Often the single largest saving available. | | contradictory-instructions | "Answer in English" three paragraphs above "reply in the customer's own language". A correctness bug that also costs tokens twice. | | redundant-examples | Few-shot examples that are near-copies of an earlier one. | | restated-output-format | A schema shown in a code block and then walked again in prose. | | movable-output-schema | A schema the request could carry as a parameter instead — cheaper and stricter, and the one finding that is not a trade-off. Reported, never edited: it changes the call, not the prompt. | | model-downgrade | A keyword heuristic, not a quality judgement — validate with evaluations before acting on it. | | output-dominated | You pay more for the answer than the prompt, so shortening it has a ceiling. | | batch-api, below-cache-minimum, context-window, promotional-pricing | |

The last three structural findings are advisory only. A contradiction has a right answer only you know, and an example that looks redundant may be demonstrating a boundary case on purpose. Trazum points; it does not cut.

Measured usage

measuredUsage(report, label) turns one label's slice of a profileUsage() report into the UsageProfile that optimize() multiplies by — the real call count, output size and cache-read share instead of typed guesses — with the provenance attached: the span, the scaling factor when a month was derived (never under seven days of data), the chosen model's share when the label ran on several, and whether output was ever recorded. labelCoverage(report, labels) names both mismatches between a config's label→prompt map and the log: prompts mapped to labels with no traffic, and labels carrying money with no prompt mapped.

The fleet

assignSources(files, sources) assigns log files to named services by the most specific matching glob — the budget patterns' own precedence rule — and returns the files matching no source rather than dropping them. fleetRollup(sources) sums the fleet, names the dearest source with its share, flags spans too different to compare as rates, finds the same label running on different models in different sources (judged on each source's dearest model, so a stray experiment is not a migration), and names sources where caching loses money while the aggregate pays off.

The plan

buildPlan(report, levers, pricingLastReviewed) turns a report and its levers into a ranked PlanDocument: route and batch on one slice arrive as a single pre-combined action (combinedUsd, never a sum), the truncation action's stake is the measured retry bill, and a cache action exists only for a settled loss — an unsettled verdict is a missing field, and "add the field" is the report's advice, not a plan's. Projected savings and measured stakes are totalled separately; every action carries typed assumptions (PlanAssumption) the log cannot confirm, as data rather than prose, so the renderer localizes them and a later verification can match them structurally. planLabelName renders the unlabelled bucket without leaking the sentinel.

Did it work?

verifyPlan(plan, newerReport, { currentPricingLastReviewed }) holds a saved plan to the report of a later log, with three outcomes and never two: arrived, not-arrived, or cannot-tell — the workload vanished, the fields the detection needs stopped being recorded, or tokens cannot say which tier billed them. Differences carry the world's measured movement from the plan's recorded baseline (calls, tokens per call, both numbers and never a verdict), a repricing between the two documents is flagged rather than silently priced through, and each verdict says whether it fails a gate: not-arrived always, fields-stopped too — a team must not pass on the strength of its own log's silence — and a vanished workload never.

The long run

buildHistory(reports, plans) turns stored reports into the series no pairwise comparison can see: per-label spend, per-model share and cache share per period, with consecutive movement named as runs (MIN_RUN rises or falls at least — two is a comparison, one is noise) and the same plan action appearing in two or more plans reported as a decision nobody is executing. storedReportFrom(name, parsed) reads one stored profile document into the slice history needs, returning null for anything else so the caller names the file instead of absorbing it. No forecasts anywhere: shapes are stated with their first and last values, and where they go next is the reader's.

The bill, from the provider

normalizeAnthropicUsage(payload) and normalizeOpenAIUsage(payload) turn a usage API response into UsageBuckets — token sums per window and model, with the two cache-write TTLs kept apart and a request count only where the provider actually serves one (null otherwise, never zero). bucketedProfile(pull, { catalogue }) prices them, and bucketedCacheEconomics(report) runs the same counterfactual cacheEconomics runs per call. The result is deliberately its own shape rather than a UsageProfileReport with holes in it, so no per-call finding can read a zero this module wrote: every finding a sum cannot support is listed in unavailable with why and what would unlock it. Anything unreadable in the payload becomes a named PullGap, never a default of zero. Pure and browser-safe — the fetch, the credentials and the pagination live in the CLI.

The bill, from what is already on disk

claudeCodeRecords(text, { label }) converts a Claude Code transcript into usage-log records — the token counts and the model cross, the words never do, and that absence is asserted by test rather than promised. looksLikeClaudeCodeTranscript(text) detects one, so a mixed folder routes itself. otelRecords(text) does the same for an OpenTelemetry export's GenAI spans, and returns what it skipped beside what it converted — "1 LLM span priced, 1 other ignored" is a different sentence from a bare total. Both are pure and browser-safe; the web app's Bill tab runs them on a dropped folder.

Should we switch models?

switchAnalysis(report, targetId, { catalogue, on, migrationUsd, evalCases }) prices the decision a what-if only gestures at: the saving on the same tokens (the sign is proven in both directions — a switch that costs money says so), the break-even of a declared migration cost as division over the measured days — refused by name (no-saving, no-clock) rather than approximated — and the cost of the evaluation itself, three provider calls per case. Quality is never in the result: the analysis defers to route, every time. ownRate({ gpuUsdPerHour, tokensPerSecond, utilization }) derives a self-hosted $/MTok from your declared numbers — the one price source here that is neither published nor bundled: it is your own measurement, and the function refuses rather than defaults when a number is missing or out of range.

The store

resolveStore(records) collapses an append-only log into the current truth: one record per identity — provider, window, model, grouping — with the later pull winning, so overlapping pulls converge instead of double-counting. Records it cannot tell apart are returned as possiblyDouble rather than merged, and lines from a newer schema are counted rather than dropped. recordsFromBuckets and bucketsFromRecords round-trip a pull through disk so a stored month prices exactly as a fresh one does; storeInventory summarises what is held; pruneRecords returns what a retention cutoff would remove, with its span, because silence about deleted measurements is the one thing a store must not do.

Watching

evaluateWatch({ report, thresholds, nowMs, ... }) decides what has crossed. Crossings are measured and carry provenance as a field, so a later change cannot smuggle an estimate past a consumer by staying silent. A period too short to judge becomes an abstention rather than a pass — three states, never two — and a crossing already reported comes back as suppressed rather than vanishing, because "we alerted about this" and "this is fine now" are different sentences. The unwatched stretch between cycles is returned as gap.

Answering before the call

answerCost(request, { catalogue }) answers the two questions asked at call time. The budget consumed is measured, the cost of the described call is estimated, and the two never merge: the composed afterCall.usd carries its halves beside it, and restsOn says whether the verdict needed the estimate (measured when the budget is already past its limit, measured+estimated when it takes this call to cross). Three outcomes rather than two — within, over, cannot-tell — and the reasons are kept apart because their fixes differ: no budget configured, nothing measured, or a model the catalogue cannot price. Pure and synchronous, because a function that reads a file cannot promise an answer in milliseconds.

The guard

guardSpend(request, { catalogue }) wraps answerCost with what to do instead. A refusal carries alternatives — route, batch, or both combined the way billLevers combines them rather than summed — each priced for the single call being decided, each carrying its typed assumption, and each filtered to models whose context window the prompt actually fits. cannot-tell never becomes yes: a guard that permits whatever it cannot judge permits everything the moment its inputs go missing.

Comparing two versions

import { comparePrompts, formatSignedUsd } from '@trazum/core';

const change = comparePrompts(before, after, { usage });

change.tokenDelta;                       //  +37  (grew)
formatSignedUsd(change.monthlyDeltaUsd); //  "+$9.25"
change.advisories.appeared;              //  what the edit broke

Note the sign. Everything comparePrompts returns is after - before, so positive means worse — the opposite of result.savings. That is why it lives in its own module and why nothing in it is called a saving.

Prices

The bundled catalogue is correct as of PRICING_LAST_REVIEWED and needs no setup. When a published price moves, correct it without upgrading this package:

import { catalogueFromOverlay, optimize } from '@trazum/core';

const pricing = catalogueFromOverlay(`{
  "lastReviewed": "2027-01-15",
  "models": { "claude-opus-5": { "inputPerMTok": 6 } }
}`);

const result = optimize(prompt, { usage, pricing });
result.pricingSource; // says which models came from the overlay, and its date

A catalogue is a value: applying an overlay returns a new one and mutates nothing, so your prices never leak into another caller's report.

openrouterOverlay(payload, { knownIds, lastReviewed }) turns an OpenRouter /models response into that same overlay shape — models you already price are left alone, and anything unreadable comes back in skipped with a reason rather than vanishing. It is pure, so the browser can run it on a pasted response; the CLI's --pricing-live is this function behind a fetch.

Two entry points

@trazum/core imports no Node builtins — enforced by a test that walks the import graph, because the browser bundles it. Anything that reads the filesystem lives on @trazum/core/node:

import { loadConfig, walkPrompts } from '@trazum/core/node';

Optional LLM pass

For the compression rules cannot do. The result is only accepted if it is shorter and leaves protected content byte-identical — it never returns something worse than where it started.

import { openAiCompatible, refineWithLlm } from '@trazum/core';

const refined = await refineWithLlm(result, openAiCompatible({
  baseUrl: 'https://your-llm/v1',
  apiKey: process.env.LLM_KEY,
  model: 'your-model',
}));

Token counts

The bundled estimator is a dependency-free heuristic, and it compares two versions of the same prompt well — which is what it is for. Its error band is measured per kind of text, because one band for all text was a measurement of its own calibration set rather than of the estimator:

| Kind of text | Band | Worst sample | Samples | | --- | --- | --- | --- | | CJK, all three scripts | ±4% | 3.2% | 6 | | Latin prose and few-shot blocks | ±6% | 5.6% | 18 | | Code, markup and quoting | ±26% | 25.1% | 16 | | Digit-dominant tables and ledgers | ±33% | 32.5% | 7 |

Call bandFor(text) to get the band for a specific prompt. ESTIMATE_ERROR_BAND_PCT is still exported and is the widest of the four, for callers that have to print one figure without holding the text.

That band is measured, against the official counting endpoint, over 47 samples in ten languages and 6 text types. The margin between each bucket and its own worst sample is a point or less, and no bucket is allowed to overlap the next: a sample sorted into a friendlier bucket gets a smaller band and fails the test.

The single band of 10% this replaced was an unchecked design target for eight releases and it was false; the 1.9.0 entry in the changelog says what was wrong, and the 1.82.0 entry says what extending the corpus from 21 samples to 47 found.

Three things follow from how it was measured, and they matter if you depend on the number:

  • The band is a Claude number, and the others are far outside it. The same 47 samples measured against DeepSeek's own counter came out 94.5% wrong at worst, and against Mistral's 103.1% — Trazum prices 7 providers and the band belongs to one. foreignTokenizer answers with the provider id whenever the model is not Anthropic's, and the report says so on the line rather than printing a figure that was measured somewhere else.
  • It detects the language and divides accordingly, because one divisor calibrated on English measured −37.3% on German. detectTextLanguage answers null when it cannot tell, which falls back to the English behaviour.
  • Kana, han and hangul cost different amounts. Charging one token per CJK character put Japanese at +11.2% and Chinese at −3.2%; kana measure 0.75 tokens per character, han 1.05 and hangul 1.35. Hangul had been carrying a placeholder nothing measured until two Korean samples agreed in lockstep on 1.35, which took the CJK bucket's worst error from 10.6% to 3.2%.

For exact figures, pass a real counter — the counting endpoint is free:

import { countTokensAnthropic, withExactTokenCounts } from '@trazum/core';

const exact = await withExactTokenCounts(result, countTokensAnthropic({ apiKey }));

Locales

English and Spanish. A locale changes the report, never the optimisation — the same prompt in any locale produces the same optimised text, the same token counts and the same advisory ids. Match on ids, not on prose.

Versioning

See VERSIONING.md. Rule and advisory identifiers are stable across locales and versions on purpose; message text is copy and gets improved.

MIT.