Open source core · pytest & Robot compatible

HiL tests proven to catch regressions

CruciHiL is the Python-first Hardware-in-the-Loop testing platform for AV, robotics, and automotive firmware teams. Write a test once — it runs against simulation today and real hardware tomorrow, and mutation verification proves it actually fails when your firmware breaks.

Tests are mutation-verified — a green suite means something Simulation → real hardware with zero test changes Bring your existing pytest and Robot suites unchanged
crucihil run · crucihil verify
Built for teams shipping
AV Startups Robotics Automotive Tier 2 Suppliers Firmware Teams
Why CruciHiL

A passing test suite you can actually trust

Legacy HiL toolchains tell you your tests passed. CruciHiL tells you whether they would fail when it matters — and gets you there without rewriting anything.

Tests proven to catch regressions

crucihil verify breaks the simulated DUT on purpose — dead device, stuck outputs, latency violations, injected faults — and scores every test: did it catch the breakage, or stay green? No other HiL tool does this.

crucihil verify → suite mutation score

Simulation to hardware, zero test changes

The exact same test file runs against a virtual simulation or real hardware. Switch from virtual.toml to orin.toml — the test never mentions hardware.

--rig rigs/virtual.toml → rigs/orin.toml

Keep your existing pytest & Robot suites

A pytest plugin and a Robot Framework library run your current test base through CruciHiL unchanged — rig fixture injected, results synced, and mutation verification works on those suites too.

crucihil run --framework pytest --suite legacy/

Self-verifying test authoring

crucihil author reads your component source, extracts its signal contract, generates a suite, gates it on a baseline run, then mutation-verifies and regenerates weak tests. Broken output never reaches disk.

crucihil author src/brake/ --verify

Python-first, CI-native

Plain async Python with full IDE support — no proprietary scripting languages. Runs headless, emits JUnit XML, and drops into GitHub Actions, GitLab CI, or Jenkins with one command.

async def test_engine_startup(rig: Rig)

AI that sees your test data

18 MCP tools connect Claude, GPT, or any MCP client directly to runs, results, signal traces, and rig state. Bring your own key — ask what broke and get the root cause with evidence.

describe_failure(run_id) → root cause
How it works

Author → simulate → verify → hardware → CI

One pipeline from first test to gated releases. No MATLAB, no proprietary scripting, no $50K licenses.

1

Author

Write plain async Python against the injected Rig — or point crucihil author at your component source and get a generated suite.

async def test_startup(rig):
 await rig.can.send(...)
 assert result.passed
2

Simulate

The virtual rig runs in-process — no hardware, no CAN adapters. Full DBC-driven bus simulation catches logic bugs before day one.

$ crucihil run \
 --rig rigs/virtual.toml

✓ 5 passed · 0.34s
3

Verify

Mutation verification breaks the DUT on purpose and proves every test fails when the behavior it claims to check is broken.

$ crucihil verify \
 --rig rigs/virtual.toml

Mutation score: 100%
4

Hardware

Swap the TOML. The test file is unchanged — the CAN backend switches from virtual to SocketCAN or PEAK. Same assertions, real signals.

$ crucihil run \
 --rig rigs/orin.toml

✓ 5 passed · 3.84s
5

CI & cloud

Headless runs emit JUnit XML for any CI system; the agent streams results to the dashboard, where the run history and strength matrix live.

$ crucihil run \
 --output results.xml

# GitHub Actions-ready
Mutation verification

Would your suite actually catch a regression?

Most test suites have never been tested. CruciHiL scores yours against deliberately broken firmware behavior — this is real crucihil verify output, not marketing art.

The simulated DUT is broken on purpose — dead DUT (output messages stop), stuck outputs (a signal freezes), latency violations (responses arrive too late), and every declared fault from your suite metadata. Each test is then scored:

caughtThe test failed under the mutation — it guards the behavior it claims to.
missedThe test stayed green while the behavior was broken — it's vacuous, and now you know.
wrong_reasonThe test went blocked/error instead of failing — it detects something, but not the right thing.

Weak tests don't stop at a report: crucihil author --verify feeds the mutation evidence back into generation and regenerates them. And it works on existing pytest and Robot suites with zero rewrites — point --framework pytest at your legacy tree and get its strength report.

crucihil verify --suite suites/brake.yaml --rig rigs/virtual.toml terminal
  test_brake_pressure_response
    ✓ CAUGHT       dead_dut[BrakeStatus]
    ✓ CAUGHT       stuck_output[BrakeStatus.Pressure]
    ✓ CAUGHT       latency[BrakeStatus+3.0s]
  test_abs_engage_on_slip
    ✓ CAUGHT       dead_dut[BrakeStatus]
    ✗ MISSED       stuck_output[BrakeStatus.AbsActive]
        test stayed green while AbsActive was frozen for the full window
    ✓ CAUGHT       fault[can_dropout]

  ── Mutation scores ──
  test_brake_pressure_response    3/3 caught  ██████████
  test_abs_engage_on_slip         2/3 caught  ██████

  Suite mutation score: 83%

$ crucihil author src/brake_controller/ --verify # regenerate the weak test
Adoption

Already have a test bed? Keep it.

Three adoption tiers, lowest friction first. No forced migration — your pytest and Robot Framework suites run through CruciHiL unchanged.

Tier 1 — Import

Import your existing results

Point at the JUnit XML or Robot output.xml your current runner already produces. History, trends, and AI querying work before any rig integration — re-imports never duplicate.

$ crucihil import-results build/junit.xml
$ crucihil import-results output.xml --format robot
Tier 2 — Run unchanged

Run your suites through the rig

The pytest plugin injects the rig fixture into your existing tests; the Robot library adds rig keywords. Same files, now with simulation, hardware parity, and cloud results.

$ crucihil run --framework pytest \
  --suite legacy/tests/ --rig rigs/bench.toml
Tier 3 — Verify

Score the suite you already trust

Mutation verification is framework-agnostic: get a strength report for your legacy suite with zero rewrites, and find out which of those green tests would actually catch a regression.

$ crucihil verify --framework robot \
  --suite legacy/robot/ --rig rigs/virtual.toml
Web Dashboard

Results stream in. Failures surface instantly.

Live WebSocket streaming from the agent to your browser. Every run, every signal, every failure — in real time.

app.crucihil.io
live
Dashboard
0Total runs
0%Pass rate (7d)
0Rigs online
Recent Runs
SuiteRigStatusPass
Test Runs
SuiteRigStatusPass
Back to runs
Engine Validation ✓ passed
orin-bench-01 5 tests 3.8s
Back to rigs
orin-bench-01
online
0Total runs
0%Pass rate
Recent Runs
SuiteStatusPass
Overview
Runs
Run Detail
Rig Detail
In practice

A real fault injection test

CAN dropout, assertion after recovery — 17 lines of Python, works on virtual and real hardware.

test_can_recovery.py Python
1import asyncio
2from crucihil.hal.rig import Rig
3
4async def test_can_dropout_recovery(rig: Rig):
5  # Inject a 1-second CAN dropout on engine messages
6  async with rig.fault.inject(
7    rig.fault.can_dropout(arb_id=0x100, duration=1.0)
8  ):
9    await asyncio.sleep(1.0)
10
11  # Bus restored — firmware should recover within 3s
12  result = await rig.can.expect(
13    signal="EngineData.RPM",
14    condition=lambda v: v > 0,
15    timeout=3.0,
16  )
17  assert result.passed, result.fail_msg
terminal output crucihil run
$ crucihil run \
  --suite recovery_tests.yaml \
  --rig rigs/bench.toml

Suite : Recovery Tests v1.2 (3 tests)
Rig : rigs/bench.toml

  ✓ [PASS ] test_engine_startup 0.023s
  ✓ [PASS ] test_can_dropout_recovery 1.234s
  ✓ [PASS ] test_firmware_resilience 2.891s

3 passed · 0 failed · 4.148s
Protocols & hardware

Every interface has a virtual twin

Develop and verify against simulation, then swap the TOML to real adapters. Custom protocols are declared as data — a wire-format YAML the built-in codec interprets, never generated code.

Interface
Simulation
Real hardware
CAN
DBC-driven bus simulation — scheduled messages, signal store, fault hooks
Linux SocketCAN · PEAK PCAN
SOME/IP
Virtual service twin — events & fields
vsomeip
DoIP / UDS
Virtual ECU twin
python-doip — routing activation, UDS, entity discovery; [rig.uds] diagnostics
UDP
Virtual twin
[rig.udp] datagram transport
Custom protocols
Declarative wire-format YAML (framing, packing, CRCs) over virtual UART / TCP / SPI / I2C twins — every transport ships with one
Bring your own adapter: backend = "myorg.rig_io_board" — any class implementing the transport ABC loads via TOML
GPIO / Power
Virtual backends for pin state and power cycling
Custom backends via the same TOML module path
Architecture

Six layers. Clean separation.

Test code only ever touches Layer 2. Hardware details live in TOML config, never in test code.

LAYER 6
Interfaces
Web Dashboard · CLI · CI/CD webhooks · REST API
LAYER 5
AI Interface
MCP Server (FastMCP) — 18 tools — vendor-agnostic
LAYER 4
Cloud Control
FastAPI + PostgreSQL — orchestration and test history
LAYER 3
Local Agent
Test runner · YAML executor · result reporter · SQLite cache
LAYER 2
Rig HAL
rig.can · rig.sim · rig.fault · rig.ecu · rig.bus — your tests live here
LAYER 1
Hardware
CAN · Ethernet · GPIO · Power · Qualcomm / Nvidia ECUs
Pricing

Start free. Scale with your team.

The open source core is free forever on your own infrastructure — with no rig limits. The hosted cloud starts free and grows per rig.

Self-Hosted
$0 forever

Run the entire stack on your own infrastructure. It's your hardware — we don't meter it.

  • Unlimited rigs — no quotas, ever
  • Full platform: authoring, verification, dashboard
  • Docker Compose deploy
  • MCP server — bring your own AI key
Get started
Hosted Free
$0 / month

The managed cloud control plane — no infrastructure to run. One rig on us.

  • 1 rig included
  • Web dashboard + run history
  • Result sync + MCP access
  • Upgrade any time
Get started
Enterprise
Custom

For teams with procurement, security review, or on-premise requirements.

  • On-premise control plane
  • Custom rig counts & SLAs
  • Dedicated support engineer
  • Security & procurement review
Contact sales

Self-hosted deployments never enforce rig quotas — the open source core has no limits on your own server.

Prove your tests. Then trust them.

Start free with the virtual rig — no hardware, no credit card, no dSPACE license. Just Python.