uConsole cyberdeck: ua-node container + cyberpunk Textual TUI client
  • Python 94.1%
  • Shell 5.9%
Find a file
pete d425ae749b
Some checks failed
CI / test (push) Failing after 12s
CI / bundle-skeleton (push) Has been skipped
CI / snapshots (push) Has been skipped
cli 0.2.13: bump __init__.__version__ (missed in prior commit)
2026-06-21 19:39:43 +00:00
.forgejo/workflows Phase 0.5 Step 4: CI gate workflow (Forgejo Actions) 2026-06-07 23:25:19 +00:00
cli cli 0.2.13: bump __init__.__version__ (missed in prior commit) 2026-06-21 19:39:43 +00:00
docs docs: Phase 3.5 multi-RX cluster + dual-TX chains design 2026-06-10 05:21:17 +00:00
node Phase 0.5 Step 5: qemu integration harness for auto-update chain 2026-06-07 23:33:40 +00:00
scripts Pre-provisioning docs: SD prep, LUKS, cellular, boot flow, security 2026-06-07 22:04:16 +00:00
.gitignore Initial scaffold: ua-node container + cyberpunk Textual TUI 2026-06-07 21:30:57 +00:00
LICENSE Initial scaffold: ua-node container + cyberpunk Textual TUI 2026-06-07 21:30:57 +00:00
README.md docs: update uConsole radios board v2 spec across all docs 2026-06-10 04:21:53 +00:00

ua-deck

uConsole cyberdeck for the Unified Assistant mesh.

A self-contained cyberdeck stack for the ClockworkPi uConsole (Raspberry Pi CM4) — a local ua-node mesh peer running in Docker, plus a cyberpunk-themed Textual TUI that talks to it on localhost:8200.

+----------------------------------------------------------------+
| uConsole (CM4 Lite, 4 GB, arm64, microSD)                      |
|                                                                |
|   Docker                                                       |
|   +---- ua-node container ---------------------------+         |
|   |  MeshModule -> https://agents.lab.lostsource.net |         |
|   |  MemModule, ChatModule (local cache + sync)      |         |
|   |  GatewayModule -> 127.0.0.1:8200                 |         |
|   +--------------------------------------------------+         |
|                            ^                                   |
|                            | localhost HTTP / SSE              |
|                            |                                   |
|   ua-deck (Textual TUI)  --+                                   |
|       streaming chat, mem browser, tasks, frigate              |
+----------------------------------------------------------------+

Why two layers?

  1. The TUI stays trivial. It's a localhost HTTP/SSE client. No Tailscale handling, no WSS reconnect logic, no token shipping. Just plain HTTP to 127.0.0.1:8200 — identical to how the UA web UI talks to its own gateway.
  2. Offline-resilient. Memory and chat history live locally and sync upstream in the background. Search, browse, and compose still work when WiFi flakes.
  3. First-class mesh identity. The node carries an Apricorn-issued Ed25519 leaf cert and announces itself via POST /mesh/hello — same trust model as pete-device.

Layout

ua-deck/
├── node/                 # ua-node container deployment
│   ├── docker-compose.yml
│   ├── config.yaml       # mesh upstream + module wiring
│   ├── env.example       # UA_NODE_CERT_FILE, UA_MASTER_PUBKEY_B64, etc.
│   └── systemd/          # ua-deck-node.service (manages docker compose)
│
├── cli/                  # Textual TUI client
│   ├── pyproject.toml
│   ├── ua_deck/
│   │   ├── __main__.py
│   │   ├── app.py
│   │   ├── config.py
│   │   ├── api/          # gateway HTTP/SSE client
│   │   ├── auth/         # localhost token reader
│   │   ├── screens/      # main, memory, tasks, frigate, settings
│   │   ├── widgets/      # chat_log, input_bar, tool_drawer, status_bar
│   │   └── themes/
│   │       └── cyberpunk.tcss
│   └── tests/
│
└── docs/
    ├── PROVISIONING.md   # ClockworkOS first-boot
    ├── CERT_CEREMONY.md  # Apricorn mint flow for this node
    └── ARCHITECTURE.md

Quick start (development, before uConsole arrives)

The CLI can be developed against a ua-node running on any amd64 host:

# Pull the ua-node image and start it (amd64 host)
cd node
docker compose up -d

# In another terminal, install + run the TUI
cd cli
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
ua-deck

The TUI connects to http://127.0.0.1:8200 by default. Override with UA_DECK_BACKEND=http://other-host:8200.

Hardware target

Spec Value
SBC Raspberry Pi CM4 Lite (socketed, SD-boot)
RAM 4 GB LPDDR4
Arch linux/arm64/v8 (Cortex-A72)
Storage microSD only (no eMMC — that's what "Lite" means)
Display 5" IPS 1280×720, landscape orientation
Char grid ~150×45 (11-12px font) / ~110×38 (14px) / ~90×30 (16px)
Input Backlit QWERTY + optical trackball
OS ClockworkOS (Debian)
Network Wi-Fi 5 + BT 5.0 + SIM7600G-H LTE Cat-4 + dual GNSS
Radio board v2 RTL2832U+R860 SDR (100 kHz1.74 GHz, TCXO, bias tee), SX1262 LoRa (860960 MHz, 22 dBm), GPS+BDS+GNSS, PCF85063A RTC, RJ45 1 Gbps, Type-C side port

Why Kit RPI-CM4 Lite (vs. Kit A-06 Rockchip RK3399)

Same chassis, same display, same keyboard, same expansion slots — only the compute module differs. We picked CM4 Lite because:

  1. Software ecosystem. Raspberry Pi OS / Debian aarch64 means Docker, systemd, RAUC, NetworkManager, ModemManager are first-class. RK3399 community stacks lag on kernel/driver updates.
  2. arm64 pipeline already wired. linux/arm64 is in the unified-assistant buildx matrix (commit e806739). RK3399 would mean rebuilding the RAUC integration from scratch.
  3. SD-boot matches pre-provisioning. "Lite" = no eMMC, so scripts/prepare-sd.sh flashes an SD and the user inserts and boots — no rpiboot USB-OTG flash path needed.
  4. Socketed module = upgrade path. The CM4 is not soldered. Pull it, drop in a CM5, keep the chassis.

Upgrade path: CM5 Lite drop-in (future)

The uConsole carrier uses the standard 100-pin Hirose connector shared by CM4 and CM5. ClockworkPi confirmed CM5 compatibility on the uConsole carrier; the community has been running CM5s in this chassis. When a swap makes sense:

Spec CM4 Lite (today) CM5 Lite (future)
SoC BCM2711 BCM2712
CPU 4× Cortex-A72 @ 1.5 GHz 4× Cortex-A76 @ 2.4 GHz
Perf delta baseline ~23× single-thread, ~2× multi-thread
RAM 1/2/4/8 GB LPDDR4 2/4/8/16 GB LPDDR4X
GPU VideoCore VI VideoCore VII (~2× faster)
Peak power ~6 W ~9 W (hotter, shorter battery)
Cost (4 GB) ~$45 ~$7090 (8 GB ~$120, 16 GB ~$165)

What CM5 unlocks for ua-deck:

  • Local LLM inference becomes viable on a 16 GB CM5 — small quantized models (Qwen2.5-3B 8-bit, small Gemma) run offline. CM4 4 GB can't load them. Aligns with the blackwall directive — substrate independence if the link dies.
  • Multi-app mode (Phase 1.5+2) gets cheap — i3 + Firefox + ua-deck + terminal panes on 8+ GB without warming the chassis.

The two preemptive design hooks needed to make a CM5 swap a no-op reflash — shipping both DTBs in the RAUC bundle and adding a SoC-detection branch to the healthcheck thermal budget — are tracked in docs/ROADMAP.md under Phase 1 backlog.

Roadmap

See docs/ROADMAP.md for the full phase plan. Headline:

  • Phase 0 (scaffold + provisioning) — Shipped
  • Phase 0.5 (auto-update + auto-rollback) — 🔄 In progress (design + RAUC + arm64 + deck profile shipped; healthcheck next)
  • Phase 1 (streaming chat TUI) — 📋 Awaits hardware
  • Phase 1.5 (sidebar + embedded terminal pane) — 📋 New, ~3 hrs
  • Phase 2 (desktop launcher + audio + Bluetooth) — 📋 New, ~3 hrs

Known blockers (carried over from the bigger UA roadmap)

  1. ua-node does not yet publish linux/arm64. Resolved 2026-06-07: unified-assistant e806739 adds linux/arm64 to the buildx matrix for both ua-node and ua-mem. Images now publish for amd64 + arm/v7 + arm64.

  2. node profile is mesh-only. Resolved 2026-06-07: unified-assistant e806739 adds a deck profile in ua_node/core/profiles.py with the full chat surface, mem, mesh, and supporting modules. Set UA_MODULES_PROFILE=deck in the compose file once a deploy with that commit lands.

  3. First-boot cert ceremony. Requires the Apricorn-mounted master key on an operator workstation. See docs/CERT_CEREMONY.md.

License

Same as the rest of the UA stack. Air-gap, sovereignty, defense in depth.