Skip to main content

code-size

Use when firmware's flash/RAM footprint must be measured or compared - sizing a project's builds per file, section or symbol (report), diffing them against a base ref to judge a change's size impact (diff), or reading or debugging a PR's "Code size" comment (CI snapshot/compare) - in a repository whose build contract has a Code size section (tinyusb, tinyuf2).

Source facts

Repository
hathach/agentrc
Last source activity
October 29, 2026 at 02:08
Detected SKILL.md language
English
Stars
2
Forks
2

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
2 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
code-size
description
Use when firmware's flash/RAM footprint must be measured or compared - sizing a project's builds per file, section or symbol (report), diffing them against a base ref to judge a change's size impact (diff), or reading or debugging a PR's "Code size" comment (CI snapshot/compare) - in a repository whose build contract has a Code size section (tinyusb, tinyuf2).
# Code Size `scripts/code_size.py` is the engine; a project runs it through its own launcher with its profile, both named by the `## Code size` section of the skill or document its `CLAUDE.md`'s `Build contract:` line names. Read that section first: it gives the launcher, the default engine and board, what is sized, and the project's limits. No section means the project has not adopted this skill: measure nothing rather than compose a build. The engine's module docstring defines the commands, the engines and the profile protocol; `<launcher> <command> --help` the flags. `report` sizes the working tree, uncommitted changes included. `diff` sizes the working tree against a base ref (default the profile's `BASE_BRANCH`), pairs elfs by board and elf path, and reports per-file deltas. Pick the narrowest scope that exercises the change; sizes are never summed or averaged across boards, examples or images. | Scope | Command | |-----------------------------|------------------------------------------| | one board (one example) | `<launcher> diff -b BOARD [-e EXAMPLE]` | | several boards, combined | `<launcher> diff -b B1 -b B2 --combined` | | CI's board set, combined | `<launcher> diff --ci` (when offered) | | one tree, no diff | `<launcher> report -b BOARD` | The base comes from the CI snapshots the project stores for the base commit, or its nearest stored ancestor (the `Base:` line names the commit used and how far back it is; changes after it count as yours), when the profile offers them; otherwise, or when `--base-source local`, `-f`, `--bloaty` or another `--engine` needs an elf, the base is built locally in a detached worktree under the output dir, and the `Base:` line says why. `--base-source ci` fails instead of falling back. `--base-branch` means its tip; pass a merge-base SHA to diff against that. A run holds `<out dir>/.lock` and refuses while another run holds it; it removes only a base worktree an earlier run of its own left (owner marker plus git registration), and refuses any other occupant. ## Engines - `membrowse`: symbols of `membrowse report`, attributed to source files; needs the profile's link inputs and the membrowse version CI pins (the engine's `MEMBROWSE_CI_VERSION`). - `linkermap`: the GNU ld map's input sections, when the profile names linkermap. - `bloaty`: DWARF compile units, with `bloaty` on PATH. An LTO build (`<artificial>` unit) has no per-file attribution: the filter check fails, reported, never zero. - `sections`: the elf's allocated sections, each a row, with its Flash/RAM buckets as columns; no filter, no tool. Its total is the elf's allocated-section Flash/RAM: what a size budget is usually about, but not the image length or a region's occupancy. Flash/RAM buckets come from the elf's section and program headers for every engine (a section loaded in flash and run in RAM counts in both). Each other engine's whole-elf total sums what it attributes, so compare totals only within one engine. `--symbols` when Flash/RAM cancel: a pair counts as changed when its sections or symbols moved. ## Results Reports go under the project's output dir, `<board>/report*.md` or `<board>/diff*.md`, combined diffs under `_combined/`; `--json` adds the data beside each. A command exits nonzero on a build or sizing failure or when no project file matched; `report` also when it sized no elf, `diff` when it compared no pair. A scope the board does not build is skipped: no report and no failure. Unknown boards, and an example in neither tree, are refused before anything builds. A failed build prints an excerpt; its report records the first error. Each report opens with a coverage line. `INCOMPLETE` means a build, measurement or filter match failed, or an elf exists on one side only; those elfs are listed and excluded, never counted as zero. Show the coverage line and the relevant tables, then: - A many-elf report summarizes each elf, a many-pair diff each file; per-elf tables are in the `.md`'s `<details>`. Diff statistics cover compared pairs only: `Changed / present` is the pairs whose Flash or RAM of the file changed over the compared pairs containing it. min > 0 means growth in every such pair, max > 0 in at least one; name the worst-growth pair. - A whole-elf Δ with a zero project-file Δ (`filtered` under a custom `-f`) is code outside the filter (inlined headers, vendor or board code) or an attribution difference; check the per-file table for rows that cancel, and the `sections` engine for the whole-elf view. - A local base symlinks or clones its dependencies as the project's section says; a dependency bump the base does not build at its own pin is not in the diff. - Corroborate a surprising delta on its own board, not the whole sweep: another `--engine`, plus `--bloaty` if bloaty is on PATH. A diff rebuilds every tree it builds on each run, so ask for `--symbols` or `--bloaty` in the same run, and run a long sweep in the background. On Windows run the launcher as `python -X utf8` (or with `PYTHONUTF8=1`), else redirected output fails on `Δ`. A non-ASCII checkout, CMake or toolchain path needs ninja >= 1.11 whose `ninja -t wincodepage` reports UTF-8, and a local base symlinks its dependencies: enable Developer Mode unless running elevated. ## CI snapshots A project whose profile stores snapshots runs `snapshot` in each CI build leg (one `code-size-<board>.json` per board, plus `leg.json`) and `compare` on two runs' downloaded artifacts, which writes the full report, its JSON and the comment body. CI never rebuilds for sizing. Its comment lists every changed project file with its min and max Flash and RAM Δ across the builds containing it; `Not compared:` is the full report's `INCOMPLETE`. Compiler and membrowse version differences are noted, not failed. The project's section says how its workflow selects the baseline run, posts the comment and how to reproduce one.
View on GitHub