# Thirteen policies, one GGUF each, and a support matrix that admits gaps

> vla.cpp is a C++ inference engine for Vision-Language-Action models built on llama.cpp, and its bet is that every open policy can be packaged as a single self-contained GGUF that needs no Python or PyTorch at inference time. The interesting parts are the edges: thirteen models against six backends, an install line that can drop protobuf and ZeroMQ entirely, and a Python tooling project that is explicitly not a package.

**VinRobotics/vla.cpp** — A unified inference runtime for VLA models.

- Repository: https://github.com/VinRobotics/vla.cpp
- Website: https://fai-modelopt-tech.github.io/vla-cpp.github.io/
- Stars: 247 · Forks: 49
- Language: C++
- License: Apache-2.0
- Published: 2026-08-21 · Updated: 2026-08-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/vinrobotics-vla-cpp

## One GGUF per policy, and no Python on the robot

The core claim is a packaging decision. The open VLA policies named in the README, SmolVLA, pi0, BitVLA, Evo-1, and GR00T N1.5, N1.6, and N1.7 among them, are each distributed as a single self-contained GGUF file that needs no Python or PyTorch at inference time. The engine underneath is llama.cpp, so the ggml kernels and the quantisation story come from a project with a large existing community rather than from a fresh implementation. The reason this matters is deployment rather than research: a robot computer that has to carry a Python environment and a deep learning framework is a robot computer with a large dependency surface and a slow cold start. The engine targets CPU, Apple Silicon, CUDA from consumer GPUs down to Jetson-class boards, Intel GPUs and NPUs through SYCL and OpenVINO, and Qualcomm Snapdragon CPUs, Adreno GPUs, and Hexagon NPUs through OpenCL and the Hexagon backend. Two companion resources sit alongside the code: a learn site that walks through the engine design and how each policy is implemented on ggml, and an arXiv entry linked from the badge row.

## The prebuilt tarball names six platforms and what each one needs

Each release publishes a vla.cpp-<tag>-<platform>.tar.gz containing libvla, vla.h, and the binaries, and the platform table is specific enough to plan against. The CPU x86-64 build wants AVX2, meaning Haswell or newer. The aarch64 CPU build wants ARMv8.2-A with dotprod and fp16, naming Cortex-A76 and Neoverse N1 as the floor. Two CUDA variants exist, one on CUDA 12.8 and one on 13.4, and the 13.4 build additionally requires driver 580 or newer. The aarch64 CUDA build lists sm_87 for Orin, sm_110 for Thor, and sm_121 for DGX Spark. The macOS arm64 Metal build is narrower than the rest and ships vla-cli and vla-bench only. The Linux tarballs need Ubuntu 24.04's glibc or newer, libzmq5 for the servers, and a CUDA runtime shipped as a separate cudart tarball.

## A flag pair turns the server dependencies off

The build instructions ask you to install four development packages before anything else:

```bash
sudo apt-get install -y libzmq3-dev cppzmq-dev libprotobuf-dev protobuf-compiler
```

The useful detail is that you may not need them. Passing -DVLA_BUILD_SERVER=OFF and -DVLA_SPM=OFF builds vla-cli, vla-bench, and libvla without protobuf, ZeroMQ, or SentencePiece, so none of those apt packages are required. That turns the dependency list from a fixed set into a choice, and the choice has a visible consequence the README spells out: without SentencePiece you pass Octo a --tokens argument instead of --text. In other words the tokenisation path changes, not just the build. For anyone evaluating the engine on a locked-down machine, or on a platform where ZeroMQ is awkward to obtain, that single flag pair is the difference between a viable and a non-viable dependency.

## CMake fetches llama.cpp, so there is no submodule to track

The source build needs CMake 3.22 or newer and a C++17 compiler, GCC 11 or Clang 14, with CUDA 12.x or 13.x optional and required only for CUDA GPU builds. Intel oneAPI 2025.x and an OpenVINO 2026.x runtime are each optional for their own backend, and a C++17 floor is what the whole build rests on rather than a newer standard. The configure step is two commands, and the CUDA variant differs only by three flags: which is why the README spends a table on GPU families: Ampere on Jetson is 87, Ampere consumer is 86, Ada Lovelace is 89, Hopper is 90, and the Blackwell entries split into 120 for consumer, 100 for datacenter, 110 for Jetson Thor, and 121 for DGX Spark. Both forms appear in one block, and the CUDA half expects a shell variable to be set beforehand:

```bash
# CPU build:
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc)

# CUDA build (set CMAKE_CUDA_ARCHITECTURES for your GPU):
cmake -B build \
    -DGGML_CUDA=ON \
    -DCMAKE_BUILD_TYPE=Release \
    -DCMAKE_CUDA_ARCHITECTURES=$CUDA_ARCHITECTURE
cmake --build build -j$(nproc)
```

If CMake cannot find CUDA on its own, the README gives two environment variables to export by hand, a PATH entry pointing at the bin directory and an LD_LIBRARY_PATH entry pointing at lib64. The dependency handling is worth noting because it is not the usual arrangement: CMake fetches and pins llama.cpp automatically, with no patch and no submodule to keep in sync. WSL2, Apple Silicon, and Intel GPU are all stated as tested, and container builds are covered by a separate document.

## The support matrix has thirteen models and three states

The README publishes a matrix of models against platforms with a three-value legend, where Y means supported, released and benchmarked, a tilde means in progress, and a dash means planned. Reading it row by row is more informative than the headline. SmolVLA, Evo-1, and TurboVLA are Y in all six columns, so they work everywhere including SYCL and Hexagon. The three GR00T rows are Y everywhere except SYCL, which is a dash. Octo-Small is Y in five columns with OpenVINO as the dash. pi0 is the only row with two non-Y cells, a dash for SYCL and a tilde for Hexagon. VLA-JEPA is a tilde on Hexagon, VLA-Adapter is a tilde on SYCL, and BitVLA is the weakest row with a tilde on Metal and dashes on OpenVINO and Hexagon. The pattern is that CPU and CUDA are universally Y, and the specialised backends are where coverage thins out.

## A tilde in the Hexagon column is the honest signal

Two rows in that matrix describe their own evidence more carefully than the others, and they are the ones worth reading before you plan a deployment. VLA-JEPA is marked as in progress on Hexagon, which means the pairing exists in some form but has not been released and benchmarked to the standard the legend requires. pi0 carries the same tilde on Hexagon and is additionally planned rather than in progress on SYCL, so there are two separate reasons not to assume pi0 will run there. Everything else that is not Y is a dash, which the legend defines as planned, and planned is not the same as forthcoming with a date. Since the matrix distinguishes three states rather than collapsing them into working or not working, you can tell the difference between a backend nobody has tried and a backend somebody is halfway through, which is the distinction that matters when you are choosing a board.

## The Python project is tooling, and it says so

The pyproject.toml describes a package called vla-cpp-tooling, version 0.4.0, requiring Python 3.10 or newer with a single runtime dependency of numpy. Its description is Python tooling for vla.cpp: HuggingFace to GGUF converters and the ZeroMQ eval client. The two optional dependency groups are convert, which pulls torch, safetensors, gguf, and transformers for the conversion scripts, and client, which pulls pyzmq, msgpack, pillow, torch, torchvision, transformers, protobuf, and opencv-python-headless for the eval client. The most useful line in the file is the last comment: deps-only project, the code lives in scripts/ and eval/, not an importable package, with the tool.uv package setting set to false. So pip installing this gets you a manifest, not a library.

## A client extra needs transformers 5.4 for one model

Two of the dependency comments explain decisions that would otherwise look arbitrary. The first says the simulators, naming LIBERO, SimplerEnv, and ALOHA, keep their own pinned virtual environments, with setup scripts under eval/sim, and are not packaged here. That is a deliberate isolation: the eval harness does not drag three simulators into one environment. The second is narrower and more surprising. The client group requires transformers 5.4 or newer, and the comment says that only AutoTokenizer and AutoProcessor are needed, but vla_jepa passes processor_kwargs into apply_chat_template, and 5.4 is the first release that accepts it. So a single row in the support matrix, the one already marked as a tilde on Hexagon, is also the reason the eval client cannot be installed alongside an older transformers.

## Conclusion

vla.cpp suits a robotics team that has a policy checkpoint and a board but no appetite for a PyTorch runtime on the robot, and that cares which of the six backends its model actually supports. It does not suit you if you need the newest model on day one, since several rows in the support matrix are still marked in progress or planned. Before you commit, read the support matrix row for your model rather than the headline, check whether your GPU architecture appears in the CUDA table, and decide up front whether you need the server features that pull in ZeroMQ and protobuf.

## FAQ

### What is vla.cpp?

A C++ inference engine for Vision-Language-Action models, built on llama.cpp. Each open policy, including SmolVLA, pi0, BitVLA, Evo-1, and the GR00T N1.5 through N1.7 models, is packaged as a single self-contained GGUF that needs no Python or PyTorch at inference time.

### Which hardware backends does vla.cpp support?

CPU, Apple Silicon through Metal, CUDA from consumer GPUs down to Jetson-class boards, Intel GPUs and NPUs through SYCL and OpenVINO, and Qualcomm Snapdragon CPUs, Adreno GPUs, and Hexagon NPUs through OpenCL and the Hexagon backend. Prebuilt binaries cover six platform names, and the macOS Metal build ships vla-cli and vla-bench only.

### Can I build vla.cpp without ZeroMQ or protobuf?

Yes. Passing -DVLA_BUILD_SERVER=OFF and -DVLA_SPM=OFF builds vla-cli, vla-bench, and libvla without protobuf, ZeroMQ, or SentencePiece, so the apt packages for them are not needed. Without SentencePiece, Octo takes a --tokens argument instead of --text.

### How does vla.cpp obtain llama.cpp?

CMake fetches and pins it automatically, with no patch and no submodule. The build needs CMake 3.22 or newer and a C++17 compiler, GCC 11 or newer or Clang 14 or newer, with CUDA 12.x or 13.x needed only for CUDA GPU builds.

### Does vla.cpp work without PyTorch on the robot?

That is the design goal. Each policy is a single self-contained GGUF and inference needs no Python or PyTorch, which is what lets the binaries drive robots on CPU, Apple Silicon, CUDA, Intel, and Qualcomm hardware. Python and PyTorch appear only in the optional tooling extras for checkpoint conversion and the eval client.

### How do I know if my model works on a given backend in vla.cpp?

The README publishes a support matrix with three states: Y for supported, released and benchmarked, a tilde for in progress, and a dash for planned. CPU and CUDA are Y for all thirteen models, and the gaps are in the specialised columns, with pi0 and BitVLA the weakest rows.

## Sources

- [Official documentation](https://fai-modelopt-tech.github.io/vla-cpp.github.io/)
- [Official README](https://github.com/VinRobotics/vla.cpp#readme)
- [Project repository](https://github.com/VinRobotics/vla.cpp)
- [Release notes](https://github.com/VinRobotics/vla.cpp/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/vinrobotics-vla-cpp
