Skip to content

Wisp CLI 0.5.0 (alpha)

Deploy static sites to the AT Protocol

The Wisp CLI is a command-line tool for deploying static websites directly to your AT Protocol account. Host your sites on wisp.place with full ownership and control, backed by the decentralized AT Protocol.

  • Deploy: Push static sites directly from your terminal
  • Pull: Download sites from the PDS for development or backup
  • Serve: Run a local server with real-time firehose updates
  • Authenticate with app password or OAuth
  • Incremental updates: Only upload changed files

Download v0.5.0

macOS (Universal): wisp-cli-darwin-universal

macOS (Apple Silicon): wisp-cli-aarch64-darwin

macOS (Intel): wisp-cli-darwin-x86_64

Linux (ARM64): wisp-cli-aarch64-linux

Linux (x86_64): wisp-cli-x86_64-linux

Windows (x86_64): wisp-cli-x86_64-windows.exe

SHA-1 Checksums


7d0cc968d2a130158c3b204d9a15bcc29b8af252  wisp-cli-darwin-universal

912f8f99c2b55ca6ad75e0a89903688bd2c1cb4b  wisp-cli-aarch64-darwin

40d26d4a9c058e42e7911a195c3e078e8a4b5e82  wisp-cli-darwin-x86_64

ef1992d8850f8fef1d719e4e8fab5431475c352e  wisp-cli-aarch64-linux

3018dde8fec495abcae044079564ced93cdeb4f8  wisp-cli-x86_64-linux

d6bc789d7fd7c787e5520eb476cee70c97ccb3ce  wisp-cli-x86_64-windows.exe

Deploy automatically on every push using Tangled Spindle:

when:
- event: ['push']
branch: ['main']
- event: ['manual']
engine: 'nixery'
dependencies:
nixpkgs:
- nodejs
- coreutils
- curl
github:NixOS/nixpkgs/nixpkgs-unstable:
- bun
environment:
SITE_PATH: 'dist'
SITE_NAME: 'my-site'
WISP_HANDLE: 'your-handle.bsky.social'
steps:
- name: build site
command: |
export PATH="$HOME/.nix-profile/bin:$PATH"
# you may need to regenerate the lockfile due to nixery being weird
# rm package-lock.json bun.lock
bun install
bun run build
- name: deploy to wisp
command: |
# Download Wisp CLI
curl https://sites.wisp.place/nekomimi.pet/wisp-cli-binaries/wisp-cli-x86_64-linux -o wisp-cli
chmod +x wisp-cli
# Deploy to Wisp
./wisp-cli \
"$WISP_HANDLE" \
--path "$SITE_PATH" \
--site "$SITE_NAME" \
--password "$WISP_APP_PASSWORD"

Note: Set WISP_APP_PASSWORD as a secret in your Tangled Spindle repository settings. Generate an app password from your AT Protocol account settings.

Terminal window
# Download and make executable
curl -O https://sites.wisp.place/nekomimi.pet/wisp-cli-binaries/wisp-cli-aarch64-darwin
chmod +x wisp-cli-aarch64-darwin
# Deploy your site
./wisp-cli-aarch64-darwin deploy your-handle.bsky.social \
--path ./dist \
--site my-site

Your site will be available at: https://sites.wisp.place/your-handle/my-site

Download a site from the PDS to your local machine:

Terminal window
# Pull a site to a specific directory
wisp-cli pull your-handle.bsky.social \
--site my-site \
--path ./my-site
# Pull to current directory
wisp-cli pull your-handle.bsky.social \
--site my-site

Serve a Site Locally with Real-Time Updates

Section titled “Serve a Site Locally with Real-Time Updates”

Run a local server that monitors the firehose for real-time updates:

Terminal window
# Serve on http://localhost:8080 (default)
wisp-cli serve your-handle.bsky.social \
--site my-site
# Serve on a custom port
wisp-cli serve your-handle.bsky.social \
--site my-site \
--port 3000
# Enable SPA mode (serve index.html for all routes)
wisp-cli serve your-handle.bsky.social \
--site my-site \
--spa
# Enable directory listing for paths without index files
wisp-cli serve your-handle.bsky.social \
--site my-site \
--directory

Downloads site, serves it, and watches firehose for live updates!

The CLI uses OAuth by default, opening your browser for secure authentication:

Terminal window
wisp-cli deploy your-handle.bsky.social --path ./dist --site my-site

This creates a session stored locally (default: /tmp/wisp-oauth-session.json).

For headless environments or CI/CD, use an app password:

Terminal window
wisp-cli deploy your-handle.bsky.social \
--path ./dist \
--site my-site \
--password YOUR_APP_PASSWORD

Generate app passwords from your AT Protocol account settings.

The CLI handles all file processing automatically to ensure reliable storage and delivery. Files are compressed with gzip at level 9 for optimal size reduction, then base64 encoded to bypass PDS content sniffing restrictions. Everything is uploaded as application/octet-stream blobs while preserving the original MIME type as metadata. When serving your site, the hosting service automatically decompresses non-HTML/CSS/JS files, ensuring your content is delivered correctly to visitors.

File Filtering: The CLI automatically excludes common files like .git, node_modules, .env, and other development artifacts. Customize this with a .wispignore file.

The CLI tracks file changes using CID-based content addressing to minimize upload times and bandwidth usage. On your first deploy, all files are uploaded to establish the initial site. For subsequent deploys, the CLI compares content-addressed CIDs to detect which files have actually changed, uploading only those that differ from the previous version. This makes fast iterations possible even for large sites, with deploys completing in seconds when only a few files have changed.

  • Max file size: 100MB per file (after compression)
  • Max total size: 300MB per site
  • Max files: 1000 files per site
  • Site name: Must follow AT Protocol rkey format (alphanumeric, hyphens, underscores)
Terminal window
wisp-cli deploy [OPTIONS] <INPUT>
Arguments:
<INPUT> Handle (e.g., alice.bsky.social), DID, or PDS URL
Options:
-p, --path <PATH> Path to site directory [default: .]
-s, --site <SITE> Site name (defaults to directory name)
--store <STORE> OAuth session file path [default: /tmp/wisp-oauth-session.json]
--password <PASSWORD> App password for authentication
-h, --help Print help
Terminal window
wisp-cli pull [OPTIONS] --site <SITE> <INPUT>
Arguments:
<INPUT> Handle or DID
Options:
-s, --site <SITE> Site name to download
-p, --path <PATH> Output directory [default: .]
-h, --help Print help
Terminal window
wisp-cli serve [OPTIONS] --site <SITE> <INPUT>
Arguments:
<INPUT> Handle or DID
Options:
-s, --site <SITE> Site name to serve
-p, --path <PATH> Site files directory [default: .]
-P, --port <PORT> Port to serve on [default: 8080]
--spa Enable SPA mode (serve index.html for all routes)
--directory Enable directory listing mode for paths without index files
-h, --help Print help

The CLI is written in Rust using the Jacquard AT Protocol library. To build from source:

Terminal window
git clone https://tangled.org/@nekomimi.pet/wisp.place-monorepo
cd cli
cargo build --release

Built binaries are available in target/release/.