# Hibe agent quickstart **API version: 1.1.0** · `GET https://hibe.dev/api/version` to check. Hibe deploys static HTML apps. Get a token, push your workdir, share it. That's the contract. Every endpoint authenticates via the bearer token from the device flow. Every JSON-emitting curl in this doc uses `python3 -c '…'` for parsing so you don't need `jq`. ## 0. Version handshake (read this first, every session) Cache the `version` string the first time you read `/help`. Before every operation, fetch `/api/version` (or read the `X-Hibe-API-Version` response header on any other call) and compare: ```bash SEEN=1.1.0 # the version YOU cached when you parsed /help LIVE=$(curl -s https://hibe.dev/api/version | python3 -c 'import json,sys; print(json.load(sys.stdin)["version"])') if [ "$LIVE" != "$SEEN" ]; then # The API changed. Re-fetch /help, re-parse, then continue. curl -s https://hibe.dev/help > /tmp/hibe-help.txt fi ``` Every response also carries `X-Hibe-API-Version: 1.1.0`. If you see a different value on any call, treat it as a re-read trigger. Versioning policy: - MAJOR change ⇒ a previously-documented endpoint or schema is broken. - MINOR change ⇒ a new endpoint or new optional field; old contract still works. - PATCH change ⇒ doc clarification or behaviour-preserving fix. Any change at any level requires re-reading `/help`. ## 1. Get a token (one-time) ```bash RESP=$(curl -s -X POST https://hibe.dev/api/auth/device) USER_CODE=$(echo "$RESP" | python3 -c 'import json,sys; print(json.load(sys.stdin)["user_code"])') DEVICE_CODE=$(echo "$RESP" | python3 -c 'import json,sys; print(json.load(sys.stdin)["device_code"])') echo "Open https://hibe.dev/device and enter: $USER_CODE" # Poll until the user approves (max 10 min): while true; do P=$(curl -s -X POST https://hibe.dev/api/auth/device/poll \ -H 'content-type: application/json' \ -d "{\"device_code\":\"$DEVICE_CODE\"}") TOK=$(echo "$P" | python3 -c 'import json,sys; d=json.load(sys.stdin); print(d.get("access_token",""))') [ -n "$TOK" ] && break sleep 5 done mkdir -p ~/.config/hibe && echo "$TOK" > ~/.config/hibe/token chmod 600 ~/.config/hibe/token ``` All later commands attach the token via `Authorization: Bearer $TOK`. ## 2. List your projects (GET /api/projects) ```bash TOK=$(cat ~/.config/hibe/token) curl -s https://hibe.dev/api/projects -H "Authorization: Bearer $TOK" # → [{ "id": "…", "name": "my-app", "share_enabled": false, # "share_id": null, "share_public": false, … }] ``` ## 3. Push the current workdir — tarball (POST /api/projects) ```bash NAME=my-app # must be unique within your account # Workdir root MUST contain either index.html OR index.md (markdown). test -f index.html || test -f index.md || echo "Need index.html or index.md at root." tar --exclude='.git' --exclude='node_modules' -czf /tmp/$NAME.tgz . curl -X POST https://hibe.dev/api/projects \ -H "Authorization: Bearer $TOK" \ -F "name=$NAME" \ -F "tar=@/tmp/$NAME.tgz" ``` Your project goes live at `https://hibe.dev/p//$NAME/`. If the entry is `index.md`, Hibe renders it to a styled HTML page on every fetch using the Hibe prose theme. Other `.md` files inside the project also render to HTML when fetched directly. ## 4. Push a single HTML file (POST /api/projects/single-html) For one-file pages with no assets — the file is stored as `index.html`. ```bash curl -X POST https://hibe.dev/api/projects/single-html \ -H "Authorization: Bearer $TOK" \ -F "name=$NAME" \ -F "html=@./page.html" ``` ### Push a single Markdown file (POST /api/projects/single-md) Same shape, but the file is stored as `index.md` and rendered to a styled HTML page on every serve. Form field name is `md`. ```bash curl -X POST https://hibe.dev/api/projects/single-md \ -H "Authorization: Bearer $TOK" \ -F "name=$NAME" \ -F "md=@./README.md" ``` ## 5. Replace contents of an existing project (PUT /api/projects/{id}) The share URL is preserved. ```bash PROJ_ID=… # from GET /api/projects tar --exclude='.git' -czf /tmp/update.tgz . curl -X PUT https://hibe.dev/api/projects/$PROJ_ID \ -H "Authorization: Bearer $TOK" \ -F "tar=@/tmp/update.tgz" ``` ## 6. Rename a project (PATCH /api/projects/{id}) ```bash curl -X PATCH https://hibe.dev/api/projects/$PROJ_ID \ -H "Authorization: Bearer $TOK" \ -H 'content-type: application/json' \ -d '{"name":"new-name"}' ``` ## 7. Browse the files in a project ```bash # Recursive tree: curl -s https://hibe.dev/api/projects/$PROJ_ID/files \ -H "Authorization: Bearer $TOK" # → [{ "path": "index.html", "type": "file", "size": 1234 }, …] # Raw content of one file: curl -s https://hibe.dev/api/projects/$PROJ_ID/files/index.html \ -H "Authorization: Bearer $TOK" ``` ## 8. Share — public (no password) `PATCH /api/projects/{id}` with `share_enabled:true, share_public:true`. Anyone with the URL can view. A `share_id` is minted on first enable and preserved across rename, update, and public ↔ private flips. Works for both HTML and Markdown projects — visitors load `/s//` and see the rendered page directly (markdown is rendered to styled HTML on every fetch). ```bash SHARE=$(curl -s -X PATCH https://hibe.dev/api/projects/$PROJ_ID \ -H "Authorization: Bearer $TOK" \ -H 'content-type: application/json' \ -d '{"share_enabled":true,"share_public":true}') SID=$(echo "$SHARE" | python3 -c 'import json,sys; print(json.load(sys.stdin)["share_id"])') echo "Public share URL: https://hibe.dev/s/$SID/" ``` ## 9. Share — private (4-character password gate) `share_password` MUST match `^[a-z0-9]{4}$` exactly. The page renders a password form for any visitor without a valid share cookie; the cookie lives 24h. ```bash curl -X PATCH https://hibe.dev/api/projects/$PROJ_ID \ -H "Authorization: Bearer $TOK" \ -H 'content-type: application/json' \ -d '{"share_enabled":true,"share_public":false,"share_password":"abcd"}' ``` Visitors POST to `/s//auth` with `password=abcd` to get the cookie; uppercase submissions are folded to lowercase server-side. Markdown projects gate the same way: visitors see the password form first, and after admit the rendered HTML page is served. ## 10. Rotate the share password Send only `share_password` — the new hash replaces the old one, and **every existing viewer session is invalidated on the very next request** (the cookie's password fingerprint stops matching). The `share_id` does not change, so the URL stays the same. ```bash curl -X PATCH https://hibe.dev/api/projects/$PROJ_ID \ -H "Authorization: Bearer $TOK" \ -H 'content-type: application/json' \ -d '{"share_password":"wxyz"}' ``` ## 11. Disable sharing (PATCH /api/projects/{id}) ```bash curl -X PATCH https://hibe.dev/api/projects/$PROJ_ID \ -H "Authorization: Bearer $TOK" \ -H 'content-type: application/json' \ -d '{"share_enabled":false}' ``` The old `share_id` immediately returns 404; re-enabling later mints a fresh one. ## 12. Delete a project (DELETE /api/projects/{id}) ```bash curl -X DELETE https://hibe.dev/api/projects/$PROJ_ID \ -H "Authorization: Bearer $TOK" ``` The directory and share URL are gone. ## 13. Manage your tokens ```bash # List tokens (no plaintext returned): curl -s https://hibe.dev/api/auth/tokens -H "Authorization: Bearer $TOK" # Revoke a token (the bearer is invalidated immediately): curl -X DELETE https://hibe.dev/api/auth/tokens/ \ -H "Authorization: Bearer $TOK" ``` ## Rules - The project root MUST contain `index.html` or `index.md` (`.markdown` also accepted). When both are present `index.html` wins. Either may be a symlink, but the link MUST resolve inside the project dir. - Markdown files are rendered to styled HTML on each fetch (the Hibe prose theme). Source bytes still accessible at `/api/projects/{id}/files/`. - No symlinks may escape the project dir. - No `..` segments or absolute paths in tarball entries (rejected at extract time). - Project names: 1-64 chars, alphanumeric / `-` / `_`. Cannot start with `.`. Per-user unique. - Share passwords: exactly `[a-z0-9]{4}` — 4 lowercase alphanumeric characters. Uppercase or symbols → 400. - Share session cookie TTL: 24 hours. Rotating the password evicts all in-flight sessions instantly. - A renamed project keeps the same share URL.