ciq-forge
v0.1.0
Published
CLI-first automation and scaffolding for Garmin Connect IQ projects
Maintainers
Readme
CIQ Forge
Deterministic scaffolding, builds, simulator runs, profiling, and visual regression testing for Garmin Connect IQ projects.
CIQ Forge turns the fragmented Connect IQ development loop into one explicit CLI workflow. It creates self-contained watch face and device app projects, validates their inputs, compiles isolated device targets with Garmin's official SDK, injects deterministic scenarios, drives simulator runs, and produces machine-readable evidence for CI.
It does not emulate Monkey C or replace Garmin's simulator. CIQ Forge orchestrates the official tools and makes their results repeatable.
Project website · Commands · Configuration · Contributing
Highlights
- Interactive and non-interactive project scaffolding.
- Watch face and device app templates with a generated manifest UUID.
- Self-contained projects with a vendored CIQ Forge Monkey Barrel.
- Strict validation for Forge, device, and scenario YAML.
- Stable
device × scenarioexecution matrices. - Garmin SDK discovery and official
monkeyccompilation. - Fixture-backed time, system, activity, weather, settings, and low-power state.
- Simulator lifecycle assertions and structured diagnostics.
- Screenshot normalization, approved baselines, and pixel diffs.
- Binary size, memory, render-time, and relative energy budgets.
- JSON, JUnit, HTML, log, metric, and image artifacts.
Requirements
- Node.js 20 or newer.
- Garmin Connect IQ SDK for real builds and simulator runs.
- A Garmin developer key for signed PRGs.
The SDK and developer key remain local. They are not included in the npm package and key material is never printed by the CLI.
Install
After the first npm release, run CIQ Forge without a permanent installation:
npx ciq-forge --helpOr install it globally:
npm install --global ciq-forge
ciq-forge --helpFor repository development, see Development.
Quick start
Launch the mini assistant:
ciq-forge newOr create a watch face non-interactively:
ciq-forge new solar-face `
--type watchface `
--name "Solar Face" `
--devices fenix7,forerunner965,venu3 `
--min-api 3.2.0 `
--yesCreate a device app:
ciq-forge new trail-notes --type app --name "Trail Notes" --devices venu3 --yesThe generated project is ready for inspection:
cd solar-face
ciq-forge inspect
ciq-forge doctorGenerated project
solar-face/
├── source/
│ ├── SolarFaceApp.mc
│ ├── SolarFaceView.mc
│ └── ForgeBootstrap.mc
├── resources/
│ ├── drawables/
│ └── strings/
├── devices/
├── scenarios/
├── vendor/ciq-forge/
├── manifest.xml
├── monkey.jungle
├── forge.yml
└── README.mdThe generator refuses to overwrite a non-empty destination.
Commands
| Command | Purpose |
| --- | --- |
| ciq-forge new [directory] | Create a watch face or device app project. |
| ciq-forge inspect | Validate the project, manifest, devices, scenarios, and matrix. |
| ciq-forge matrix | Print the stable device/scenario job matrix. |
| ciq-forge doctor | Check the Garmin SDK, simulator tools, and developer key. |
| ciq-forge build | Compile one isolated PRG per selected device. |
| ciq-forge run | Build and execute instrumented simulator jobs. |
| ciq-forge profile | Collect memory, render-time, binary, and energy metrics. |
| ciq-forge screenshot | Capture the visible Garmin Simulator window. |
| ciq-forge baseline approve | Explicitly approve a captured visual baseline. |
Every command supports --help for its complete options.
Validate the local toolchain
ciq-forge doctor --developer-key C:\path\to\developer_keyThe key can be supplied without storing its path in the project:
$env:CIQ_DEVELOPER_KEY = "C:\path\to\developer_key"
ciq-forge doctor --compile-probeSDK discovery order:
compiler.pathinforge.yml.CIQ_MONKEYC.- Garmin SDK Manager's
current-sdk.cfg. - The newest SDK in the standard Windows SDK directory.
Build and run
ciq-forge build --device venu3
ciq-forge run --device venu3 --scenario normal
ciq-forge run --device venu3 --scenario normal --screenshotBuild outputs and reports are written below .ciq-forge/results/ by default.
Profile budgets
Scenarios can turn performance regressions into CI failures:
budgets:
compileWarnings: 0
binaryBytes: 100000
memoryPeakBytes: 90000
memoryPeakPercent: 80
renderAverageMs: 10
energyScore: 15The reported energy.relativeScore is a regression proxy based on active render time. It is not a physical battery-life estimate.
Visual baselines
ciq-forge run --device venu3 --scenario normal --screenshot
ciq-forge baseline approve --run venu3__normalrun never overwrites an approved baseline. Changed pixels are highlighted and the job fails when the configured difference threshold is exceeded.
Configuration
forge.yml is the entrypoint for a project:
project:
root: .
jungle: monkey.jungle
manifest: manifest.xml
inputs:
devicesDir: devices
scenariosDir: scenarios
execution:
workers: 4
timeoutMs: 30000
output: .ciq-forge/results
compiler:
maxConcurrency: 1
visual:
baselinesDir: baselines
differenceThreshold: 0.001
pixelThreshold: 16Unknown properties are rejected so misspelled configuration cannot silently alter a run.
How instrumentation works
Instrumented builds generate an isolated ForgeBootstrap.mc for each matrix job and add it through a temporary Jungle overlay. The production bootstrap is excluded by annotation, while the generated bootstrap provides fixture-backed services to the same app code.
Runtime diagnostics use versioned lines such as:
CIQ_FORGE_EVENT|1|venu3__normal|view.update|09:42This keeps application behavior on Garmin's runtime while making external state deterministic and assertions parseable.
Development
This repository uses pnpm 11 workspaces.
pnpm.cmd install
pnpm.cmd typecheck
pnpm.cmd test
pnpm.cmd buildRun the TypeScript entrypoint during development:
pnpm.cmd ciq-forge inspectRepository layout:
packages/
cli/ command surface and project scaffolding
core/ schemas, loaders, matrix, reporting, and instrumentation
garmin-compiler/ SDK discovery and monkeyc adapter
garmin-simulator/ simulator launch and screenshot capture
barrels/ciq-forge/ Monkey C integration barrel
examples/ example watch face
devices/ device definitions
scenarios/ deterministic fixture definitions
docs/ GitHub Pages website
tests/ Vitest suitenpm release
Inspect and test the exact package before publishing:
npm pack --dry-run
npm pack
npm install --global .\ciq-forge-0.1.0.tgz
ciq-forge --versionprepack rebuilds dist; prepublishOnly runs the test suite and typecheck.
npm login
npm publishGitHub Pages
The static website lives in docs/. The workflow at .github/workflows/pages.yml deploys it after pushes to main or master.
After pushing the repository for the first time:
- Open Settings → Pages in GitHub.
- Set Source to GitHub Actions.
- Run Deploy GitHub Pages from the Actions tab, or push a change under
docs/.
Current limitations
- Real compilation and simulator runs require Garmin's local Connect IQ tools.
- Screenshot automation currently requires an interactive Windows desktop.
- Device-specific capture coordinates are recommended for stable visual baselines.
- Energy profiling is relative; calibrated battery estimates require physical-device measurements.
- The Jungle loader handles direct
sourcePathandresourcePathvalues, not complete Jungle evaluation.
Project status
CIQ Forge is an early-stage project. The command surface and configuration may evolve before 1.0.0. See ROADMAP.md for planned work.
