Phone-local AI toolchain: layers, switching, and bounded acceptance
This lab composes six repositories without copying their installation logic.
Ownership
| Layer | Repository | Success condition |
|---|---|---|
| Android, Termux, Kali PRoot | pocket-pentest |
Base runtime starts and privilege boundaries are explicit |
| OpenCode, Claude Code, local Happy stack, and Mobile Lab Control | android-ai-stack |
CLI/TUI/Web, local server/daemon, and three native widgets pass separately |
| User-facing assistant and action layer | xiaohei-phone-agent |
Invocation, short command, risk policy, action, global stop, and rollback have independent state and evidence |
| On-device interaction evidence | android-device-test |
Prefer text assertions; capture one screenshot only when needed |
| Optional remote Happy relay | happy-relay-deploy |
Add only for an explicit remote-access requirement |
| Cross-repository review | this hub | Facts, inferences, unknowns, versions, and dates remain traceable |
The default phone is a self-contained control plane: the Happy app connects to the server on phone loopback, and its daemon and Claude Code are also local. Model inference may still use a cloud or private-relay URL/token. A remote Happy relay is not a prerequisite.
Minimal sequence
- Record device, Android, Termux, Kali, and tool versions without serials or credentials.
- Run
quick,tui, andweb-startfromandroid-ai-stack: zero model calls. - Only after they pass, make one exact-echo request from OpenCode and one from Claude.
- Perform one complete Happy-app message round trip; a connected badge is not end-to-end proof.
- Use Xiaohei’s explicit entry to run one deterministic low-risk action. Select a model profile only for a planning case, and verify that profile change did not start or stop services.
- Stop at the first failure and retain at most 60 redacted log lines. Change one cause before one retry.
Phone control surface
Keep model configuration separate from service lifecycle. ai-model use
PROFILE changes configuration only; Happy and llama.cpp have explicit,
independent controls. The native Mobile Lab Control app exposes three widgets
that can be placed separately: Happy, llama.cpp, and Model profiles. The
first two manage only their service lifecycle, while the model widget changes
configuration only. If a profile changes while Happy is running, its status
becomes STALE until the operator chooses to restart it.
The app requests the Termux command permission but no Internet permission. A
phone-local mode-0600 mapping gives fixed slots readable labels without exposing
tokens, endpoint URLs, or the CC Switch database to the app. The public repository
contains bilingual UI, complete source, the allow-listed bridge, deploy/validate
Skills, CI builds, and a
release-signed APK.
Version 0.3.0 completed the three-widget device exercise; public version 0.4.0
then generalized configuration, added English/Chinese localization and scoped
widget state, and passed repository tests plus APK build, permission, and
signature checks. Moving once from a debug-signed build to the public signature
requires uninstalling the old app and re-adding the widgets.
The verified optional fallback is Qwen3 0.6B Q8 through llama.cpp with context
8192, one request slot, and four CPU threads. It passed a short no-tool
local-lite OpenCode case but not the default build-agent budget. Keep it
loopback-only, authenticated, and stopped when unused; exact evidence belongs
in the android-ai-stack case study.
The result must report each layer as PASS, FAIL, BLOCKED, or NOT TESTED
and state the model-call count. “Installed” must not be rewritten as “working.”
Xiaohei is the product action layer in this chain, not a sixth runtime. It
reuses model profiles and device evidence while owning invocation, bounded
sessions, risk policy, confirmation, and rollback. Base mode does not depend on
root, pocket-pentest, or a remote Happy relay.