~6 min readgrounded in apps/cli/src/cli.ts · apps/cli/src/config.ts · apps/cli/README.md · docs/CLI.md · docs/EVIDENCE.md
CLI: npx tiny-vercel·
The CLI lives in the repository at apps/cli and ships as the npm package tiny-vercel. It is tiny-tech — the program behind every laptop on the production account — with its 54 hard-coded tiny.technology references replaced by one setting: where your deployment is.
Three commands: point, sign in, run. Until the package is on npm (an owner decision, D-013) use a checkout: npm ci --prefix apps/cli && node apps/cli/dist/cli.js ….
The one setting·
init fetches <url>/api/health. That endpoint is public on every tiny-vercel deployment and answers with the site's name and the worker origin it uses — the same value its own browser bundle already ships — so the CLI never has to be told about the worker separately:
$ npx tiny-vercel init https://tiny-vercel-scratch.vercel.app
Checking https://tiny-vercel-scratch.vercel.app/api/health …
✓ tiny-vercel at https://tiny-vercel-scratch.vercel.app · worker https://tiny-vercel-worker.cagatay.workers.dev
saved to ~/.tiny/config.json
~/.tiny/config.json (mode 0600) holds api, worker and siteName. When more than one source names a deployment the CLI takes the first of:
| Order | Source | When you would use it |
|---|---|---|
| 1 | --api <url> on the command line |
one-off commands against another deployment |
| 2 | TINY_API_URL |
CI, a daemon unit file, a second account on one machine (TINY_HOME moves the whole ~/.tiny) |
| 3 | ~/.tiny/config.json |
the normal case — written by init and by login |
| 4 | the origin recorded by an earlier login (credentials.json) or enrollment (device.json) |
upgrading a machine that never ran init |
| 5 | an interactive prompt | first run in a terminal with nothing configured |
Inside an MCP client there is no terminal to prompt, so a missing setting is an error whose text is the init command. TINY_WORKER_URL overrides the advertised worker if you ever need to.
What it does·
| Face | Start it with | What you get |
|---|---|---|
| MCP server | claude mcp add tiny -- npx -y tiny-vercel — or {"command":"npx","args":["-y","tiny-vercel"]} in any MCP client's config |
30+ tiny_* tools: identity, cross-agent memory (tiny_learn / tiny_recall), DMs, your tinys, forged tools, scheduled jobs, wallet, use_device — all proxied to your app's /api/* with your token. tiny_login opens the browser when a token is missing. |
| Local agent | npx tiny-vercel (TUI) · npx tiny-vercel repl · npx tiny-vercel "one question" |
A Strands agent running on this machine: shell, files, HTTP, screen control, Apple / Spotify / Google / WhatsApp / Telegram / Flipper / ADB, npm / PyPI / OpenAPI / MCP bridges, local memory, notifications, background loops, parallel sub-agents. Bring a model key (tiny-vercel onboard, or TINY_MODEL_* / OPENAI_API_KEY / Bedrock / Ollama) or let your deployment's /api/chat run the turns. |
| Device daemon | npx tiny-vercel mesh · npx tiny-vercel daemon install (launchd / systemd --user) |
Heartbeats so this machine shows online on /devices; polls the relay mailbox so the web agent's use_device can run work here; joins the devduck-compatible LAN mesh; serves a control socket (tiny-vercel tray status) that the optional Swift menu bar in apps/cli/menubar speaks. |
| Account plumbing | login · logout · whoami · devices · onboard · sync · connect [google\|spotify\|telegram\|whatsapp] |
The consent flow (browser approves, code returns on 127.0.0.1, exchanged for a 90-day token), model-provider and voice settings synced through your account, optional app connections stored locally with 0600 permissions. |
login also enrolls the machine as a device in the same step, so the very first mesh already heartbeats.
How it reaches your deployment·
Everything credentialed goes to the web app as Authorization: Bearer <token> against app/api/* — 27 routes, listed in docs/CLI.md. Three public reads (/retrieve, /list, /tools/browse) go straight to the worker the app advertised, and the same origin is the only place use_device will fetch a device's screenshot from. Nothing else on the network is contacted; there is no telemetry.
Proven against the demo·
On 2026-09-15 the exact sequence above was run from a clean TINY_HOME against the live demo: init derived the worker, login completed the loopback code exchange and enrolled the Mac, the daemon's heartbeat showed it online with 18 declared capabilities, and a chat on the demo asking the agent to use_device made the Mac run cat on a file that existed nowhere else — the file's contents came back in the chat 22 seconds later. Timings, sizes (npm pack 425 kB) and the raw tool results are in docs/EVIDENCE.md.
Where things live on disk·
| Path | Mode | Contents |
|---|---|---|
~/.tiny/config.json |
0600 | the deployment (api, worker, siteName) |
~/.tiny/credentials.json |
0600 | your 90-day token and login |
~/.tiny/device.json |
0600 | this machine's device id and token |
~/.tiny/model-config.json, integrations.json |
0600 | onboarded providers, connected apps |
~/.tiny/tools/ |
— | your own tools (.mjs exporting {name, description, handler}); use_tools reload picks up edits |
~/.tiny/tray.sock |
0600 | the daemon's control socket |
TINY_HOME relocates all of it. logout removes credentials and the device identity, nothing else.
Testing and packaging·
npm test --prefix apps/cli builds with tsc and runs 1,445 tests in about 17 s; none of them touch a real backend — the MCP smoke test starts a loopback stand-in deployment. swift test in apps/cli/menubar covers the menu bar. The CLI keeps its own package-lock.json because its TUI needs React 19 while the web app pins React 18 (D-012); root npm test and CI run it via --prefix.