- 3
- Supported targets
- 11
- Built-in templates
- 40 s
- Scaffold time
- 6 MB
- Binary size
Forge exists because I counted how long it took me to start a new embedded project properly — toolchain, directory layout, CI, a way to test anything — and it was most of an afternoon. Every time. So most projects skipped the “properly” part, and I paid for it later when a regression in an ESP32 project took two evenings to bisect because nothing had tests. Forge compresses that afternoon into about forty seconds.
Template architecture
A forge new invocation picks a target (ESP-IDF, Arduino, or RP2040) and renders a template tree through Tera. Templates aren’t just file copies: each one carries a manifest declaring required toolchain versions, post-render hooks, and which files are target-specific versus shared. The shared layer is the interesting part — every generated project gets the same src/app/ core that is pure C++ with no vendor headers, plus a thin src/hal/ layer per target. That split is what makes host testing possible at all.
Host-side unit tests for firmware
The default template builds twice: once with the vendor toolchain for the board, once with the host compiler against mock HAL implementations. The generated CMake handles the split:
if(FORGE_HOST_BUILD)
add_subdirectory(test/mocks) # fake GPIO, I2C, timers
add_executable(app_tests test/test_app.cpp src/app/logic.cpp)
target_link_libraries(app_tests unity hal_mocks)
endif()
Business logic — state machines, parsers, sensor filtering — runs under Unity on the host in milliseconds, in CI, with no board attached. Hardware-touching code stays thin enough to verify by hand. This caught a debounce bug in my own doorbell project before it ever got flashed.
Why Rust
The first version was a shell script and it broke on Windows immediately. Rust gave me a single static binary for all three OSes, clap for a CLI that documents itself, and real error handling around the messiest part of the job: probing for toolchains. Cross-platform path handling alone justified the rewrite — half the bugs in the script era were backslash-related. The 6 MB binary embeds all eleven templates, so forge new works offline.
The lesson so far: the scaffold is the easy part. Keeping generated projects upgradeable after the template evolves is the hard problem, and it’s most of the current roadmap.
Development timeline
- 2025-11
First prototype
A shell script that copied a folder — enough to prove I kept redoing the same setup.
- 2025-12
Rust rewrite
Ported to Rust with clap and Tera templates, single static binary on all three OSes.
- 2026-02
Host testing
Landed the dual-target build so firmware logic runs under Unity on the host.
- 2026-05
Public release
Tagged v0.3, published install script, first outside contributor PR merged.