Introduction
Welcome to the Certo Desktop Developer Reference. This site provides technical documentation, API references, and version history for the Certo Desktop application.
The Central Hub
The Certo Desktop Application is the foundational “wrapper” for the entire Certo Systems ecosystem. While individual products like EMU handle the low-level heavy lifting of hardware emulation and system call interception, the Desktop App serves as the command center that manages your global environment.
It is designed to be a lightweight, persistent utility that ensures your tools are licensed, updated, and communicating effectively.
Key Responsibilities
The Desktop App manages several critical subsystems that are shared across all Certo products:
Product Launching & Management
Certo Desktop acts as the primary launcher. It manages the lifecycle of the underlying engines, allowing you to switch between different workspaces (like the EMU environment) while maintaining a consistent global state.
Licensing & Entitlements
This is the authoritative source for your Certo license. The app handles key validation, tier entitlements (Beta, Professional, Enterprise), and expiration tracking. By housing the license at the desktop level, all sub-products can instantly verify their operational limits without requiring individual activation.
User Profiles & Global Settings
Certo Desktop serves as the central identity provider for the system. It manages user profiles, team affiliations, and global preferences—such as UI themes (Light/Dark mode) and directory defaults—that persist across all Certo-branded tools.
Unified Notification System
Certo Desktop provides a cross-process notification bus. Whether the EMU engine detects a critical hardware crash or a new software update is available, the desktop wrapper aggregates these alerts into a single, non-intrusive system tray notification modal.
Software Updates & Security
The app ensures your virtualization environment is running the latest architecture. It handles the secure download and installation of engine updates and provides granular controls over privacy, such as auto-declining crash reports and managing telemetry data.
How to Use This Reference
This documentation is organized into sections to help you manage your Certo installation:
-
User Interface Overview: A breakdown of the global sidebar, settings modal, and system tray.
-
Licensing & Profiles: Details on how to manage user identity, team seats, and license activation.
-
Notification API: For developers looking to understand how engine alerts are surfaced to the UI.
-
Security & Privacy: Information on how Certo handles data and local file permissions.
If you are looking for technical documentation specifically for the emulation engine, please refer to the Certo EMU Documentation.
Getting Started
This guide provides a rapid, frictionless overview of installing the Certo Desktop application and unlocking your workspace. The entire process is designed to take less than 60 seconds from the moment of purchase.
Installation Overview
The setup process begins immediately after purchase on the order confirmation screen. Certo provides native packages for major Linux distributions to ensure a seamless integration with your existing system management tools.
Downloading the Package
Follow the installation instructions from the email provided after purchasing a subscription.
License Activation
Once the application is installed and launched for the first time, you will be prompted to enter your license key. This key is provided on your order confirmation screen or via your team manager.
- Launch the Certo Desktop application.
- Navigate to the Account Profile section in the Settings Modal.
- Paste the license key into the activation prompt.
- Click “Update License.”
Technical Implementation: Invisible Latching
Certo utilizes a hardware-latching security model to ensure license integrity without requiring constant manual check-ins.
When you provide a license key, the desktop application automatically performs the following actions:
-
Machine ID Collection: The software generates a unique identifier based on your hardware’s specific configuration.
-
Hardware Latching: The license key is cryptographically tied to that Machine ID on the Certo authentication servers.
-
Local Storage: The validated license state is stored locally in the
~/.certo/directory.
This process happens entirely in the background. Once the license is latched, your dashboard is instantly unlocked and ready for virtualization tasks.
The Result
After successful activation, the dashboard will transition from an “Unregistered” state to a “Registered” status reflecting the subscription you pruchased.
Introduction to EMU
What is EMU?
EMU is a universal, OS-level hardware emulation framework. It functions as a transparent, user-space virtualization engine that sits between your application and the operating system’s kernel, allowing developers to spoof physical hardware, network streams, and character devices purely through software.
Instead of relying on physical USB dongles, serial cables, or active network servers, EMU dynamically intercepts the application’s standard system calls. By seamlessly routing resource handles and system requests through a lightweight scripting engine, EMU allows highly complex, hardware-dependent applications to execute exactly as if they were interacting with real physical devices—all without modifying a single line of your application’s source code.
Why Use EMU?
Developing and testing hardware-dependent software is notoriously difficult. Physical hardware is expensive, fragile, and often heavily constrained. EMU was built to solve the most painful bottlenecks in hardware/software integration:
Eliminating Hardware Bottlenecks
Engineering teams frequently have to share a limited pool of physical prototypes or development boards. EMU allows every developer to run a fully functional, virtualized hardware environment directly on their local machine—meaning you can write and test hardware-dependent code anywhere.
Surviving Agile Software Churn
Traditional software simulators inject fake data at the application layer. In an Agile environment where software architecture changes rapidly, these high-level simulators constantly break and require continuous maintenance.
EMU intercepts at the OS/kernel boundary—the absolute most stable layer in a product’s lifecycle. While your software may be patched and updated weekly, the physical hardware specifications and underlying system calls rarely change.
Extreme Fault Injection
How does your application handle a physical device randomly unplugging? What if a sensor suddenly starts sending garbage memory, or a network pipe completely stalls? With EMU, you can script edge-case hardware failures that are physically impossible or dangerous to reproduce in the real world.
True CI/CD Automation (Coming Soon)
You cannot easily plug physical hardware into a cloud-hosted testing runner. Future updates to EMU will include a headless CLI, allowing you to run full end-to-end integration tests in the cloud by virtually mocking the hardware environment on demand.
Architecture Overview
To achieve universal compatibility, EMU completely separates the Mechanism (how system calls are intercepted) from the Policy (how the virtual hardware behaves).
| Component | Technology | Responsibility |
|---|---|---|
| The Engine | Rust | A high-performance, memory-safe backend that intercepts system calls, manages memory mapping, and handles OS-level blocking. It knows nothing about specific application protocols. |
| The Logic | TCL | The “brain” of your virtual hardware. Scripts parse incoming data, calculate virtual state, and dynamically generate the raw bytes to send back to the application. |
| Intuitive UI | Desktop App | The central workspace for configuring intercepts and monitoring behavior. It translates raw C-struct memory pointers into human-readable variables. |
How it Works
-
Intercept: The Rust Engine catches a system call (e.g.,
readorwrite). -
Consult: It pauses the application and passes the context to a user-defined TCL script.
-
Respond: The script determines the hardware’s response, and the Engine feeds that data back to the application transparently.
Core Concepts
Before writing your first hardware simulation script, it is important to understand the mental model behind Certo.
Everything is a Resource
Most modern operating systems abstract hardware interactions into a generic “Resource” or “File” concept. Whether your application is opening a text document, connecting to a Bluetooth module, speaking to an I2C sensor, or opening a network socket, the operating system treats them all as a stream of bytes managed by a numeric identifier (a File Descriptor or Handle).
Because of this universal abstraction, all hardware interactions follow the same basic lifecycle:
-
Initialization: The application asks the OS to access a resource (
open,connect). -
Configuration: The application sends specific setup commands to the resource (
ioctl,stat). -
Data Transfer: The application sends or receives data from the resource (
read,write,sendto,recvfrom). -
Teardown: The application releases the resource (
close).
EMU works by letting you target specific paths, network ports, or resources, and then overriding any or all of these lifecycle events.
The Intercept Lifecycle
When EMU is actively targeting an application, the normal flow of execution is gracefully rerouted. Here is exactly what happens in milliseconds when your application attempts to talk to a targeted device:
-
The Trap: The application executes a system call (e.g., asking to read 1024 bytes from a sensor).
-
The Pause: The EMU Engine catches the system call before it reaches the OS kernel. The application is temporarily frozen.
-
Data Translation: The Engine reads the arguments passed by the application. If you have linked a C-schema, it decodes the raw memory pointers into structured, accessible data.
-
The Policy Execution: EMU triggers your custom TCL script. Your script can read the application’s request, update its internal virtual state, print to the logger, and populate the memory buffers with fake sensor data.
-
The Return: Once the script finishes, EMU resumes the application.
Tip
You can configure EMU to either bypass the native OS entirely (returning your spoofed data instantly) or to allow the real OS call to proceed after your modifications.
To the application, the pause was imperceptible. It simply believes the physical hardware successfully responded.
Intercept Target Syntax
When configuring your .vhb or setting up a new intercept, EMU’s engine supports flexible pattern matching to make targeting dynamic resources effortless:
| Syntax Type | Example | Description |
|---|---|---|
| Exact Paths | /dev/ttyUSB0 | Matches the strict, absolute path. Best for targeting a single, predictable hardware device. |
| Directory Prefixes | /dev/snd/ | Matches any file opened inside this directory. Perfect for complex subsystems like ALSA or USB buses. |
| Global Wildcard | * | A global catch-all. Instructs Certo to intercept absolutely every system call the application makes. |
| Filename Matching | alsa.conf | Matches the filename regardless of directory (e.g., /etc/alsa.conf or ./alsa.conf). |
User Interface Overview
The Header Menu
The top navigation bar provides quick access to project management, your C-schema extraction tools, and general application support.
File
The File menu handles all standard project management operations, allowing you to load, save, and organize your .vhb bundles and workspace configurations.
- New Project: Initializes a clean workspace with a blank
.vhbfile and default target settings. - Open Project: Loads an existing EMU project from your local file system.
- Save: Commits the current workspace configurations and TCL script changes to your active project file.
- Save As: Duplicates the current workspace into a new project file at a location of your choosing.
- Close: Safely shuts down the current project and returns you to the launch screen.
Schemas
Because EMU translates raw kernel memory into readable TCL variables, it needs to know the exact shape of that memory. The Schemas menu is the powerhouse of the application, giving you multiple ways to map out those memory structures.
- Schema Builder: Opens a graphical interface where you can manually define or edit existing structs, padding, and data types.
- Scan DWARF Library: Analyzes compiled binaries (
.so,.elf) that contain DWARF debug symbols to automatically extract the exact memory structures used by the target application. - Scan C Header: Parses raw C/C++ source code headers (
.hfiles) to automatically generate EMU schemas, perfect for when you are testing against proprietary driver code. - Inspect Schemas: Opens a viewer to let you verify, search, and audit all currently loaded memory schemas within your project.
- Import Standard Schemas: Instantly loads EMU’s pre-packaged, architecture-specific OS schemas (like POSIX networking, ALSA audio, or V4L2 video structs) so you don’t have to extract them yourself.
Help
- About EMU: Displays the current version of the EMU engine you are running, along with a brief overview of the EMU product suite.
- Send Feedback: Opens a direct line to the development team. You can provide a star rating and leave specific comments or feature requests, which are automatically routed to our community Discord server.
Pre-Shipped Standard Schemas
When you select Import Standard Schemas from the header menu, EMU instantly loads a curated library of pre-compiled memory structures for common Linux hardware subsystems.
| Subsystem | Standard Header(s) | Use Case |
|---|---|---|
| Audio (ALSA) | /usr/include/sound/asound.h | Virtualizing sound cards, microphones, speakers, and DSP interactions (like SDR++). |
| USB Core | /usr/include/linux/usbdevice_fs.h | Defining usbfs structures; crucial for intercepting raw USB communications via libusb. |
| Video (V4L2) | /usr/include/linux/videodev2.h | Mocking webcams, video capture cards, and hardware video encoders/decoders. |
| Bluetooth (BlueZ) | bluetooth.h, hci.h, rfcomm.h | Spoofing device discovery, HCI commands, and RFCOMM serial connections. |
| Input (evdev) | /usr/include/linux/input.h | Mocking keyboards, mice, touchscreens, and gamepads. |
| I2C & SPI | i2c-dev.h, spidev.h | Low-level peripheral communication (temperature sensors, EEPROMs, etc.). |
| TUN/TAP | if_tun.h, sockios.h | Mocking virtual network adapters, VPN tunnels (TUN), or network bridges (TAP). |
| Networking | <sys/socket.h>, <netinet/in.h> | Standard POSIX networking (IPv4, IPv6, and UNIX domain sockets). |
Interface Modes Overview
EMU’s workflow is divided into four distinct operational modes: Design, Driver, Emulate, and Observe. Each mode serves a specific phase of the virtualization lifecycle, from initial hardware mapping to live execution.
Design Mode: The Interface Blueprint
Design Mode is where you define the architectural blueprint of your virtual hardware. It establishes the fundamental rules: what system calls constitute your hardware interface, what memory shapes they use, and how data flows.
Hardware Spec Management (Left Panel)
- Search & Filter: Quickly isolate specifications by type (e.g.,
ioctl), Group ID, or Alias. - Auto-Import from Capture (Magic Wand): Automatically generates a new spec based on a live capture feed, populating the System Call Type and Hardware Code.
Global Identity (The Core Hook)
Defines the mechanical trigger for the system call:
- System Call Type: The POSIX operation (e.g.,
open,read,ioctl). - Data Capture Phase: * Outbound (Pre-Kernel): Application pushing data out.
- Inbound (Post-Kernel): Application requesting data from the system.
- Hardware Code & Label: The hex signature (e.g.,
0x81785501) and its C-macro label (e.g.,SNDRV_CTL_IOCTL_CARD_INFO).
Argument Specifications & Payloads
- Payload Data Type: Links the primary payload to a specific C-schema.
- Argument Specifications: Defines data types for every variable or nested pointer passed in the call.
Driver Mode: Programming the Behavior
If Design Mode is the blueprint, Driver Mode is the brain. Here, you write the TCL scripts that dictate how the mock hardware responds.
TCL Scripting Console
- The Environment: Supports standard TCL plus EMU extensions like
certo::payload_data::*andcerto::force_return_value. - Validate Syntax: Runs static analysis without saving.
- Apply: Hot-reloads the updated logic directly into the running engine.
Emulated Hardware Output (Isolated Logging)
To avoid the “noise” of global system traffic, this window only displays output (puts) and error traces related to the specific script you are editing.
Hardware Driver vs Software Driver
Driver Mode has two sub-modes controlled by the Driver Mode toggle in the toolbar.
| Hardware Driver (default) | Software Driver | |
|---|---|---|
| Engine role | Sits below software, simulates hardware responses | Sits above hardware, acts as the software layer |
| Script edited | tcl_script — hardware behavior | software_driver_script — outgoing payload construction |
| Script label | Hardware Behavior Script | Software Driver Script (amber accent) |
| Execution | Runs when the target process makes a system call | Runs when you invoke the interaction explicitly (CLI shell or executeInteraction) |
| Data direction | Inbound = hardware sending data up to software | Inbound = hardware sending data back to the engine |
The two modes use separate script fields because the semantics of “inbound” and “outbound” reverse completely. A single shared script would be ambiguous about which direction it describes.
When software driver mode is active, the Design Mode panel shows an additional Software Driver Script editor (amber border) alongside the Hardware Behavior Script. Both can be authored independently.
See Software Driver Mode for a full explanation, worked examples, and the
emu shell --software-driverCLI workflow.
Emulate Mode: Live Execution & Overrides
This is the live control center where you toggle behaviors and monitor performance.
Emulation Activation & Metrics
- Emulation Enabled Toggle: Explicitly injects your TCL script into the execution pipeline.
- Avg Round Trip Time: Total latency from capture to returning the result to the app.
- Avg TCL Exec Time: The specific time taken by your script logic.
Pure Virtual Emulation
When enabled, EMU isolates the application from the host OS hardware stack entirely. The app no longer requires physical file paths or host drivers; everything is satisfied in user-space.
Observe Mode: Telemetry & Inspection
The primary diagnostic window providing a chronological feed of every system call.
Discovery & Linking
- Add as New: Convert an unmapped call into a Design Mode spec.
- Link to Existing: Map a new memory offset to a previously defined hardware spec.
Call Inspection & Metrics
Clicking a call provides:
- Metadata: Unique Call ID, PID, and precise Timestamps.
- Memory Payload Inspection: Parses raw bytes against your C-schema into a human-readable structure.
Status Bar & Global Logs
Located at the bottom of the interface, providing persistent context:
- Workspace Context: Shows Active Mode and the current
.vhbproject file. - Unified Console: Access to Engine logs, UI logs, and the Target Process (stdout/stderr of the app being tested).
EMU Desktop Wrapper
The outer shell managing global state, identity, and licensing.
Settings Modal
| Tab | Responsibility |
|---|---|
| Profile & License | Manages user identity, license tier, and keys. |
| Notifications | Toggle “Mute All” for presentations. |
| Security | Manage privacy and auto-declining of crash reports. |
| Software Updates | Check for latest stable releases of the engine and wrapper. |
Software Driver Mode
What Is It?
EMU normally operates as a hardware simulator: it attaches to a running process, intercepts its system calls, and returns scripted responses — effectively impersonating the hardware layer.
Software driver mode inverts this. The engine now acts as the software layer and proactively issues real system calls down to actual hardware. You script what your software would send, and EMU dispatches it as a genuine OS call, returning whatever the hardware responds with.
This is useful when you want to:
- Drive real hardware from a controlled, reproducible script without a full software stack running
- Test firmware or kernel drivers by acting as their software counterpart
- Prototype or replay a driver’s communication sequence interactively
Enabling Software Driver Mode
In the Desktop UI
Open the Driver Mode toggle in the toolbar. When enabled, the TCL editor label switches from Hardware Behavior Script to Software Driver Script so it’s always clear which script you’re editing.
In the CLI Shell
Pass --software-driver to the shell subcommand:
certo emu shell --software-driver --vhb ./behaviors/my_device.vhb
Programmatically
#![allow(unused)]
fn main() {
session.set_software_driver_mode(true);
}
The Two Script Fields
Each interaction in a VHB has two separate TCL fields:
| Field | Used in | Purpose |
|---|---|---|
tcl_script | Hardware driver mode | Defines how the hardware responds to an incoming call |
software_driver_script | Software driver mode | Builds the payload the software sends to hardware |
They are kept separate because the meaning of “inbound” and “outbound” reverses completely between modes. A single shared field would be ambiguous.
In the UI, the Driver Mode tab shows the appropriate field with an amber accent when in software driver mode so you always know which script you’re editing.
How Execution Works
When you run an interaction in software driver mode:
- Spec lookup — the interaction is found by ID or alias from the loaded VHB
- TCL preamble — the engine builds and prepends:
namespace eval certo {} set certo::direction "Inbound" ;# data back from hardware is inbound set <override_key> <value> ;# one line per caller override - Script execution — the spec’s
software_driver_scriptis appended and run - OS dispatch — the script’s return value becomes the payload for the system call
certo::direction is always preset to "Inbound" because from the engine-as-software perspective, data that comes back from hardware is inbound.
Call Types and What They Do
Not all call types behave the same way.
Auto-dispatched — engine opens, calls, and closes
| Type | What happens |
|---|---|
ioctl | Opens resource_path, calls ioctl with the TCL-built buffer in-place, reads response, closes |
write | Opens resource_path (or uses fd override), writes the payload, closes if auto-opened |
read | Opens resource_path (or uses fd override), reads into a buffer sized by max_data_length (default 4096 bytes) |
send | Sends the payload on the provided fd |
recv | Receives data from the provided fd into a buffer |
sendto | Sends a UDP datagram — requires fd, host, and port overrides |
recvfrom | Receives a UDP datagram — requires fd override |
TCL-only — no OS dispatch, user manages fds
| Type | Notes |
|---|---|
open | Script sets up state, returns a value |
close | Script handles teardown |
socket | Script creates the socket and returns the fd |
connect | Script handles connection setup |
bind | Script handles binding |
shutdown | Script handles shutdown |
These types are TCL-only because they manage file descriptor lifetime. If the engine auto-closed the socket inside a socket interaction, the fd would be gone before your subsequent send calls could use it. The TCL-only pattern keeps you in control of when fds are created and destroyed.
The fd Override Pattern
For multi-step socket interactions, the workflow is:
1. select socket-open 2. set fd <result from step 1> 3. select send-data
send select send-data send
→ fields["result"] = "7" set host 192.168.1.10
set port 9000
The socket interaction’s TCL script creates the socket and returns the fd number. You capture it from fields["result"] and pass it as the fd override to the data-transfer interactions that follow.
Override Keys
Overrides serve two purposes: they are injected into TCL as variables (so your script can read them), and certain keys are additionally consumed by the dispatch logic.
| Key | Type | Used by |
|---|---|---|
fd | i32 (string) | write, read, send, recv, sendto, recvfrom — uses existing fd instead of auto-opening |
host | dotted-decimal IPv4 | sendto — destination address |
port | u16 (string) | sendto — destination port |
flags | i32 (string) | send, recv, sendto, recvfrom — OS-level flags |
All other keys you set are available in your TCL script as $varname but have no effect on the dispatch mechanism.
Example: Reading a Sensor via ioctl
In the shell:
emu> select sensor-read
Selected: sensor-read
emu(sensor-read)> defaults
# Script output:
binary format H* "0102030405060708"
emu(sensor-read)> send
{"fields":{},"raw_bytes":[12,0,128,0,0,0,0,0]}
The engine opened /dev/my_sensor, called ioctl with the 8-byte request buffer your script produced, read the hardware’s in-place response, and returned it as raw_bytes.
Example: UDP Round-Trip
emu> select udp-socket
emu(udp-socket)> send
{"fields":{"result":"7"},"raw_bytes":[]}
↑ fd = 7 returned by socket script
emu> select udp-send
emu(udp-send)> set fd 7
emu(udp-send)> set host 192.168.1.10
emu(udp-send)> set port 9000
emu(udp-send)> send
{"fields":{},"raw_bytes":[80,73,78,71]}
emu> select udp-recv
emu(udp-recv)> set fd 7
emu(udp-recv)> send
{"fields":{},"raw_bytes":[80,79,78,71]}
Transport Templates
A transport template is a prepackaged .vhb that gives you everything above
the device-specific behavior for one communication mode — the intercept targets,
the syscall vocabulary, the decode schemas, and a dump-and-default TCL stub for
every call — so you only fill in the logic that makes your device your device.
Importing a template is one action: File → New from Template. You pick a
transport, EMU opens a fresh unsaved session pre-wired with that transport’s
targets, embedded schemas, and stubs. Run your unmodified target application
against it and every intercepted call prints its decoded fields; turn the mock
into a working device by editing only the marked USER-LOGIC sections.
Bundled transports
| Template | Intercept target | Class |
|---|---|---|
usb | /dev/bus/usb/*/* (usbfs ioctls incl. async URB submit/reap) | device-file |
i2c | /dev/i2c-* (I2C_RDWR, I2C_SMBUS, slave/funcs) | device-file |
spi | /dev/spidev* (mode/speed/bits, SPI_IOC_MESSAGE) | device-file |
tty | /dev/ttyS*, ttyUSB*, ttyACM* (termios, modem lines) | device-file |
hidraw | /dev/hidraw* (report descriptor + report streams) | device-file |
socket-inet | AF_INET / AF_INET6 TCP/UDP | socket-family |
wifi-nl80211 | AF_NETLINK/NETLINK_GENERIC → nl80211 | socket-family |
bluetooth-hci | AF_BLUETOOTH/BTPROTO_HCI | socket-family |
socketcan | AF_CAN/CAN_RAW | socket-family |
Intercept target syntax
Device-file transports target glob patterns (e.g. /dev/bus/usb/*/*,
/dev/ttyUSB*). Socket-family transports use the socket: prefix:
socket:AF_FAMILY or socket:AF_FAMILY/PROTOCOL, for example
socket:AF_CAN/CAN_RAW or socket:AF_NETLINK/NETLINK_GENERIC. A family-only
spec matches any protocol of that family.
Anatomy of a template
A template is authored as a source directory and compiled with
certo emu package-template:
templates/usb/
manifest.json # targets, headers, and the syscall list
tcl/
_dict_printer.tcl # shared decode-and-print helper (inlined)
open_template.tcl # one dump-and-default stub per syscall
USBDEVFS_SUBMITURB_template.tcl
...
manifest.json names the intercept targets, the kernel headers to scan for
decode schemas, and each syscall (its type, the ioctl/ schema it decodes, and
the stub file that handles it). The packager scans the headers, embeds the
resulting schemas directly in the .vhb, and inlines each stub as the syscall’s
TCL — so the produced file is fully self-contained and loads like any project.
Async transports and the waker
Asynchronous transports (USB URBs, netlink, HCI events) split one operation
across a submit syscall and a later collect syscall. The stubs hold the
completion in device-model state and hand it back on collect. When the target
blocks in poll/epoll between the two calls, the stub announces readiness
with certo_set_ready_in; see
Asynchronous Readiness.
Extending a template into a real device
Each stub prints the decoded call and returns a permissive default, with the spot you edit clearly marked:
# i2c :: I2C_SMBUS — SMBus byte/word/block transfer.
set req_addr [lindex $certo::arguments 2]
set smbus [::certo::dump_struct i2c_smbus_ioctl_data $req_addr "smbus"]
# --- USER-LOGIC: implement your register map -----------------------------------
# On a read, write the register value back through the data union pointer.
# -------------------------------------------------------------------------------
certo_set_return_value 0
Device state lives in your own model variables (the stubs use globals like
::usb_pending_urbs as a starting point). See the
TCL API Reference for the decode, memory, and return-value helpers
available inside a stub.
Engine Capabilities & Reference
EMU supports intercepting a vast array of system calls and ships with standard Linux subsystem headers for immediate decoding. It operates in two primary modes depending on your hardware availability.
Standard Intercept Mode (Default)
By default, EMU acts as a transparent virtualization layer between your application and existing system resources.
In this mode, when the application calls open() on a device path or connect() to a server, the OS processes the request normally. The physical driver, file, or server must actually exist on the system.
EMU pauses the subsequent data transfer functions (such as read, write, ioctl, or recvfrom), allowing your TCL scripts to:
- Inspect or modify the payloads.
- Pass modified data to the real hardware.
- Return spoofed data back to the application.
Best For: Extending existing hardware, fault injection into real data streams, or modifying live configurations.
Pure Virtual Mode
Traditionally, if an application attempts to open() a missing device path like /dev/ttyUSB0, the OS rejects the call with an error, often crashing the application. EMU bypasses this limitation using Pure Virtual Mode, allowing you to create synthetic hardware without real drivers or servers.
| Resource Type | Interception Logic |
|---|---|
| Character Devices | EMU intercepts the open failure, opens a handle to /dev/null, and hands that valid File Descriptor to the application. |
| Network Sockets | EMU generates a kernel-level socketpair, hands one end to the app, and reserves the other for the TCL engine. |
This allows the application’s blocking loops (like poll()) to run natively against synthetic file descriptors, achieving a true “no hardware” test environment.
Intercepted System Calls
EMU’s engine is capable of hooking into the following POSIX operations:
Initialization & Teardown
open,openat,open64,openat64fopen,fopen64close
Character Devices
read,writelseek,ioctl,mmap
Networking
socket,connect,bindshutdown,send,recv,sendto,recvfrom
Discovery (sysfs)
stat,fstat,accessreaddir,opendir,closedirgetdents64
Polling
poll,epoll_wait
TCL API Reference
While the EMU Engine handles the heavy lifting of system call interception, the TCL scripting layer acts as the “brain” of your virtual hardware. Standard TCL language features are fully supported, supplemented by the injected certo:: namespace.
Hardware State Management
Because EMU intercepts individual system calls, your scripts need a way to remember what happened previously. Use standard TCL global variables by prefixing variables with :: to create a state that persists across different system calls.
# In your 'sendto' script (Setting the state)
set ::virtual_radio_freq 100000000
# In your 'recvfrom' script (Reading the state)
if {$::virtual_radio_freq > 90000000} {
# Generate high-frequency tone...
}
Accessing Syscall Parameters
EMU provides the raw arguments passed by the application as a standard TCL list via certo::arguments.
# Example: recvfrom(int fd, void *restrict buf, size_t len, ...)
set fd_num [lindex $certo::arguments 0]
set buf_addr [lindex $certo::arguments 1]
set requested_size [lindex $certo::arguments 2]
Memory Manipulation
For direct access to the application’s memory pointers:
::certo::read_memory addr ?len?: Reads raw bytes from the target process’s memory.::certo::write_memory addr payload: Writes a raw byte array back into the target process’s memory.
# Example: Modifying a write() buffer
set buf_addr [lindex $certo::arguments 1]
set write_size [lindex $certo::arguments 2]
set raw_bytes [::certo::read_memory $buf_addr $write_size]
set modified_bytes [string map {"OFF" "ON "} $raw_bytes]
::certo::write_memory $buf_addr $modified_bytes
Schema Parsing
Translate between raw C memory bytes and TCL Dictionaries using registered schemas.
::certo::bytes_to_dict schema_name bytes: Decodes raw bytes into a dictionary.::certo::dict_to_bytes schema_name dict: Encodes a dictionary back into raw C-struct bytes.::certo::create_struct schema_name: Generates a zero-initialized dictionary for a schema.
System Control & Logging
::certo::logger ?message...?: Sends a formatted log message to the UI. Standardputsis automatically intercepted and funneled here.certo_set_return_value value: Spoofs the return value of the intercepted system call.
Asynchronous Readiness (Completion Waker)
Some transports split one logical operation across multiple syscalls: a request
is submitted by one call and collected by a later one (USB URB
submit/reap, netlink request/response, HCI command/event). When the target
application blocks in poll/epoll_wait between those calls, the engine needs
to know when the pending result becomes ready so it can wake the wait.
certo_set_ready_in ?fd? ms: Declares that the intercepted file descriptor becomes readablemsmilliseconds from now (0= immediately). A target blocked inpoll/epollon that fd wakes when the deadline passes. Readiness is level-triggered — it persists across polls until cleared.certo_clear_ready ?fd?: Drops the readiness state for the fd, e.g. once the collect-side stub has delivered the last queued result.$certo::fd: The file descriptor of the syscall currently under evaluation. The readiness commands default to this fd when one is not given, so a stub can simply callcerto_set_ready_in 0.
# Submit side (e.g. USBDEVFS_SUBMITURB): queue the completion and announce it.
lappend ::pending_urbs $urb_addr
certo_set_ready_in 5 ;# this fd becomes readable in 5ms
# Collect side (e.g. USBDEVFS_REAPURB): hand back the result, clear when drained.
set urb [lindex $::pending_urbs 0]
set ::pending_urbs [lrange $::pending_urbs 1 end]
if {[llength $::pending_urbs] == 0} { certo_clear_ready }
Lazy / polling targets work without any waker — the collect-side stub simply returns the queued result.
certo_set_ready_inis only needed to wake targets that block inpoll/epoll/select-style waits.
Lifecycle & Context
Emulation Callbacks
proc certo::emulation_enabled {} {
set ::virtual_radio_freq 0
}
proc certo::emulation_disabled {} {
unset -nocomplain ::virtual_radio_freq
}
Execution Direction
The variable $certo::direction indicates if the script is currently being evaluated before the real system call (“Inbound”) or after (“Outbound”).
if {$certo::direction eq "Inbound"} {
::certo::logger "PRE phase logic"
} else {
::certo::logger "POST phase logic"
}
The .vhb Ecosystem (Portability & Sharing)
EMU is designed for collaboration. Once you have successfully virtualized a piece of hardware, you shouldn’t have to keep it to yourself. This portability is managed through the .vhb (Virtual Hardware Behavior) file format family.
File Formats
EMU supports two project file formats, giving you control over how sensitive your shared hardware profile is.
.vhb — Plain Text (Non-Sensitive Sharing)
A .vhb file is a portable, human-readable container that holds everything required to spoof a specific piece of hardware. Use this format when sharing within a trusted environment (e.g., internal teams, version control).
It encapsulates:
- The Intercept Targets: The specific file paths (e.g.,
/dev/ttyUSB0) or network ports the Engine needs to hook. - The Hardware Specs: Your list of tracked system calls and communications to and from the hardware.
- Schema References: The structs and schemas used to map raw memory into structured data.
- The TCL Scripts: All of your custom logic and state-machine behavior associated with your Hardware Specs.
.vhbx — Encrypted (Sensitive Sharing)
A .vhbx file contains the same profile data as a .vhb file, but the contents are encoded before being written to disk. Use this format when distributing a hardware profile outside of a trusted context — for example, sharing with an external contractor, a customer, or over an untrusted channel.
When saving a project, select VHB Encrypted Project in the file dialog to produce a .vhbx file. EMU will automatically decrypt it on load.
Warning — Limited Security in Current Release
.vhbxfiles are currently encoded using Base64 only. Base64 is an encoding scheme, not true encryption — a determined party can decode the contents without a key. Do not rely on.vhbxfor strong confidentiality at this time.A future release will upgrade
.vhbxto full AES-256-GCM encryption, where files will be locked to a specific individual or team license key. Only holders of the matching license will be able to open the file. Until that upgrade ships, treat.vhbxas obfuscated rather than secure.
Choosing the Right Format
| Scenario | Recommended Format |
|---|---|
| Committing to a team Git repository | .vhb |
| Sharing with an external partner or customer | .vhbx |
| Automated CI/CD pipelines (internal infrastructure) | .vhb |
| Distributing a hardware profile publicly or externally | .vhbx |
Collaboration & Version Control
Because the .vhb file completely encapsulates the virtual hardware profile, it is perfect for modern development workflows:
Git Integration
You can commit .vhb files directly to your Git repository alongside your application source code. This ensures that the hardware environment is versioned right next to the software that depends on it.
Team Consistency
Any other developer on your team can simply download the EMU app, import your .vhb or .vhbx file, and instantly possess the exact same virtual hardware environment. This eliminates the “it works on my machine” problem caused by differing physical hardware revisions or local driver configurations.
CI/CD Ready
By bundling hardware behavior into a file, you enable automated testing environments to “plug in” virtual devices on demand, guaranteeing test consistency across your entire organization.
CLI Reference
While the Certo Desktop Wrapper provides a comprehensive visual environment for designing and executing your virtual hardware, Certo also ships with a lightweight Command Line Interface (CLI).
The CLI is currently focused on providing quick access to engine tools and schema extraction directly from your terminal.
EMU Tools: certo emu
The emu cli provides direct terminal access to the underlying emulation engine’s utility functions.
Usage
certo emu [OPTIONS] <COMMAND>
Options
-h, --help: Prints the help manual for theemutools.-V, --version: Prints the specific version of the EMU engine currently running under the hood.
Sub-Commands
scan
Initiates the schema extraction engine. You can pass a raw C/C++ header file (.h) or a compiled binary target (.so, .elf) containing DWARF debug symbols.
Usage
certo emu scan [OPTIONS] <TARGET>
The engine will parse the file and automatically generate the JSON-based memory schemas Certo uses to translate system call payloads.
Options
--outdir <DIR>: Output directory for scanned schemas. (Default:ui/src-tauri/schemas).--include-host: Include host standard headers (/usr/include).-I, --include <DIR>: Additional include directories for clang (can be specified multiple times).
Example:
certo emu scan ./include/driver_interface.h
package-template
Compile a transport-template source directory into a single self-contained
.vhb for the “New from Template” gallery (see
Transport Templates). The packager scans the
manifest’s headers, embeds the decode schemas, and inlines each
<syscall>_template.tcl dump-and-default stub, stamping
Meta.kind = "TransportTemplate".
Usage
certo emu package-template [OPTIONS] <DIR>
<DIR> must contain a manifest.json and a tcl/ directory of stubs.
Options
--out <PATH>: Explicit output.vhbpath.--outdir <DIR>: Output directory when--outis not given. (Default:ui/src-tauri/templates).--include-host: Include host standard headers (/usr/include) when scanning.
Example:
certo emu package-template ui/src/plugins/emu/templates/usb --include-host
The bundled templates are normally produced for you at build time by
tools/generate_templates.sh(invoked fromtools/init-bundle.sh); run the command directly only when authoring or iterating on a template.
info
Inspect a virtual hardware behavior file (.vhb or .vhbx) without booting the emulation engine. This allows you to check static configurations, structure, and behavior logic beforehand.
Usage
certo emu info [OPTIONS] --vhb <PATH>
Options
--vhb <PATH>: Path to the.vhbor.vhbxfile.-f, --format <FORMAT>: Output format, eithertextorjson. (Default:text).-v, --verbose: Print expanded details, including raw TCL logic.
Example:
certo emu info --vhb ./behaviors/ethernet.vhb --format json
run
Boot the emulation engine and execute a target command within the simulated hardware environment.
Usage
certo emu run [OPTIONS] --vhb <PATH> [-- <COMMAND> [ARGS]...]
Options
--vhb <PATH>: Path to the.vhbor.vhbxfile.--pure-virtual: Force strict virtual mode, disabling any fallback to host hardware.-v, --verbose: Stream emulation engine logs alongside the target command output.
Example:
certo emu run --vhb ./behaviors/ethernet.vhb --pure-virtual -- ping -c 3 192.168.1.1
shell
An interactive REPL for building and sending VHB interaction payloads. Loads a VHB project, arms the engine, and drops into a prompt where you can select interactions, set field overrides, and execute them — all without writing a target process or test harness.
The shell is particularly useful for iterating on software_driver_script logic in software driver mode (see Software Driver Mode).
Usage
certo emu shell [OPTIONS] --vhb <PATH>
Options
--vhb <PATH>: Path to the.vhbor.vhbxfile to load.--software-driver: Enable software driver mode. The engine acts as the software layer and sends payloads to real hardware, returning the hardware’s response. Without this flag the engine runs in hardware driver mode (default).
Shell Commands
Once inside the prompt (emu>), the following commands are available:
| Command | Description |
|---|---|
list | List all interactions from the loaded VHB, with their type and alias. In software driver mode, Inbound/Outbound labels are shown from the software’s perspective. |
select <id> | Select an interaction by ID or alias. The prompt changes to emu(<id>)> to confirm the selection. |
set <field> <value> | Accumulate a field override for the selected interaction. Overrides are injected as TCL variables before the script runs. Certain keys (fd, host, port, flags) also control OS dispatch. |
defaults | Print the software_driver_script for the selected interaction. |
send | Execute the selected interaction with all accumulated overrides. Prints the result as JSON: { "fields": {...}, "raw_bytes": [...] }. |
reset | Clear all accumulated field overrides for the selected interaction. |
help | Print the command reference. |
exit / quit / ^D | Exit the shell. |
Example: Hardware Driver Mode (inspect interactions)
certo emu shell --vhb ./behaviors/audio_device.vhb
Certo EMU Shell — hardware-driver mode
VHB: ./behaviors/audio_device.vhb
Type 'help' for available commands.
emu> list
ctl-card-info [Inbound] — card_info_ioctl
pcm-write [Outbound] — pcm_write
emu> select ctl-card-info
Selected: ctl-card-info
emu(ctl-card-info)> defaults
(no software_driver_script defined)
emu(ctl-card-info)> exit
Exiting EMU shell.
Example: Software Driver Mode (drive real hardware)
certo emu shell --software-driver --vhb ./behaviors/sensor.vhb
Certo EMU Shell — software-driver mode
VHB: ./behaviors/sensor.vhb
emu> select sensor-read
emu(sensor-read)> defaults
binary format H* "0102030405060708"
emu(sensor-read)> send
{"fields":{},"raw_bytes":[12,0,128,0,0,0,0,0]}
Spoofing a Character Device
In this guide, we will virtually spoof a radar sensor for a drone application. The software expects a device at /dev/radar, but we will provide it entirely through software.
The Target Application
Our C application attempts to open the radar and read its configuration.
certo_symbol_import_demo.h
struct RadarConfig {
int range;
int sweep_speed;
char status[16];
};
main.c
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include "certo_symbol_import_demo.h"
int main() {
// 1. Attempt to connect to the physical hardware
int fd = open("/dev/radar", O_RDONLY);
if (fd < 0) {
printf("CRITICAL ERROR: Radar hardware not found!\n");
return -1;
}
// 2. Read the hardware's internal configuration
struct RadarConfig my_radar;
read(fd, &my_radar, sizeof(my_radar));
printf("Radar Online! Range: %d, Status: %s\n", my_radar.range, my_radar.status);
// 3. Teardown
close(fd);
return 0;
}
Step 1: Target and Schema
- Create a new Hardware Spec in Certo.
- Set the intercept target path to
/dev/radar. - Import
certo_symbol_import_demo.hto map theRadarConfigstruct.
Step 2: The open Hook
Intercept the initialization to tell the app the hardware is connected.
certo::logger "Intercepted attempt to open /dev/radar!"
# Initialize our virtual hardware state
set ::radar_is_healthy 1
# Bypass real OS and return a fake File Descriptor (e.g., 99)
certo_set_return_value 99
Step 3: The read Hook
Generate the structured data and write it to the app's memory.
::certo::logger info "Application requested Radar data."
# 1. Create a zeroed-out dictionary based on our C-Schema
set my_radar [::certo::create_struct "RadarConfig"]
# 2. Populate the dict based on virtual state
if {$::radar_is_healthy == 1} {
dict set my_radar range 10000
dict set my_radar sweep_speed 5
dict set my_radar status "ACTIVE"
} else {
dict set my_radar status "OFFLINE"
}
# 3. Convert to raw bytes and write to the app's pointer
set raw_bytes [::certo::dict_to_bytes "RadarConfig" $my_radar]
set buf_addr [lindex $certo::arguments 1]
::certo::write_memory $buf_addr $raw_bytes
# 4. Return the requested size to indicate success
set requested_size [lindex $certo::arguments 2]
certo_set_return_value $requested_size
Network Stream
Spoofing a Network Stream
In this scenario, we mock a high-performance TCP telemetry stream on Port 1234.
Step 1: Target the Port
- Create a new intercept target in Certo.
- Set the target to Port 1234.
Step 2: The connect Hook
Certo automatically swaps the app’s socket with a virtual socketpair.
certo::logger "Intercepted connection attempt to Port 1234!"
Step 3: The recvfrom Hook
Feed the stream by generating payloads on the fly.
set buf_addr [lindex $certo::arguments 1]
set requested_size [lindex $certo::arguments 2]
::certo::logger info "Feeding $requested_size bytes of telemetry."
# 1. Generate fake payload
set fake_packet "SENSOR_TEMP: 72F | STATUS: NOMINAL"
# 2. Pad to match requested size
set pad_length [expr {$requested_size - [string length $fake_packet]}]
if {$pad_length > 0} {
append fake_packet [string repeat "\x00" $pad_length]
}
# 3. Inject into the application's buffer
::certo::write_memory $buf_addr $fake_packet
certo_set_return_value $requested_size
The Result
The application successfully connects even if the network is down, and its poll() loops run natively against your high-throughput virtual stream.
0.43.0 (2026-06-12)
Features
- #18: transport templates — importable VHBs per communication mode (1f3e203), closes #18 emu#18
0.42.0 (2026-06-03)
Features
- #17: Software driver mode: EMU shell REPL, set_driver_mode, and execute_interaction (ebe7941), closes #17
0.41.0 (2026-05-31)
Features
- #16: Resolve “Update Engine dependency for async syscall support” (392ecab), closes #16
0.40.1 (2026-05-29)
Bug Fixes
- register target resources during session load and add pure-virtual TCP hang test, plus include roadmap documentation (8df76da)
0.40.0 (2026-05-27)
Features
- pass license key to engine for feedback enrichment (89a3642)
0.39.0 (2026-05-24)
Bug Fixes
- add serialized_scanned_maps to test VHB fixtures (7da5159)
Features
- add support for encrypted .vhbx project files and implement set_history_limit command permissions (852b766)
0.38.0 (2026-05-23)
Features
- implement core CLI commands (info and run) (5553adf)
0.37.8 (2026-05-17)
0.37.7 (2026-05-15)
0.37.6 (2026-05-15)
0.37.5 (2026-05-14)
0.37.4 (2026-05-14)
Bug Fixes
- rely on template needs (82527a2)
0.37.3 (2026-05-14)
0.37.2 (2026-05-14)
0.37.1 (2026-05-13)
0.37.0 (2026-05-13)
Features
- add global navigation banner to EMU documentation pages and update reference links (833cf37)
0.36.0 (2026-05-13)
Features
- implement custom Certo branding and theme for documentation and rustdoc (4b488f7)
0.35.4 (2026-05-13)
0.35.3 (2026-05-12)
0.35.2 (2026-05-12)
0.35.1 (2026-05-11)
Bug Fixes
- make sure icons are present (f51253b)
- move setup icons to before pages (72a73ee)
0.35.0 (2026-05-11)
Features
- add CLI support, initialize developer documentation, and improve Docker build script configuration (26a7d8e)
0.34.0 (2026-05-06)
Bug Fixes
- test syntax (03e7430)
Features
- add initial benchmarking suite and fix symbol length assertion in emulator library (dbb11b2)
- upgrade test coverage and move emu to a tauri plugin (bab04d5)
0.33.0 (2026-04-29)
Features
- add SchemaBuilder component to manage and edit custom packet structures (6bf2d1e)
- incorporate IOCTL seal data into variable metadata and increase dialog z-index for overlay display (d93e00c)
0.32.1 (2026-04-26)
0.32.0 (2026-04-25)
Features
- add schema removal functionality to ScanInspectModal and implement typedef resolution and auto-mocking logic in SystemCallDetails (2a031de)
- implement native memory merge support for system call data overrides and update telemetry initialization. (9cc8875)
- implement structural schema serialization to optimize project loading and reduce memory usage (915db25)
0.31.0 (2026-04-16)
Features
- add history search, system call status styling, and local cache schema resolution support (ae6068b)
0.30.3 (2026-04-13)
0.30.2 (2026-04-13)
0.30.1 (2026-04-12)
0.30.0 (2026-04-12)
Features
- implement persistent project-level schema imports and rehydration (256a934)
0.29.0 (2026-04-12)
Bug Fixes
- update tauri-plugin-dialog to 2.7.0 and defer dropdown menu actions to prevent focus issues (7cf6f1b)
Features
- add C header scanning support, improve library import reporting, and refine syscall matching logic (b768f41)
0.28.0 (2026-04-08)
Features
- add configurable system call history limit to engine and UI (5e1c9a2)
- add ImportLibraryModal to allow loading bundled standard library schemas into the engine (4a97032)
0.27.0 (2026-04-04)
Features
- reduce alias and call limits for anonymous and free tiers (b45ded1)
0.26.2 (2026-04-04)
0.26.1 (2026-04-04)
Bug Fixes
- general fixes for associating historical calls to existing specs (cb0256f)
0.26.0 (2026-04-02)
Features
- implement binary scanning functionality with symbol map inspection and UI components (083d240)
0.25.0 (2026-04-01)
Bug Fixes
- a few updates after refactor (a9d0e72)
Features
- add search and filtering functionality to TraceExplorer component (7b8fa65)
0.24.0 (2026-04-01)
Features
- add ioctl hardware code field and implement auto-healing for system call offsets (db6de1d)
0.23.0 (2026-04-01)
Features
- support faster system calls (c2564e4)
0.22.1 (2026-04-01)
0.22.0 (2026-03-31)
Features
- add about page in emu and general fixes (a263b49)
0.21.4 (2026-03-30)
0.21.3 (2026-03-30)
0.21.2 (2026-03-30)
Bug Fixes
- licensing: updated field access for updated LicensePayload struct (26f7af4)
0.21.1 (2026-03-30)
Bug Fixes
- ui: reorder elements in bottom status bar footer (afe70db)
0.21.0 (2026-03-29)
Bug Fixes
- update versions (fe9419c)
- update versions (bae230f)
Features
- support engine/portal updates (6204a95)
0.20.0 (2026-03-23)
Features
- Implement batched telemetry events and virtualized history display with
react-virtuosofor improved performance, and update CI templates. (d5c7724)
0.19.0 (2026-03-23)
Features
- make emu work in standalone (9f92f00)
0.18.0 (2026-03-22)
Features
- add tests (7e6d896)
- make emu itself again (bf32686)
- make emu itself again (d4d8cb9)
0.17.0 (2026-03-22)
Features
- come up with the logic for having an outer desktop view (172cf94)
0.16.2 (2026-03-21)
0.16.1 (2026-03-21)
Bug Fixes
- lagging behavior with too many log statements (9b592fa)
0.16.0 (2026-03-21)
Bug Fixes
- rely on env, not config.toml (cfa86ba)
Features
- Bump engine dependency to v0.17.0 and add NODE_MODULES_PATH variable to the CI build configuration. (092075d)
0.15.2 (2026-03-20)
0.15.1 (2026-03-20)
Bug Fixes
- update config cargo targets (d8da235)
0.15.0 (2026-03-18)
Features
- support spawning process and playback files (e022e1c)
0.14.0 (2026-03-18)
Features
- finalize ui in relationship to wireframe (13c58dd)
- finalize ui in relationship to wireframe (7e5e848)
0.13.0 (2026-03-12)
Bug Fixes
- add before script to test job (ac4cd29)
- add simple test to run (d58418b)
- ci: Re-adding dummy webhooks to config.toml, and patching CI job url replacement (f1adf6c)
- fetch icons ahead of time (8f7d850)
- grabbing icons at build time (b8b622d)
- grabbing icons at build time (e809fcc)
- minor ui updates and fixes (cfcb28c)
Features
- add tests updates (b3eface)
- full front end mock up created (d8e0a57)
- overhaul front end (e867262)
- use the updated ui-lite (343733b)
0.12.1-clayui (2026-03-03)
Features
- update native ui to look like the wasm target (a78a57c)
0.11.0 (2026-02-27)
Features
- add first example, support new tcl and telemetry feature (0f96a26)
0.10.3 (2026-02-25)
Bug Fixes
- package name for beta (eb17c16)
0.10.2 (2026-02-25)
Bug Fixes
- try updating the prefix url (5659f3a)
0.10.1 (2026-02-25)
Bug Fixes
- collect the new version variable properly (928d650)
0.10.0 (2026-02-25)
Bug Fixes
- remove problematic : (37e302a)
- single block commands (8750b11)
- tie deploy to run after tag job (e94c544)
Features
- add deploy stage to add url for download (fd5c6f2)
0.9.5 (2026-02-25)
Bug Fixes
- add graceful engine shutdown (60a3767)
- old depndecy problem (a263d78)
0.9.4 (2026-02-24)
Bug Fixes
- update invoking emu (d83e3b4)
0.9.3 (2026-02-24)
0.9.2 (2026-02-23)
0.9.1 (2026-02-23)
Bug Fixes
- caching (be9185b)
- job cache (f034190)
0.9.0 (2026-02-22)
Features
- add hardening across products (57a46cd)
- add some docs (bd86eab)
- allow updates to make it to ui and encode public key (d230b85)
0.8.5 (2026-02-16)
0.8.4 (2026-02-15)
Bug Fixes
- collect new version before build (283e032)
0.8.3 (2026-02-14)
0.8.2 (2026-02-14)
0.8.1 (2026-02-14)
Bug Fixes
- add tcl init and other missing libs (0ee62b9)
0.8.0 (2026-02-14)
Features
- update release builds (0dd9f68)
0.7.1 (2026-02-13)
Bug Fixes
- dep libs and license file inclusion (f7f6655)
- script syntax (e5a64da)
0.7.0 (2026-02-13)
Features
- add beta tag support (66987df)
- add beta tag support (fb2c191)
0.6.0 (2026-02-12)
Features
- add license file support (dc7a71b)
0.5.4 (2026-02-12)
0.5.3 (2026-02-08)
0.5.2 (2026-02-07)
0.5.1 (2026-02-05)
0.5.0 (2026-02-05)
Features
- add build info to app (d5d51a0)
0.4.0 (2026-02-04)
Features
- add logging and crashpad support (898e232)
- add logging and crashpad support (cebb602)
0.3.0 (2026-02-02)
Features
- make calls more unique (b9425e4)
0.2.1 (2026-02-01)
0.2.0 (2026-01-30)
Bug Fixes
- update with new data entity (04c4dc8)
Features
- translate between ui and engine, update versions (6336591)
0.1.3 (2026-01-12)
0.1.2 (2025-12-16)
Bug Fixes
- Remove cache policies from test-emu and memcheck-emu jobs (aa0aaff)
0.1.1 (2025-12-16)
0.1.0 (2025-12-02)
Bug Fixes
- engine version (486cec0)
- fix needed job name (83fe995)
- pipeline syntax (3f20b20)
- remove implementing pages in cpp template (2d0dc62)
- remove same url replacement (5948ebc)
- try changing url in script (ae9b422)
- try using in-link auth instead of ci replacement (e37b7ce)
- update sast stage vars (8260172)
Features
- add doxygen api auto docs (2190f19)
- add replacement of the url (f093486)
- add tests to emu project (b069935)
- remove submodules in favor of fetching source code, general refactor (d969822)
- update build to use binary artifacts (4e54057)
- update deps and improve install (6ca9e92)
- update pipeline file (fdcced1)
Roadmap
Core Architecture Enhancements
Asynchronous USB — Pure Virtual Mode Support (URBs)
Full support for intercepting the libusb and usbfs URB (USB Request Block) lifecycle. This will natively queue and reap background memory pointers for ultra-high-speed USB virtualization.
Delivered (core): The
usbtransport template intercepts the usbfs URB submit/reap lifecycle, and the completion waker wakes targets blocked inpoll/epollbetween submit and reap. The remaining work here is the zero-copy / mmap’d fast path below.
Zero-Copy Memory — Pure Virtual Mode Support (mmap)
Support for allocating and mapping shared memory buffers. This will allow applications to read virtual hardware memory directly without invoking standard system calls, perfect for PCIe, GPU, or V4L2 video buffer spoofing.
Hardware Interrupts — Default and Pure Virtual Mode Support (eventfd / timerfd)
Native routing for asynchronous hardware “ticks” and GPIO pin triggers.
Native Raw File Playback
Expanded native support for playing back data via raw files.
Enterprise Scaling & CI/CD
Virtual Hardware Recording (.vhr) — Desktop App
Record actual physical hardware interactions or spoofed sessions, capturing the exact data payloads and timing of events. Testers can share .vhr files with developers to perfectly replay and debug intermittent hardware bugs or specific edge-case scenarios.
Remote Hardware Broadcasting — Hub & Spoke Model (Certo Daemon)
A centralized Certo daemon that runs on a lab server physically connected to rare or expensive hardware. All developers can connect their local Certo instances to this daemon, broadcasting the real hardware’s live data streams directly into their local virtualized environments.
True CI/CD Automation — Desktop App
A headless CLI environment allowing you to inject Certo hardware profiles directly into cloud-hosted runners (such as GitHub Actions or GitLab CI) for complete end-to-end integration testing without physical hardware.
Enterprise FAT Reporting Dashboard — Certo Daemon & Webserver
A full web-server interface tailored for VPs, stakeholders, and customers. Provides a clean, high-level dashboard to observe and sign off on virtualized Factory Acceptance Tests (FAT) in real-time.
Unified Virtual Twins — Multi-Layer Testing (Desktop App)
Evolving the .vhb ecosystem from single-target intercepts to a unified, multi-layer hardware model. A single .vhb file will contain a core simulation state machine and multiple interface bindings. This allows:
- Software Teams to spoof high-level data (e.g.,
/dev/radar) - Driver Engineers to spoof raw buses (e.g.,
/dev/i2c-1) - QA Teams to inject faults into physical hardware
All synchronized against the exact same virtual source of truth.
AI & Machine Learning
MCP (Model Context Protocol) Server — Desktop App
Certo will act as a safe-space sandbox for AI agents. By exposing Certo via MCP, Large Language Models (LLMs) will be able to read virtual hardware states, inject edge-case faults, and interact with the system. This enables organizations to train AI models on hardware systems to autonomously detect hardware problems and develop real-time mitigation techniques without risking physical damage.
Version History
0.20.1 (2026-06-12)
Bug Fixes
- seed templates/ dummy in beforeBuildCommand so release bundles compile (950bed4)
0.20.0 (2026-06-12)
Bug Fixes
- commit pinned workspace Cargo.lock to stop CI floating tauri-utils to 2.9.2 (d6cd683)
- seed templates/ dummy in CI so the tauri resource glob resolves (e0e56cf)
Features
- bundle transport templates and update emu to v0.43.0 (2993285)
0.19.1 (2026-06-03)
0.19.0 (2026-06-03)
Bug Fixes
- update init-bundle.sh schema generator path to plugins/ (e2642de)
Features
- #2: Software driver mode: UI driver toggle, inbound_defaults editor, direction badges (94b18ba), closes #2
0.18.0 (2026-05-31)
Features
- #1: Resolve “Update EMU dependency for async syscall support” (1c7ca00), closes #1
0.17.2 (2026-05-29)
0.17.1 (2026-05-27)
0.17.0 (2026-05-24)
Features
- update emu to v0.39.0 and integrate license key changes (6225aa4)
0.16.0 (2026-05-17)
Features
- display actual version alias in version-picker dropdown for latest tag (5d622a5)
0.15.6 (2026-05-17)
0.15.5 (2026-05-15)
0.15.4 (2026-05-14)
0.15.3 (2026-05-14)
0.15.2 (2026-05-14)
0.15.1 (2026-05-14)
0.15.0 (2026-05-14)
Features
- add CI pipeline job to prepare and upload public Certo documentation to S3 (38bd1c3)
0.14.2 (2026-05-14)
0.14.1 (2026-05-14)
0.14.0 (2026-05-14)
Features
- integrate Emu documentation into Certo Desktop docs with custom CSS branding and automated build pipeline updates (efb9853)
0.13.1 (2026-05-12)
0.13.0 (2026-05-11)
Bug Fixes
- correct regex escaping for cargo registry path in test coverage aliases (5c88879)
- remove panic on IPC “not found” errors to prevent false positives in CI environments (8e494b8)
Features
- implement license validation for Emu CLI and add developer reference documentation (b67e329)
- implement license validation for Emu CLI and add developer reference documentation (4b3f604)
0.12.0 (2026-04-29)
Features
- implement persistent user settings and update data structures for binary buffers (731060d)
0.11.1 (2026-04-26)
Bug Fixes
- add libhooks.so to build initialization and bundle resources (e6a3072)
0.11.0 (2026-04-25)
Features
- add resource path tracking, system fcntl wrapper, and UI styling updates with engine dependency patches (b4645e8)
- add set_no_hardware_mode command and enable local engine and portal patches (e3aa4eb)
- add sync_project_state command, update build environment prompts, and comment out local path patches (abff300)
- implement toast notifications, add clear-all functionality to modal, and integrate Emu layout into PlatformShell (55e4560)
- include imported schemas and serialized scanned maps in project save and load operations (5c0327d)
0.10.3 (2026-04-13)
Bug Fixes
- dwarf scanner array size (88be5c2)
0.10.2 (2026-04-13)
0.10.1 (2026-04-13)
0.10.0 (2026-04-13)
Features
- add imported schemas to session data and remove redundant libclang installation from CI (13ee344)
- centralize build and bundle initialization scripts within Tauri configuration (e56935f)
0.9.0 (2026-04-10)
Features
- add deploy-alias-certo job to CI pipeline for alias deployment (df2793f)
0.8.0 (2026-04-08)
Features
- implement standard library debug symbol fetching and engine integration for hardware emulation (2de9f36)
0.7.3 (2026-04-04)
0.7.2 (2026-04-04)
0.7.1 (2026-04-04)
0.7.0 (2026-04-02)
Features
- emu adds target meta data scanner (3cac1d8)
0.6.0 (2026-04-01)
Features
- support faster system call capturing (aaf3298)
- update emu version (f65c4c4)
- update submodule and general fixes (0baee61)
0.5.3 (2026-03-30)
0.5.2 (2026-03-30)
0.5.1 (2026-03-30)
Bug Fixes
- migrate update check to startup invocation, improve logging, and update notification link handling (ca1bf94)
0.5.0 (2026-03-30)
Features
- add software update check UI and improve updater logging and dependency versioning (4a78c3e)
0.4.1 (2026-03-30)
0.4.0 (2026-03-30)
Bug Fixes
- launching link to customer portal (2059efc)
Features
- add update checker and rpm fixes (f92c845)
- add update checker and rpm fixes (910cfc0)
0.3.1 (2026-03-29)
0.3.0 (2026-03-29)
Bug Fixes
- update submodules and add rustls-tls fix (8f095fc)
Features
- update license file support (34be211)
0.2.1 (2026-03-23)
0.2.0 (2026-03-23)
Features
- Refactor CI/CD to use
certospecific templates and tags, removeIS_BETAvariable, addSAST_EXCLUDED_ANALYZERS, and deleteapp-icon.png. (af38f03) - update emu dependency to v0.20.0 (377b385)
0.1.0 (2026-03-23)
Bug Fixes
- arch caching (e4d6a53)
- caching with arm jobs (a9bfdc6)
- remove unreleased portion from changelog (6f95c30)
- testing profile (cf6dcdd)
Features
- update desktop to work as a platform (7626d6b)
Roadmap
Desktop-specific roadmap updates will go here.