Never hard fault again

The HAL for AI Agents

Hard Fault is a local embedded-debug agent built on pyOCD. Bring your own model — Codex, Claude, or an OpenAI / Anthropic API key — and it flashes images, reads UART, and drives SWD on your board, behind safety guardrails.

01 — install uv
$ brew install uv$ pip install uv$ pip install uv
02 — clone & run
$ git clone https://github.com/JasonPeng2019/Firmware-CLI$ cd Firmware-CLI$ uv sync$ uv run pyocd-debug
SESSION · nrf52833dk LINK
SWD 4 MHzUART 115200probe 7f3a…
decoded "boot ok"
  1. connectsession 7f3a… opened · SWD @ 4 MHz
  2. decideplan: flash → read UART → verify
  3. actflash_firmware firmware.elf …… ok
  4. verifygreen criteria …… PASS ✓
full_success 12 / 12 · avg 100.0

Safe enough to hand a model a debug probe.Every mutating action passes a gate, and watchers stop a runaway before it can brick a board.

Guardrails →

// the loop

A closed loop, not a script.

Every run cycles Connect → Decide → Act → Verify until the board meets its green criteria — or a guardrail stops it.

01

Connect

Resolve the board from its YAML — target, probe, baud, recover policy — and open an SWD session with a tracked run id.

02

Decide

The model plans the next action from compact run memory: structured decisions in, one governed action out.

03

Act

Flash an image, run a build, write to UART, or step the core — every action routed through the brain gate.

04

Verify

Check UART boot text and green criteria, then persist evidence and events to the run log.

↻ the loop repeats until green criteria pass

// capabilities

A firmware engineer's bench, driven by a model.

Session

Open and inspect a debug session against the resolved board.

connectdisconnectget_board_infoget_state

Execution control

Drive the core exactly as you would by hand at the bench.

haltresumestepreset

Registers & memory

Read and write core registers and memory, including block reads.

read_core_registerwrite_core_registerread_memorywrite_memory

Firmware & UART

Flash validated images and capture serial output for verification.

flash_firmwareread_serial

Recovery

Board-policy-aware unlock for supported recover modes.

unlock_recover

Governed by MCP

Every operation is an MCP tool — wire the same governed actions into your own client or agent.

set_breakpointremove_breakpointread_memory_block

// guardrails

Safe to hand a model direct control.

A model can iterate on a fix, but it cannot silently loop on a destructive action or brick a board without an explicit, validated request.

Flash gate

Flashing validates its input before touching the board — a tracked baseline or a valid .elf/.hex succeeds; a missing path or bad suffix refuses.

$flash_firmware notes.txtrefused · invalid suffix

Recover gate

Recovery is board-policy aware: it needs explicit confirmation where a recover_mode exists, and refuses outright where none is tracked.

$unlock_recover (no recover_mode)refused · unsupported

Mutation watchers

Scoped watchers stop a run thrashing on a broken op — and only that op. Disconnecting and reconnecting clears the block.

$flash_firmware ×3 failedflash blocked

// benchmark

Proven on a frozen suite, not a demo.

The current turnkey corpus runs end-to-end on the scoped board pair — nRF52833-DK and Nucleo-L476RG — with the Codex backend.

12 / 12
frozen benchmark cases passed
100.0
average turnkey score
3
supported dev boards
4
model backends

// hardware

Boards it runs on today.

Bring-up, Stage 0 validation, and the benchmark suite are proven on these targets. New boards are added as a YAML definition plus a runbook.

PASS

Nordic nRF52833-DK

nRF52833 · Cortex-M4FOn-board J-Link / CMSIS-DAP
nrf52833dkofficial pair
PASS

ST Nucleo-L476RG

STM32L476 · Cortex-M4FOn-board ST-LINK
nucleo_l476rgofficial pair
tracked

Nordic nRF52840-DK

nRF52840 · Cortex-M4FOn-board J-Link
nrf52840dkalternate profile

// providers

Bring your own model.

Pick one of four backends. Your own subscription or keys — credentials are never proxied or repackaged; you authenticate the official vendor CLI yourself.

codex-cli
authLocal codex CLI auth

Whatever Codex auth you configured — a ChatGPT/Codex subscription or Codex API key.

claude-cli
authLocal claude CLI auth

A Claude subscription or ANTHROPIC_API_KEY. Not bundled Claude access.

openai-api
authOPENAI_API_KEY

Requires an explicit model via --model or PYOCD_TURNKEY_MODEL.

anthropic-api
authANTHROPIC_API_KEY

Requires an explicit model; stateless at the Messages API layer.

// get started

Point it at a board and give it a task.