The plan

Positioning, the engine bet, every known platform constraint with its chosen answer, and the road from CLI to app. This page is the product's honesty contract.

Positioning

Existing “Linux on Android” apps tell a Linux desktop on your phone story. Cellar tells a different one: your pocket AI homelab — machines you tap to start, agent stacks you tap to install, schedules that respect battery and heat, and a bridge that gives agents the one thing no cloud VPS has: your phone's senses.

Engine choice

engineroot?verdict
proot (ptrace fake-root)no ✅ Core engine. Works on every device; proven by UserLAnd and Termux.
QEMU full-systemno Too slow without KVM. Possible later “compat mode”.
AVF / pKVM (real VMs)no, device-gated 🔭 The future backend, once the third-party API surface opens. The engine interface is designed so a VM backend can slot in.
Real containers (root)yesKills 95% of the audience. No.

“Machines” are one rootfs directory each — create / start / stop / exec / export / delete. For real OCI images, udocker (proot-backed) is the honest path and arrives as a catalog item, not the foundation.

Engine language: Go. One static arm64 binary, shipped inside the APK later; zero interpreter dependencies; CLI-first with --json on every read command so UIs and agents drive the same surface.

Constraints → solutions

Every known platform problem, with the chosen answer — this doubles as the FAQ's long form.

constraintsolution
No isolation between machines — one Android UID Positioned as a single-user lab, never multi-tenant. Secrets never live in a rootfs; the phone bridge is permission-gated per machine. Real walls arrive with the AVF backend.
proot performance tax Mostly moot for network-bound agents; honest benchmarks ship in the README. The CPU-hot path — local inference — runs native, outside proot, exposed to machines as an OpenAI-compatible localhost endpoint.
W^X exec restrictions (Android 10+) All binaries ship as lib*.so in the APK's native library dir — the jniLibs pattern UserLAnd proves viable — built 16 KB-page-aligned from day one.
Play Store policy risk Open source with the beta; Play attempted with current targetSdk, but F-Droid and GitHub releases are first-class, not a fallback of shame.
Phantom process killer, Doze, OEM app-sleepers Foreground service + wake lock + guided battery-exemption setup; one proot per running machine with a tiny init inside keeps the process tree far under Android's limits; guided (Shizuku/ADB) toggle for the phantom killer.
Thermals & battery Watt-awareness as a feature: thermal/battery gauges on the dashboard, “only while charging / under N°C” as scheduler conditions, auto-pause on thermal throttle.
Uptime honesty Agents as scheduled runs, not 24/7 daemons. Daemon mode exists; the UI is honest about what Android may do to it.
Storage Rootfs lives app-private (shared storage can't hold one). First-class export/backup; uninstall-wipes-everything is documented loudly.
arm64 only The catalog is curated arm64-native; amd64-only things are marked slow-lane (qemu-user).
Licensing Cellar's code is MIT. GPL binaries (proot, ttyd) are exec'd as separate processes, never linked; the terminal is ttyd in a WebView rather than GPLv3 view code.
Google ships AVF Terminal Treated as the future backend, not the competitor. Differentiation is everything a bare terminal will never do: catalog, keys, schedules, bridge, homelab console.

The phone bridge (the moat)

Cellar doesn't need a helper app for phone powers — it is an Android app. It can request notification access, SMS, location and sensors natively, and expose them to machines as a local HTTP API with a per-machine token:

GET  /v1/battery                 → { level, charging, temp }
GET  /v1/notifications?since=…   → permission-gated
POST /v1/notify                  → agent posts a notification
POST /v1/sms/send                → guarded, rate-limited, audit-logged
GET  /v1/location                → coarse/fine, permission-gated
GET  /v1/sensors/…               → accelerometer, light, …

Every capability is off by default, toggled per machine, and every call lands in a visible audit log (“agent research read 3 notifications today”). That design is both the ethics and the pitch.

The app (full GUI)

Kotlin + Jetpack Compose, with two WebView islands (ttyd terminal, web-app previews). Screens: Dashboard (thermal/battery/RAM gauges, activity feed), Machines (cards + create wizard), Catalog, Schedules (cron-with-conditions), Keys (Android Keystore), Bridge (permission matrix + audit log), Terminal, and later Share (Tailscale/cloudflared tunnels — phones sit behind carrier NAT, so reachability is a tunnel story).

One foreground service owns everything long-running; its notification is the machine-room status board (2 machines up · 41°C · agent running).

Roadmap

milestonedeliverablestatus
M0 — planRepo, design, CI skeleton✅ done
M1 — engine v0 Machines + catalog on real devices; a real agent harness running inside for a week of daily use 🟡 engine verified on-device, hardened by multi-lens code review and CI; dogfood week running
M2 — app skeleton Compose app: machines, create wizard, terminal, foreground service, engine embedded as a jniLib. Fresh phone → running Debian machine in <5 min next
M3 — AI layer Keystore keys, agent catalog in-app, schedules, bridge v1 with audit log planned
M4 — polish & ship Dashboard gauges, export/backup UX, local models, F-Droid metadata, Play attempt, benchmarks + demo videos planned

Sequencing rule: engine before app. If the engine isn't pleasant to drive from a terminal for a week, no amount of Compose fixes it.