Monorepo for wisp.place. A static site hosting service built on top of the AT Protocol.
wisp.place
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>Wisp CLI - Download</title>
7 <link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism.min.css" rel="stylesheet" />
8 <link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-tomorrow.min.css" rel="stylesheet" media="(prefers-color-scheme: dark)" />
9 <style>
10 :root {
11 /* Light theme */
12 --demo-bg: #eeeeee;
13 --demo-text: #1a1a1a;
14 --demo-text-secondary: #666;
15 --demo-border: #ddd;
16 --demo-input-bg: #fff;
17 --demo-button-bg: #0066cc;
18 --demo-button-text: #fff;
19 --demo-code-bg: #f5f5f5;
20 --demo-code-border: #e0e0e0;
21 --demo-hr: #e0e0e0;
22 }
23
24 /* Dark theme */
25 @media (prefers-color-scheme: dark) {
26 :root {
27 --demo-bg: #1a1a1a;
28 --demo-text: #e0e0e0;
29 --demo-text-secondary: #999;
30 --demo-border: #444;
31 --demo-input-bg: #2a2a2a;
32 --demo-button-bg: #0066cc;
33 --demo-button-text: #fff;
34 --demo-code-bg: #2a2a2a;
35 --demo-code-border: #444;
36 --demo-hr: #444;
37 }
38 }
39
40 * {
41 margin: 0;
42 padding: 0;
43 box-sizing: border-box;
44 }
45
46 body {
47 margin: 0;
48 padding: 0;
49 background: var(--demo-bg);
50 color: var(--demo-text);
51 transition: background-color 200ms ease, color 200ms ease;
52 font-family: system-ui, sans-serif;
53 line-height: 1.6;
54 display: flex;
55 flex-direction: column;
56 min-height: 100vh;
57 }
58
59 .container {
60 max-width: 860px;
61 margin: 40px auto;
62 padding: 0 20px;
63 flex: 1;
64 display: flex;
65 flex-direction: column;
66 width: 100%;
67 }
68
69 h1 {
70 margin-top: 0;
71 color: var(--demo-text);
72 font-size: 2.5rem;
73 margin-bottom: 0.5rem;
74 }
75
76 .subtitle {
77 color: var(--demo-text-secondary);
78 font-size: 1.1rem;
79 margin-bottom: 2rem;
80 line-height: 1.4;
81 }
82
83 .description {
84 margin-bottom: 2rem;
85 line-height: 1.6;
86 color: var(--demo-text);
87 }
88
89 hr {
90 margin: 32px 0;
91 border: none;
92 border-top: 1px solid var(--demo-hr);
93 }
94
95 h2 {
96 color: var(--demo-text);
97 margin-bottom: 1rem;
98 margin-top: 2rem;
99 font-size: 1.5rem;
100 }
101
102 h3 {
103 color: var(--demo-text);
104 margin-bottom: 0.75rem;
105 margin-top: 1.5rem;
106 font-size: 1.2rem;
107 }
108
109 .downloads {
110 background: var(--demo-code-bg);
111 border: 1px solid var(--demo-code-border);
112 border-radius: 8px;
113 padding: 2rem;
114 margin-bottom: 2rem;
115 }
116
117 .downloads h2 {
118 margin-top: 0;
119 }
120
121 .download-link {
122 display: block;
123 background: var(--demo-button-bg);
124 color: var(--demo-button-text);
125 text-decoration: none;
126 padding: 12px 16px;
127 border-radius: 8px;
128 margin-bottom: 8px;
129 transition: opacity 0.2s;
130 font-family: 'Monaco', 'Menlo', 'Courier New', monospace;
131 font-size: 0.9rem;
132 }
133
134 .download-link:hover {
135 opacity: 0.85;
136 }
137
138 .platform {
139 font-weight: bold;
140 margin-right: 0.5rem;
141 }
142
143 .cicd-section {
144 margin-top: 2rem;
145 }
146
147 .cicd-section h2 {
148 margin-top: 0;
149 }
150
151 .cicd-section > p {
152 color: var(--demo-text-secondary);
153 margin-bottom: 1rem;
154 }
155
156 pre {
157 background: var(--demo-code-bg) !important;
158 border: 1px solid var(--demo-code-border);
159 padding: 1.5rem !important;
160 border-radius: 8px;
161 overflow-x: auto;
162 font-size: 0.85rem;
163 line-height: 1.5;
164 margin: 1rem 0;
165 }
166
167 pre code {
168 color: var(--demo-text);
169 background: none !important;
170 padding: 0 !important;
171 text-shadow: none !important;
172 }
173
174 code {
175 font-family: 'Monaco', 'Menlo', 'Courier New', monospace;
176 }
177
178 .note {
179 background: var(--demo-code-bg);
180 border-left: 4px solid var(--demo-button-bg);
181 border: 1px solid var(--demo-code-border);
182 border-left: 4px solid var(--demo-button-bg);
183 padding: 1rem;
184 margin-top: 1rem;
185 border-radius: 4px;
186 }
187
188 .note strong {
189 color: var(--demo-text);
190 }
191
192 .note code {
193 background: var(--demo-input-bg);
194 padding: 2px 6px;
195 border-radius: 4px;
196 border: 1px solid var(--demo-border);
197 }
198
199 a {
200 color: var(--demo-button-bg);
201 text-decoration: none;
202 }
203
204 a:hover {
205 text-decoration: underline;
206 }
207
208 .features {
209 margin: 2rem 0;
210 }
211
212 .features ul {
213 list-style: none;
214 padding-left: 0;
215 }
216
217 .features li {
218 padding: 0.5rem 0;
219 padding-left: 1.5rem;
220 position: relative;
221 line-height: 1.6;
222 }
223
224 .features li:before {
225 content: "✓";
226 position: absolute;
227 left: 0;
228 color: var(--demo-button-bg);
229 font-weight: bold;
230 }
231
232 .footer {
233 margin-top: auto;
234 padding-top: 2rem;
235 padding-bottom: 2rem;
236 border-top: 1px solid var(--demo-hr);
237 text-align: center;
238 color: var(--demo-text-secondary);
239 }
240 </style>
241</head>
242<body>
243 <div class="container">
244 <h1>Wisp CLI <span style="font-size: 1.5rem; color: var(--demo-text-secondary);">v0.4.1</span></h1>
245 <p class="subtitle">Deploy static sites to the AT Protocol</p>
246
247 <div class="description">
248 <p>
249 The Wisp CLI is a command-line tool for deploying static websites directly to your AT Protocol account.
250 Host your sites on <a href="https://wisp.place" target="_blank">wisp.place</a> with full ownership and control,
251 backed by the decentralized AT Protocol.
252 </p>
253 </div>
254
255 <div class="features">
256 <h2>Features</h2>
257 <ul>
258 <li><strong>Deploy:</strong> Push static sites directly from your terminal</li>
259 <li><strong>Pull:</strong> Download sites from the PDS for development or backup</li>
260 <li><strong>Serve:</strong> Run a local server with real-time firehose updates</li>
261 <li>Authenticate with app password or OAuth</li>
262 </ul>
263 </div>
264
265 <div class="downloads">
266 <h2>Download v0.4.1</h2>
267 <a href="https://sites.wisp.place/nekomimi.pet/wisp-cli-binaries/wisp-cli-aarch64-darwin" class="download-link" download>
268 <span class="platform">macOS (Apple Silicon):</span> wisp-cli-aarch64-darwin
269 </a>
270 <a href="https://sites.wisp.place/nekomimi.pet/wisp-cli-binaries/wisp-cli-aarch64-linux" class="download-link" download>
271 <span class="platform">Linux (ARM64):</span> wisp-cli-aarch64-linux
272 </a>
273 <a href="https://sites.wisp.place/nekomimi.pet/wisp-cli-binaries/wisp-cli-x86_64-linux" class="download-link" download>
274 <span class="platform">Linux (x86_64):</span> wisp-cli-x86_64-linux
275 </a>
276 <a href="https://sites.wisp.place/nekomimi.pet/wisp-cli-binaries/wisp-cli-x86_64-windows.exe" class="download-link" download>
277 <span class="platform">Windows (x86_64):</span> wisp-cli-x86_64-windows.exe
278 </a>
279
280 <h3 style="margin-top: 1.5rem; margin-bottom: 0.5rem;">SHA-1 Checksums</h3>
281 <pre style="font-size: 0.75rem; padding: 1rem;"><code class="language-bash">69de880e160a2f26e3c26b7c28030457913754dc wisp-cli-aarch64-darwin
282026189f2c10077a2be4705102e169e66cb207f84 wisp-cli-aarch64-linux
2834777cff07558906717402484a3313359880eae96 wisp-cli-x86_64-linux
284d6bc789d7fd7c787e5520eb476cee70c97ccb3ce wisp-cli-x86_64-windows.exe</code></pre>
285 </div>
286
287 <div class="cicd-section">
288 <h2>CI/CD Integration</h2>
289 <p>Deploy automatically on every push using <a href="https://tangledspindle.org" target="_blank">Tangled Spindle</a>:</p>
290
291 <pre><code class="language-yaml">when:
292 - event: ['push']
293 branch: ['main']
294 - event: ['manual']
295
296engine: 'nixery'
297
298clone:
299 skip: false
300 depth: 1
301 submodules: false
302
303dependencies:
304 nixpkgs:
305 - nodejs
306 - coreutils
307 - curl
308 github:NixOS/nixpkgs/nixpkgs-unstable:
309 - bun
310
311environment:
312 SITE_PATH: 'dist'
313 SITE_NAME: 'my-site'
314 WISP_HANDLE: 'your-handle.bsky.social'
315
316steps:
317 - name: build site
318 command: |
319 export PATH="$HOME/.nix-profile/bin:$PATH"
320
321 # regenerate lockfile, https://github.com/npm/cli/pull/8184 makes rolldown not install
322 rm package-lock.json bun.lock
323 bun install @rolldown/binding-linux-arm64-gnu --save-optional
324 bun install
325
326 # run directly with bun because of shebang issues in nix
327 bun node_modules/.bin/vite build
328
329 - name: deploy to wisp
330 command: |
331 # Download Wisp CLI
332 curl https://sites.wisp.place/nekomimi.pet/wisp-cli-binaries/wisp-cli-x86_64-linux -o wisp-cli
333 chmod +x wisp-cli
334
335 # Deploy to Wisp
336 ./wisp-cli \
337 "$WISP_HANDLE" \
338 --path "$SITE_PATH" \
339 --site "$SITE_NAME" \
340 --password "$WISP_APP_PASSWORD"</code></pre>
341
342 <div class="note">
343 <strong>Note:</strong> Set <code>WISP_APP_PASSWORD</code> as a secret in your Tangled Spindle repository settings.
344 Generate an app password from your AT Protocol account settings.
345 </div>
346 </div>
347
348 <div class="cicd-section">
349 <h2>Basic Usage</h2>
350
351 <h3>Deploy a Site</h3>
352 <pre><code class="language-bash"># Download and make executable
353curl -O https://sites.wisp.place/nekomimi.pet/wisp-cli-binaries/wisp-cli-macos-arm64
354chmod +x wisp-cli-macos-arm64
355
356# Deploy your site
357./wisp-cli-macos-arm64 deploy your-handle.bsky.social \
358 --path ./dist \
359 --site my-site \
360
361# Your site will be available at:
362# https://sites.wisp.place/your-handle/my-site</code></pre>
363
364 <h3>Pull a Site from PDS</h3>
365 <p style="color: var(--demo-text-secondary); margin-bottom: 0.5rem;">Download a site from the PDS to your local machine (uses OAuth authentication):</p>
366 <pre><code class="language-bash"># Pull a site to a specific directory
367wisp-cli pull your-handle.bsky.social \
368 --site my-site \
369 --output ./my-site
370
371# Pull to current directory
372wisp-cli pull your-handle.bsky.social \
373 --site my-site
374</code></pre>
375 <h3>Serve a Site Locally with Real-Time Updates</h3>
376 <p style="color: var(--demo-text-secondary); margin-bottom: 0.5rem;">Run a local server that monitors the firehose for real-time updates (uses OAuth authentication):</p>
377 <pre><code class="language-bash"># Serve on http://localhost:8080 (default)
378wisp-cli serve your-handle.bsky.social \
379 --site my-site
380
381# Serve on a custom port
382wisp-cli serve your-handle.bsky.social \
383 --site my-site \
384 --port 3000
385
386# Downloads site, serves it, and watches firehose for live updates!
387
388# Enable SPA mode (serve index.html for all routes)
389wisp-cli serve your-handle.bsky.social \
390 --site my-site \
391 --spa
392
393# Enable directory listing for paths without index files
394wisp-cli serve your-handle.bsky.social \
395 --site my-site \
396 --directory</code></pre>
397 </div>
398
399 <div class="footer">
400 <p>Learn more at <a href="https://wisp.place">wisp.place</a></p>
401 </div>
402 </div>
403 <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-core.min.js"></script>
404 <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>
405 <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-bash.min.js"></script>
406 <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-yaml.min.js"></script>
407</body>
408</html>