---
title: Release and Versioning
description: dev, rc, stable, and package publishing.
pageType: workflow
---

Caracal uses only three versioning modes: dev, rc, and stable. rc and stable artifacts use the same artifact destinations; dev artifacts stay local.

---

## Version scheme

| Mode | Purpose | OCI/binary example | npm example | PyPI example |
| --- | --- | --- | --- | --- |
| dev | Development builds | `2026.05.14-dev.shaabc1234` | `1.4.2-dev.shaabc1234` | not published |
| rc | rc builds | `2026.05.14-rc.shaabc1234` | `1.4.2-rc.shaabc1234` | `1.4.2rc0+shaabc1234` |
| stable | Released production versions | `2026.05.14` | `1.4.2` | `1.4.2` |

The PyPI rc form is PEP 440 compatible while preserving the same rc/sha meaning used by npm, OCI tags, binaries, and GitHub tags.

Git tags use a leading `v`:

- stable: `vYYYY.MM.DD[.N]`
- rc: `vYYYY.MM.DD[.N]-rc.<number>` or `vYYYY.MM.DD[.N]-rc.sha<gitsha>`

The tag drives binaries, OCI image tags, GitHub Releases, and release manifests. Package metadata drives npm and PyPI publishing.

---

## rc workflow

Use rc when a downstream project must consume Caracal as a normal third-party dependency before stable. The consumer changes only package versions and registry/index endpoints; it must not reference Caracal source paths, workspace links, editable installs, or Docker build contexts from the Caracal checkout.

```sh
scripts/rc.sh prepare
git add -A
git commit -m "rc: vYYYY.MM.DD-rc.sha<gitsha>"
git tag -a vYYYY.MM.DD-rc.sha<gitsha> -m vYYYY.MM.DD-rc.sha<gitsha>
git push origin HEAD
git push origin vYYYY.MM.DD-rc.sha<gitsha>
```

`scripts/rc.sh prepare` writes `releases/<rc-tag>/manifest.json`, stamps npm package versions as `<base>-rc.sha<gitsha>`, and stamps PyPI versions as `<base>rc0+sha<gitsha>`. Use `scripts/rc.sh version` only when you need to preview the manifest without stamping package metadata. Pushing the rc tag runs the release workflow, publishes GHCR images, and creates a GitHub Release for rc.

Publish packages after `prepare`:

```sh
./scripts/publishNpm.sh       # rc versions publish with dist-tag rc
./scripts/publishPypi.sh      # rc versions use PEP 440 rc metadata
```

Switch a downstream project between rc and stable by changing only the Caracal versions it already consumes:

```sh
npm install @caracalai/sdk@1.4.2-rc.sha<gitsha>   # rc
npm install @caracalai/sdk@1.4.2                  # stable
uv add caracalai-sdk==1.4.2rc0+sha<gitsha>        # rc
uv add caracalai-sdk==1.4.2                       # stable
```

For containers, change only `ghcr.io/garudex-labs/caracal-{svc}:v<version>`. For binaries, install the desired `--version`. Consumers must not add Caracal source paths, editable installs, Docker build contexts from this checkout, or extra env files.

---

## stable workflow

stable is created by pushing a CalVer tag to `main`:

```sh
git tag v2026.05.12
git push origin v2026.05.12
```

This triggers `release.yml` in GitHub Actions. The stable pipeline:

1. Verifies the pushing actor is listed in `.github/MAINTAINERS`.
2. Builds CLI/TUI binaries and container images in parallel.
3. Pushes images to GHCR with SLSA provenance and SBOM.
4. Creates a GitHub Release with generated release notes, binaries, checksums, and provenance attestations.

Only maintainers push stable tags. Do not push CalVer tags from feature branches.

---

## Shell, CLI, and TUI binaries

The shell (`caracal`), CLI command binary (`caracal-cli`), and TUI (`caracal-tui`) are compiled to self-contained binaries using `bun --compile`. Fifteen archives are produced per release (five targets × three binaries), each containing one executable:

| Target | Shell archive | CLI archive | TUI archive |
| --- | --- | --- | --- |
| `linux-amd64` | `caracal-shell-linux-amd64-vYYYY.MM.DD.tar.gz` | `caracal-cli-linux-amd64-vYYYY.MM.DD.tar.gz` | `caracal-tui-linux-amd64-vYYYY.MM.DD.tar.gz` |
| `linux-arm64` | `caracal-shell-linux-arm64-vYYYY.MM.DD.tar.gz` | `caracal-cli-linux-arm64-vYYYY.MM.DD.tar.gz` | `caracal-tui-linux-arm64-vYYYY.MM.DD.tar.gz` |
| `darwin-amd64` | `caracal-shell-darwin-amd64-vYYYY.MM.DD.tar.gz` | `caracal-cli-darwin-amd64-vYYYY.MM.DD.tar.gz` | `caracal-tui-darwin-amd64-vYYYY.MM.DD.tar.gz` |
| `darwin-arm64` | `caracal-shell-darwin-arm64-vYYYY.MM.DD.tar.gz` | `caracal-cli-darwin-arm64-vYYYY.MM.DD.tar.gz` | `caracal-tui-darwin-arm64-vYYYY.MM.DD.tar.gz` |
| `windows-amd64` | `caracal-shell-windows-amd64-vYYYY.MM.DD.zip` | `caracal-cli-windows-amd64-vYYYY.MM.DD.zip` | `caracal-tui-windows-amd64-vYYYY.MM.DD.zip` |

Archives are attached to the GitHub Release with a `SHA256SUMS` file and SLSA provenance attestations. rc tags create GitHub Releases for rc; stable tags create GitHub Releases for stable.

### Install

The CLI and TUI have separate install targets:

```sh
# Linux/macOS — CLI
curl -fsSL https://raw.githubusercontent.com/Garudex-Labs/caracal/main/install-cli.sh | sh

# Linux/macOS — TUI
curl -fsSL https://raw.githubusercontent.com/Garudex-Labs/caracal/main/install-tui.sh | sh

# Windows — CLI
iwr -useb https://raw.githubusercontent.com/Garudex-Labs/caracal/main/install-cli.ps1 | iex

# Windows — TUI
iwr -useb https://raw.githubusercontent.com/Garudex-Labs/caracal/main/install-tui.ps1 | iex
```

The installers detect OS and architecture, resolve the latest release tag from the GitHub API (or accept `--version`/`-Version`), download the matching shell and selected tool archives, verify them against `SHA256SUMS`, extract them, and place the binaries on `PATH`.

### Upgrade

Re-run the same install command. The installer overwrites the binary in place with the new version.

### Uninstall

Linux/macOS: remove the installed binaries from `~/.local/bin` (`caracal`, plus `caracal-cli` or `caracal-tui`).

Windows: delete `%LOCALAPPDATA%\Programs\caracal` and remove the user PATH entry.

---

## Container images

Seven container images are published to GitHub Container Registry on every release:

| Image | Service |
| --- | --- |
| `ghcr.io/garudex-labs/caracal-api` | Control-Plane API |
| `ghcr.io/garudex-labs/caracal-sts` | Security Token Service |
| `ghcr.io/garudex-labs/caracal-gateway` | Gateway |
| `ghcr.io/garudex-labs/caracal-coordinator` | Coordinator |
| `ghcr.io/garudex-labs/caracal-audit` | Audit service |
| `ghcr.io/garudex-labs/caracal-postgres` | PostgreSQL image |
| `ghcr.io/garudex-labs/caracal-redis` | Redis image |

All images are multi-arch (`linux/amd64`, `linux/arm64`) and are tagged with the CalVer version, the `vYYYY.MM` series, and `latest`.

---

## npm and PyPI packages

npm and PyPI packages are published from a maintainer workstation using the scripts in `scripts/`. Each script opens an interactive picker (up/down, space to toggle, `a` toggles all, enter confirms), prompts for the registry token, builds the selected packages, and uploads them — skipping versions already present on the registry. npm rc versions publish with the `rc` dist-tag; stable versions publish with `latest`.

```sh
./scripts/publishNpm.sh
./scripts/publishPypi.sh             # PyPI
./scripts/publishPypi.sh --testpypi  # TestPyPI
```

**npm packages** (`@caracalai/*`): `core`, `oauth`, `admin`, `identity`, `revocation`, `sdk`, `transport-mcp`, `transport-a2a`, `mcp-express`, `mcp-fastmcp`, `tokenstate-postgres`, `revocation-redis`. Browse at [npmjs.com/~caracal-run](https://www.npmjs.com/~caracal-run).

**PyPI packages** (`caracalai-*`): `core`, `identity`, `revocation`, `sdk`, `transport-mcp`, `mcp-fastmcp`, `revocation-redis`. Browse at [pypi.org/user/CaracalAI](https://pypi.org/user/CaracalAI).

---

## SLSA provenance

The release pipeline generates SLSA Level 3 provenance attestations for binaries and container images. Verify an artifact:

```sh
gh attestation verify caracal-cli-linux-amd64-v2026.05.12.tar.gz --repo garudex-labs/caracal
```

---

## Hotfixes

For a critical fix on an already-released version:

1. Branch from the release tag: `git checkout -b hotfix-jti v2026.05.12`
2. Apply the fix and open a PR against `main`.
3. Merge after review; cherry-pick to `main` if needed.
4. Tag the hotfix: `git tag v2026.05.12.1 && git push origin v2026.05.12.1`.

Tags must point to commits reachable from `main`.

---

## Post-release validation

Every release tag has a directory under `caracal/releases/<tag>/` that owns all of its metadata:

- `manifest.json` — pins every artifact (binaries, containers, PyPI, npm) to a mode and version, committed alongside the changeset version bump or rc preparation commit.
- `validation.md` — the aggregated post-release validation report.
- `findings/*.jsonl` — raw per-area findings.

The `.github/workflows/postReleaseValidation.yml` workflow triggers after `release.yml` completes successfully for a release tag, or via `workflow_dispatch`, and opens a PR that adds `validation.md` and `findings/` to that directory.

Run a single check locally:

```sh
CARACAL_RELEASE=v2026.05.12 FINDINGS_DIR=/tmp/findings \
  bash caracal/scripts/postRelease/validateRegistryMetadata.sh
```
