Integrate MemBrowse memory tracking into an embedded firmware project. Use when the user wants to set up MemBrowse, add memory analysis GitHub workflows, or create membrowse-targets.json for tracking RAM/Flash usage.
/plugin marketplace add membrowse/membrowse-action/plugin install membrowse@membrowse-marketplaceThis skill is limited to using the following tools:
You are integrating MemBrowse memory analysis into an embedded firmware project. Follow these steps to identify build targets, create the configuration file, and set up GitHub workflows.
First, understand what the project builds and how.
# Find build configuration files
find . -name "Makefile*" -o -name "CMakeLists.txt" -o -name "*.mk" 2>/dev/null | head -20
# Look for board/port directories
find . -name "boards" -type d 2>/dev/null
find . -name "ports" -type d 2>/dev/null
# Check existing CI workflows for build patterns
ls -la .github/workflows/ 2>/dev/null
Read existing workflow files to understand:
# Find all linker scripts
find . -name "*.ld" -o -name "*.lds" 2>/dev/null
# Check Makefiles for linker script references
grep -r "LDSCRIPT\|\.ld\|-T " --include="Makefile*" --include="*.mk" 2>/dev/null | head -20
# Check for ELF references in CI
grep -r "\.elf\|firmware" .github/workflows/ --include="*.yml" 2>/dev/null | head -20
# Common patterns to look for:
# - build/firmware.elf
# - build-BOARDNAME/firmware.elf
# - build/PROJECT_NAME.elf
For each target you identify, gather:
| Field | Description |
|---|---|
target_name | Unique identifier (e.g., stm32-pybv10, esp32-devkit) |
port | Platform folder name (for ccache key) |
board | Board variant name (for ccache key) |
setup_cmd | Commands to install build dependencies |
build_cmd | Commands to compile the firmware |
elf | Path to output ELF file after build |
ld | Space-separated linker script paths (can be empty) |
linker_vars | Optional: variable definitions for linker parsing |
ARM Cortex-M (STM32, SAMD, NXP, etc.):
sudo apt-get update && sudo apt-get install -y gcc-arm-none-eabi libnewlib-arm-none-eabi
ESP32/ESP8266:
# Usually handled by project CI scripts or ESP-IDF setup
. $IDF_PATH/export.sh
RISC-V:
# Check project docs for specific toolchain
sudo apt-get update && sudo apt-get install -y gcc-riscv64-unknown-elf
x86/Unix builds:
sudo apt-get update && sudo apt-get install -y build-essential libffi-dev pkg-config
Before creating files, present the discovered targets to the user and ask them to confirm or modify:
Create .github/membrowse-targets.json with the confirmed targets:
[
{
"target_name": "target-identifier",
"port": "port-name",
"board": "BOARD_NAME",
"setup_cmd": "setup commands here",
"build_cmd": "build commands here",
"elf": "path/to/firmware.elf",
"ld": "path/to/linker.ld",
"linker_vars": "optional_var=value"
}
]
target_name: Must be unique, used in artifact namesld: Space-separated if multiple scripts; empty string "" if nonelinker_vars: Only needed if linker scripts use undefined variablesport and board: Used for ccache keys, can be empty stringsCreate three workflow files in .github/workflows/:
name: Membrowse Memory Report
on:
pull_request:
push:
branches:
- main # IMPORTANT: Change to match the project's default branch
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
load-targets:
runs-on: ubuntu-22.04
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Checkout repository
uses: actions/checkout@v5
- name: Load target matrix
id: set-matrix
run: echo "matrix=$(jq -c '.' .github/membrowse-targets.json)" >> $GITHUB_OUTPUT
analyze:
needs: load-targets
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
include: ${{ fromJson(needs.load-targets.outputs.matrix) }}
steps:
- name: Checkout repository
uses: actions/checkout@v5
with:
fetch-depth: 0
submodules: recursive
- name: Install packages
run: ${{ matrix.setup_cmd }}
- name: Setup ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${{ matrix.port }}-${{ matrix.board }}
- name: Build firmware
run: ${{ matrix.build_cmd }}
- name: Run Membrowse PR Action
id: analyze
continue-on-error: true
uses: membrowse/membrowse-action@v1
with:
target_name: ${{ matrix.target_name }}
elf: ${{ matrix.elf }}
ld: ${{ matrix.ld }}
linker_vars: ${{ matrix.linker_vars }}
api_key: ${{ secrets.MEMBROWSE_API_KEY }}
api_url: ${{ vars.MEMBROWSE_API_URL }}
verbose: INFO
- name: Upload report artifact
if: ${{ steps.analyze.outcome == 'success' }}
uses: actions/upload-artifact@v4
with:
name: membrowse-report-${{ matrix.target_name }}
path: ${{ steps.analyze.outputs.report_path }}
name: Membrowse PR Comment
on:
workflow_run:
workflows: [Membrowse Memory Report]
types: [completed]
permissions:
contents: read
actions: read
pull-requests: write
jobs:
comment:
runs-on: ubuntu-22.04
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success'
steps:
- name: Checkout repository
uses: actions/checkout@v5
- name: Download report artifacts
id: download-reports
uses: actions/github-script@v7
with:
result-encoding: string
script: |
const fs = require('fs');
const allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.payload.workflow_run.id,
});
const reportArtifacts = allArtifacts.data.artifacts.filter(
artifact => artifact.name.startsWith('membrowse-report-')
);
if (reportArtifacts.length === 0) {
console.log('No report artifacts found');
return 'skip';
}
fs.mkdirSync('reports', { recursive: true });
for (const artifact of reportArtifacts) {
console.log(`Downloading ${artifact.name}...`);
const download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: artifact.id,
archive_format: 'zip',
});
const zipPath = `${artifact.name}.zip`;
fs.writeFileSync(zipPath, Buffer.from(download.data));
await exec.exec('unzip', ['-o', zipPath, '-d', 'reports']);
}
return 'ok';
- name: Post combined PR comment
if: steps.download-reports.outputs.result == 'ok'
uses: membrowse/membrowse-action/comment-action@v1
with:
json_files: "reports/*.json"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
name: Onboard to Membrowse
on:
workflow_dispatch:
inputs:
num_commits:
description: 'Number of commits to process'
required: true
default: '100'
type: string
jobs:
load-targets:
runs-on: ubuntu-22.04
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Checkout repository
uses: actions/checkout@v5
- name: Load target matrix
id: set-matrix
run: echo "matrix=$(jq -c '.' .github/membrowse-targets.json)" >> $GITHUB_OUTPUT
onboard:
needs: load-targets
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
include: ${{ fromJson(needs.load-targets.outputs.matrix) }}
steps:
- name: Checkout repository
uses: actions/checkout@v5
with:
fetch-depth: 0
submodules: recursive
- name: Install packages
run: ${{ matrix.setup_cmd }}
- name: Setup ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${{ matrix.port }}-${{ matrix.board }}
- name: Run Membrowse Onboard Action
uses: membrowse/membrowse-action/onboard-action@v1
with:
target_name: ${{ matrix.target_name }}
num_commits: ${{ github.event.inputs.num_commits }}
build_script: ${{ matrix.build_cmd }}
elf: ${{ matrix.elf }}
ld: ${{ matrix.ld }}
linker_vars: ${{ matrix.linker_vars }}
api_key: ${{ secrets.MEMBROWSE_API_KEY }}
api_url: ${{ vars.MEMBROWSE_API_URL }}
After creating the files, tell the user they need to configure:
MEMBROWSE_API_KEY - API key from MemBrowse dashboardMEMBROWSE_API_URL - API URL (optional, defaults to https://www.membrowse.com)Location: Repository Settings → Secrets and variables → Actions
Tell the user how to test:
membrowse-report.ymlIf builds fail:
setup_cmdgit submodule update --init --recursiveIf linker parsing fails:
linker_varsld field is valid but limits analysisIf ELF not found:
ls -la path/to/build/ after build step to debugCreating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.
Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.
Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.