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

@magician-network/attendant

v0.1.0

Published

The Attendant: Magician as a Telegram-native bot — the same trust engine, spoken. Deep-link joins, consent by button, the receipt loop closed inside the chat.

Readme

@magician-network/attendant

Magician, Telegram-native: the same trust engine, spoken — deep-link joins, consent by button, the receipt loop closed inside the chat. This is the native tier of the three-tier architecture (docs/boardroom-2026-09-02-telegram.md): sovereign (CLI) is the home, open (/join) is the credibility surface, native is growth.

Run it

npm run build -w @magician-network/core -w @magician-network/attendant
TELEGRAM_BOT_TOKEN=<from @BotFather> node packages/attendant/dist/main.js

| Env | Required | What it does | |---|---|---| | TELEGRAM_BOT_TOKEN | yes | Two minutes at @BotFather. Long-polling — no webhook, any host. | | ATTENDANT_STORE | no (default ./.attendant-store) | Where member stores live. Never inside a repo; git-ignored here. | | ANTHROPIC_API_KEY | no | Switches the conversational layer on. Absent, every command still works and free text gets a truthful sentence — the seam is honest, never a stub. |

Running it non-stop

sudo bash deploy/install.sh                    # install or deploy a revision
node packages/attendant/dist/main.js --check   # verify without polling

docs/attendant-operations.md is the deployment: one small always-on VM, a persistent disk, systemd, the token in Secret Manager, and a nightly encrypted snapshot. deploy/ holds the unit files and the snapshot script. It says why not Cloud Run in particular — a platform that can run two instances gives you two processes polling one bot token, and two writers on one member's directory.

Three properties make a restart safe, and none of them is visible in a session where the bot is started once by hand and never dies:

  • Every store write is a rename. A truncated graph.json locks a member out of their own graph permanently, because every parser here is strict — a half-written document does not degrade, it throws.
  • The Telegram offset is on disk, saved after every update. Held only in memory, a restart re-handles the whole last batch — and here that is a second consent notification about a consent given once. The save happens after the messages go out, so a crash re-delivers rather than drops: a duplicated prompt is visible and recoverable, a consent request that never arrived is neither.
  • One writer, or none. The store is locked before the first update is fetched. A dead process's lock is taken over; a lock held by another host is refused rather than judged, and the message names the file.
  • A failure to start names its own cause. The startup check was once (await fetch(…)).json() with nothing around it, so anything that answered with something other than JSON — a proxy error page, a captive portal, an HTML 502 — killed the process with a SyntaxError about JSON.parse. Under Restart=always that is a crash loop blaming a parser for a network fault. preflight.ts separates a rejected token from a rate limit from a failed lookup from something-that-was-not- Telegram, because each sends you somewhere different.

What a member can do

/start (or tap an invite deep link) · /invite [note] (with a QR button for the person in front of you — same code, same single-use rules, a photo the member shows rather than a link they read aloud) · /add (quick-add lines, shared grammar with the CLI and /join) · /intent <sentence> then confirm wants by button · /paths, then Request the introduction by button · /requests (watch consents land, make the introduction, seal the outcome) · /suggest · /renewals · /metrics · /export (the file loads straight into magician ingest) · /delete (total, confirmed, no copy kept) · /help.

The ask loop — consent made forwardable

Requesting an introduction opens the engine's consent machine and hands the REQUESTER one forwardable t.me/…?start=a_<code> link per consent still needed. The bot never messages a hop owner itself — it may not even know them; the ask travels on the requester's own relationship, which is the point. A non-member who taps one onboards first and answers second: the network grows through being needed, not through being advertised. The bot cannot verify the tapper IS the named owner — the same trust posture as the CLI's envelope transport, stated rather than hidden. The first answer consumes the link. A yes notifies the requester (a yes is consent to be known); a no sends nothing, ever — the requester's /requests reads unavailable, indistinguishable from a route that never existed. When every hop is in, the requester makes the introduction and seals the outcome — kind by button, note by sentence, sealed through introduction/1 and learned by the graph the same way the CLI does it. Each ask also offers a per-hop QR — the in-person version of forwarding it. A QR for a spent code is refused: it would only mislead the person scanning it.

Sealing also hands the requester the outcome card — nameless by construction (outcomeCard in core: built from kind, date and digest, never from the record's people), stating 'none' as plainly as a deal, with standing never rendered. Forwarding it is the holder's choice.

QR encoding is qrcode-generator, the reference implementation this repository deliberately does not re-derive: an encoder written here could pass every structural test and still be unscannable, and no offline decoder exists in CI to say otherwise. The PNG wrapper IS written here because it is provable — the test inflates the IDAT and compares every pixel.

Architecture: everything with a decision in it is a pure function

Telegram ⇄ telegram.ts (thin executor, the only file with a network)
              │ TgUpdate            ▲ Action[]
              ▼                     │
           bot.ts  — handleUpdate(update, store, cfg) → Action[]
              │  free text that is not a command or quick-add
              ▼
          claude.ts — the conversational layer (optional, seam-honest)
              │
           store.ts — one directory per member; filesystem plays RLS
  • bot.ts is the CLI's run.ts pattern aimed at Telegram: every flow tested without a network (bot.test.ts).
  • store.ts is the H1 shape ahead of the H1 server: per-member directories, strict parsers on every load, reads never create, and two deliberate cross-member surfaces — inviteByCode (deep links cap at 64 chars so invites travel as digest-derived codes, re-verified by the same parser on resolution) and askByCode (a consent ask forwarded by the requester; the answer lands on the requester's request, its natural home, only downstream of the answerer's button).
  • claude.ts gives the model the engine's operations as its only hands. The tool roster IS its reach (a test asserts the roster by name and that no tool can address a person), so conversation structurally cannot exceed the consent model.
  • telegram.ts maps actions to Bot API calls and decides nothing; a test pins it to importing no engine function.

The refusals, each a test or a structural absence

  • No broadcast. Every action addresses the chat its update came from; the TWO exceptions — receipt delivery to the inviter, and the consent-YES notification to the requester — each exist only downstream of an explicit button press by the person the message is about, and the no-broadcast test walks every flow asserting no other cross-chat message can exist. A decline sends nothing, ever.
  • "Keep it private" is first-class. Not sending the receipt means the inviter never learns of the join, and the copy says so.
  • Inline mode is refused, as a decision. An inline result can land in a group of hundreds; an invite is for one person. The refusal is written at the one place it could be undone (handleUpdate).
  • No contact import, no member directory, no auto-DM, no gold.
  • The register rule reaches the model. A strength the model fills in is a figure nobody asserted — the tool description says to ask, and the engine refuses the malformed line regardless.

Suite

vitest run — 43 tests: the full join loop across two members, the full ask loop across three (a forwarded ask onboarding a non-member, the silent decline, single-use codes, seal → learn), consent both ways, replay refusal, the two-lane no-broadcast invariant, activation at the thumb, data rights (export/delete), member isolation and traversal refusal, code-registry shape checks, tampered-store refusal, the honest seam, every conversational tool, transport action mapping against a stubbed wire, and the 4096-character cap.

Gates (roadmap v5)

T0 (this package) is built. T1 — the founding circle running on it — is the operator's move and carries the unchanged baseline gates; T3, the public viral loop, opens only past Stage 1's evidence. Growth mechanics never precede the evidence.