Toolchain inventory
As of 2026-10-06. Compiled from the repositories themselves and from the
machine: build-host/CMakeCache.txt records the exact path and version of
every tool the last host build resolved, so most of what follows is measured
rather than remembered. It covers all five tag-designs repositories, not only
this one.
What lives outside the home directory
A backup of ~ carries most of this work, including ~/Research,
~/Software, ~/bin, ~/Qt and the login keychain that holds the Developer
ID identity. The following are the pieces it does not carry, and so the
real reinstall list.
Outside ~ |
What it is | How it comes back |
|---|---|---|
/opt/homebrew |
The whole Homebrew prefix: arm-none-eabi-gcc, protobuf/protoc-29.3.0, libusb 1.0.30, pkg-config, fmpp 0.9.16, graphviz, nanopb, mkdocs, python@3.13 |
Reinstall Homebrew, then the formulae below. Nothing here is restorable by copying. |
/Applications/Xcode.app |
Apple toolchain, SDK MacOSX14.4, clang 15.0.0, and the SQLite3 headers the host build links against | App Store or developer.apple.com. Install before configuring anything. |
/Applications/CMake.app |
CMake 3.28.3 — the one that configured the current build trees | cmake.org disk image |
/Applications/Doxygen.app |
Doxygen | doxygen.nl, or use the Homebrew formula instead |
/Applications/KiCad/KiCad.app |
KiCad, including kicad-cli |
kicad.org |
/usr/local/bin/openocd |
OpenOCD, used as the embedded-debugger backend for U375 |
Not a Homebrew path — it was installed by hand and will not return with brew install |
/usr/local/arm/bin/arm-none-eabi-gdb |
Referenced by .vscode/launch.json |
Already stale; the working GDB is in the Homebrew Arm toolchain |
/usr/bin/{git,make,python3,codesign,install_name_tool} |
Provided by macOS and the Xcode command-line tools | xcode-select --install, or Xcode itself |
Two home-directory items are worth calling out even though a backup carries
them, because losing them is expensive: the login keychain
(~/Library/Keychains) holding the Developer ID Application: Indiana
University (5J69S77A7G) identity, and ~/.ssh, since all five git remotes
are SSH.
Save before you wipe
The five repos are on GitHub and come back with a clone. These will not.
| What | Where | Why it matters |
|---|---|---|
| Developer ID signing key | Login keychain, Developer ID Application: Indiana University (5J69S77A7G) |
Every signed macOS release is cut on this Mac because CI deliberately has no access to this key. Export the identity and its private key as a .p12 first. |
| SSH key for GitHub | ~/.ssh |
All five remotes are git@github.com:tag-designs/…. |
~/Software |
local | Hand-placed: ChibiOS copies, nanopb distributions, vcpkg checkout, STM32CubeProgrammer, OpenSCAD 2021.01, freecad-cli, freecad-mcp. |
~/bin |
local | hugo binary, chibios-*-migrate scripts. |
| Uncommitted work | all five repos | Most firmware build manifests in build-host record a -dirty describe; the newest, UIUCTag at 3 Oct, reads fw-v0.0.3-55-g8a055a8-dirty. Check git status in each repo. |
captures/, Claude outputs/ |
~/Research/tag-designs |
Not git repos. Nine capture sessions, 30 Sep – 3 Oct 2026. |
| Joulescope venv | ~/opt/joulescope-mcp/.venv or ~/.venvs/joulescope |
pip freeze it before it goes. |
| Qt account credentials | Qt Maintenance Tool | Reinstalling Qt 6.10.3 needs the Qt account login. |
Homebrew
Homebrew at /opt/homebrew (Apple Silicon). The first group is confirmed by
the recorded path in build-host/CMakeCache.txt.
| Formula | Version seen | Serves |
|---|---|---|
arm-none-eabi-gcc |
14.2.1 | All tag firmware; version is pinned. |
protobuf |
protoc 29.3.0 (/opt/homebrew/bin/protoc-29.3.0) |
Host protobuf; pulls abseil, utf8_range. |
python@3.13 |
3.13.2 | What find_package(Python3) resolved to, and what builds the config-gen virtualenv. |
libusb |
1.0.30 | Host tools' USB transport. |
pkg-config |
— | Locates libusb-1.0. |
fmpp |
0.9.16 | Board file generation; needs a Java runtime. |
mkdocs, mkdocs-material |
binary at /opt/homebrew/bin/mkdocs; the repo pins mkdocs>=1.6,<2.0 and mkdocs-material>=9.5 as pip ranges |
Host user documentation. The READMEs install them with python3 -m pip install -r host/docs/requirements.txt. |
graphviz |
dot |
Doxygen graphs. |
nanopb |
symlinked into ~/Software/nanopb/generator-bin |
See Traps. |
Named in the READMEs, install alongside:
| Formula | Needed for |
|---|---|
autoconf, autoconf-archive, automake, libtool |
vcpkg's libusb port on macOS (build-only). |
ninja |
CI's macOS generator; local presets use Unix Makefiles. |
go, node, hugo, pdf2svg, rsync |
The Hugo documentation site. |
mactex-no-gui (cask) |
Only to regenerate TikZ-derived SVGs. |
ripgrep |
rg, the search tool AGENTS.md specifies. |
gh |
GitHub CLI; release workflows upload through it. |
doxygen |
A Doxygen.app is installed instead here; the formula is simpler. |
ngspice (or LTspice / Xyce) |
The spice skill treats simulation as required during a board review when any simulator is installed. None is currently present. |
Two prerequisites the READMEs name that come from macOS rather than Homebrew:
Git (used by the version-generation helpers in every repo) and
codesign (required when MACOS_SIGN_APPS=ON).
Applications and standalone installs
| Tool | Version | Path |
|---|---|---|
| Xcode | SDK MacOSX14.4, clang 15.0.0 | /Applications/Xcode.app — cc, c++, ar, ld, objdump, and the SQLite3 headers |
| CMake | 3.28.3 installed; the project's floor is 3.20 | /Applications/CMake.app/Contents/bin/cmake, not Homebrew's |
| Doxygen | — | /Applications/Doxygen.app/Contents/Resources/doxygen |
| KiCad | — | /Applications/KiCad/KiCad.app; kicad-cli is not on PATH |
| OpenOCD | — | /usr/local/bin/openocd, installed by hand |
| STM32CubeProgrammer | 2.4.0 | ~/Software/STM32CubeProgrammer/STM32CubeProgrammer.app/Contents/Resources/bin/STM32_Programmer_CLI |
| OpenSCAD | 2021.01 | ~/Software/OpenSCAD-2021.01.app — the default in the Mechanical makefiles |
| FreeCAD | — | freecadcmd drives the parametric cases; a freecad MCP server is registered |
| Joulescope desktop app | — | Confirming supply voltage; detach before scripted measurement |
| DB Browser for SQLite | — | Inspecting tag logs |
| Zotero | — | Present in the home directory; docs/docs/resources/My Library.json is the exported library the Hugo bibliography draws on |
Also in ~/Software, decide rather than restore blindly: ChibiOS (a symlink
to Chibios-21.11), ChibiOS-20.3.x, ChibiOS-back — all superseded by the
software repo's submodule — nanopb-0.4.8-macosx-x86, protobuf,
protobuf-29.3, protobuf-build, qt6, libusb, STM32CubeProgrammer-old,
Doxygen.app, MotionCal, NXP-ISSDK-SensorFusion, QFlightinstruments,
condortools.
Qt
Qt 6.10.3 for macOS at ~/Qt/6.10.3/macos, installed by the Qt Maintenance
Tool. The macos-vcpkg preset hard-codes that path, and macdeployqt comes
from its bin, which must be on PATH for packaging. Qt sources are present
at ~/Qt/6.10.3/Src, which is what LICENSES/tools/generate_qt_notices.py
needs if the shipped Qt version ever changes.
The macOS preset moved up from 6.8.2 because the AGL framework Qt's
FindWrapOpenGL looked for was removed in the macOS 15 SDK. macOS and Windows
presets now name the same Qt version, 6.10.3.
Also installed: Qt 6.8.2, Qt Creator, Qt Design Studio, Maintenance Tool. Only
6.10.3 is referenced. CI pins its own Qt version in
release.yml and is not driven by the
presets.
Modules required: Core, Gui, Widgets, Concurrent, PrintSupport, Svg,
SvgWidgets, Qml, Quick, QuickWidgets. -DBUILD_QT_APPS=OFF avoids all of it.
Embedded toolchain and generators
Four versions are pinned because generated sources are committed. By default a
mismatch is a warning; -DREPRODUCIBLE_BUILD=ON turns the checks that go
through reproducibility_problem() into errors. The nanopb generator version
check is never fatal.
| Tool | Pin | Source |
|---|---|---|
| Arm GNU Toolchain | 14.2.1 (14.2.rel1) | /opt/homebrew/bin/arm-none-eabi-gcc |
| nanopb generator + runtime | 0.4.9.1 | docs/decisions/0011-build-pin-nanopb-0-4-9-1.md |
Python protobuf for config-gen |
5.28.1 | embedded/proto-c/requirements.txt — the protobuf the pinned nanopb bundles |
| ChibiOS | branch stable_21.11.x |
Submodule; last built at e209b17c, ver21.11.1@15221-412 |
Also required:
fmpp0.9.16 and a Java runtime — prototype boards do not commit generated files, so a default configure fails without it.protoc— normally the one besidenanopb_generator, deliberately not PyPI.- Python 3.
find_package(Python3)resolved to Homebrew'spython@3.13(3.13.2); the legacyPYTHON_EXECUTABLEcache entry points at/usr/bin/python3. The first configure builds the pinnedconfig-genvirtualenv and needs network once. make(/usr/bin/make), required by ChibiOS firmware builds.- A native C/C++ compiler, even for an embedded-only configure.
Escape hatch before the generators are back: -DREGENERATE_SOURCES=OFF with
the distributed_firmware target needs only Arm GCC, make, CMake, a native
compiler and the ChibiOS submodule.
Bench and instrumentation
| Piece | Detail |
|---|---|
| Joulescope JS220 | pyjoulescope_driver must be importable — a virtualenv, not system Python. |
| Measurement interpreter | power_experiment.py searches ~/opt/joulescope-mcp/.venv/bin/python, ~/.venvs/joulescope/bin/python, <repo>/.venv/bin/python; override with --measure-python or JOULESCOPE_PYTHON. |
| Joulescope desktop app | Setting and confirming supply voltage. Detach before scripted runs. |
joulescope-js220 MCP server |
Not to be used; it holds the device. Kill stray joulescope-mcp processes. |
| ST-LINK probes | Tag programmer base 0483:3748 (preferred), STLINK-V3PWR 0483:3757. Select with STM32_PROGRAMMER_PROBE. |
| STM32CubeProgrammer CLI | SWD with mode=UR, and DFU. 2.4.0 here. |
tag-capture |
Host tool from this repo; halts the core before firmware runs. |
embedded-debugger MCP |
Probe inspection, core control, memory reads, breakpoints, RTT, over probe-rs or OpenOCD. probe-rs has no STM32U3 target, so U375 work needs the OpenOCD backend at /usr/local/bin/openocd. |
| GDB over SWD | arm-none-eabi-gdb from the Arm toolchain; the VS Code configs use cortex-debug. |
The bench scripts themselves live in software/embedded/tools and come back
with the repo. What does not come back is the interpreter that can run them.
Hardware and mechanical
| Tool | Role |
|---|---|
| KiCad | 72 .kicad_pro files under hardware/BoardDesigns, 52 outside Archive/ and Obsolete/. kicad-cli pcb drc --format json; remember --refill-zones. |
kicad-happy review suite |
kicad, emc, spice, datasheets, bom, distributor and fab skills. A copy of the kicad skill is vendored at hardware/.agents/skills/kicad; the rest is installed outside the repo. |
| SPICE simulator | ngspice, LTspice or Xyce. The kicad skill runs which ngspice ltspice xyce and treats simulation as required when one is found. |
| Distributor API credentials | DIGIKEY_CLIENT_ID/SECRET, MOUSER_SEARCH_API_KEY, ELEMENT14_API_KEY enable datasheet sync and BOM pricing; LCSC needs none. None are currently configured. |
kicad-helpers |
In-repo Python probes over analyzer JSON. Plain Python 3. |
STM32_open_pin_data |
Hardware repo submodule; ST's machine-readable pin data behind the AF tables. |
| KiBot | Fab outputs; configs at BoardDesigns/Kibot-config/. |
FreeCAD + freecadcmd |
Parametric tag cases via tagcase_param.py. |
freecad-cli, freecad-mcp 0.1.22 |
uv-managed Python projects, Python >= 3.12 — so uv is a tool to reinstall. |
| OpenSCAD 2021.01 | Older .scad case models and the acrylic charger DXF. |
| Slicer | Implied by the .stl output; not referenced by any file here. |
Documentation stacks
Two stacks, one per repo, sharing nothing.
MkDocs — the software repo. MkDocs with Material, pinned in
host/docs/requirements.txt. Builds the packaged end-user manual
(BUILD_HOST_DOCS) and the developer portal (BUILD_DEVELOPER_DOCS).
docs/tools/docs.py index and docs.py check regenerate the index from front
matter. Doxygen with Graphviz covers the API reference.
Hugo — the tag-designs.github.io repo:
| Requirement | Minimum |
|---|---|
| Hugo Extended | 0.155.3 (a hugo binary also sits in ~/bin) |
| Go | 1.22, for Hugo Modules (Docsy, hugo-cite) |
| Node.js + npm | 22 LTS; npm ci in docs/ installs the PostCSS toolchain |
| CMake | 3.10 |
pdflatex + pdf2svg |
Only to regenerate TikZ-derived SVGs |
rsync |
Only for the sync-gh-pages target |
The first site build needs network to populate the Hugo module cache. The
separate docs repo carries the themes as submodules: Docsy, hugo-cite,
font-awesome.
Repos, submodules and identity
All five remotes are SSH to github.com:tag-designs.
| Repo | Submodules |
|---|---|
software |
ChibiOS (branch stable_21.11.x) |
hardware |
STM32_open_pin_data |
docs |
docsy, hugo-cite, font-awesome |
protobuf |
— |
tag-designs.github.io |
— |
Not repos: captures/ and Claude outputs/.
- vcpkg at
~/Software/vcpkg, checkout8defa4b8(13 May 2026). The manifest baseline the project pins is99a97de2cb371449d4fb9dc970f2ac562d689ec2. Manifest installslibusb,protobuf,sqlite3, hostpkgconf. MACOS_CODE_SIGN_IDENTITYdefaults toDeveloper ID Application: Indiana University (5J69S77A7G). Without it,sign-latestandhost/tools/release-macos.shcannot cut a release;-DMACOS_SIGN_APPS=OFFbuilds unsigned.
Traps
~/Software/nanopb is not a nanopb install. CMake recorded
NANOPB_SRC_ROOT_FOLDER=~/Software/nanopb and the generator at
~/Software/nanopb/generator-bin/nanopb_generator, but that generator-bin
holds exactly one entry: a symlink to /opt/homebrew/bin/nanopb_generator. The
directory itself is a git checkout at nanopb-0.4.8-11-g1f0c2e1, two versions
behind the 0.4.9.1 pin. The build is using the Homebrew generator through a
hand-made shim. A full nanopb-0.4.9.1-macosx-x86 distribution also sits in
~/Software, unused by that cache entry. On the rebuilt machine, point
NANOPB_ROOT at the real 0.4.9.1 distribution rather than recreating the shim,
and check that protoc sits beside the generator.
Path casing. The presets reference $HOME/qt/6.10.3/macos; the directory is
~/Qt. This works only on a case-insensitive volume.
Absolute paths baked into the tree.
hardware/Mechanical/{BitPresTag,IMUTag}/Makefile default to
$(HOME)/Software/OpenSCAD-2021.01.app/Contents/MacOS/OpenSCAD — overridable
with OPENSCAD=, but wrong out of the box if OpenSCAD lands elsewhere.
hardware/CLAUDE.md names
/Applications/KiCad/KiCad.app/Contents/MacOS/kicad-cli.
software/.vscode/launch.json names
/usr/local/arm/bin/arm-none-eabi-gdb, which is already stale — the installed
Arm toolchain is Homebrew's.
CMake is the app bundle, not Homebrew's. /Applications/CMake.app 3.28.3
configured the current build trees; the project's stated floor is 3.20.
SQLite comes from the macOS SDK. SQLite3_LIBRARY resolved to
libsqlite3.tbd inside the Xcode SDK. Install Xcode before configuring.
Old build trees are stale the moment the machine changes.
software/build-host, build-docs and ~/Build/tag-designs embed absolute
paths — delete and reconfigure, but read build-host/CMakeCache.txt once more
first, since it is the best record of what was installed.
An Xcode SDK upgrade orphans every existing build tree. CMAKE_OSX_SYSROOT
is a cache variable, so a reconfigure keeps pointing at the SDK that was current
when the tree was first configured. Once that SDK directory is gone, anything
derived from it fails: WrapOpenGL_AGL leaves a literal -framework AGL on
every Qt link line, and Qt6::PrintSupport carries a <sysroot>/usr/include
CUPS path that fails at generate time. None of it is fixed by reconfiguring —
the tree has to be deleted. Note that the preset build trees live under
~/Build/tag-designs, not in the repository, so deleting software/build-host
does not touch what cmake --preset macos-vcpkg actually writes to.