binthere
v0.1.0
Published
CLI for binthere — a zero-knowledge, end-to-end encrypted pastebin. Encrypts locally with AES-256-GCM; the key rides in the URL fragment and never reaches the server.
Downloads
56
Maintainers
Readme
binthere (CLI)
Command-line client for binthere — a zero-knowledge,
end-to-end encrypted pastebin. Content is encrypted locally with AES-256-GCM before any
network request; the decryption key travels in the URL #fragment and is never sent to the
server. The CLI implements the same frozen protocol as the web client
(SPEC.md), verified against the same
pinned test vectors.
Zero runtime dependencies — Node ≥ 20 built-ins only (WebCrypto, CompressionStream,
fetch, node:util parseArgs).
Install
npm install -g binthere
# or run without installing:
npx binthere --helpEvery note has the same lifecycle as the website: it deletes after one read, or after 24 hours — whichever comes first. There is nothing to configure.
Usage
Interactive: just type binthere
On a terminal, a bare binthere opens a full-screen menu — the wordmark materialises in
glyph by glyph, then pick an action with the arrow keys (or 1–3) and confirm with Enter:
binthere
✦
██▄ █ █▄ █ ▀█▀ █▄█ ██▀ █▀▄ ██▀
█▄█ █ █ ▀█ █ █ █ █▄▄ █▀▄ █▄▄
Zero-knowledge encrypted notes.
encrypted locally · one read · gone in 24 hours
server https://binthere.gaury.dev
╭───────────────────────────────────────────────────────────╮
│ ❯ 1 Create a note write, seal, and get a one-time link │
│ 2 View a note paste a share URL — reading burns it │
│ 3 Delete a note remove it early with the delete token │
╰───────────────────────────────────────────────────────────╯
↑↓ move · ↵ select · 1-3 jump · ^c quit- Create — write (or paste) your note on its own screen, press Ctrl+Q to seal it,
optionally add a password, and get the share link, a scannable terminal QR code, and
the delete token on a result screen (the typed note is cleared from view; a shine beam
sweeps the wordmark now and then while you decide). Press c
there to copy the link to the clipboard, t for the delete token — via the platform's
native tool (
clip/pbcopy/wl-copy/xclip/xsel, fed over stdin so secrets never hit argv), with an OSC 52 escape fallback that works over SSH. - View — paste a share URL; the note is decrypted locally after the usual destructive-read confirmation (a wrong password never burns it).
- Delete — paste the share URL or id and the delete token from create time.
All decoration is drawn on stderr; only machine-readable output (the share URL on create,
the plaintext on view) goes to stdout, so binthere | pbcopy (macOS) or binthere | clip
(Windows) still copies just the link. Colors follow the website's palette, degrade to
16-color terminals, and switch off entirely under NO_COLOR or when stderr is not a TTY.
Scripting
# Encrypt stdin, print the share URL
git diff | binthere create
# When stdin is piped — or --text is given — "create" is the default command
cat notes.md | binthere
binthere -t "meet at 6"
# From a file, password-protected, machine-readable output
binthere create --file secrets.txt --password --json
# Fetch and decrypt ("view" is an alias for "get"; -y skips the burn confirmation)
binthere get 'https://binthere.gaury.dev/p/<id>#<key>'
binthere view 'https://binthere.gaury.dev/p/<id>#<key>' -y
# Delete with the token printed at create time
BT_TOKEN=... binthere delete <share-url-or-id> --token-env BT_TOKENbinthere create [flags]
Reads content from stdin (or --text / --file), encrypts it locally, uploads only
ciphertext, and prints the share URL on stdout — the delete token and lifecycle note go
to stderr, so binthere create | pbcopy copies just the link.
| Flag | Meaning |
| --- | --- |
| -t, --text <string> | Use the given string as the note content |
| -f, --file <path> | Read content from a file instead of stdin |
| --fmt <fmt> | plaintext (default), code, markdown (affects web rendering) |
| --password | Prompt for a password (hidden; never a flag value) |
| --password-env <VAR> | Read the password from an environment variable (for scripts) |
| -q, --qr | Also print a scannable QR code (to stderr) |
| -j, --json | Print {url, id, deletetoken, expire, burn} as JSON |
binthere get <share-url | -> (alias: view)
Fetches and decrypts a note; plaintext goes to stdout (or --out <path>). Pass - to read
the share URL from stdin.
Reading uses the same safe flow as the browser: a non-consuming metadata peek verifies the
password before the single destructive read, so a wrong password never burns the note.
The destructive read asks for confirmation on a TTY (--yes skips it).
| Flag | Meaning |
| --- | --- |
| -o, --out <path> | Write plaintext to a file instead of stdout |
| -y, --yes | Skip the burn-after-read confirmation |
| --password-env <VAR> | Read the password from an environment variable |
binthere delete <share-url | id>
Deletes a paste using its delete token (prompted, or --token-env <VAR>). The token is sent
only in the X-Delete-Token header, never in a URL.
Global
| Flag / env | Meaning |
| --- | --- |
| -s, --server <url> | API origin for create/delete (default $BINTHERE_SERVER, then https://binthere.gaury.dev); get takes it from the share URL |
| --help, --version | The usual |
HTTPS is enforced for every server except localhost / 127.0.0.1 (for wrangler dev).
Exit codes: 0 ok · 1 crypto/API error · 2 usage error. Distinct messages
distinguish "not found / expired" (404) from "already burned" (410).
Security notes
- The share URL is the secret. Anyone with the full URL (and the password, if set) can
read the paste. Command-line arguments are visible to other local processes and may land
in shell history — on shared machines prefer
echo '<url>' | binthere get -so the URL never appears in argv. --textputs the note itself in argv (shell history, process listings). It's for quick throwaway notes — pipe stdin or use--filefor anything sensitive.- Passwords and delete tokens are never accepted as plain flag values — only via a
hidden interactive prompt or
--password-env/--token-env, so they cannot leak into shell history or process listings. - The fragment key never leaves the process except inside the printed share URL; it is never sent to the server in any request.
- The zero-knowledge boundary and its limits (metadata, deployment compromise) are
documented in the project's
SECURITY.md.
How it relates to the repo
This package lives in the cli/
subdirectory of the binthere repo. The modules in vendor/ are byte-identical copies of the
repo's shared public/js/{bytes,format,crypto,qrcode}.js (the crypto files are the single
source of truth for protocol v1; qrcode.js is vendored as qrcode.cjs for Node's CommonJS
loader); a CI test fails on any drift, and node scripts/sync-shared.mjs re-aligns them.
Publishing is monorepo-only: npm publish runs a prepack gate (vendor-drift check +
test suite) that reads the repo's public/js/ and the root install's vitest, so it must run
from a full clone of the repo — never from a standalone copy of this directory. Releases are
normally cut by CI from a cli-v* tag; see the repo's CONTRIBUTING.md "Releasing".
License
MIT © 2026 nxfu
