Skip to main content
You want a pull request checked on a virtual board, and the job failed when the captured UART is missing what you expect.

What you’ll do

1

Create a personal access token

On API keys, create a personal access token and give it a name. Chiplab shows the token once. Copy it into a CI secret. The job sends it as a bearer token, CHIPLAB_API_KEY.
CHIPLAB_API_KEY stays in the CI environment. The config file holds the ${CHIPLAB_API_KEY} placeholder, so the token is expanded when the job connects.
2

Start from the GitHub Actions template

The examples repository ships .github/workflows/claude-chiplab-smoke.yml. The template runs Claude Code in the job, which then uses Chiplab. It runs when someone comments /smoke-test on a pull request. It builds examples/bare-metal/stm32f4-discovery and checks the captured UART. It needs two secrets: CHIPLAB_API_KEY (a Chiplab personal access token, starts with veecle_pat_) and ANTHROPIC_API_KEY (for Claude Code). Treat it as a template: the trigger, the agent, and the example path are yours to change. Changing the on: trigger by itself is not enough. The job checks that the comment contains /smoke-test, and it checks out the pull request number from that comment.
3

Run on every pull request

To run on every pull_request, change the trigger, the job-level comment check, and the checkout together. A pull_request event has no comment body, and github.event.issue.number is empty.
Delete the job-level if. It looks for /smoke-test in the comment. Deleting it also drops the check that the commenter is OWNER, MEMBER, or COLLABORATOR.
Check out the pull request head:
The fork-guard step calls gh pr view with that same number. Point it at the pull request:
4

Run on the virtual board

The job calls ask for the current boards, tools, and gotchas, produces an ELF, uploads it, and runs it on the target board with the UART the firmware writes. It then waits and downloads uart.
5

Fail when the expected output is missing

Fail the pipeline unless uart contains what you expect. The public examples expect Hello world!. The check must look at the uart output, not the run status, because a crashing firmware still returns succeeded.
6

Gate on each test

To get a pass or fail per test, swap that UART check for run_test_suite. In your copy of the template, the prompt tells the agent to fail when the captured UART does not contain Hello world!. Change it so the agent uploads a suite, calls run_test_suite, and fails unless every test passed. result.summary has planned, passed, and failed. A null summary means the suite did not compile, or it threw before any test ran.

Ask your agent

What you get back

The job downloads uart and fails the pipeline unless that output contains what you expect. The public examples expect Hello world!.

Next

test

Get a pass or fail for each test.

run

Execute an ELF on a virtual board and read the UART.
Last modified on October 5, 2026