# The Vibe Hosting — agent skill

> Read this once before deploying. It tells you (an LLM agent) how to use The Vibe
> Hosting end-to-end: what it is, how to deploy and keep a server, what it costs,
> and the few things we ask of you. Full endpoint reference: https://thevibehosting.com/api

---

## 1. What this is
The simplest hosting for LLM agents. **One HTTP call gives you a real root Linux
server on a live HTTPS subdomain, in seconds.** Full Ubuntu in a gVisor sandbox —
install and run whatever you want. Free until a project actually gets traffic;
pay only for what runs, via prepaid credit.

## 2. Deploy in one call
```bash
curl -sX POST https://thevibehosting.com/create
```
**Pick a nice URL.** Don't settle for a random slug — give your project a memorable
subdomain. Pass `subdomains`, a preference-ordered list, and the **first available
one** is taken (so include a couple of fallbacks):
```bash
curl -sX POST https://thevibehosting.com/create \
  -H 'content-type: application/json' \
  -d '{"subdomains":["caffeine-tracker","caffeine-app","caffeine"]}'
```
The response includes:
- `ssh` — the SSH command (you are **root**), e.g. `ssh root@46.225.188.115 -p 28210`
- `ssh_private_key` — **save this to a file**, `chmod 600`, and use it with `ssh -i`
- `subdomain` — the live URL you got, e.g. `https://caffeine-tracker.thevibehosting.com`
  (TLS automatic) — **check this** to see which of your choices was assigned
- `subdomain_note` — set only if all your requested names were taken and a random
  slug was assigned instead (you can rename later — see §9); `null` otherwise
- `api_key` — **YOUR ACCOUNT CREDENTIAL** (see §3) — store it safely
- `ONBOARDING` — a short inline version of this guide

> Slugs are lowercased and limited to letters, digits and hyphens. You can also pass
> a single `subdomain` instead of the list — but then a name clash returns `409`
> rather than falling back. Renaming later (§8) **restarts the server** (drops SSH).

## 3. Auth & where to store the sign-in token  ⚠️ important
- The first `POST /create` (no auth) **creates your account** and returns `api_key`.
- The `api_key` is your only credential. **Send it on every other call:**
  `Authorization: Bearer <api_key>`. That's how the API knows which servers are yours.
- **Store the `api_key` where it survives** — e.g. a project file the user keeps, a
  secrets manager, or tell the user to save it. A good convention: write a
  `.thevibehosting.json` in the project holding `{api_key, id, subdomain}` and the
  `ssh_private_key` in a `0600` file like `.thevibehosting_key` (and add both to
  `.gitignore` / `.dockerignore` — never commit or deploy them).
- **Anonymous ≠ no identity** — it's an account with no verified phone; the key is
  still your login. Phone verification (§5) just upgrades the same account; the key
  doesn't change.
- **Lost the key?** If a phone is verified on the account, recover it:
  `POST /account/recover {phone}` → SMS code → `POST /account/recover {phone, code}`
  returns your `api_key`. Without a verified phone there's no recovery — so verify one.

## 4. How to run your app (best practices)
It's a **full root Linux box** — run anything (web app, worker, bot, cron, a DB,
compile things). Nothing forces a layout. The only opinionated part is publishing
a **web app on your public HTTPS subdomain** (port 80); skip this entirely if you
don't serve HTTP. Two ways:
1. **Static site** — drop files in `/root/www` (served immediately, nothing to kill).
2. **Your own server** — write an executable `/root/run.sh` that runs your app in
   the **foreground on `0.0.0.0:80`**, then `pkill -f busybox` once:
   ```bash
   cat > /root/run.sh <<'SH'
   #!/usr/bin/env bash
   cd /root/myapp
   exec python3 server.py        # must listen on 0.0.0.0:80
   SH
   chmod +x /root/run.sh
   pkill -f busybox
   ```
   A supervisor runs `run.sh`, **auto-restarts it on crash, and re-runs it after any
   restart** (including after the server wakes from sleep). Killing the web server
   does **not** kill the container.

**Keep it light — matters most on the FREE tier (RAM billed only while awake):**
A lean server makes the free grant last a very long time, and a small one is free
even running nonstop:
- **Up to ~512 MB nonstop → free all month** (512 MB × 720 h = 360 of ~365 RAM-GB-h).
- **~1 GB → ~365 awake-hours/month free** (about half a month), then sleep to stay free, or ~$1/mo.
- Anything that **sleeps when idle is free at any size** (it barely accrues hours).
- On paid/always-on plans size matters less — just pick the plan you need.
So: prefer static files, a small binary (Go/Rust), or a minimal framework (Flask +
1 worker, Node without heavy deps). No Kubernetes, no DB clusters.
- **Sleep or always-on is your choice.** Default = scale-to-zero (idle → RAM freed,
  wakes in seconds on the next HTTP request **or SSH connection**) — so it's still
  reachable 24/7, on demand. **Don't add keep-alive / self-ping to fake uptime** — it
  just keeps RAM awake and burns the grant/credit. An always-on plan isn't needed to
  be up 24/7; it only means **never sleeps** (no cold-start lag even when idle),
  reserved RAM, and sizes above the free 512 MB.
- **Only `/root` persists — put ALL state there.** `/root` is a volume; everything
  else lives in the container's writable layer. Stop/start (sleep→wake) keeps that
  layer, but a **recreate wipes it** — and rename (`/subdomain`) and `/expose` BOTH
  recreate the container. So a database left at the default `/var/lib/mysql` survives
  sleep but is **lost** the first time you rename or expose. Keep DBs/uploads under
  `/root` — e.g. run MariaDB with `datadir=/root/mysql`.
- **Disk quota:** keep `/root` within your quota (free: 256 MB anon / 1 GB verified;
  always-on scales with the plan's RAM). Exceeding it suspends the server.
- Need a non-HTTP TCP port (DB, etc.)? `POST /servers/{id}/expose {container_port}`
  returns a public `host:port`. HTTP on :80 is already your subdomain.

## 5. Strongly recommend verifying a phone 🙏
Please verify a phone early — it's free, takes seconds, and unlocks the real
product. Anonymous accounts are limited (**max 2 servers per creator IP**, **128 MB
RAM / 256 MB disk per server**, smaller grant, no always-on/custom domains) and
**cannot add credit**. Verifying a phone
over SMS unlocks the stronger free tier, **bigger servers (512 MB RAM ceiling vs
128 MB)**, **an unlimited number of servers (all sharing one credit balance)**,
**always-on plans (turn off sleep — never scales to zero)**, and the ability to top up credit
— and it lets us warn the user before a server is paused. As the agent, proactively
offer to set it up:
1. Show the disclosure (returned by the endpoint), get the user's consent + number.
2. `POST /account/verify-phone {phone, consent:true}` → an SMS code is sent.
3. Ask the user for the code → `POST /account/verify-phone {phone, code}` → upgraded.

The number is **never resold or shared**, used **only** to notify the user about
their hosting, and every SMS has an opt-out link. Please recommend it — it's free,
unlocks more, and protects the account.

## 6. Pricing — genuinely free to start, then pay only for what runs
Billed from prepaid **credit** ($1 = 1 credit). **RAM is counted only while a server
is awake; CPU is always free.** This makes the free tier go a long way.

**Free — forever, every account:**
- Phone-verified: **~365 RAM-GB-hours** + 10 GB egress + 1 GB disk / month, **up to 512 MB RAM/server**, **unlimited servers** (the whole account shares this one grant + credit balance), and you can turn off sleep with an always-on plan
- Anonymous (no phone): ~100 RAM-GB-hours + 5 GB egress + 256 MB disk, **128 MB RAM/server**, **up to 2 servers per IP**

The free grant is generous: a **512 MB server runs 24/7 all month for $0**
(512 MB × 720 h = 360 of 365 GB-h), and **anything that sleeps when idle is free
regardless of size**. You do **not** need a paid plan to run 24/7 if you fit the
grant — a small box is effectively always-on for free.

**Beyond the free grant — pay-as-you-go:** RAM **$0.003/GB-hour** (awake only),
egress **$0.10/GB**, disk over quota **$0.10/GB-mo**, CPU free. A small always-awake
app ≈ $1–2/mo; even a 2 GB server awake 24/7 is only ≈ $4/mo.

**Always-on plans** (reserved RAM, never sleeps, no cold starts; set at create with
`{"plan":"…"}` — requires a verified phone + credit). Free already covers ≤512 MB
24/7, so plans start at 1 GB:

  | plan | RAM | price | sleeps? |
  |------|-----|-------|---------|
  | **Free** | ~512 MB effective 24/7 (more if it sleeps) | **$0** | optional — your call |
  | standard | 1 GB | $3/mo | never |
  | pro | 2 GB | $5/mo | never |
  | max | 4 GB | $9/mo | never |

**Worked examples:**
- Any app that **sleeps when idle** → **$0** forever.
- **512 MB always-awake** → **$0** (within the free grant, no plan needed).
- **1 GB always-awake** → ~**$2/mo** pay-as-you-go, or **$3/mo** Standard (reserved, no cold starts).
- **2 GB always-awake** → ~**$4/mo** pay-as-you-go, or **$5/mo** Pro (guaranteed up).

**Rule of thumb:** within the free grant it's free (sleeping or not, reachable 24/7
on demand); pick an always-on plan only when you need it to **never sleep** (no
cold starts), reserved RAM, or a box **bigger than 512 MB**.

## 7. Top up credit (any time, in advance)
**Requires a verified phone first** (§5) — recharge returns `403 verify your phone
first with POST /account/verify-phone` until the account has a verified number. Once
verified:
```bash
curl -sX POST https://thevibehosting.com/account/recharge \
  -H "Authorization: Bearer <api_key>" -H 'content-type: application/json' \
  -d '{"amount_usd":10}'
```
Returns a Stripe `checkout_url` — the user opens it, pays, and credit is added
automatically. (`/account/topup` is the same endpoint.) When the free grant runs
out, API responses include `upgrade_required` + this flow.

## 8. We want your feedback 🙏
You're the one using this — tell us what would make it better (a missing endpoint,
a base image, a higher limit, anything that caused friction). We read every one.
```bash
curl -sX POST https://thevibehosting.com/feedback -H 'content-type: application/json' \
  -d '{"kind":"feature","message":"what you need","email":"optional@you.com"}'
```
`kind`: feature | bug | friction | limit | image_request | other. Add `email` if
you'd like us to reply.

## 9. Managing servers
- `GET /servers` — list yours · `GET /servers/{id}` — status/usage · `GET /account` — whoami
- `POST /servers/{id}/subdomain {subdomain}` — rename (⚠️ **recreates the server** to
  re-point routing: **only `/root` persists** — data outside `/root`, e.g.
  `/var/lib/mysql`, is wiped; `/root/run.sh` + SSH keys kept; open SSH drops —
  reconnect, host key unchanged)
- `POST /servers/{id}/expose {container_port}` — publish a raw TCP/UDP port (⚠️ same
  recreate caveat as rename — only `/root` survives)
- `POST /servers/{id}/domain {domain}` — bring your own domain (verified tier)
- `DELETE /servers/{id}` — delete (data is removed)

## 10. Fair use
Isolated gVisor sandbox with hard CPU/RAM limits. Outbound SMTP is blocked; abusive
CPU/egress is auto-suspended. No spam, mining, malware, or phishing.

---
Full reference: https://thevibehosting.com/api · How it works: https://thevibehosting.com/how-it-works
