# weeny.cloud — full reference weeny gives a coding agent a real, persistent Linux server (root, SSH, systemd) with a control plane that turns processes into managed apps with public HTTPS URLs, logs, and off-machine backups. Flat plans (teeny $3 · weeny $8 · meany $20, founding pricing), 7-day free trial, no usage metering. You do NOT need Docker, Kubernetes, GitHub, or any framework. It's a normal computer. Two CLIs, one job each: `weeny-cloud` (laptop) gets code and people TO the server; `weeny` (server) operates apps. Everything else is bare Linux. ================================================================================ QUICKSTART (from the user's laptop) ================================================================================ npx weeny-cloud login # email → 6-digit code (ask the user to paste it) npx weeny-cloud create # server in ~2 min; prints the ssh command npx weeny-cloud push ./myapp # build locally, ship it → /apps/myapp on the server npx weeny-cloud ssh # go to the server Then on the server: cd /apps/myapp npm install # you handle deps/builds (node_modules isn't pushed) weeny start myapp -- npm start # supervise it weeny expose myapp 3000 # → https://myapp-xxxx.onweeny.com Iterate: edit locally → `npx weeny-cloud push ./myapp` → refresh. push ships SOURCE only (respects .gitignore; node_modules + .git never shipped) and then, on the server, installs deps + re-runs the build step (if the app has one — Next/Vite/etc.) + restarts. So an update is one command and never serves a stale build. `git clone` on the server works too. When unsure, bare `npx weeny-cloud` (laptop) or bare `weeny` (server) prints what to type next. ================================================================================ weeny-cloud CLI (laptop — `npx weeny-cloud `) ================================================================================ (bare) Where you stand: account, server + ssh command, next step. Also repairs the ~/.ssh/config shortcut for the server. login [--email X --code N] Sign in / claim a waitlist spot with email + 6-digit code. Non-interactive: pass --email, then --email + --code. The code lands in the human's inbox — unless you already have access to their emails, stop and ask them for it. keys [--revoke ID|--register] This account's device SSH keys. Every signed-in device can register its own key, so a lost/deleted key is never a lost server: `login` + `ssh` self-heals with a fresh key. create Provision your server (uses your SSH public key, generates one if needed). Starts the free trial. One server per account for now. push [folder] [app] Ship a local folder to /apps/ on the server (app defaults to the folder name; skips .git + node_modules; restarts the app if it's running — the update loop). --no-restart to skip the restart. ssh [command] Open a shell (or run one command) on the server with the right key + IP — no ssh config guessing. tier [name] The plans (bare = see them). Changing plan changes what the user PAYS — hand this to your human, don't run it. skill Install the weeny Claude skill into ~/.claude/skills. help [command] Details + examples. ================================================================================ weeny CLI (on the server) ================================================================================ (bare) Your apps: state, URLs, the Linux cheat lines, all commands. start -- Turn a command into an app: supervised (systemd), logged, surviving crashes/reboots. This is how ANYTHING (web app, worker, cron, database) becomes a managed app. Records the folder you run it from — run it from the app's directory. Re-run with a new command to update. Bare `weeny start ` brings a stopped app back. Managed env vars are injected on start; a local .env is also auto-loaded. expose Attach a public URL → https://-xxxx.onweeny.com Each app needs its own port (expose refuses a taken one). Re-exposing keeps the URL; a brand-new URL can take ~1 min to resolve everywhere. Add --private to require a weeny login to view (optionally --allow a@b.com,c@d.com). unexpose Take an app off the internet (keeps running; same URL on re-expose). remove The app stops being an app: process stopped, URL released for good (a re-created app mints a new one), gone from the dashboard. Files in /apps/ are NOT touched. env KEY=value … Set env vars: encrypted, injected on start, survive rebuilds, restart the app. Bare `weeny env ` shows them; `--unset KEY[,KEY2]` removes. domain Attach a custom domain (free, public apps) — prints the CNAME to add at the DNS provider. Bare `weeny domain ` checks progress; `--remove` detaches. allow [who] Access to a private app. Bare = who's in. `a@b.com` grants a person, `@company.com` a whole email domain, `everyone` makes the app public. revoke Take access away. `revoke everyone` = just you. health [--json] Memory/swap/disk/OOM — how the box is doing (see PLANS & MEMORY). help [command] Details + examples. Logs and process control are bare Linux — apps are systemd units named weeny-: journalctl -u weeny- -f logs (follow); -n 100 for recent journalctl -u 'weeny-*' --since -1h all apps at once systemctl stop weeny- stop (bring back: weeny start ) systemctl restart weeny- ================================================================================ CONVENTIONS ================================================================================ - /apps/ app code (apps live here) - Durability it's a normal computer — the whole machine persists and is backed up, so keep data wherever makes sense - App names lowercase letters, digits, hyphens - Env vars `weeny env KEY=value` — encrypted, survive rebuilds, restart the app. A local .env is also auto-loaded, but managed vars win over it. - Ports one localhost port per app; expose maps it to a URL - Public URLs everything exposed is public unless --private; don't expose secrets - Machine state /var/lib/weeny/apps.json is the machine-readable app registry ================================================================================ PRIVATE APPS ================================================================================ - `weeny expose --private` → the URL requires a weeny login to view. - `weeny allow a@b.com @company.com` — grant a person / a whole email domain. - `weeny allow ` — who's in. `weeny revoke a@b.com` — undo. - `weeny allow everyone` — make it public. - Your app receives the visitor's email in the `X-Weeny-User` header. - Agents/terminals: `npx weeny-cloud token ` (as any allowed user) prints a 12h bearer — call the app with `Authorization: Bearer `. Unauthenticated programmatic requests get a 401 that explains this; browsers still get the login flow. - People you `allow` can sign in to weeny with just their email — no invite needed (view-only accounts; servers stay waitlisted). - Discovery: every *.onweeny.com app answers `GET /__weeny` with what it is (public or private) and how to connect, and every response carries an `X-Weeny` header pointing there. ================================================================================ CUSTOM DOMAINS (free, public apps) ================================================================================ - `weeny domain app.example.com` — prints a CNAME to add at your DNS provider. - `weeny domain ` — check until the record + certificate are active. - `weeny domain --remove` — detach. ================================================================================ DURABILITY (so you can trust it) ================================================================================ - It's a normal computer — everything you do persists. The WHOLE machine is snapshotted and backed up off-machine (R2) regularly, not just one directory. - If a server breaks, the dashboard has a "rebuild" button: the entire machine is restored from the latest snapshot — apps, data, and everything else come back, same URLs. ================================================================================ PLANS & MEMORY (what your box can take) ================================================================================ Three flat plans, no metering, unlimited apps on all of them (founding pricing): teeny 1 vCPU · 1GB $3/mo (list $5) a teeny weeny server: small sites and bots. builds are slow — push pre-built or be patient. weeny 2 vCPU · 4GB $8/mo (list $10) can run anything: many apps, n8n, postgres, fast build loops. the trial runs on this one. meany 4 vCPU · 8GB $20/mo (list $25) for production apps hitting scale. - `weeny health` (on the box) = memory, swap, disk, per-app peaks, OOM kills. The same warnings appear automatically in push/start/expose output when the box is tight. - An OOM-killed app is a MEMORY problem, not a code problem. Fixes in order: stop an app you don't need · a bigger plan. - Changing plan changes what the USER pays — that decision is theirs, always. Tell them what you saw and point them at app.weeny.cloud/dashboard/billing (or they run `npx weeny-cloud tier`). The box reboots into its new size in about a minute; apps come back automatically. Never try to change the plan yourself. ================================================================================ RUNNING A REAL SERVICE (databases, n8n, etc.) — the 5 gotchas ================================================================================ Stateful services work well, but each of these will bite a naive deploy: - Apps run as ROOT: daemons that refuse root (postgres) need a privilege-drop wrapper (`exec setpriv --reuid= --regid= --init-groups `). - apt packages auto-start their OWN systemd unit that fights `weeny start` (port clash + boot race) → `systemctl disable --now ; systemctl mask `. - TLS is terminated at the edge: your app gets plain HTTP locally but is public over HTTPS → tell it (`*_PROTOCOL=https` / public-URL env). The public hostname exists only AFTER `weeny expose`, so: start → expose → set the URL env (auto-restarts). - "Lose-it-and-you're-done" secrets (e.g. an app's encryption key): pin them in `weeny env KEY=...` (encrypted, survives rebuilds) so they never regenerate. Docker works fully (bridge networking + `-p` publishing; no --network host needed) — supervise `docker run` in the foreground under `weeny start`, then `weeny expose` the published port. Full worked recipes (copy-paste): - Default stack (start here — Node + SQLite, any frontend): https://app.weeny.cloud/recipes/default.txt - teeny (1 GB) box — no server-side builds (no-build or build-locally): https://app.weeny.cloud/recipes/teeny.txt - Next.js / build-step app: https://app.weeny.cloud/recipes/nextjs.txt - Python (Flask/FastAPI): https://app.weeny.cloud/recipes/python.txt - PostgreSQL: https://app.weeny.cloud/recipes/postgres.txt - n8n: https://app.weeny.cloud/recipes/n8n.txt - Docker: https://app.weeny.cloud/recipes/docker.txt ================================================================================ MAKING YOUR APP USABLE BY OTHER AGENTS ================================================================================ Serve a /llms.txt from your app describing what it does, its API base, how to authenticate, and key endpoints. Then someone else's agent can use your app directly.