quickish
Publish a folder of HTML and assets to the web in one command.
npm i -g quickish
quickish login # sign in with Google
quickish # publish the current folderYour page goes live at https://<you>.quickish.site/ (personal) or
https://<company>.quickish.space/ (work account). No build step, no config,
no server. Just a folder of files.
Commands
| Command | What it does |
|---|---|
quickish login |
Sign in with Google (opens a browser; a token is returned to a throwaway 127.0.0.1 listener, so the CLI never holds Google credentials). |
quickish [folder] [page] |
Publish a folder (default .) to your root page. An optional sub-page name publishes to /name/, e.g. quickish ./site deck. |
quickish --localish |
Tunnel your local dev server to a private Quickish URL (see below). |
quickish whoami |
Show the signed-in account. |
quickish open |
Print your space's URL. |
quickish logout |
Forget the stored token. |
Visibility
Pages default to sensible visibility and you can override per push:
- Personal accounts → public (after a one-time content-policy consent on the web).
- Workspace accounts → company-visible (anyone signed in at your domain).
--private→ only you.--invites a@co.com,b@co.com→ private to you and the people you list (they sign in to prove it).--public→ share with the world (one-time consent).--workspace→ share with your company.
Need fine-grained, per-person access without Google Drive? Use --invites.
(Drive-folder publishing is coming soon.)
Scheduled functions (triggers)
Run a server-side function (functions/<name>.js) on a schedule by declaring a
trigger in your app's quickish.json:
{
"name": "Flipboard",
"timezone": "America/Los_Angeles", // optional — for time-of-day triggers
"triggers": {
"weather": { "type": "timed", "value": "15m" }, // every 15 minutes
"digest": { "type": "timed", "value": "9:00am", "daysOfWeek": ["mon","wed","fri"] }
}
}valueis a frequency (30s,5m,1h,10 minutes,5 hours— minimum 30s) or a time of day (9:00am,13:00,1pm— runs once a day in your timezone).daysOfWeekis optional (omit = every day); usemon…sunor full names.- A function may have several triggers (pass an array).
quickish validates triggers before publishing — a bad schedule (below the 30s floor,
an unparseable time, a trigger for a function that doesn't exist) aborts the publish with a
clear message; nothing is uploaded. quickish dev runs the same schedules locally so you can
verify them offline first.
Localish — your localhost on a Quickish URL
quickish --localish # auto-detect your dev server and tunnel it
quickish --localish # in a docker-compose repo: pick which service to tunnel
quickish --localish --port 5173 # tunnel a specific port
quickish --localish --service api # tunnel a specific compose service (no prompt)
quickish --localish --name app # choose the URL handle--localish turns the CLI into a reverse tunnel from a stable Quickish URL to
your local dev server (pnpm dev / npm start). Your app becomes reachable at
https://<you>.quickish.site/_localish/<name>/ — live, served straight from your
machine, with no build and no publish. Stop the CLI (Ctrl-C) and the URL goes
offline. It's ngrok, but owned by Quickish, private by default, and stable
across restarts.
- Attach or start. If a dev server is already running it's tunnelled; otherwise the CLI offers to run your detected dev script and supervises it.
- docker-compose + monorepo aware. Localish discovers what you can tunnel from both
sides: Docker services (from
docker compose ps) and host-side dev servers in a pnpm/npm/yarn workspace (each package'sdevscript + its port). That covers the common mixed setup — FE on the host viapnpm/turbo, API in Docker — showing both in one picker. It ranks them (frontend / API / database; databases are shown but skipped — it tunnels HTTP, not the DB wire protocol), navigable with arrow keys or number keys. If nothing's running it offers to bring things up — a Makefilestart/devtarget (e.g.make start→pnpm turbo run dev), a rootpnpm dev/npm startscript, ordocker compose up -d— and if you pick a host dev server that's stopped, it starts that package for you. Your choice is remembered per project (--serviceto pin,--forgetto reset). - HMR works. WebSocket upgrades tunnel end-to-end, so Vite/Next hot-reload
through the URL (set the framework's
baseto/_localish/<name>/for HMR on an already-running root-base server). - Private only. A localish site is company-visible on a work account (org
members can reach it), owner-only on personal;
--privateforces owner-only. It can never be public. - Resilient. The tunnel reconnects automatically (with backoff) if the connection drops — the same URL resumes.
- Plan limits. Free includes 1 active localish tunnel; paid is unlimited.
- Agent-friendly. A desktop coding agent gets a URL it can verify changes
against;
GET /_localish/<name>/__statusreturns JSON readiness (online,port).
Environment overrides
QUICKISH_CONTROL: control-plane base URL (defaulthttps://quickish.website).QUICKISH_API: API base URL (defaulthttps://api.quickish.website).XDG_CONFIG_HOME: where the token is stored (default~/.config/quickish).