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

taleseal

v0.6.0

Published

Seal an agent run as a shareable tale — taleseal CLI

Readme

taleseal

Seal a local Claude Code, Codex or Cursor session as a published tale — the shareable narrative of one run: what triggered it, what it did, what came out, with the receipts to verify it. Loom for agent runs.

npx taleseal seal --preview      # what would be published — nothing leaves your machine
npx taleseal seal                # publish; get back a link for the PR or Slack thread

seal finds the newest Claude Code session for your current directory and composes the tale locally. The first publish signs you in on the spot — login opens the browser, creates an account if you need one, and saves the key on your machine.

Login

Bare taleseal login opens the browser: approve there — signing up on the way if needed — and an API key is created and stored in ~/.config/taleseal/config.json ($XDG_CONFIG_HOME respected, file mode 0600). It works from SSH boxes and containers too: open the printed URL on any device and match the confirmation code. Codes last ten minutes and work once.

For CI, scripts and browserless machines, taleseal login --key tk_… stores a key minted by hand in the dashboard instead. It is validated against the server first: a key rejected with 401 is never stored; if the server is unreachable the key is stored anyway, with a warning. taleseal logout removes the stored key.

Usage

taleseal seal [--transcript <path>] [--agent <name>] [--status <status>]
              [--publisher <name>] [--transcript-url <url>] [--preview]
              [--yes] [--dry-run] [--json]
taleseal login [--key <tk_…>]
taleseal logout

| Flag | Meaning | | --- | --- | | --transcript <path> | Transcript JSONL to seal. Omitted → newest *.jsonl in ~/.claude/projects/<this directory>/ | | --agent <name> | Agent name shown on the tale (default: taken from the transcript format) | | --status <status> | Outcome status recorded on the tale: succeeded | partial | failed (default succeeded) — a tale is allowed to be an honest failure report | | --publisher <name> | Recorded as provenance.publisher — who ran this / under whose authority | | --transcript-url <url> | Recorded as provenance.transcriptUrl — a link to the full raw session. Must be an http(s) URL; local paths are rejected | | --preview | Print the human-readable pre-publish preview (title, status, beats, receipts, redaction report) to stdout and exit 0 — no key needed, nothing leaves your machine. This is what plugins show before asking "publish?" | | --yes | Skip the pre-publish redaction gate prompt. Required when stdout is not a TTY (hooks, CI, pipes) | | --dry-run | Print the composed tale JSON to stdout — nothing leaves your machine | | --json | On publish, print {"id","url"} instead of the bare URL |

On success the tale URL is printed to stdout. Errors go to stderr with exit code 1.

The redaction gate

Secrets travel nowhere without a human seeing the redaction report. When seal is about to publish (i.e. not --dry-run), it first builds a redaction report — how many [REDACTED:<kind>] markers the scrubber left in the tale, counted by kind, with up to three sample matches shown in their (already-redacted) context. Then:

  • Interactive terminal: a compact preview (title, status, beats, evidence count, the redaction report) is printed and you are asked Publish? [y/N]. Anything but yes cancels; nothing leaves the machine.
  • Not a TTY (git hooks, CI, piped output): publishing is refused with exit code 1 unless --yes is passed. Automation must opt in explicitly to publishing unseen.
  • --yes skips the prompt in both cases.

taleseal seal --preview prints exactly this preview to stdout and exits without publishing, so you (or a plugin) can see the report before deciding anything. --dry-run is unchanged: it prints the tale JSON and never gates.

Configuration

Both values resolve in the same order everywhere — env var first, then the config file written by taleseal login, then the default:

| Value | Resolution order | | --- | --- | | API key | TALESEAL_API_KEY env var → config "apiKey" | | Base URL | TALESEAL_URL env var → config "url"https://taleseal.com |

The config file is ~/.config/taleseal/config.json ($XDG_CONFIG_HOME/taleseal/config.json when set), shape {"apiKey": "tk_…", "url"?: "https://…"}, mode 0600. A key is required to publish; --preview and --dry-run need none.

Supported agents

| Agent | Transcript source | Status | | --- | --- | --- | | Claude Code | ~/.claude/projects/<project>/<session>.jsonl | ✅ | | Codex | ~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl | ✅ | | Cursor | ~/.cursor/projects/<project>/agent-transcripts/<session>/<session>.jsonl (--cursor, or the hook's $CURSOR_TRANSCRIPT_PATH) | ✅ |

What the composed tale contains (format v2)

Composition is fully local and deterministic — no LLM pass, no telemetry. Beyond the v1 narrative (title, trigger, beats, metrics), a v2 tale carries:

  • outcome.statussucceeded / partial / failed, from --status.
  • provenance — auto-filled: tool is the harness that ran the work (claude-code, codex or cursor, with the version when the transcript records one), extent is fully_ai, publisher and transcriptUrl come from their flags.
  • Beat ids — stable slugs generated from each beat's title (deduplicated), so beats can be deep-linked.
  • evidence — receipts extracted deterministically from the transcript's tool calls and attached to the beat they occurred in (at most 6 per beat; overflow is noted in the prose):
    • shell commands → command evidence (command + captured output excerpt + exit code when the transcript records one);
    • test-runner commands (bun test, jest, vitest, pytest, go test, …) → test evidence, with passed decided only by explicit output markers ("12 pass", "0 fail" vs "fail"/"error") — undecidable runs stay plain command evidence, never a claimed result;
    • edit/write calls → one aggregated diff evidence per beat ("N files touched" + the file list when knowable);
    • web/search calls with a URL → citation evidence.

Before any string enters the tale it is scrubbed client-side: AWS access keys, GitHub/Slack tokens, sk- API keys, JWTs, Bearer headers, PEM private-key blocks and password=/secret:-style assignments are replaced with [REDACTED:<kind>] markers — before truncation, so a secret can never be split into an unrecognisable half.

A tale carries the whole run. Every step becomes a beat and every receipt is kept — nothing is folded away for length. A tale exists to show the evidence behind what an agent did, and the evidence a reader came to check (the test that failed, the diff, the command that proved it) lives in the middle of a long session, exactly where a digest would cut.

Anyone holding the published URL can view the tale; the redaction gate above exists so you see exactly what that is before it ships.

Programmatic API

import { buildRedactionReport, composeTale, decideGate, readTranscript, redact } from "taleseal";
import { publishTale } from "@taleseal/sdk";

const run = await readTranscript("/path/to/session.jsonl");
const tale = composeTale(run, { agent: "release-bot", status: "succeeded", publisher: "goran" });
const report = buildRedactionReport(tale); // counts by kind + sample matches in context
await publishTale(tale); // reads TALESEAL_API_KEY; TALESEAL_URL defaults to https://taleseal.com

Requires Node ≥ 22.