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

bitplan

v0.0.21

Published

Create encrypted hosted plans and publish them as 1Sat Ordinals.

Readme

bitplan

Create encrypted HTML plans. Keep them hosted while they change, then publish them as 1Sat Ordinals when they should be permanent.

The CLI validates a self-contained HTML document and encrypts it with standard @bsv/sdk and wallet operations. A hosted draft stores the sealed envelope on bitplan.dev and costs no BSV. When the plan is ready, the BRC-100 wallet can publish it as a 1Sat Ordinal. On-chain updates spend the current draft coin with a new inscription, so one origin identifies the plan and its version history.

Requirements

A running BRC-100 wallet on this machine. bitplan never receives identity private keys: BRC-2 wrapping, unwrapping, signing, and funding are wallet calls. The shared document key exists transiently in the CLI. BSV Desktop serves the JSON API on 127.0.0.1:3321, which is where bitplan looks by default.

If no wallet answers, the command fails and says so.

CLI

Upload a draft:

npx bitplan upload ./plan.html
bunx bitplan upload ./plan.html

By default, BitPlan notifies 1Sat after the wallet publishes so ORDFS can capture the transaction as quickly as possible. Opt out when needed:

npx bitplan upload ./plan.html --no-relay

Normally, the wallet publishes first. Afterward, bitplan sends the wallet-returned Atomic BEEF through 1Sat, which attempts to capture it for ORDFS and forwards the transaction to Arcade. This may make the viewer available sooner. A relay failure is only a warning because the wallet publish may already have succeeded. --no-relay skips only this notification.

Attach an optional description (shown in bitplan list and the My drafts page). Re-running with --description updates it; omitting it leaves the existing one untouched:

npx bitplan upload ./plan.html --description "Q3 warehouse migration plan"

Confirm the wallet is there:

npx bitplan auth
npx bitplan whoami
npx bitplan version

Share the next version with one or more wallet identity public keys, local contacts, or local teams. Existing raw-key readers remain authorized unless you explicitly publish a private version:

npx bitplan upload ./plan.html --share-with <identity-key>
npx bitplan upload ./plan.html \
  --share-with <identity-key-a> \
  --share-with <identity-key-b>
npx bitplan upload ./plan.html --private
npx bitplan upload ./plan.html --link

bitplan whoami prints the connected wallet's identity key. A shared version stores the encrypted document once, then asks the wallet to wrap its 32-byte document key for each reader. Identity keys and the access list are public, and --private only affects the new version; older shared inscriptions remain readable by their original recipients. Security level 2 lets the wallet ask for permission for each new reader.

Give public identity keys memorable local names, then group those contacts:

npx bitplan contact set alice <identity-key>
npx bitplan contact set bob <identity-key>
npx bitplan team set acme-dev alice bob
npx bitplan upload ./plan.html --share-with acme-dev

contact list and team list [name] show the address book; both accept --json. Use team add, team remove, or team set to change membership. The next version of a locally tracked draft using that team resolves its members again, so removed members are left out of that version. Versions that were already shared remain readable by their original readers.

Save one or more default readers for every new plan:

npx bitplan config --share-with <identity-key>
npx bitplan config --share-with acme-dev
npx bitplan config --clear-share-with

Updates keep their existing readers. Use --share-with to add a reader to one plan, or --private to publish the new version for this wallet only.

List the drafts this wallet holds. The default table shortens origins and outpoints. --verbose switches to one labeled detail block per draft so full identifiers and timestamps do not stretch the table:

npx bitplan list
npx bitplan list --verbose

Read one back (HTML to stdout, metadata to stderr with --meta). Metadata includes the envelope version, access mode, and public reader list:

npx bitplan fetch <origin> --meta > plan.html
npx bitplan fetch https://bitplan.dev/d/<origin>
npx bitplan fetch <origin> --version 2

Agents and scripts can ask for one JSON value instead of parsing the text made for people:

npx bitplan upload ./plan.html --yes --json
npx bitplan fetch <origin> --json

The upload result includes the origin, current outpoint, version, access list, relay status, and viewer URL. --json still requires --yes; it never treats a machine-readable response as permission to publish. Fetch JSON includes both the decrypted HTML and its metadata, so --meta is not needed.

Hosted drafts

bitplan upload plan.html --hosted seals the same envelope, then stores it on bitplan.dev instead of inscribing it. There is no transaction and no BSV. A wallet is still required to create and update the plan. Re-uploading the same file writes a new hosted version. bitplan inscribe <h_id|file> puts the latest hosted version on the chain; --all-versions replays the whole history. After inscribe, the hosted viewer URL redirects to the chain origin.

npx bitplan upload ./plan.html --hosted
npx bitplan inscribe h_xxxxxxxxxxxxxxxxxxxx
npx bitplan fetch h_xxxxxxxxxxxxxxxxxxxx
npx bitplan fetch https://bitplan.dev/d/h_xxxxxxxxxxxxxxxxxxxx

bitplan list includes hosted drafts marked (hosted, not on chain). Pass --site-url on upload, inscribe, and fetch to point at a different bitplan.dev origin.

The hosted ID is a random locator, not a decryption key. bitplan.dev stores the ciphertext and public envelope header. The separate write secret stays in the CLI's local state; the server stores only its hash.

The CLI stores optional config and file-to-origin mappings in ~/.bitplan.

Pass --wallet-url to point at a different BRC-100 endpoint; upload and fetch also accept --ordfs-url.

Every publish prints the draft's origin, its version, and a viewer URL:

Origin:   <txid>_0
Outpoint: <txid>_0
Version:  1
Viewer:   https://bitplan.dev/d/<txid>_0

Before an on-chain confirmation, the CLI reads Arcade's public /policy and shows a payload-only cost at the current network floor. It uses the estimated encrypted payload size for uploads and the sum of independently rounded payload costs for multi-version inscribes. This is not a wallet quote: it excludes transaction overhead and wallet rate or ancestor differences. If the policy cannot be read, the floor is shown as unavailable and publishing still continues. Hosted uploads and quiet --json output do not request the policy.

Flags

bitplan upload <file>
  --draft <origin>         Update a specific draft
  --new                    Always create a new draft
  --hosted                 Store the encrypted draft on bitplan.dev instead of the chain
  --site-url <url>         bitplan.dev origin for hosted drafts
  --description <text>     Set a short description
  --share-with <reader>    Add a key, contact, or team (repeatable)
  --private                Make the new version wallet-only
  --link                   Add a reader link anyone can open
  --no-relay               Skip the default 1Sat notification for ORDFS capture
  -y, --yes                Skip the confirmation prompt
  --json                   Print one JSON result (requires --yes)
  --allow-finding <id>     Waive one secret-scanner finding (repeatable)

bitplan inscribe <h_id|file>
  --all-versions           Inscribe every hosted version, not only the latest
  --site-url <url>
  -y, --yes
  --json

bitplan list
  --json
  -v, --verbose            One detailed block per draft
  --limit <n>

bitplan fetch <origin|url>
  --meta
  --json                   Print the HTML and metadata as JSON
  --version <n>
  --site-url <url>

bitplan config
  --share-with <reader>    Default key, contact, or team (repeatable)
  --clear-share-with       Clear default readers

bitplan contact set <name> <identity-key>
bitplan contact remove <name>
bitplan contact list [--json]

bitplan team set <name> <contacts...>
bitplan team add <name> <contacts...>
bitplan team remove <name> <contacts...>
bitplan team delete <name>
bitplan team list [name] [--json]

bitplan version

In a non-interactive shell, upload requires --yes; otherwise it stops before encryption or publishing rather than assuming consent.

Reader links

bitplan upload plan.html --link adds a reader anyone can use: a throwaway secp256k1 key whose public half is an ordinary reader slot and whose private half travels in the viewer URL fragment. Later versions keep the same link until you publish with --private. bitplan fetch can open that URL without a wallet. Anyone with the complete link can read, so treat it like a password. When adopting a draft without its local record, --link adds a new link but cannot distinguish an earlier link slot from another wallet reader; inherited readers remain authorized. Publish a wallet-only version with --private before adding a replacement link when every previous reader must be removed.

npx bitplan upload ./plan.html --link
npx bitplan fetch 'https://bitplan.dev/d/<origin>#k=...'

How it works

  • Encryption. Each draft is the bitplan envelope: the SDK's SymmetricKey encrypts the document once, then BRC-2-wraps that 32-byte key for the publisher and each invited reader. A plan with no invited readers has one slot, the publisher's. The CLI never handles identity private keys or implements its own cipher. See ENVELOPE.md for the byte layout.
  • Versioning. The first publish inscribes a 1-satoshi output. Later publishes spend that satoshi back to you carrying a new envelope. Only the wallet holding the coin can publish the next one.
  • Propagation. By default, the CLI sends the wallet-returned Atomic BEEF to 1Sat. 1Sat attempts to store it for ORDFS and forwards the leaf transaction to Arcade. The wallet remains the publisher. Pass --no-relay to opt out.
  • Batch plumbing (internal). publishBatch can create or update several ordinal outputs in one wallet action. It returns a separate origin/outpoint receipt for every item and preserves the existing encryption envelope. Existing-ordinal items must precede new inscriptions to preserve satoshi ordering. upload and inscribe still expose their existing single-document workflows; a combined document/annotation publish UI is not shipped yet.
  • Metadata. The cleartext MAP on chain is three fields: { app: "bitplan", type: "plan", enc: "1" }. Titles, descriptions and git provenance live inside the ciphertext.

Before it publishes

bitplan upload refuses to spend until the document passes two gates.

HTML policy (ported from postplan, MIT): no <form>, <iframe>, <object>, <embed>, <applet>, <base> or <link>; no external script sources; no inline event handlers; no srcdoc; no javascript: / vbscript: / file: URLs; no meta refresh; 5 MB cap.

Secret scanner: private key blocks, cloud and SaaS token shapes, JWTs, database URLs carrying credentials, long secrets behind key= / token= / secret=, and absolute home paths. Findings block the upload. Waive one at a time with the id the scanner prints:

npx bitplan upload plan.html --allow-finding home-path-macos-3f2a91c40b7d

The scan runs on the plaintext even though the output is encrypted.

State

~/.bitplan/ (directory 0700, files 0600):

  • config.json: optional wallet/ORDFS overrides, default readers, contacts, and teams. Contacts contain public identity keys only.
  • drafts.json: which local file maps to which draft: origin, keyID, latest outpoint, latest version, and any local contact/team references used for its access list. It stores each active reader-link private key and, for hosted drafts, the write secret used to update them. Treat this file like a password store even though these capabilities cannot fund or sign transactions.

Neither file holds the connected wallet's identity, funding, or signing private keys. Losing drafts.json also loses this machine's saved reader-link secrets and hosted mutation capabilities. Chain origins and keyIDs remain recoverable from public data, but a hosted draft cannot be updated from this machine without its write secret.

License

MIT. Bundled dependency notices are in THIRD_PARTY_NOTICES.md.