eunomia-bpf: eBPF as OCI images you can run with one command
A Tool to make Build and Run eBPF programs easier
At a glance
- What is it?
- eunomia-bpf is a Rust toolchain and runtime for eBPF that removes the boilerplate from CO-RE programs and packages them as OCI images containing a WebAssembly module, so a pre-built tool can be pulled from a registry and run against the kernel without recompiling. Two binaries do the work, ecli for running and distributing and ecc for compiling kernel code to a JSON config or a Wasm module.
- Who is it for?
- Adopt eunomia-bpf if you write eBPF and want to stop hand writing the userspace side of every program, because the framework generates the perf event or ring buffer plumbing, the histogram printing and the command line arguments from your kernel code alone.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 75 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem it solves is the userspace half
eunomia-bpf is described as a dynamic loading library and runtime plus a compile toolchain framework, aimed at helping you build and distribute eBPF programs more easily.
The specific pain is well known to anyone who has written eBPF. The kernel side is a small C file, but you also need a userspace program to open the perf event or ring buffer, read the data, and print something useful. That userspace program is boilerplate, it is different for every tool, and it is where most of the friction in a small eBPF project lives.
The framework addresses that directly. You write the eBPF kernel code only, and the framework automatically exposes your data with a perf event or a ring buffer from the kernel. It automatically samples the data from hash maps and prints histograms in userspace. And it automatically generates and configures the command line arguments for your program.
You can write the kernel part in either BCC or libbpf styles, which is the practical detail for people porting existing code.
The topic list on the repository names the mechanism: ebpf, ebpf-co-re, bcc, libbpf, wasm, webassembly, oci, oci-image, oras, riscv and linux. The CO-RE footnote points at the Compile Once Run Everywhere idea, and the RISC-V and WASM tags tell you the portability direction the project is pushing toward.
Running a pre-built eBPF tool from a registry
The headline capability is running eBPF code that was compiled somewhere else, on a kernel and architecture you did not build on, without a compiler on the target machine.
The install is a single download of the ecli binary, and then one command runs a published tool.
# download the latest release from GitHub Releases
$ wget https://github.com/eunomia-bpf/eunomia-bpf/releases/latest/download/ecli -O ecli && chmod +x ./ecli
$ sudo ./ecli run ghcr.io/eunomia-bpf/execve:latest # run a pre-compiled ebpf tool from OCI registry
[79130] node -> /bin/sh -c which ps
[79131] sh -> which ps
[79132] node -> /bin/sh -c /usr/bin/ps -ax -o pid=,ppid=,pcpu=,pmem=,c That output is an execve trace, showing the process tree as it runs. The point of the sample is that the execve program was pulled from a container registry and loaded into the kernel without anything being compiled locally.
The ecli help output shows the three subcommands: run, push and pull. The run subcommand takes an executable that could be a local path, a URL, or a dash to read from stdin, with the remaining arguments passed through to the program. The help text also notes that the command line position is not preferred and is kept for compatibility with older versions.
One removal is worth flagging for anyone following an older tutorial. The legacy remote HTTP mode, the ecli client and ecli-server pairing, has been removed from the main branch to reduce maintenance overhead. The last implementation is preserved on the archive/ecli-remote-http branch.
The compiler side and the Docker escape hatch
The second binary, ecc, compiles eBPF kernel code into either a JSON config file or a Wasm module.
$ wget https://github.com/eunomia-bpf/eunomia-bpf/releases/latest/download/ecc && chmod +x ./ecc
$ ./ecc -h
eunomia-bpf compiler
Usage: ecc [OPTIONS] <SOURCE_PATH> [EXPORT_EVENT_HEADER]
....The usage line shows the two outputs, a config file and an optional exported event header. The compiler needs clang, llvm and libclang installed.
If you would rather not install a toolchain, there is a container image per architecture.
# for x86_64 and aarch64
docker run -it -v `pwd`/:/src/ ghcr.io/eunomia-bpf/ecc-`uname -m`:latest # compile with docker. `pwd` should contains *.bpf.c files and *.h files.The image name is built from uname, so the same command works on x86_64 and aarch64, and your working directory is mounted at /src/ with the expectation that it holds the.bpf.c files and the headers. The Makefile has an install-deps target for the native route, which installs libcurl4-openssl-dev, libelf-dev, clang, llvm, cmake and zlib1g-dev.
There is also a loader library, bpf-loader-rs, which can dynamically load eBPF programs with a JSON config file or a Wasm module,
The Wasm route is a separate project
Building eBPF programs with Wasm is handled by the wasm-bpf project rather than by this repository, and the distinction matters because it is a different toolchain and a different deployment story.
The wasm-bpf project provides runtime, libraries and toolchains to write eBPF with Wasm in C, C++, Rust and Go, covering use cases from tracing, networking and security. There is a proof of concept video of writing eBPF programs in Wasm.
Why WebAssembly is interesting here connects back to the distribution story. A Wasm module is a portable binary artefact that a loader can consume at runtime, which is exactly what makes the OCI image approach work. The same image can be pulled and run on a different kernel version and a different architecture, because the kernel specific parts are handled by CO-RE and the portable part is the Wasm module.
The wasm-bpf repository also has its own examples tree, and this repository has an examples directory of its own with a Makefile, a README, a bpftools directory, a simple-runner-rs directory and a tests directory.
The repository also holds an eunomia-sdks directory, and the Makefile has an eunomia-exporter target that builds the bpf loader and then a cargo release build of the OpenTelemetry exporter for custom metrics, so the framework is not limited to printing histograms to a terminal.
How the repository is laid out
The top level structure follows the three-part architecture of the project.
The compiler/ directory holds the ecc compiler toolchain, ecli/ holds the command line tool with its own Makefile and a Rust build, and bpf-loader-rs/ is the core runtime library. The examples/ directory contains the sample eBPF tools and the library usage examples, and eunomia-sdks/ holds the SDK and exporter crates.
There are also a few entries worth noting for what they imply. third_party/ and .gitmodules together tell you that some dependencies come from other repositories as submodules. internal-docs/ holds documentation that does not live on the website. There is a flake.nix and a flake.lock, so there is a Nix path for reproducible builds, and a Makefile whose default goal builds both the loader and the CLI.
The Makefile also has a small piece of tooling that is unusual to see. The help target is generated by a Python script piped through the Makefile, which parses lines matching a target name followed by a double hash comment and prints them as a target list, and the browser target uses a similar Python snippet to open a file in the default web browser. Small touches, but they tell you the build is meant to be usable rather than only automated.
For contributors there is a CONTRIBUTING.md, a CODE_OF_CONDUCT.md, a CLAUDE.md file, and formatting configuration in .clang-format and .editorconfig. The project publishes static analysis through DeepSource and CodeFactor and coverage through Codecov.
Maintenance state, licensing and where to start
The repository is not archived and the last push was on 2026-08-09. The listed releases are v1.0.38 on 2026-03-08, v1.0.37 on 2026-03-08 and v1.0.36 on 2026-03-08, three releases on the same day, which is the pattern of a project that ships a build per change rather than batching.
The licence is MIT.
The documentation has moved. It is maintained at eunomia.dev, and the source for the documentation site now lives in its own repository, eunomia-bpf/eunomia.dev. The README still carries a Chinese version in README_zh.md, and the documentation site covers the introduction and the setup and build details.
Three entry points are suggested for a new user. The ebpm-template repository is a GitHub template for starting a project. The examples/bpftools directory holds example eBPF programs. And the bpf-developer-tutorial repository is a tutorial.
The overall shape is worth restating, because it determines what this tool replaces and what it does not. It does not replace libbpf or BCC, it builds on them. It removes the userspace boilerplate, it adds a distribution format based on OCI images, and it adds a portability story through CO-RE and WebAssembly. If your pain is the userspace half, it is aimed squarely at you. If your pain is the kernel half, it will not help much.
Editorial conclusion
Adopt eunomia-bpf if you write eBPF and want to stop hand writing the userspace side of every program, because the framework generates the perf event or ring buffer plumbing, the histogram printing and the command line arguments from your kernel code alone. Do not adopt it if your programs need custom userspace logic that the generated loader cannot express, since the point is that the userspace half disappears, and expect to read the Wasm route rather than the C route if portability across kernels and architectures is your goal. Verify first that you have clang, llvm and libclang installed if you are compiling locally, that your kernel supports the eBPF features your program uses, and that you read the migration note about the removed remote HTTP mode before you rely on the ecli client and ecli-server workflow.
Frequently asked questions
How do I run a pre-compiled eBPF program with eunomia-bpf?
Download the ecli binary from the GitHub releases, make it executable, then run ecli run with the OCI image reference, for example sudo ./ecli run ghcr.io/eunomia-bpf/execve:latest. The program is pulled from the registry and loaded into the kernel without local compilation.
What does the ecc compiler produce?
It compiles eBPF kernel code into either a JSON config file or a Wasm module, with an optional exported event header. It needs clang, llvm and libclang installed, and there is a per architecture container image so you can compile with Docker instead of installing a toolchain locally.
Do I still need to write userspace code for my eBPF program with eunomia-bpf?
That is the main thing the framework removes. You write the kernel code only, and the framework exposes your data with a perf event or ring buffer, samples data from hash maps and prints histograms in userspace, and generates and configures the command line arguments. You can write the kernel part in BCC or libbpf style.
What happened to the remote HTTP mode in ecli?
The legacy remote HTTP mode, the ecli client and ecli-server pairing, has been removed from the main branch to reduce maintenance overhead. The last implementation is preserved on the archive/ecli-remote-http branch.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/eunomia-bpf-eunomia-bpf)Was this useful?