Skip to content

FelineStateMachine/nzip

Repository files navigation

nzip

Push a directory of HTML from the terminal. Get a four-character URL back.

Deno CLI → Cloudflare Worker → R2 + D1. Free-tier-oriented static site hosting with optional expiration, password protection, owner notifications, and enumeration alerts.

JSR

github.com/FelineStateMachine/nzip · args.io/cat/nzip

$ nzip site push ./demo work:demo --ttl 30d
  bundling ./demo … 3 files, 197 B
  manifest 4a91d75d — 3 new blobs (197 B), 0 deduped
✓ pushed work:demo -> https://12d8.demo.dev/  (expires in 30d, push #1)

Install

The CLI ships on JSR. With Deno on your PATH:

deno install -g -A -f -n nzip jsr:@nzip/cli
nzip --version
nzip auth --server https://share.demo.dev
nzip site push ./site work:demo

nzip auth prompts for omitted values and saves configuration to ~/.config/nzip/config.json with mode 0600. nzip --version reports the installed JSR release without requiring authentication; add --json for machine-readable output. Try the CLI without installing it with deno run -A jsr:@nzip/cli --help.

On another machine, install the CLI and authenticate with the same server and token. Hosted vaults and sites are already available; only the nzip site where breadcrumb registry is machine-local.

How addresses work

Every share lives at four hex characters. The first digit selects one of 16 registered vaults, and the remaining three select one of 4,096 randomly allocated sites within that vault.

https://2a3f.demo.dev/
        |+- site 0xa3f
        +-- vault 0x2 ("work")

Aliases such as work:demo are resolved by the authenticated API; public URLs do not expose them. The control-plane shorthand https://share.demo.dev/2a3f permanently redirects to the canonical site hostname. Each site hostname is a separate browser origin, so its storage, service workers, and host-only cookies are isolated from other nzip sites. The default passkey relying-party ID is also the site hostname; see the parent-domain caveat in SECURITY.md.

form example meaning
address 2a3f direct hexadecimal address
vault alias work:demo alias within a named vault
bare alias demo alias in the default vault

Features

  • Instant and content-addressed. Push one canonical manifest and only the blobs the server does not already have. Identical files are stored once across every site.
  • Ephemeral by default. Shares expire after 14 days unless --ttl selects another finite duration or forever.
  • Revertible. The last ten pushes per site are retained and available through nzip site revert.
  • Password-protectable. Password policy is committed atomically with content. Signed, host-only per-site cookies are invalidated when the policy changes.
  • Recoverable. nzip site cp reconstructs and verifies the currently hosted bundle.
  • Owner notifications. Explicitly approved phones receive Web Push notifications with bounded, same-origin click targets.
  • Machine-local breadcrumbs. nzip site where locates the source directory recorded during a push.
  • Vault guardrails. Optional allowVaults configuration refuses disallowed vaults and raw addresses before upload.
  • Observable abuse controls. Enumeration is rate-limited and evaluated through bounded, privacy-preserving telemetry.

Commands

nzip
├─ --version [--json]                     show the installed CLI version
├─ auth [--server URL] [--token T]       authenticate and save config
├─ status                                show server and vault status
├─ vault
│  ├─ add <name> [--slot N] [--description TEXT]
│  ├─ update <name> [--name NEW_NAME] [--description TEXT | --no-description]
│  ├─ ls                                 list vaults
│  └─ default <name>                     set the default vault
├─ site
│  ├─ push <dir|file> [target] [--ttl …] [--password PW | --no-password]
│  ├─ cp <target> [dir] [--overwrite]    copy a hosted bundle
│  ├─ show <target>                      show site details
│  ├─ update <target> [--ttl …] [--password PW | --no-password]
│  ├─ ls [vault]                         list sites
│  ├─ where <target>                     print this machine's source directory
│  ├─ rm <target> [--yes]                delete a site
│  └─ revert <target> [--to N] [--list]  inspect or restore push history
└─ notify
   ├─ send <body> [--title TEXT] [--open TARGET] [--tag TEXT]
   ├─ test                               send a diagnostic notification
   ├─ pair                               allow device pairing for 10 minutes
   ├─ approve <code> --name NAME [--yes]
   ├─ devices [--all]                    list notification devices
   └─ revoke <device-id> [--yes]         revoke a notification device

Password and TTL values are committed with content. On an existing site, omitted settings preserve their current values; --no-password clears protection explicitly. Directory pushes skip dotfiles and node_modules and honor a .nzipignore file containing one glob per line.

See cli/README.md for detailed CLI behavior and examples.

Owner notifications

Pairing is closed by default. Open a 10-minute window, then tap the temporary pair action on the deployment root and approve the displayed code:

nzip notify pair
nzip notify approve ABCD-1234 --name "Personal phone"

Wait for paired before installing the PWA. In the installed app, tap notifications off to request permission and attach the subscription. Send a notification with:

nzip notify send "Build finished" --open work:report

Notification content may be visible on a lock screen. Never include passwords, tokens, private URLs, or sensitive personal information. See SECURITY.md for the enrollment and delivery trust boundaries.

Self-hosting

nzip is self-hosted; there is no bundled public service. The Worker uses an exact control hostname, a wildcard site route, R2, D1, rate-limit bindings, and optional Email Routing and Web Push configuration.

Follow worker/setup.md for provisioning, migrations, secrets, notification setup, deployment, and operational checks. The system is designed for small personal deployments on Cloudflare's included usage; see the architecture budget notes before exposing a busy or multi-tenant instance.

Project documentation

  • ARCHITECTURE.md — components, push protocol, caching, storage, background work, observability, and resource budgets.
  • SECURITY.md — trust boundaries, pairing security, enumeration controls, reporting, and monitoring.
  • CONTRIBUTING.md — development setup, checks, local Worker workflow, documentation conventions, and releases.
  • worker/setup.md — production Cloudflare deployment and upgrades.
  • cli/README.md — CLI installation and command reference.
  • shared/README.md — shared package contract and usage.

MIT licensed.

About

Push a directory of HTML from the terminal, get a four-character URL back. Deno CLI + Cloudflare Worker (R2 + D1). cli and shared are published to JSR.

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Contributors