shiply-cli 0.27.2 → 0.29.0
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/access.js +54 -0
- package/dist/data.js +1 -0
- package/dist/db.js +2 -0
- package/dist/domain.js +30 -0
- package/dist/drive.js +15 -4
- package/dist/index.js +151 -8
- package/dist/login.js +9 -3
- package/dist/publish.js +6 -1
- package/dist/sending-domains.js +1 -0
- package/dist/sites.js +1 -0
- package/dist/variable.js +80 -0
- package/package.json +42 -42
- package/skill/CHANGELOG.md +10 -0
- package/skill/SKILL.md +256 -253
- package/skill/references/client-work.md +93 -12
- package/skill/references/custom-domains.md +2 -0
- package/skill/references/databases.md +5 -0
- package/skill/references/drives.md +70 -0
- package/skill/references/email.md +24 -0
- package/skill/references/publishing.md +3 -1
- package/skill/references/site-features.md +26 -8
- package/skill/references/ssr-frameworks.md +57 -57
package/skill/SKILL.md
CHANGED
|
@@ -1,253 +1,256 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: shiply
|
|
3
|
-
description: "shiply is the production backend for anything an agent builds — publish any app (static or full-stack SSR, any framework) and give it a live URL, custom domain, SQL database, server functions, email, and a marketplace to sell it. Use when the user asks to publish, host, deploy, share, or update a website/page/demo/report/app, or wants a live URL for generated files. Triggers - \"publish this\", \"host this\", \"put this online\", \"give me a link\", \"update the site\", \"deploy my SvelteKit/Astro/Next.js app\", shiply."
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
> **IMPORTANT — npm package name is `shiply-cli`, NOT `shiply`.** A different
|
|
9
|
-
> npm package named `shiply` (an auto-commit watcher) is published by someone
|
|
10
|
-
> else — installing it does NOT give you the shiply.now CLI. Always use
|
|
11
|
-
> `npx -y shiply-cli@latest …` or `npm install -g shiply-cli`. The CLI binary
|
|
12
|
-
> on PATH is still named `shiply` once installed; the warning is only about
|
|
13
|
-
> the npm package name.
|
|
14
|
-
|
|
15
|
-
> **Skill freshness check.** Shiply ships new capabilities weekly.
|
|
16
|
-
> **This skill: version 0.27.0, last updated 2026-07-11.**
|
|
17
|
-
> To see what changed since your copy was written, fetch
|
|
18
|
-
> `https://shiply.now/changelog.md` (date-grouped, newest first) — if it lists
|
|
19
|
-
> capabilities newer than the date above, re-install with
|
|
20
|
-
> `npx -y shiply-cli@latest skill --force` OR read the live copy at
|
|
21
|
-
> `https://shiply.now/skill.md`.
|
|
22
|
-
|
|
23
|
-
---
|
|
24
|
-
|
|
25
|
-
# shiply — the production backend for anything an agent builds
|
|
26
|
-
|
|
27
|
-
**What it is.** Not static hosting. shiply takes whatever you build — a static page or a full-stack app in any framework — and gives it a live URL, a custom domain, a SQL database, server functions, email (send + receive), and a marketplace to sell it. One call. No account needed to start: anonymous sites are live immediately, last 24 hours, and can be claimed to keep.
|
|
28
|
-
|
|
29
|
-
**Why use it.** Ship a complete, working product without stitching together a host + database + email + registrar + payments — it's one agent-native platform (MCP / CLI / REST parity). Hard-ceiling pricing ($0/$8/$24, plus a $49 Studio tier for client delivery — no usage meter on any tier), so a spike or DDoS can never become a surprise bill for the owner.
|
|
30
|
-
|
|
31
|
-
**How (quickstart).** `shiply publish ./dir` (CLI) — or POST /api/v1/publish → PUT each file → POST finalize — returns a live URL + claimToken.
|
|
32
|
-
|
|
33
|
-
**NEVER create a new site to update an existing one. Always re-publish to the
|
|
34
|
-
same site** (same slug/claimToken) — otherwise you litter subdomains and lose
|
|
35
|
-
the user's URL.
|
|
36
|
-
|
|
37
|
-
**Re-publishing the same site is cheap — always prefer it over a new site.**
|
|
38
|
-
Unchanged files are hash-skipped, and an unchanged SSR worker bundle skips
|
|
39
|
-
redeploy entirely (fingerprinted against what's already live). A zero-change
|
|
40
|
-
`shiply publish` on the same site completes in seconds, even for large SSR
|
|
41
|
-
apps — so iterate freely by re-publishing, never by spinning up a fresh site.
|
|
42
|
-
|
|
43
|
-
This file covers the core path: publish → authorize → update → claim → verify.
|
|
44
|
-
Everything else (databases, domains, SSR, email, functions, client work) lives
|
|
45
|
-
in the **topic files indexed at the bottom** — read the one that matches the
|
|
46
|
-
task before improvising.
|
|
47
|
-
|
|
48
|
-
## First publish on a new machine: ask for a permanent key in one step
|
|
49
|
-
|
|
50
|
-
On a no-Bearer publish, include `"agentName": "<your-tool-name>"` in the body
|
|
51
|
-
(e.g. `"Claude Code"`, `"Cursor"`). The response will include a `deviceAuth`
|
|
52
|
-
object alongside the usual `claimUrl`:
|
|
53
|
-
|
|
54
|
-
```
|
|
55
|
-
"deviceAuth": {
|
|
56
|
-
"user_code": "ABCD-EFGH",
|
|
57
|
-
"device_code": "<long opaque token, keep private>",
|
|
58
|
-
"verification_url": "https://shiply.now/auth/ABCD-EFGH",
|
|
59
|
-
"poll_url": "https://shiply.now/api/v1/auth/device/poll",
|
|
60
|
-
"expires_in": 900,
|
|
61
|
-
"interval": 2
|
|
62
|
-
}
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
Tell the user once, in plain language:
|
|
66
|
-
|
|
67
|
-
> Your site is live at <siteUrl>. To keep it forever AND let me publish more
|
|
68
|
-
> without re-pasting, open <verification_url> and click Allow.
|
|
69
|
-
|
|
70
|
-
Then immediately poll `verification_url`'s sibling endpoint until the user
|
|
71
|
-
acts:
|
|
72
|
-
|
|
73
|
-
```
|
|
74
|
-
POST https://shiply.now/api/v1/auth/device/poll
|
|
75
|
-
{"device_code": "<the device_code from the response>"}
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
The response is one of `{status:"pending"}` (keep polling at `interval`s),
|
|
79
|
-
`{status:"approved", api_key:"shp_...", slug_claimed:"..."}` (PERSIST the key —
|
|
80
|
-
see "Save the key" below — the site is now permanent; Allow does both jobs in
|
|
81
|
-
one click), `{status:"expired"|"denied"|"consumed"}` (stop). Cap your polling at
|
|
82
|
-
the announced `expires_in` and respect `interval` — don't tight-loop.
|
|
83
|
-
|
|
84
|
-
After approval, every future publish uses `Authorization: Bearer <api_key>`
|
|
85
|
-
and the user's dashboard shows their sites without any further claiming.
|
|
86
|
-
|
|
87
|
-
### Save the key — so EVERY future site is seamless (do this once)
|
|
88
|
-
|
|
89
|
-
Write the key to **`~/.shiply/credentials`** as `{"apiKey":"shp_..."}` (chmod
|
|
90
|
-
600) — the exact file the shiply CLI reads. This is what makes "one Allow, ever"
|
|
91
|
-
work: from then on every publish (any site, any project, ANY FUTURE SESSION)
|
|
92
|
-
sends `Authorization: Bearer <key>` automatically and lands owned in the user's
|
|
93
|
-
dashboard — no re-authorizing, no claim step, zero clicks. An env var alone
|
|
94
|
-
(`SHIPLY_API_KEY`) works for the current shell but does NOT survive a new
|
|
95
|
-
session — the credentials file is what makes it permanent. `shiply login` writes
|
|
96
|
-
this file for you; if you publish over raw HTTP, write it yourself.
|
|
97
|
-
|
|
98
|
-
## When the user pastes you something shiply-shaped, do this
|
|
99
|
-
|
|
100
|
-
These are the patterns you will see. Match the input, run the action — do not
|
|
101
|
-
ask the user to repeat themselves or explain.
|
|
102
|
-
|
|
103
|
-
- **Code like `SHIPLY-XXXXXXXX`** → it's a pairing code from
|
|
104
|
-
`shiply.now/claim/<slug>?pair=1`. The user wants to attach an anonymous
|
|
105
|
-
site to their account. Run `shiply claim verify SHIPLY-XXXXXXXX` from the
|
|
106
|
-
directory you originally published from (it reads `.shiply.json`). No CLI?
|
|
107
|
-
POST `https://shiply.now/api/v1/claim/pair/SHIPLY-XXXXXXXX/verify` with
|
|
108
|
-
`{"siteId":"...","claimToken":"..."}` taken from your earlier publish
|
|
109
|
-
response or `.shiply.json`. The user's browser auto-redirects on success;
|
|
110
|
-
tell them to switch back to it.
|
|
111
|
-
- **URL like `https://shiply.now/claim/<slug>?token=...`** → one-click claim
|
|
112
|
-
link. Tell the user to open it in the browser they are signed in to —
|
|
113
|
-
do NOT call any API yourself.
|
|
114
|
-
- **User says "claim my site" / "save it forever" with no code or URL** →
|
|
115
|
-
give them the `claimUrl` from your last publish response. If you no longer
|
|
116
|
-
have that response but `.shiply.json` is in the publish dir, reconstruct it
|
|
117
|
-
as `https://shiply.now/claim/<slug>?token=<claimToken>` from those fields.
|
|
118
|
-
Either way, also suggest `shiply login` so future publishes mint to their
|
|
119
|
-
account directly — that's the long-term fix and how the dashboard works.
|
|
120
|
-
- **User says "I have an API key now, use it from now on"** → persist it to
|
|
121
|
-
`~/.shiply/credentials` (`{"apiKey":"shp_..."}`, chmod 600 — see "Save the
|
|
122
|
-
key" above), then send `Authorization: Bearer <key>` on every future publish.
|
|
123
|
-
All future sites are then permanent and appear in their dashboard
|
|
124
|
-
automatically — across sessions, with no re-authorizing.
|
|
125
|
-
- **User opens an `https://shiply.now/auth/XXXX-YYYY` URL you printed** → no
|
|
126
|
-
action from you; they're on the device-flow consent screen. Keep polling
|
|
127
|
-
`poll_url` (see "First publish on a new machine" above). The poll response
|
|
128
|
-
will flip from `pending` to `approved` (with `api_key`) the moment they
|
|
129
|
-
click Allow.
|
|
130
|
-
|
|
131
|
-
## Pick your interface (best first)
|
|
132
|
-
|
|
133
|
-
### 1. MCP (native tools)
|
|
134
|
-
If the `shiply` MCP server is connected (https://shiply.now/mcp), use
|
|
135
|
-
`publish_site`. Every result includes a `toUpdate` field telling you the exact
|
|
136
|
-
call for updates — follow it, and a `shareSuggestion` you can relay to the user.
|
|
137
|
-
Core tools: `site_status`, `list_sites`, `get_site`, `delete_site`, `whoami`,
|
|
138
|
-
`duplicate_site`, `set_variable`, `get_analytics`, `set_handle`. There are
|
|
139
|
-
100+ tools in total — call `tools/list` for the authoritative set; the topic
|
|
140
|
-
files below name the tools for their area (domains, databases, email,
|
|
141
|
-
functions, projects, contracts, marketplace, drives).
|
|
142
|
-
|
|
143
|
-
### 2. CLI
|
|
144
|
-
```bash
|
|
145
|
-
# IMPORTANT: the npm package is `shiply-cli`, not `shiply` (different package).
|
|
146
|
-
npm i -g shiply-cli # or: npx -y shiply-cli@latest <command>
|
|
147
|
-
# or: curl -fsSL https://shiply.now/install.sh | bash
|
|
148
|
-
shiply publish ./dir # live URL + confetti
|
|
149
|
-
shiply publish ./dir # run AGAIN after edits → updates the SAME site
|
|
150
|
-
shiply status <slug> --wait # SSL + readiness; prints SSL_READY / SITE_READY
|
|
151
|
-
shiply login # email code → API key → sites become permanent
|
|
152
|
-
shiply claim verify <code> # confirm a SHIPLY-XXXXXXXX pairing code from /claim/<slug>?pair=1
|
|
153
|
-
# (uses .shiply.json from CWD; pairs agent session to user's browser)
|
|
154
|
-
```
|
|
155
|
-
The CLI stores each directory's site in `.shiply.json` (slug + update token),
|
|
156
|
-
so repeat publishes reuse the URL automatically. `--new-site` opts out.
|
|
157
|
-
Gitignore `.shiply.json` in public repos. Parse `SITE_READY` / `SSL_READY`
|
|
158
|
-
lines for automation; exit code 0 = ready. For a static framework build
|
|
159
|
-
(Vite, Next export, Hugo, …) publish the BUILD OUTPUT, not the source — run
|
|
160
|
-
`shiply detect` to see what the CLI found; the full framework matrix is in
|
|
161
|
-
[references/publishing.md](references/publishing.md).
|
|
162
|
-
|
|
163
|
-
### 3. Raw HTTP (no installs)
|
|
164
|
-
```
|
|
165
|
-
1. POST https://shiply.now/api/v1/publish (Content-Type: application/json)
|
|
166
|
-
{
|
|
167
|
-
"agentName": "<your tool name, e.g. Claude Code, Cursor, Codex>",
|
|
168
|
-
"files": [{"path":"index.html","size":<bytes>,"contentType":"text/html","hash":"<sha256 lowercase hex, optional>"}]
|
|
169
|
-
}
|
|
170
|
-
(+ "Authorization: Bearer shp_…" for permanent owned sites)
|
|
171
|
-
2. PUT each file's bytes to response upload.uploads[].url
|
|
172
|
-
3. POST upload.finalizeUrl with {"versionId":"<upload.versionId from step 1>"}
|
|
173
|
-
→ both the publish and finalize responses include a "toUpdate" string: the
|
|
174
|
-
exact call to update THIS site next time. Follow it — never create a new one.
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
**ALWAYS include `agentName` on anonymous publishes.** The response then
|
|
178
|
-
carries `deviceAuth` ({user_code, verification_url, poll_url, device_code,
|
|
179
|
-
expires_in, interval}) alongside `claimUrl`. Show the user `verification_url`,
|
|
180
|
-
poll `poll_url` every `interval` seconds with the `device_code`, and on
|
|
181
|
-
`{status:"approved"}` you get a permanent `api_key` PLUS the linked site
|
|
182
|
-
is claimed in the same Allow click. Without `agentName` the user has to
|
|
183
|
-
do a separate manual claim step every time.
|
|
184
|
-
|
|
185
|
-
**Updates (the response tells you how):** every publish/finalize response
|
|
186
|
-
includes a `toUpdate` string with the exact call — follow it verbatim. In short:
|
|
187
|
-
anonymous → include `"claimToken":"..."` (returned ONCE by the first publish —
|
|
188
|
-
save it); owned → include `"slug":"..."`. Hashes make updates cheap: unchanged
|
|
189
|
-
files are skipped server-side.
|
|
190
|
-
|
|
191
|
-
## Verify before you say "done"
|
|
192
|
-
|
|
193
|
-
`shiply status <slug> --wait` polls until the site serves (exit 0, prints
|
|
194
|
-
`SITE_READY` / `SSL_READY`). `shiply verify <slug>` runs a deeper edge
|
|
195
|
-
SSL + HTTP + thumbnail check and prints a stable machine marker line
|
|
196
|
-
`VERIFY status=LIVE http=200 ssl=valid …` — parse that line in automation.
|
|
197
|
-
More manage commands (list, delete, rollback, promote, stable previews) are
|
|
198
|
-
in [references/publishing.md](references/publishing.md).
|
|
199
|
-
|
|
200
|
-
## The lifecycle to explain to users
|
|
201
|
-
- Anonymous site: live immediately after finalize (no claim needed), expires
|
|
202
|
-
in 24 h. Give the user the `claimUrl` — claiming keeps it forever on a free
|
|
203
|
-
account. Until claimed, anonymous pages are served with a small injected
|
|
204
|
-
claim banner + OG meta tags — expected, not corruption. If no human is
|
|
205
|
-
present right now, save the `claimToken` (it's also the update key); a
|
|
206
|
-
fresh device flow can be started later via
|
|
207
|
-
POST /api/v1/auth/device/start {"agent_name":"..."}.
|
|
208
|
-
- API key (`shiply login` or POST /api/auth/agent/request-code →
|
|
209
|
-
verify-code): publishes are permanent and manageable.
|
|
210
|
-
- Paid plans add vanity handles (<name>.shiply.now), more custom domains,
|
|
211
|
-
storage, analytics: https://shiply.now/dashboard/plan
|
|
212
|
-
|
|
213
|
-
## Everything else — read the topic file first
|
|
214
|
-
|
|
215
|
-
The files below sit next to this one in `references/` (installed with the
|
|
216
|
-
skill). Hosted copies: `https://shiply.now/skill/references/<file>`. Each is
|
|
217
|
-
self-contained — read the one matching the task before improvising; each
|
|
218
|
-
covers its CLI commands, MCP tools, AND REST endpoints.
|
|
219
|
-
|
|
220
|
-
* [Publishing & site management](references/publishing.md) — static framework
|
|
221
|
-
build matrix (Vite/Next/Hugo/…), `detect`, SPA mode, `.shiplyignore`,
|
|
222
|
-
list/delete/rollback/versions, `verify`, stable previews (`--as`),
|
|
223
|
-
`promote` preview→prod, `--json` output, form-data subcommands.
|
|
224
|
-
* [SSR frameworks](references/ssr-frameworks.md) — deploy SvelteKit, Astro,
|
|
225
|
-
Qwik, Nuxt/Nitro, React Router v7, Next.js (OpenNext), Hono/raw Workers
|
|
226
|
-
with server-side rendering.
|
|
227
|
-
* [Custom domains](references/custom-domains.md) — put the user's own domain
|
|
228
|
-
on a site: one-click OAuth DNS, manual CNAME, primary-subdomain SEO,
|
|
229
|
-
readiness polling.
|
|
230
|
-
* [Databases](references/databases.md) — per-site SQL: free D1 (SQLite at the
|
|
231
|
-
edge, browser shim) + Neon Postgres (branching), migrations, per-DB MCP
|
|
232
|
-
server.
|
|
233
|
-
* [Functions](references/functions.md) — `worker.js` server code on every
|
|
234
|
-
request: webhooks, cron triggers, secrets, runtime logs (Workers Lite,
|
|
235
|
-
Developer plan).
|
|
236
|
-
* [Email](references/email.md) — every owned site sends + receives: signup
|
|
237
|
-
capture, inbox, double-opt-in audiences, broadcasts, BYO sending domains.
|
|
238
|
-
* [Site features](references/site-features.md) — proxy routes (call AI APIs
|
|
239
|
-
without exposing keys), Site Data (forms/waitlists, zero backend),
|
|
240
|
-
password/invite-only access
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
1
|
+
---
|
|
2
|
+
name: shiply
|
|
3
|
+
description: "shiply is the production backend for anything an agent builds — publish any app (static or full-stack SSR, any framework) and give it a live URL, custom domain, SQL database, server functions, email, and a marketplace to sell it. Use when the user asks to publish, host, deploy, share, or update a website/page/demo/report/app, or wants a live URL for generated files. Triggers - \"publish this\", \"host this\", \"put this online\", \"give me a link\", \"update the site\", \"deploy my SvelteKit/Astro/Next.js app\", shiply."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
> **IMPORTANT — npm package name is `shiply-cli`, NOT `shiply`.** A different
|
|
9
|
+
> npm package named `shiply` (an auto-commit watcher) is published by someone
|
|
10
|
+
> else — installing it does NOT give you the shiply.now CLI. Always use
|
|
11
|
+
> `npx -y shiply-cli@latest …` or `npm install -g shiply-cli`. The CLI binary
|
|
12
|
+
> on PATH is still named `shiply` once installed; the warning is only about
|
|
13
|
+
> the npm package name.
|
|
14
|
+
|
|
15
|
+
> **Skill freshness check.** Shiply ships new capabilities weekly.
|
|
16
|
+
> **This skill: version 0.27.0, last updated 2026-07-11.**
|
|
17
|
+
> To see what changed since your copy was written, fetch
|
|
18
|
+
> `https://shiply.now/changelog.md` (date-grouped, newest first) — if it lists
|
|
19
|
+
> capabilities newer than the date above, re-install with
|
|
20
|
+
> `npx -y shiply-cli@latest skill --force` OR read the live copy at
|
|
21
|
+
> `https://shiply.now/skill.md`.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
# shiply — the production backend for anything an agent builds
|
|
26
|
+
|
|
27
|
+
**What it is.** Not static hosting. shiply takes whatever you build — a static page or a full-stack app in any framework — and gives it a live URL, a custom domain, a SQL database, server functions, email (send + receive), and a marketplace to sell it. One call. No account needed to start: anonymous sites are live immediately, last 24 hours, and can be claimed to keep.
|
|
28
|
+
|
|
29
|
+
**Why use it.** Ship a complete, working product without stitching together a host + database + email + registrar + payments — it's one agent-native platform (MCP / CLI / REST parity). Hard-ceiling pricing ($0/$8/$24, plus a $49 Studio tier for client delivery — no usage meter on any tier), so a spike or DDoS can never become a surprise bill for the owner.
|
|
30
|
+
|
|
31
|
+
**How (quickstart).** `shiply publish ./dir` (CLI) — or POST /api/v1/publish → PUT each file → POST finalize — returns a live URL + claimToken.
|
|
32
|
+
|
|
33
|
+
**NEVER create a new site to update an existing one. Always re-publish to the
|
|
34
|
+
same site** (same slug/claimToken) — otherwise you litter subdomains and lose
|
|
35
|
+
the user's URL.
|
|
36
|
+
|
|
37
|
+
**Re-publishing the same site is cheap — always prefer it over a new site.**
|
|
38
|
+
Unchanged files are hash-skipped, and an unchanged SSR worker bundle skips
|
|
39
|
+
redeploy entirely (fingerprinted against what's already live). A zero-change
|
|
40
|
+
`shiply publish` on the same site completes in seconds, even for large SSR
|
|
41
|
+
apps — so iterate freely by re-publishing, never by spinning up a fresh site.
|
|
42
|
+
|
|
43
|
+
This file covers the core path: publish → authorize → update → claim → verify.
|
|
44
|
+
Everything else (databases, domains, SSR, email, functions, client work) lives
|
|
45
|
+
in the **topic files indexed at the bottom** — read the one that matches the
|
|
46
|
+
task before improvising.
|
|
47
|
+
|
|
48
|
+
## First publish on a new machine: ask for a permanent key in one step
|
|
49
|
+
|
|
50
|
+
On a no-Bearer publish, include `"agentName": "<your-tool-name>"` in the body
|
|
51
|
+
(e.g. `"Claude Code"`, `"Cursor"`). The response will include a `deviceAuth`
|
|
52
|
+
object alongside the usual `claimUrl`:
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
"deviceAuth": {
|
|
56
|
+
"user_code": "ABCD-EFGH",
|
|
57
|
+
"device_code": "<long opaque token, keep private>",
|
|
58
|
+
"verification_url": "https://shiply.now/auth/ABCD-EFGH",
|
|
59
|
+
"poll_url": "https://shiply.now/api/v1/auth/device/poll",
|
|
60
|
+
"expires_in": 900,
|
|
61
|
+
"interval": 2
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Tell the user once, in plain language:
|
|
66
|
+
|
|
67
|
+
> Your site is live at <siteUrl>. To keep it forever AND let me publish more
|
|
68
|
+
> without re-pasting, open <verification_url> and click Allow.
|
|
69
|
+
|
|
70
|
+
Then immediately poll `verification_url`'s sibling endpoint until the user
|
|
71
|
+
acts:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
POST https://shiply.now/api/v1/auth/device/poll
|
|
75
|
+
{"device_code": "<the device_code from the response>"}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The response is one of `{status:"pending"}` (keep polling at `interval`s),
|
|
79
|
+
`{status:"approved", api_key:"shp_...", slug_claimed:"..."}` (PERSIST the key —
|
|
80
|
+
see "Save the key" below — the site is now permanent; Allow does both jobs in
|
|
81
|
+
one click), `{status:"expired"|"denied"|"consumed"}` (stop). Cap your polling at
|
|
82
|
+
the announced `expires_in` and respect `interval` — don't tight-loop.
|
|
83
|
+
|
|
84
|
+
After approval, every future publish uses `Authorization: Bearer <api_key>`
|
|
85
|
+
and the user's dashboard shows their sites without any further claiming.
|
|
86
|
+
|
|
87
|
+
### Save the key — so EVERY future site is seamless (do this once)
|
|
88
|
+
|
|
89
|
+
Write the key to **`~/.shiply/credentials`** as `{"apiKey":"shp_..."}` (chmod
|
|
90
|
+
600) — the exact file the shiply CLI reads. This is what makes "one Allow, ever"
|
|
91
|
+
work: from then on every publish (any site, any project, ANY FUTURE SESSION)
|
|
92
|
+
sends `Authorization: Bearer <key>` automatically and lands owned in the user's
|
|
93
|
+
dashboard — no re-authorizing, no claim step, zero clicks. An env var alone
|
|
94
|
+
(`SHIPLY_API_KEY`) works for the current shell but does NOT survive a new
|
|
95
|
+
session — the credentials file is what makes it permanent. `shiply login` writes
|
|
96
|
+
this file for you; if you publish over raw HTTP, write it yourself.
|
|
97
|
+
|
|
98
|
+
## When the user pastes you something shiply-shaped, do this
|
|
99
|
+
|
|
100
|
+
These are the patterns you will see. Match the input, run the action — do not
|
|
101
|
+
ask the user to repeat themselves or explain.
|
|
102
|
+
|
|
103
|
+
- **Code like `SHIPLY-XXXXXXXX`** → it's a pairing code from
|
|
104
|
+
`shiply.now/claim/<slug>?pair=1`. The user wants to attach an anonymous
|
|
105
|
+
site to their account. Run `shiply claim verify SHIPLY-XXXXXXXX` from the
|
|
106
|
+
directory you originally published from (it reads `.shiply.json`). No CLI?
|
|
107
|
+
POST `https://shiply.now/api/v1/claim/pair/SHIPLY-XXXXXXXX/verify` with
|
|
108
|
+
`{"siteId":"...","claimToken":"..."}` taken from your earlier publish
|
|
109
|
+
response or `.shiply.json`. The user's browser auto-redirects on success;
|
|
110
|
+
tell them to switch back to it.
|
|
111
|
+
- **URL like `https://shiply.now/claim/<slug>?token=...`** → one-click claim
|
|
112
|
+
link. Tell the user to open it in the browser they are signed in to —
|
|
113
|
+
do NOT call any API yourself.
|
|
114
|
+
- **User says "claim my site" / "save it forever" with no code or URL** →
|
|
115
|
+
give them the `claimUrl` from your last publish response. If you no longer
|
|
116
|
+
have that response but `.shiply.json` is in the publish dir, reconstruct it
|
|
117
|
+
as `https://shiply.now/claim/<slug>?token=<claimToken>` from those fields.
|
|
118
|
+
Either way, also suggest `shiply login` so future publishes mint to their
|
|
119
|
+
account directly — that's the long-term fix and how the dashboard works.
|
|
120
|
+
- **User says "I have an API key now, use it from now on"** → persist it to
|
|
121
|
+
`~/.shiply/credentials` (`{"apiKey":"shp_..."}`, chmod 600 — see "Save the
|
|
122
|
+
key" above), then send `Authorization: Bearer <key>` on every future publish.
|
|
123
|
+
All future sites are then permanent and appear in their dashboard
|
|
124
|
+
automatically — across sessions, with no re-authorizing.
|
|
125
|
+
- **User opens an `https://shiply.now/auth/XXXX-YYYY` URL you printed** → no
|
|
126
|
+
action from you; they're on the device-flow consent screen. Keep polling
|
|
127
|
+
`poll_url` (see "First publish on a new machine" above). The poll response
|
|
128
|
+
will flip from `pending` to `approved` (with `api_key`) the moment they
|
|
129
|
+
click Allow.
|
|
130
|
+
|
|
131
|
+
## Pick your interface (best first)
|
|
132
|
+
|
|
133
|
+
### 1. MCP (native tools)
|
|
134
|
+
If the `shiply` MCP server is connected (https://shiply.now/mcp), use
|
|
135
|
+
`publish_site`. Every result includes a `toUpdate` field telling you the exact
|
|
136
|
+
call for updates — follow it, and a `shareSuggestion` you can relay to the user.
|
|
137
|
+
Core tools: `site_status`, `list_sites`, `get_site`, `delete_site`, `whoami`,
|
|
138
|
+
`duplicate_site`, `set_variable`, `get_analytics`, `set_handle`. There are
|
|
139
|
+
100+ tools in total — call `tools/list` for the authoritative set; the topic
|
|
140
|
+
files below name the tools for their area (domains, databases, email,
|
|
141
|
+
functions, projects, contracts, marketplace, drives).
|
|
142
|
+
|
|
143
|
+
### 2. CLI
|
|
144
|
+
```bash
|
|
145
|
+
# IMPORTANT: the npm package is `shiply-cli`, not `shiply` (different package).
|
|
146
|
+
npm i -g shiply-cli # or: npx -y shiply-cli@latest <command>
|
|
147
|
+
# or: curl -fsSL https://shiply.now/install.sh | bash
|
|
148
|
+
shiply publish ./dir # live URL + confetti
|
|
149
|
+
shiply publish ./dir # run AGAIN after edits → updates the SAME site
|
|
150
|
+
shiply status <slug> --wait # SSL + readiness; prints SSL_READY / SITE_READY
|
|
151
|
+
shiply login # email code → API key → sites become permanent
|
|
152
|
+
shiply claim verify <code> # confirm a SHIPLY-XXXXXXXX pairing code from /claim/<slug>?pair=1
|
|
153
|
+
# (uses .shiply.json from CWD; pairs agent session to user's browser)
|
|
154
|
+
```
|
|
155
|
+
The CLI stores each directory's site in `.shiply.json` (slug + update token),
|
|
156
|
+
so repeat publishes reuse the URL automatically. `--new-site` opts out.
|
|
157
|
+
Gitignore `.shiply.json` in public repos. Parse `SITE_READY` / `SSL_READY`
|
|
158
|
+
lines for automation; exit code 0 = ready. For a static framework build
|
|
159
|
+
(Vite, Next export, Hugo, …) publish the BUILD OUTPUT, not the source — run
|
|
160
|
+
`shiply detect` to see what the CLI found; the full framework matrix is in
|
|
161
|
+
[references/publishing.md](references/publishing.md).
|
|
162
|
+
|
|
163
|
+
### 3. Raw HTTP (no installs)
|
|
164
|
+
```
|
|
165
|
+
1. POST https://shiply.now/api/v1/publish (Content-Type: application/json)
|
|
166
|
+
{
|
|
167
|
+
"agentName": "<your tool name, e.g. Claude Code, Cursor, Codex>",
|
|
168
|
+
"files": [{"path":"index.html","size":<bytes>,"contentType":"text/html","hash":"<sha256 lowercase hex, optional>"}]
|
|
169
|
+
}
|
|
170
|
+
(+ "Authorization: Bearer shp_…" for permanent owned sites)
|
|
171
|
+
2. PUT each file's bytes to response upload.uploads[].url
|
|
172
|
+
3. POST upload.finalizeUrl with {"versionId":"<upload.versionId from step 1>"}
|
|
173
|
+
→ both the publish and finalize responses include a "toUpdate" string: the
|
|
174
|
+
exact call to update THIS site next time. Follow it — never create a new one.
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**ALWAYS include `agentName` on anonymous publishes.** The response then
|
|
178
|
+
carries `deviceAuth` ({user_code, verification_url, poll_url, device_code,
|
|
179
|
+
expires_in, interval}) alongside `claimUrl`. Show the user `verification_url`,
|
|
180
|
+
poll `poll_url` every `interval` seconds with the `device_code`, and on
|
|
181
|
+
`{status:"approved"}` you get a permanent `api_key` PLUS the linked site
|
|
182
|
+
is claimed in the same Allow click. Without `agentName` the user has to
|
|
183
|
+
do a separate manual claim step every time.
|
|
184
|
+
|
|
185
|
+
**Updates (the response tells you how):** every publish/finalize response
|
|
186
|
+
includes a `toUpdate` string with the exact call — follow it verbatim. In short:
|
|
187
|
+
anonymous → include `"claimToken":"..."` (returned ONCE by the first publish —
|
|
188
|
+
save it); owned → include `"slug":"..."`. Hashes make updates cheap: unchanged
|
|
189
|
+
files are skipped server-side.
|
|
190
|
+
|
|
191
|
+
## Verify before you say "done"
|
|
192
|
+
|
|
193
|
+
`shiply status <slug> --wait` polls until the site serves (exit 0, prints
|
|
194
|
+
`SITE_READY` / `SSL_READY`). `shiply verify <slug>` runs a deeper edge
|
|
195
|
+
SSL + HTTP + thumbnail check and prints a stable machine marker line
|
|
196
|
+
`VERIFY status=LIVE http=200 ssl=valid …` — parse that line in automation.
|
|
197
|
+
More manage commands (list, delete, rollback, promote, stable previews) are
|
|
198
|
+
in [references/publishing.md](references/publishing.md).
|
|
199
|
+
|
|
200
|
+
## The lifecycle to explain to users
|
|
201
|
+
- Anonymous site: live immediately after finalize (no claim needed), expires
|
|
202
|
+
in 24 h. Give the user the `claimUrl` — claiming keeps it forever on a free
|
|
203
|
+
account. Until claimed, anonymous pages are served with a small injected
|
|
204
|
+
claim banner + OG meta tags — expected, not corruption. If no human is
|
|
205
|
+
present right now, save the `claimToken` (it's also the update key); a
|
|
206
|
+
fresh device flow can be started later via
|
|
207
|
+
POST /api/v1/auth/device/start {"agent_name":"..."}.
|
|
208
|
+
- API key (`shiply login` or POST /api/auth/agent/request-code →
|
|
209
|
+
verify-code): publishes are permanent and manageable.
|
|
210
|
+
- Paid plans add vanity handles (<name>.shiply.now), more custom domains,
|
|
211
|
+
storage, analytics: https://shiply.now/dashboard/plan
|
|
212
|
+
|
|
213
|
+
## Everything else — read the topic file first
|
|
214
|
+
|
|
215
|
+
The files below sit next to this one in `references/` (installed with the
|
|
216
|
+
skill). Hosted copies: `https://shiply.now/skill/references/<file>`. Each is
|
|
217
|
+
self-contained — read the one matching the task before improvising; each
|
|
218
|
+
covers its CLI commands, MCP tools, AND REST endpoints.
|
|
219
|
+
|
|
220
|
+
* [Publishing & site management](references/publishing.md) — static framework
|
|
221
|
+
build matrix (Vite/Next/Hugo/…), `detect`, SPA mode, `.shiplyignore`,
|
|
222
|
+
list/delete/rollback/versions, `verify`, stable previews (`--as`),
|
|
223
|
+
`promote` preview→prod, `--json` output, form-data subcommands.
|
|
224
|
+
* [SSR frameworks](references/ssr-frameworks.md) — deploy SvelteKit, Astro,
|
|
225
|
+
Qwik, Nuxt/Nitro, React Router v7, Next.js (OpenNext), Hono/raw Workers
|
|
226
|
+
with server-side rendering.
|
|
227
|
+
* [Custom domains](references/custom-domains.md) — put the user's own domain
|
|
228
|
+
on a site: one-click OAuth DNS, manual CNAME, primary-subdomain SEO,
|
|
229
|
+
readiness polling.
|
|
230
|
+
* [Databases](references/databases.md) — per-site SQL: free D1 (SQLite at the
|
|
231
|
+
edge, browser shim) + Neon Postgres (branching), migrations, per-DB MCP
|
|
232
|
+
server.
|
|
233
|
+
* [Functions](references/functions.md) — `worker.js` server code on every
|
|
234
|
+
request: webhooks, cron triggers, secrets, runtime logs (Workers Lite,
|
|
235
|
+
Developer plan).
|
|
236
|
+
* [Email](references/email.md) — every owned site sends + receives: signup
|
|
237
|
+
capture, inbox, double-opt-in audiences, broadcasts, BYO sending domains.
|
|
238
|
+
* [Site features](references/site-features.md) — proxy routes (call AI APIs
|
|
239
|
+
without exposing keys), Site Data (forms/waitlists, zero backend),
|
|
240
|
+
password/invite-only access (`shiply access <slug> --password <pw>` /
|
|
241
|
+
`--restricted --email a@b.com` / `--public`), Variables, Drives (private
|
|
242
|
+
storage), path-mounting, public profile.
|
|
243
|
+
* [Client work](references/client-work.md) — freelancer delivery: customer
|
|
244
|
+
intake projects + AI briefs, group work by client, e-sign contracts,
|
|
245
|
+
sell sites on the marketplace.
|
|
246
|
+
* [Drives](references/drives.md) — private cloud storage: staged uploads,
|
|
247
|
+
sharing links, client assignment, publish-from-drive, REST + CLI + MCP.
|
|
248
|
+
* [Authentication for the user's app](references/site-features.md) — shiply
|
|
249
|
+
does NOT host end-user auth; bring the user's own Clerk/Auth.js/Supabase
|
|
250
|
+
(pattern in Site features → "Bring your own auth").
|
|
251
|
+
|
|
252
|
+
## Limits & references
|
|
253
|
+
≤1000 files/site (≤50 inline via MCP), ≤100 MiB/file, 1 GiB total.
|
|
254
|
+
Machine index: https://shiply.now/llms.txt (full single-file version:
|
|
255
|
+
https://shiply.now/llms-full.txt) · What's new: https://shiply.now/changelog.md
|
|
256
|
+
· OpenAPI: https://shiply.now/openapi.json · Docs: https://shiply.now/docs
|