# Versioning Strategies for Colibri: A Layered Approach to Multi-Component Compatibility

> Discover Colibri's versioning strategies for multi-component compatibility. Explore layered approaches to ensure backward compatibility across C engine, Python CLI, and model containers.

- Repository: [Vincenzo Fornaro/colibri](https://github.com/JustVugg/colibri)
- Tags: best-practices
- Published: 2026-09-12

---

**Colibri employs a multi-layered versioning strategy that separates public release semantics from internal ABI, protocol, and data format versions, ensuring backward compatibility across the C engine, Python CLI, and model containers.**

The JustVugg/colibri repository uses a sophisticated versioning architecture that decouples the user-facing release number from internal binary interfaces and persistence formats. This strategy allows the distributed inference engine to evolve its core C binary, Python tooling, and on-disk model formats independently while preventing silent failures due to incompatible components.

## Overview of the Layered Versioning Architecture

Colibri's versioning is not monolithic. Instead, it maintains **seven distinct version layers**, each serving a specific compatibility boundary. This design lets the project upgrade its networking protocol, modify the planner's cache layout, or introduce new quantization schemes without forcing a major version bump for the entire distribution.

The hierarchy spans from high-level release tags down to binary ABI checks:

- **Release version**: Semantic versioning for the overall distribution
- **Engine binary version**: Cluster protocol compatibility (`COLI_CLUSTER_VERSION`)
- **Runtime ABI versions**: Segment (`COLI_SEGMENT_ABI_VERSION`) and Edge (`COLI_EDGE_ABI_VERSION`) interfaces
- **Persistence format versions**: Routing traces (`RT_FORMAT_VERSION`) and analysis caches (`_ANALYSIS_CACHE_VERSION`)
- **Container format versions**: Safetensors model encoding schemes

## Public Release Versioning (Semantic Versioning)

Colibri follows **semantic versioning** (`MAJOR.MINOR.PATCH`) for its public releases. The authoritative version string lives in [`README.md`](https://github.com/JustVugg/colibri/blob/main/README.md) and is displayed by the CLI when running `colibri --version` (e.g., `colibri v1.10.2`).

GitHub tags matching the `v1.x.x` pattern serve as the canonical release markers. This version tracks the entire distribution—including documentation, packaging scripts, and the bundled Python wrapper—but changes here do not necessarily indicate binary incompatibility in the engine or data formats.

## Engine and Protocol Versioning

The C engine in [`c/colibri.c`](https://github.com/JustVugg/colibri/blob/main/c/colibri.c) maintains separate version constants for wire protocols and binary interfaces. These are hard-coded unsigned integer constants validated at runtime to prevent crashes from struct layout mismatches.

### Cluster Protocol Version

The `COLI_CLUSTER_VERSION` constant (currently `1u`) governs the message format between distributed Colibri nodes. When the engine reads or writes cluster protocol messages, it asserts that the version matches exactly.

If a client built against version 1 attempts to join a cluster running version 2, the engine rejects the connection before any data structures are parsed, preventing memory corruption from changed field offsets.

### Segment and Edge ABI Versions

Colibri supports heterogeneous backends through pluggable "segment" runtimes (for custom kernels) and "edge" runtimes (for on-device inference). These expose strict ABI contracts:

- **`COLI_SEGMENT_ABI_VERSION`** (currently `1u`): Exported in every `ColiSegmentAdapter`. The runtime validates this before loading a segment shared library.
- **`COLI_EDGE_ABI_VERSION`** (currently `2u`): Checked by the lightweight edge runtime to reject incompatible inference binaries.

When these constants increment, older plugins fail to load with a clear error message, forcing recompilation against the latest headers rather than risking silent data corruption.

## Data Format and Cache Versioning

Beyond runtime ABIs, Colibri versions its on-disk persistence formats to ensure safe upgrades across software versions.

### Routing Trace Format

The telemetry system writes routing usage data to `.coli_usage` files. The constant `RT_FORMAT_VERSION` (currently `1`) in [`c/colibri.c`](https://github.com/JustVugg/colibri/blob/main/c/colibri.c) prefixes these files. When loading a trace, the engine refuses to parse any format newer than it recognizes, preventing misinterpretation of changed telemetry layouts.

### Analysis Cache Version

The Python-based planner in [`c/resource_plan.py`](https://github.com/JustVugg/colibri/blob/main/c/resource_plan.py) maintains `_ANALYSIS_CACHE_VERSION = 7`. This integer prefixes cache filenames (e.g., `v7_analysis_cache.pkl`). When the planner's data layout changes, incrementing this constant invalidates old caches automatically, triggering a fresh analysis rather than loading stale data structures.

### Model Container Versions

Model weights use safetensors containers with quantization-specific formats (e.g., `int8-row`, `int4-gs64`). The reader implementation in [`c/st.h`](https://github.com/JustVugg/colibri/blob/main/c/st.h) validates these container versions at startup. Mismatched containers trigger explicit errors rather than silent numerical misbehavior during inference.

## API Versioning

The OpenAI-compatible HTTP server in [`openai_server.py`](https://github.com/JustVugg/colibri/blob/main/openai_server.py) implicitly versions its REST interface through the `/v1/` endpoint path. While the code does not expose a dedicated version constant, the URL structure allows clients to detect compatibility before issuing inference requests. The server validates request schemas against the expected format, ensuring that API changes surface as clear HTTP errors rather than parse failures.

## Detecting and Validating Versions in Practice

You can inspect these version layers programmatically or via command-line tools.

To check the CLI release version from Python:

```python
import subprocess
import re

def get_cli_version():
    out = subprocess.check_output(["./coli", "--version"], text=True)
    m = re.search(r"colibri v(\d+\.\d+\.\d+)", out)
    return m.group(1) if m else "unknown"

print("Colibri CLI version:", get_cli_version())

```

To validate a segment ABI match in C:

```c
/* Validating the segment ABI version at load time */
if (adapter->abi_version != COLI_SEGMENT_ABI_VERSION) {
    fprintf(stderr,
        "Incompatible segment ABI: got %u, expected %u\n",
        adapter->abi_version, COLI_SEGMENT_ABI_VERSION);
    return -1;
}

```

To inspect the cluster protocol version in a compiled binary:

```bash

# Inspecting the cluster protocol version in a binary dump

hexdump -C colibri | grep -A1 "COLI_CLUSTER_VERSION"

# shows the 4-byte little-endian value 01 00 00 00 (version 1)

```

## Summary

Colibri's versioning strategies provide a stable upgrade path across its complex, multi-language codebase:

- **Semantic release versioning** in [`README.md`](https://github.com/JustVugg/colibri/blob/main/README.md) tracks the overall distribution state without implying binary incompatibility.
- **Hard-coded ABI constants** in [`c/colibri.c`](https://github.com/JustVugg/colibri/blob/main/c/colibri.c) (`COLI_CLUSTER_VERSION`, `COLI_SEGMENT_ABI_VERSION`, `COLI_EDGE_ABI_VERSION`) prevent runtime crashes from struct mismatches.
- **Format version constants** (`RT_FORMAT_VERSION`, `_ANALYSIS_CACHE_VERSION`) ensure on-disk data is parsed safely across software upgrades.
- **Model container validation** in [`c/st.h`](https://github.com/JustVugg/colibri/blob/main/c/st.h) rejects incompatible quantization formats before inference begins.
- **API path versioning** in [`openai_server.py`](https://github.com/JustVugg/colibri/blob/main/openai_server.py) allows clients to negotiate REST compatibility.

This layered approach ensures that upgrading the CLI or engine binary never silently breaks existing models, caches, or telemetry files.

## Frequently Asked Questions

### How does Colibri handle breaking changes?

When a breaking change is introduced, the relevant version constant is incremented (e.g., `COLI_SEGMENT_ABI_VERSION` bumped from `1u` to `2u`). The loading code explicitly checks this value and rejects incompatible binaries with a descriptive error, forcing developers to rebuild segments or regenerate caches rather than risking corruption.

### Where can I find the current version of the Colibri CLI?

The CLI version is defined in [`README.md`](https://github.com/JustVugg/colibri/blob/main/README.md) (e.g., `colibri v1.10.2`) and displayed when running `./coli --version`. This follows semantic versioning and corresponds to the GitHub release tag (`v1.x.x`).

### What happens if I try to load an incompatible segment binary?

The engine checks `adapter->abi_version` against `COLI_SEGMENT_ABI_VERSION` in [`c/colibri.c`](https://github.com/JustVugg/colibri/blob/main/c/colibri.c). If they differ, the runtime prints an error message specifying the expected and received versions, then refuses to load the segment. This prevents crashes from changed struct layouts in the `ColiSegmentAdapter` interface.

### Does the analysis cache need to be cleared when upgrading?

No manual clearing is necessary. The `_ANALYSIS_CACHE_VERSION` constant in [`c/resource_plan.py`](https://github.com/JustVugg/colibri/blob/main/c/resource_plan.py) (currently `7`) prefixes cache files. When the planner detects an older version prefix, it automatically invalidates the cache and performs a fresh analysis, ensuring the new code never loads stale data structures.