shiply-cli 0.12.1 → 0.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/db.js +29 -5
- package/dist/functions.js +342 -0
- package/dist/index.js +118 -7
- package/dist/listings.js +169 -0
- package/dist/projects.js +171 -0
- package/dist/sending-domains.js +159 -0
- package/dist/skill.js +5 -1
- package/dist/status-cmd.js +117 -0
- package/package.json +1 -1
- package/skill/SKILL.md +188 -2
package/skill/SKILL.md
CHANGED
|
@@ -3,6 +3,18 @@ name: shiply
|
|
|
3
3
|
description: Publish static sites to the web instantly with shiply.now and manage them (updates, SSL checks, custom domains, variables). Use when the user asks to publish, host, deploy, share, or update a website/page/demo/report, or wants a live URL for generated files. Triggers - "publish this", "host this", "put this online", "give me a link", "update the site", shiply.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
> **Skill freshness check.** Shiply ships new capabilities weekly. If this
|
|
9
|
+
> file's "Last updated" below is more than 7 days old, re-install it with
|
|
10
|
+
> `npx -y shiply-cli@latest skill --force` OR fetch `https://shiply.now/skill.md`
|
|
11
|
+
> fresh — your cached copy may be missing features like databases, projects,
|
|
12
|
+
> marketplace, or sending domains.
|
|
13
|
+
>
|
|
14
|
+
> **Last updated: 2026-06-20**
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
6
18
|
# shiply — instant web hosting for agents
|
|
7
19
|
|
|
8
20
|
shiply.now puts files on the web in seconds. No account needed to start:
|
|
@@ -251,7 +263,7 @@ rest and surfaced to the site's Worker as `env.DATABASE_URL`.
|
|
|
251
263
|
|
|
252
264
|
### D1 (default)
|
|
253
265
|
```bash
|
|
254
|
-
shiply db create app # provision a D1 (binding
|
|
266
|
+
shiply db create app # provision a D1 (binding SITE_DB)
|
|
255
267
|
shiply db ls # list (name, provider, size, attached site)
|
|
256
268
|
shiply db sql app "SELECT 1" # one-shot query against your account
|
|
257
269
|
shiply db sql app "SELECT * FROM t WHERE id=?1" --params '[42]'
|
|
@@ -265,7 +277,7 @@ Run `shiply db create` inside a publish directory: it records the new
|
|
|
265
277
|
it. Site code then calls the shim:
|
|
266
278
|
|
|
267
279
|
```js
|
|
268
|
-
fetch('/_shiply/db/
|
|
280
|
+
fetch('/_shiply/db/SITE_DB/query', {
|
|
269
281
|
method: 'POST',
|
|
270
282
|
headers: { 'content-type': 'application/json' },
|
|
271
283
|
body: JSON.stringify({ sql: 'SELECT * FROM posts', params: [] }),
|
|
@@ -330,6 +342,180 @@ providers; `db_schema` introspects `sqlite_master` (D1) or
|
|
|
330
342
|
`information_schema` (Neon). Full docs:
|
|
331
343
|
https://shiply.now/docs/databases
|
|
332
344
|
|
|
345
|
+
## Functions (Workers Lite) — webhooks, cron, secrets, full backend (Developer plan)
|
|
346
|
+
|
|
347
|
+
shiply Workers Lite lets a published site include server-side code that runs
|
|
348
|
+
on every request. Use when the user needs:
|
|
349
|
+
- A webhook receiver (Stripe, GitHub, etc.) with raw body + signature verification
|
|
350
|
+
- A cron job (daily reminders, periodic sync, retention emails)
|
|
351
|
+
- A privileged API call using secrets (Stripe key, OpenAI key) without exposing them to the browser
|
|
352
|
+
- An authenticated mutation on D1 / Neon (do the auth check in the function before writing)
|
|
353
|
+
|
|
354
|
+
### How it works
|
|
355
|
+
|
|
356
|
+
Author `worker.js` (or `worker.ts`) at the publish root. On `shiply publish`,
|
|
357
|
+
shiply compiles (TS) + deploys it as a per-site Cloudflare Worker bound to
|
|
358
|
+
the site's hostname. The worker handles every request; pass static asset
|
|
359
|
+
requests through `env.ASSETS.fetch(request)`.
|
|
360
|
+
|
|
361
|
+
```ts
|
|
362
|
+
import { verifyStripeSig, json } from 'shiply-runtime'
|
|
363
|
+
|
|
364
|
+
export default {
|
|
365
|
+
async fetch(req: Request, env: Env): Promise<Response> {
|
|
366
|
+
const url = new URL(req.url)
|
|
367
|
+
if (url.pathname === '/api/webhooks/stripe' && req.method === 'POST') {
|
|
368
|
+
const body = await req.text()
|
|
369
|
+
if (!await verifyStripeSig(body, req.headers.get('stripe-signature'), env.STRIPE_WEBHOOK_SECRET)) {
|
|
370
|
+
return new Response('bad sig', { status: 400 })
|
|
371
|
+
}
|
|
372
|
+
// ... handle event, write to env.SITE_DB
|
|
373
|
+
return new Response('ok')
|
|
374
|
+
}
|
|
375
|
+
return env.ASSETS.fetch(req)
|
|
376
|
+
},
|
|
377
|
+
async scheduled(event: ScheduledEvent, env: Env) {
|
|
378
|
+
if (event.cron === '0 9 * * *') { /* daily job */ }
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
`.shiply/crons.json` declares cron schedules. `.shiply/secrets.json` declares
|
|
384
|
+
secret names (values set via CLI/MCP, never reach the publish payload).
|
|
385
|
+
|
|
386
|
+
### Bindings available in `env`
|
|
387
|
+
|
|
388
|
+
- `env.ASSETS` — fall through to static (`env.ASSETS.fetch(request)`)
|
|
389
|
+
- `env.SITE_DB` — attached D1 (if `shiply db attach` was run)
|
|
390
|
+
- `env.<NAME>` — each shiply Variable becomes a plain-text env var
|
|
391
|
+
- `env.<NAME>` — each secret set via `set_secret` is encrypted, accessible as env var
|
|
392
|
+
|
|
393
|
+
### MCP tools
|
|
394
|
+
|
|
395
|
+
| Tool | Purpose |
|
|
396
|
+
|---|---|
|
|
397
|
+
| `deploy_function` | Deploy a Worker function (alternative to publish auto-detection) |
|
|
398
|
+
| `get_function` | Read the deployed source + metadata |
|
|
399
|
+
| `remove_function` | Strip function + secrets + crons; fall back to static |
|
|
400
|
+
| `set_secret` / `list_secrets` / `remove_secret` | Manage CF Worker secrets |
|
|
401
|
+
| `set_cron` / `list_crons` / `remove_cron` | Manage cron triggers |
|
|
402
|
+
| `get_function_logs` | Deep-link to CF dashboard for live tail |
|
|
403
|
+
|
|
404
|
+
### CLI
|
|
405
|
+
|
|
406
|
+
```bash
|
|
407
|
+
shiply publish . # auto-detects worker.js + crons.json + secrets.json
|
|
408
|
+
shiply function deploy <slug> # alternative: upload worker.js without re-publishing
|
|
409
|
+
shiply function deploy <slug> --ts # uploads worker.ts (server-side compile)
|
|
410
|
+
shiply secret set <slug> STRIPE_KEY sk_xxx # set secret value
|
|
411
|
+
shiply cron set <slug> /api/daily "0 9 * * *"
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
### REST
|
|
415
|
+
|
|
416
|
+
`POST/GET/DELETE /api/v1/sites/{slug}/function` · `POST/GET /api/v1/sites/{slug}/secrets` · `DELETE /api/v1/sites/{slug}/secrets/{name}` · `GET/POST/DELETE /api/v1/sites/{slug}/crons`
|
|
417
|
+
|
|
418
|
+
### Limits + plan
|
|
419
|
+
|
|
420
|
+
- 1 MB compiled script size, 30s CPU per request, V8 isolate runtime (no Node APIs)
|
|
421
|
+
- 50 secrets, 20 cron triggers per site
|
|
422
|
+
- Plan-gated to Developer: Founder/Hobby see `402 payment_required`. Upgrade: shiply.now/dashboard/plan
|
|
423
|
+
|
|
424
|
+
Docs: https://shiply.now/docs/functions
|
|
425
|
+
|
|
426
|
+
## Projects — customer intake + AI brief
|
|
427
|
+
|
|
428
|
+
When a dev needs to capture a real client brief, they spin up a **project**:
|
|
429
|
+
the dashboard (or `shiply project create`) mints a one-URL intake form to
|
|
430
|
+
share with the customer. The customer fills a 10-step wizard, attaches
|
|
431
|
+
files, hits submit. An AI brief generator (MiniMax-M2 with Anthropic
|
|
432
|
+
fallback) turns the answers into a structured brief the dev reviews and
|
|
433
|
+
edits inline. All files flow into a per-project drive folder.
|
|
434
|
+
|
|
435
|
+
MCP tools:
|
|
436
|
+
```
|
|
437
|
+
list_projects — your projects (filter status/q)
|
|
438
|
+
create_project — start a new intake; pass customerName/customerEmail to email them the link
|
|
439
|
+
get_project — full project + brief
|
|
440
|
+
update_brief — patch brief jsonb (after AI generation)
|
|
441
|
+
regenerate_brief — re-run AI from current intake responses
|
|
442
|
+
archive_project / restore_project — lifecycle
|
|
443
|
+
list_project_files — files uploaded by the customer
|
|
444
|
+
resend_intake_invite — re-email the customer their intake link (requires customerEmail on project)
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
REST: `POST/GET /api/v1/projects · GET/PATCH /api/v1/projects/{id} · POST /api/v1/projects/{id}/regenerate-brief`
|
|
448
|
+
(archive: `PATCH /api/v1/projects/{id}` with `{"status":"archived"}` — no
|
|
449
|
+
dedicated `/archive` route).
|
|
450
|
+
|
|
451
|
+
CLI: `shiply project ls · shiply project create <label> [--customer-email <e>] [--customer-name <n>] · shiply project get <id> · shiply project archive <id>`
|
|
452
|
+
|
|
453
|
+
Docs: https://shiply.now/docs/projects
|
|
454
|
+
|
|
455
|
+
## Marketplace — sell built sites
|
|
456
|
+
|
|
457
|
+
Devs can list any owned site for sale: set a price + short pitch, choose
|
|
458
|
+
standard or custom terms, pick a jurisdiction. Stripe Connect Express
|
|
459
|
+
handles seller payouts — sellers complete a one-time onboarding before
|
|
460
|
+
listing (`get_connect_status` returns the onboarding URL when needed).
|
|
461
|
+
Buyers pay via Stripe Checkout; on `checkout.session.completed` the
|
|
462
|
+
webhook flips the order to `paid` and transfers site ownership
|
|
463
|
+
atomically. Refunds are available within the order's refund window
|
|
464
|
+
(`refundExpiresAt`); a refund reverts ownership to the seller.
|
|
465
|
+
|
|
466
|
+
Prices are passed as `priceCents` (whole-dollar cents between 100 and
|
|
467
|
+
999900). `termsMode='standard'` uses shiply's template; `'custom'`
|
|
468
|
+
requires `termsCustom` ≥50 chars.
|
|
469
|
+
|
|
470
|
+
MCP tools:
|
|
471
|
+
```
|
|
472
|
+
list_listings — my listings
|
|
473
|
+
create_listing — list a site (siteSlug, priceCents, pitch?, termsMode, jurisdiction, ...)
|
|
474
|
+
update_listing — change price/pitch/status (draft|live|paused)
|
|
475
|
+
delete_listing — pulls off marketplace (sets status=draft)
|
|
476
|
+
list_my_sales — orders where I'm the seller
|
|
477
|
+
list_my_orders — orders where I'm the buyer
|
|
478
|
+
refund_order — issue Stripe refund (within refund window; goes back to buyer)
|
|
479
|
+
get_connect_status — Stripe Connect onboarding state + actionable URL
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
REST: `POST /api/v1/listings · PATCH /api/v1/listings/{id} · POST /api/v1/listings/{id}/checkout · POST /api/v1/orders/{id}/refund · GET /api/v1/connect/status`
|
|
483
|
+
(no GET listing index over REST yet — use the MCP `list_listings` /
|
|
484
|
+
`list_my_sales` / `list_my_orders` tools for machine output, or the
|
|
485
|
+
dashboard `/dashboard/sales` page for humans.)
|
|
486
|
+
|
|
487
|
+
CLI: `shiply listing ls · shiply listing create <site-slug> --price <cents> --jurisdiction "<region>" · shiply listing rm <slug> --id <listing-id>`
|
|
488
|
+
|
|
489
|
+
**Stripe Connect note:** Sellers must complete one-time Stripe Connect
|
|
490
|
+
onboarding before listing. Call `get_connect_status` first — when status
|
|
491
|
+
isn't `'ready'` it returns an `onboardingUrl` you should hand to the
|
|
492
|
+
user as a clickable link.
|
|
493
|
+
|
|
494
|
+
Docs: https://shiply.now/docs/marketplace
|
|
495
|
+
|
|
496
|
+
## Sending domains — outbound email on your domain
|
|
497
|
+
|
|
498
|
+
For agents that want shiply to send emails (demand-test broadcasts,
|
|
499
|
+
project intake invites, transactional notifications) from a custom
|
|
500
|
+
verified domain instead of the shared shiply pool. Backed by Resend —
|
|
501
|
+
add the DNS records they return at your registrar, then call
|
|
502
|
+
`verify_sending_domain` to re-check.
|
|
503
|
+
|
|
504
|
+
MCP tools:
|
|
505
|
+
```
|
|
506
|
+
list_sending_domains — all your sending domains
|
|
507
|
+
add_sending_domain — start: returns DNS records to add at your registrar
|
|
508
|
+
verify_sending_domain — re-check DNS after adding records
|
|
509
|
+
remove_sending_domain — tear down
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
REST: `GET/POST /api/v1/sending-domains · POST /api/v1/sending-domains/{id}/verify · DELETE /api/v1/sending-domains/{id}`
|
|
513
|
+
|
|
514
|
+
CLI: `shiply sending-domain ls · shiply sending-domain add <domain> · shiply sending-domain verify <id> · shiply sending-domain rm <id> --yes`
|
|
515
|
+
|
|
516
|
+
Cannot be a `shiply.now` subdomain. Verified status flips once SPF +
|
|
517
|
+
DKIM (+ MX for inbound) all check out.
|
|
518
|
+
|
|
333
519
|
## Make a site private (paid plans)
|
|
334
520
|
To password-protect or restrict a site: PATCH /api/v1/publishes/<slug>/access
|
|
335
521
|
with {"mode":"password","password":"..."} or {"mode":"restricted",
|