Independent · Open source · Rust & WebAssembly

The open stack for test benches.

Test software is tied to the hardware it runs on and to the licences it was bought with. We are building the alternative in the open: a sequencer where the sequence is data, a digital twin of the bench so you can work without the instruments, and the plumbing that lets both run inside a WebAssembly sandbox.

You can evaluate it tonight, without an instrument. The bench in the terminal is simulated, and the sequencer does not know.

anvil 0.1.0 · no instrument attached
# terminal 1 — the bench that isn't there
$ ./crucible perfiles/keithley_2400_demo.yaml
Crucible: KEITHLEY-2400 en 127.0.0.1:5025

# terminal 2 — the sequencer, unmodified
$ ./anvil ejemplos/scpi.yaml

=== scpi_demo: paso ===
  [paso] medir_voltaje_scpi:
         SCPI medido: 4.501385029307777 V

# nobody wrote glue. Anvil sends
# MEASURE:VOLTAGE? because that is SCPI,
# and Crucible answers for the same reason.

Why we are building this

A test bench is one of the last places in software where the tooling is still sold per seat.

It ships as a closed binary, it refuses to run without the instrument plugged in, and it holds the one asset that genuinely outlives the product being qualified: the sequence itself. Engineers write test procedures that survive three generations of a product, and then lose them to a licence renewal or a discontinued driver.

The ingredients for a different answer already exist — they just have not been assembled. Sequences described as data instead of code. Instruments described as behaviour instead of drivers. A sandbox that arrived with a written specification instead of a vendor.

You should be able to write, run and review a test sequence before the bench exists.

The stack

Three pieces, one boundary each.

Every layer talks to the next one through a protocol, never through a direct call. That is what makes a step replaceable, a language a free choice, and a simulated instrument indistinguishable from a real one.

Architecture: a YAML sequence drives Anvil, which invokes steps over gRPC; steps talk SCPI or Modbus over TCP to either Crucible's simulated bench or real instruments. sequence.yaml Anvil — test sequencer walks the sequence without knowing what any step does gRPC over WASI sockets · wasi-grpc Steps — WebAssembly sandbox invoked by name · any language SCPI · Modbus · TCP Crucible the simulated bench Real instruments the rack you already own
Anvil cannot tell the two apart — and that is the entire point.

Anvil

v0.1.0 · in beta testing

Test sequencer

Runs sequences of steps against real equipment, retries what fails and reports the result. The sequence is data, not code: the engine walks it without knowing what each step does, and invokes every step by name over gRPC — never through a direct call. That isolates steps from each other and leaves the door open to writing them in any language.

  • Rust compiled to wasm32-wasip2, hosted by wasmtime
  • One self-contained binary — nothing to install
  • Setup → Main → Cleanup, per-step retries, JSON and CSV sinks
  • Process models as sequences, not as engine callbacks

AGPL-3.0-or-later Repository ↗

Crucible

runtime working · serving SCPI

The digital twin of the bench

An open standard for describing and simulating test benches. You describe how a Keithley 2400 behaves — its state, its commands, its measurement model — and a runtime serves it, speaking the right protocol over the right transport, like a real device. Simulink for instruments, not for physics.

  • Three layers kept apart: device, protocol, transport
  • SCPI and Modbus; TCP first, then GPIB, USB, serial, PXI
  • Deterministic models — a seeded run is a repeatable run
  • pyvisa, LabVIEW, MATLAB, C# or plain netcat, unmodified

Apache-2.0 Repository ↗

wasi-grpc

v0.1.0 · published

gRPC on native WASI sockets

Rust's gRPC stack does not reach WebAssembly: tonic needs hyper, hyper needs tokio, and tokio rejects the net feature on wasm. But wasmtime does ship native TCP through wasi:sockets. What was missing was HTTP/2 on top. This is that piece.

  • Unary RPC, client and server, blocking I/O
  • HTTP/2 framing and full RFC 7541 HPACK with Huffman
  • No tokio, no hyper, no async runtime
  • Codec-agnostic — protobuf messages stay prost's job

Apache-2.0 Repository ↗

See for yourself

Try it without an instrument.

Evaluating test software normally means booking rack time: you cannot see the tool work until the hardware it needs is in front of you. Here the instrument is described in a YAML file, so the whole thing is a laptop and an evening. What follows is the exact session shown above.

01

Serve a Keithley 2400 that does not exist

Crucible reads a profile — state, commands, measurement model — and serves the device over TCP, exactly as the real one speaks it.

# in the Crucible repository
cargo build
./target/debug/crucible \
  perfiles/keithley_2400_demo.yaml

02

Point a real sequencer at it

Anvil is not told that anything is simulated. It runs its SCPI smoke sequence the way it would against the instrument on your bench.

# in the Anvil repository
./anvil ejemplos/scpi.yaml

=== scpi_demo: paso ===
  [paso] medir_voltaje_scpi:
         SCPI medido: 4.501385… V

The two projects were built separately and were never adapted to each other. Anvil sends MEASURE:VOLTAGE? because that is SCPI; Crucible answers because that is SCPI. The decimals come from a seeded measurement model — same seed, same reading, which is what makes a simulated bench usable in continuous integration.

Principles

Four decisions we do not intend to revisit.

  1. 01

    The sequence is data.

    An engine that does not know what a step does can never become the bottleneck for what a step is allowed to be. Sequences are YAML, the engine walks them, and steps are named services on the other side of a wire.

  2. 02

    Simulate before you buy.

    A described instrument speaks exactly the same protocol as a real one. Development, continuous integration and code review stop queuing for time on a rack that costs more than the team.

  3. 03

    Sandboxed by construction.

    Everything above a thin native layer compiles to WebAssembly. Isolation becomes a property of the instruction set rather than a policy someone remembered to configure.

  4. 04

    Open, with a boundary that means something.

    What you use is copyleft. What you link is permissive. One sentence, and every licensing question about this stack answers itself.

AGPL-3.0-or-later

Anvil — the product

It gets used, not linked. Copyleft stops anyone closing it and reselling it. Running it on your plant floor, with your own sequences, or patched for internal use, triggers no obligation whatsoever — your sequences remain yours.

Apache-2.0

Crucible, wasi-grpc, the WIT interfaces

These get linked into other people's code. We want them adopted as a reference, including by companies that will never contribute a line back. That is the trade, and it is deliberate.

Where we actually are

Early, and saying so.

Most of this is young. We would rather you know that from the homepage than discover it after an afternoon of integration work.

shipped Anvil 0.1.0
A working sequencer, currently being hammered in structured beta rounds against 18 realistic benches — a solenoid valve, a battery pack, an RTD calibration, and on into a protection relay to IEC 60255-151, EMC pre-compliance to IEC 61000-4 and a class 1.0 smart meter to IEC 62053-21. Every defect the rounds find is filed in the open, in the issue tracker, including the ones that are still open.
working Crucible
The profile format and the bench topology spec are written and stable, and the reference runtime now does the job: it loads a profile, holds state across connections, matches commands and serves the device over TCP. The session at the top of this page is that runtime. What is still ahead is breadth — more protocols and more transports, starting from SCPI over TCP.
shipped wasi-grpc 0.1.0
Unary RPC works and is used in production by Anvil. Everything it does not do — streaming, TLS, connection pooling — is enumerated in the README as a known gap rather than left for you to find.

Get involved

We are looking for benches to be wrong about.

The fastest way to make this stack real is to point it at a bench we did not imagine. If you run test equipment and any of the above sounds like your problem, we want to hear about it — especially the parts where our assumptions break.

The Crucible format is still open for comment. Now is the cheap moment to change it.