Deploy a site
Deploy a folder or a single file to a live URL, with auto-detection of common build directories and machine-readable output for scripts.
Point flypod at a directory of static files:
npx flypod ./distflypod zips the folder, POSTs it to the server, and prints a live URL:
https://a3f1c2d4e5b60789.flypod.pageOpen it. The site is live. You can also deploy a single file:
npx flypod ./index.htmlflypod deploy ./dist is the same command, spelled out.
What gets uploaded
Everything in the folder, at any depth, except .git, .hg, .svn,
node_modules, .DS_Store, Thumbs.db, .env and .env.*. To leave out
more, put gitignore-style patterns in a .flypodignore file in the folder.
Whatever was left out is listed after the deploy (skipped in --json).
On flypod.dev a deploy may be at most 200 files and 10 MB. The CLI checks
before uploading and fails with too_large, naming the limit, instead of
sending a build the server would refuse.
Let flypod find the folder
Run with no path and flypod auto-detects a build directory: the first of these
that contains an index.html:
dist/ build/ out/ .output/public .vercel/output/static public/ _site/npx flypodAuto-detection only matches a directory that actually contains an index.html.
If none do, pass the path explicitly.
What the output looks like
In a terminal, flypod prints a short receipt:
✓ Deployed in 0.9s · 12 files · 1.2 MB
https://a3f1c2d4e5b60789.flypod.page
expires 19 Oct 2026 in 14 days
keep it flypod login free · removes the expiry
update flypod update publishes a new version · same URLAdd --verbose for more rows of the same receipt: the rollback and history
commands, and the site id, version id and source folder. Warnings always show,
between the URL and the grid.
The split never changes:
- The live URL goes to stdout, whenever stdout is not your terminal. At a terminal you see it once, in the receipt.
- Everything else goes to stderr.
So URL=$(npx flypod ./dist) captures just the URL. When stdout is not a TTY
(a pipe, a CI job, an agent), flypod auto-detects it and strips the animation.
No flag needed.
Machine-readable output
For structured output, use --json and parse stdout:
npx flypod ./dist --json{
"ok": true,
"action": "created",
"url": "https://a3f1c2d4e5b60789.flypod.page",
"site_id": "a3f1c2d4e5b60789",
"version_id": "8f1a0c2e44b7d913",
"expires_at": 1782929906088,
"healed": ["spa-fallback"],
"warnings": [],
"link_saved": true,
"next": {
"update": "flypod update",
"versions": "flypod versions",
"rollback": "flypod rollback",
"keep": "flypod login --json"
}
}action is "created" on a folder's first deploy and "updated" when the
folder already had a site (see below). expires_at is epoch milliseconds on an anonymous deploy, and null on an
owned one. next holds the literal commands for what comes after (keep only
appears while the site can still expire). The receipt carries no tokens;
--json --verbose adds manage_token and claim_token, along with file and
byte counts, timing, and the expiry as expires_in_days and expires_at_iso.
The one exception is link_saved: false on an anonymous deploy: then the
default receipt includes manage_token, because nothing else is holding it.
For the bare minimum, use --quiet. The URL is the only thing on stdout, and
nothing else is printed (unless the folder link could not be saved for an
anonymous site; see below):
URL=$(npx flypod ./dist --quiet)Owned vs anonymous
If you are logged in, the deploy is owned and permanent. If not, it is
anonymous and expires after 14 days. Running flypod login later
automatically claims every anonymous site this CLI remembers — no tokens to
copy. --json --verbose also includes a claim_token for the rare case where
you need to claim a site from a different machine. See
Accounts & claiming.
The folder→site link
After a successful deploy, flypod records a link between the current folder and
the site it deployed to. This lets flypod update,
flypod versions, and
flypod rollback work without an ID. The link lives in a
per-user config directory (not in your repo), and recording it is
best-effort: if it fails, the deploy still succeeds.
That link also holds the site's manage_token (mode 0600), which is why the
deploy output never prints one, and why flypod login can later claim every
anonymous site this machine remembers in one step. If the link can't be
written — a read-only or ephemeral config dir — flypod says so loudly and prints
the token, because nobody else is holding it at that point.
flypod token reveals it on demand the rest of the time.
Running flypod again in a linked folder updates that site: same URL, a
new version, exactly as flypod update does. If the
folder's site is gone (deleted, or expired), flypod makes a new one instead.
To make a separate site from a folder that already has one, run
flypod --new. It creates a new site at a new URL and points the folder at
it. The CLI says so before uploading, and --json reports the previous site
as replaced_link; the old site stays live until it expires.
Flags
| Flag | Effect |
|---|---|
--json | Emit a JSON object on stdout. |
--verbose | The full receipt, in the terminal or with --json. |
-q, --quiet | URL on stdout, nothing else. |
--new | Make a separate new site, even though this folder already has one. |
--comments | Turn on comments for the site (needs a signed-in deploy). See Enable comments. |
--mode <mode> | With --comments: anonymous (default), passcode or approved. |
--timeline / --no-timeline | Turn the version History chip on or off for the site. See Update & rollback. |
-h, --help | Print usage. |
-v, --version | Print the flypod version. |