Skip to content

hardwario/tower

Repository files navigation

TOWER

Control plane for the HARDWARIO TOWER ecosystem.

This repository orchestrates the repos behind TOWER — the firmware, the host CLI, the shared wire protocol, and the UART flasher — as Git submodules, so you can drive the whole system from a single Claude Code session with full cross-repo context. It holds no product code of its own; it holds the knowledge of how the pieces fit together and the workflow to keep them in sync.

tower/                ← you are here (the control plane)
├── protocol/         → github.com/hardwario/tower-protocol   (the contract)
├── firmware/         → github.com/hardwario/tower-firmware    (the device)
├── cli/              → github.com/hardwario/tower-cli         (the host tool)
├── jolt/             → github.com/hardwario/jolt             (UART flasher, used by cli)
├── CLAUDE.md         the operating manual for Claude across all four
└── .claude/commands/ /bootstrap · /build · /sync · /pin

The ecosystem

TOWER is HARDWARIO's wireless, modular IoT kit. The Core Module is an STM32L083CZ (Arm Cortex-M0+) with a SPIRIT1 sub-GHz radio (EU 868 / US 915 MHz, AES-128-CCM secured). The firmware emits a framed serial console; the tower CLI decodes and renders it; firmware updates ship over-the-air as Ed25519-signed images.

Repo Role Lang Version
tower-protocol Shared no_std wire-format crate: COBS+CRC framing, postcard message schema, signed FOTA manifest. The single source of truth both other repos depend on. Rust 1.0.0
tower-firmware Embassy-based firmware SDK, ready-made product apps, and the A/B FOTA bootloader for the STM32L0 Core Module. Rust 0.1.0
tower-cli Host-side tower CLI/TUI: streams logs/events, an interactive shell, flashes over UART, and serves FOTA images. Rust 0.2.0
jolt STM32L0 UART-bootloader flasher. tower-cli links it as a library for flash/erase/reset; also usable standalone. Rust 1.2.0
                 tower-protocol  (frames + FOTA manifest)
                 ▲                                        ▲
                 │ same git tag                           │ same git tag
   ┌─────────────┴──────────────┐            ┌────────────┴───────────────┐
   │  tower-firmware (device)    │  USB/UART  │  tower-cli (host)           │
   │  STM32L083CZ · Embassy      │ ── frames ▶│  decode logs/events/shell   │
   │  framed console + FOTA      │ ◀── shell ─│  flash · reset · fota serve │
   └─────────────────────────────┘            └─────────────────────────────┘

The one rule that matters: firmware and cli must pin the same tower-protocol tag. The wire format is postcard (not self-describing), so a mismatch silently mis-decodes instead of erroring. /sync checks this for you.

Quick start

# Clone with the children in one shot
git clone --recurse-submodules git@github.com:hardwario/tower.git
cd tower

# Then open Claude Code here and run:
/bootstrap          # init submodules, verify toolchains, report status

Already cloned without --recurse-submodules? Just run /bootstrap — it will git submodule update --init for you.

The workflow

Open a Claude Code session in this directory. Four slash commands cover the day-to-day loop:

Command What it does
/bootstrap First-run setup: materialize submodules, check Rust toolchains/targets (and probe-rs for firmware).
/build Compile in dependency order (protocol → jolt → cli → firmware), or a single repo. Stops at the first failure.
/sync Pull each submodule to its upstream main, then verify the tower-protocol tag is aligned across firmware and cli. Read-only with --check.
/pin Freeze the current submodule commits as a committed, known-good snapshot (with safety checks that every pinned commit is pushed). Optionally --tag.

Typical cycle: /sync/build the affected repos → /pin to record the new known-good combination.

Beyond the commands, just talk to Claude: "add a new shell command to the CLI and the matching handler in the firmware", "bump the protocol to add a humidity event", or "why does the console show garbage?"CLAUDE.md gives it the cross-repo context to do it correctly.

Working on a child repo

Each submodule is a full clone of its upstream on its own main branch. Build/test each from the control-plane root:

# protocol — the shared crate
cargo test  --manifest-path protocol/Cargo.toml --features verify

# cli — the host tool (binary: cli/target/release/tower)
cargo build --manifest-path cli/Cargo.toml --release

# firmware — embedded; uses `just`, not bare cargo
cd firmware && just examples && just build example blinky

# jolt — host UART flasher that cli links as a library
cargo build --manifest-path jolt/Cargo.toml

Firmware flashing and the console require the tower CLI on your PATH and a physical Core Module. See each child's own README.md/CLAUDE.md for depth.

Note: jolt is tower-cli's flashing dependency, pinned by git tag (v1.2.0) just like tower-protocol. But because cli links it as a Rust library, a tag mismatch is a compile error rather than the silent mis-decode that a protocol-tag mismatch causes — so it carries no lockstep hazard between firmware and cli.

Repository layout

tower/
├── README.md                 this file
├── CLAUDE.md                 cross-repo operating manual for Claude
├── .gitmodules               submodule definitions (HTTPS URLs, cloneable by anyone)
├── .claude/commands/         /bootstrap, /sync, /pin
├── protocol/   (submodule)   github.com/hardwario/tower-protocol
├── firmware/   (submodule)   github.com/hardwario/tower-firmware
├── cli/        (submodule)   github.com/hardwario/tower-cli
└── jolt/       (submodule)   github.com/hardwario/jolt

Submodules are pinned by commit SHA, so a clone of this repo reproduces an exact, coherent combination of all four. /pin advances those pins; /sync brings the working trees up to upstream before you pin.

Contributing & conventions

  • The TOWER repos develop straight on main; no feature branches unless asked.
  • Changes to a child are committed inside that child and pushed to its own upstream — never git add a child's files from this root. This repo only records the resulting SHAs (that's /pin).
  • A wire-format change is a coordinated change-set across protocol, firmware, and cli — see the runbook in CLAUDE.md.
  • Licensed MIT (© 2026 HARDWARIO a.s.), consistent with the child repos.

License

MIT — see the child repositories for their respective LICENSE files.

About

Control plane for the HARDWARIO TOWER ecosystem — orchestrates tower-firmware, tower-cli & tower-protocol as submodules with a Claude Code (/bootstrap /sync /pin) workflow.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors