Skip to main content

CLI Reference

Complete reference for the membrowse command-line tool. For the GitHub Actions integration, see the membrowse-action repository.

Installation

pip install membrowse

To update to the latest version:

pip install --upgrade membrowse

Requirements: Python 3.8+

Quick Start

# Generate a local report
membrowse report build/firmware.elf "linker.ld"

# Output as JSON (for troubleshooting)
membrowse report build/firmware.elf "linker.ld" --json

# Analyze and upload to MemBrowse
membrowse report build/firmware.elf "linker.ld" \
--upload \
--target-name my-target \
--api-key YOUR_API_KEY

Commands

membrowse report

Generate and optionally upload a memory report.

membrowse report <elf_path> [ld_scripts] [options]

Arguments

ArgumentRequiredDescription
elf_pathYes*Path to the ELF file (*not required with --identical)
ld_scriptsNoSpace-separated linker script paths in quotes — supports GNU LD (.ld) and IAR ICF (.icf) formats (if omitted, uses default Code/Data regions based on ELF section flags)

Mode Options

OptionDescription
--uploadUpload report to MemBrowse platform
--no-gitDisable auto-detection of Git metadata when uploading
--githubUse GitHub Actions environment for Git metadata detection (use with --upload)

Upload Options

Required when using --upload:

OptionDescription
--api-key KEYMemBrowse API key
--target-name NAMEBuild configuration/target (e.g., esp32, stm32, x86)
--api-url URLMemBrowse API base URL (default: https://api.membrowse.com)
--identicalMark commit as having identical memory footprint to previous (metadata-only upload, no ELF analysis required)

Git Metadata Options

These are auto-detected by default. Use --no-git to disable auto-detection, or specify manually to override:

OptionDescription
--commit-shaGit commit SHA
--parent-shaGit parent commit SHA. Use append to set the parent to the head of the default branch, or none for no parent.
--base-shaAlias for --parent-sha
--branch-nameGit branch name
--repo-nameRepository name
--commit-messageCommit message
--commit-timestampCommit timestamp (ISO format)
--author-nameCommit author name
--author-emailCommit author email
--pr-numberPull request number
--pr-namePull request name/title
--pr-author-namePull request author name
--pr-author-emailPull request author email

Performance Options

OptionDescription
--skip-line-programSkip DWARF line program processing for faster analysis
--def VAR=VALUEDefine linker script variable (can be specified multiple times)

Alert Options

OptionDescription
--dont-fail-on-alertsExit 0 even if budget alerts triggered

Output Options

OptionDescription
--jsonOutput report as JSON (default is human-readable format)
--all-symbolsDisplay all symbols instead of just top 20 (human-readable mode only)
--output-raw-responseOutput raw API response as JSON to stdout

Upload Response

When uploading with --upload, the API returns a JSON response containing:

  • success: Whether the upload succeeded
  • report_id: The ID of the uploaded report
  • alerts: Any budget alerts triggered
  • diffs: Memory differences compared to the previous commit, broken down by region and section

Use --output-raw-response to output this JSON to stdout for further processing:

RESULT=$(membrowse report \
build/firmware.elf \
"linker.ld" \
--upload \
--target-name my-target \
--api-key YOUR_API_KEY \
--output-raw-response)

echo "$RESULT" | jq '.diffs'

Examples

# Local analysis - human-readable output (default)
membrowse report build/firmware.elf "linker.ld"

# Local analysis without linker scripts (uses default Code/Data regions)
membrowse report build/firmware.elf

# Show all symbols locally
membrowse report build/firmware.elf "linker.ld" --all-symbols

# Output as JSON
membrowse report build/firmware.elf "linker.ld" --json

# Upload to MemBrowse (Git metadata auto-detected)
membrowse report build/firmware.elf "linker.ld" \
--upload \
--target-name my-target \
--api-key YOUR_API_KEY

# Upload without Git metadata
membrowse report build/firmware.elf "linker.ld" \
--upload --no-git \
--target-name my-target \
--api-key YOUR_API_KEY

# GitHub Actions mode (auto-detects Git metadata from GitHub environment)
membrowse report build/firmware.elf "linker.ld" \
--upload --github \
--target-name stm32f4 \
--api-key YOUR_API_KEY

# Multiple linker scripts
membrowse report build/firmware.elf "memory.ld sections.ld" \
--upload \
--target-name my-target \
--api-key YOUR_API_KEY

# Define linker script variables
membrowse report build/firmware.elf "linker.ld" \
--def __flash_size__=4096K \
--def __ram_size__=256K

membrowse summary

Retrieve memory footprint summaries for a commit from the MemBrowse API. Returns data for all targets associated with the commit — each target's region changes, section changes, and layout are included in the response under a targets list.

membrowse summary <commit_sha> --api-key KEY [options]

Arguments

ArgumentRequiredDescription
commit_shaYesGit commit SHA to retrieve summary for

Options

OptionDescription
--api-key KEYMemBrowse API key (required)
--api-url URLMemBrowse API base URL (default: https://api.membrowse.com)
--jsonOutput raw JSON response from API (includes targets array with per-target summaries)
--template PATHPath to custom Jinja2 template file (default: built-in template). The template receives the full response including the targets list.

--json and --template are mutually exclusive.

Examples

# Human-readable summary (all targets)
membrowse summary abc123def --api-key YOUR_API_KEY

# Raw JSON output (for scripting)
membrowse summary abc123def --api-key YOUR_API_KEY --json

# Custom template
membrowse summary abc123def --api-key YOUR_API_KEY --template my_template.j2

membrowse onboard

Analyze historical commits to build baseline data. Supports two modes: processing the last N commits, or processing a specific list of commits/tags.

# Mode 1: Last N commits
membrowse onboard <num_commits> <build_script> <elf_path> <target_name> <api_key> [api_url] [options]

# Mode 2: Specific commits
membrowse onboard <build_script> <elf_path> <target_name> <api_key> --commits "REF1 REF2 ..." [options]

Arguments

ArgumentRequiredDescription
num_commitsNoNumber of commits to process (required unless --commits is used)
build_scriptYesShell command to build the firmware (quoted)
elf_pathYesPath to ELF file after build
target_nameYesTarget name in MemBrowse
api_keyYesMemBrowse API key
api_urlNoMemBrowse API base URL (default: https://api.membrowse.com)

Options

OptionDescription
--ld-scripts SCRIPTSSpace-separated linker script paths — supports GNU LD (.ld) and IAR ICF (.icf) formats (if omitted, uses default Code/Data regions)
--def VAR=VALUEDefine linker script variable (can be specified multiple times)
--build-dirs DIR [DIR ...]Directories that trigger rebuilds. Commits with no changes in these directories upload metadata-only reports with identical=True. Mutually exclusive with --binary-search.
--initial-commit HASHStart processing from this commit hash (must be on the main branch). Only valid with num_commits.
--commits REFSSpace-separated list of commit hashes and/or tags to process. Mutually exclusive with num_commits and --initial-commit.
--initial-parent REFSet the parent of the first commit when using --commits. Used to chain multiple onboard runs together. Only valid with --commits.
--binary-searchMinimize builds using binary search — builds endpoints first, compares memory fingerprints, and only builds midpoints where changes are detected. Mutually exclusive with --build-dirs.
--dry-runRun the full workflow but skip uploading reports (logs what would be uploaded)

Examples

# Basic onboarding with linker scripts
membrowse onboard \
50 \
"make clean && make all" \
build/firmware.elf \
my-target \
YOUR_API_KEY \
--ld-scripts "linker.ld"

# Without linker scripts (uses default Code/Data regions)
membrowse onboard \
50 \
"make clean && make all" \
build/firmware.elf \
my-target \
YOUR_API_KEY

# With custom API URL
membrowse onboard \
25 \
"idf.py build" \
build/firmware.elf \
esp32 \
YOUR_API_KEY \
https://custom-api.example.com \
--ld-scripts "build/esp-idf/esp32/esp32.project.ld"

# Skip commits without changes in build directories
membrowse onboard \
100 \
"make all" \
build/firmware.elf \
my-target \
YOUR_API_KEY \
--ld-scripts "linker.ld" \
--build-dirs src/ lib/ include/

# Start from a specific commit
membrowse onboard \
50 \
"make all" \
build/firmware.elf \
my-target \
YOUR_API_KEY \
--ld-scripts "linker.ld" \
--initial-commit abc123def

# Onboard specific version tags
membrowse onboard \
"make clean && make all" \
build/firmware.elf \
my-target \
YOUR_API_KEY \
--commits "v1.0 v1.1 v2.0 v2.1" \
--ld-scripts "linker.ld"

# Chain multiple onboard runs across version boundaries
membrowse onboard \
"make clean && make all" \
build/firmware.elf \
my-target \
YOUR_API_KEY \
--commits "v2.0 v2.1 v2.2" \
--initial-parent v1.9 \
--ld-scripts "linker.ld"

# Minimize builds with binary search
membrowse onboard \
100 \
"make all" \
build/firmware.elf \
my-target \
YOUR_API_KEY \
--ld-scripts "linker.ld" \
--binary-search

# Dry run to verify setup without uploading
membrowse onboard \
10 \
"make all" \
build/firmware.elf \
my-target \
YOUR_API_KEY \
--ld-scripts "linker.ld" \
--dry-run

Behavior

  1. Fetches git history (requires full clone)
  2. Uses --first-parent to follow only main branch (not feature branch commits)
  3. Iterates from oldest to newest commit
  4. For each commit:
    • Checks out the commit
    • Runs the build script
    • Analyzes the ELF file
    • Uploads the report
  5. Skips building commits with no changes in --build-dirs (uploads metadata-only)
  6. With --binary-search, builds only endpoints first, then bisects where memory fingerprints differ
  7. Uploads empty reports for failed builds
  8. Restores original HEAD when complete

Global Options

These options apply to all commands:

OptionDescription
-v, --verbose LEVELSet logging verbosity: WARNING (default), DEBUG, INFO
--versionShow installed version
--helpShow help message
# Info output
membrowse -v INFO report build/firmware.elf "linker.ld"

# Debug output
membrowse -v DEBUG report build/firmware.elf "linker.ld"

Exit Codes

CodeMeaning
0Success
1Error (budget alert, invalid input, API error, etc.)

Use --dont-fail-on-alerts to prevent budget alerts from causing exit code 1.


Output Formats

Human-Readable (default)

Memory Report for build/firmware.elf
=====================================

FLASH: 45,234 / 262,144 bytes (17.3%)
.text: 32,456 bytes
.rodata: 12,778 bytes

RAM: 12,834 / 65,536 bytes (19.6%)
.data: 1,234 bytes
.bss: 11,600 bytes

Top Symbols by Size:
1. main 2,456 bytes (.text)
2. usb_buffer 4,096 bytes (.bss)
3. string_table 1,892 bytes (.rodata)
...

JSON (with --json)

When using --json, the report is output as JSON to stdout. When uploading with --upload, a JSON report is generated containing:

  • Memory regions with usage
  • All sections with sizes
  • Complete symbol table
  • Git metadata (commit, branch, etc.)