Skip to content
dshakesPublic

About

Control plane for AI coding CLIs (Claude Code, Codex, Gemini, Copilot): signed releases, rollout rings, A/B, canary, shadow, toggles, eval-gated promotion. Docs: https://dshakes.github.io/halos/

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

128 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Halos: policy to signed release to rollout rings to every environment, with an evidence loop back

Ship AI coding tools like software.
Versioned · signed · ring-deployed · proven by evals

CI Latest release Go Reference Apache-2.0 Docs

Open in GitHub Codespaces

Start here · Quickstart · Architecture · CLI · Threat model


Halos is the open-source control plane for AI coding CLIs: Claude Code, Codex, Gemini CLI, Copilot CLI, Cursor CLI and OpenCode.

  • One signed release per ring. A policy repo becomes versioned, content-addressed releases that halod and the gateway enforce on every machine.
  • Every change is staged and measured. Dark launch, canary, A/B and shadow behind evals and live telemetry; promotion is a PR a human merges.
  • Rollback is a pointer, not a Slack message. A regression measured at the gateway trips a signed kill list that gateways pick up in about 10 s (when halo-server serves it); any other regression opens a rollback PR.

halo rollout plan prints a six-step dark-launch, canary and holdout plan; halo rollout simulate shows a regression caught and rolled back at the 1% step

Quickstart

brew install dshakes/tap/halo      # other installs below
halo quickstart                    # the whole stack in Docker, about a minute with a warm Docker cache, 2 to 3 minutes cold
halo doctor && halo onboard local  # or pin and manage the CLIs on this machine
halo onboard company --help        # or: policy repo, gateway, IdP, fleet, first PR (six required flags)

Each path can also be driven by the AI CLI you already use: Start here.

How it works

Your platform team keeps a policy repo: a Git repo that halo init creates. It starts as one file, and developers never touch it.

# halos.yaml: the whole policy, in simple mode
org: acme
tools: {claude-code: 2.1.280, codex: {version: 0.99.0, model: codex}}
provider: anthropic                    # bedrock | vertex | openai | gemini | multi
models: {default: claude-sonnet-5-5, strong: claude-opus-5-5, codex: openai/gpt-5-codex}
gateway: https://ai.acme.example
identity: {issuer: https://login.acme.example, audience: halos, adminGroups: [ai-platform]}
safety: standard                       # strict | standard | relaxed: never bypasses permissions
rollout: standard                      # fast | standard | careful: rings, canary steps, bake times, gates

Presets expand into profiles, rings and gateway routes. Intent commands write the rest for you. The ones that write policy (upgrade start, model switch, enable, eject) support --dry-run, validate their output and list the files they change; halo kill writes to halo-server at once (no release) and takes effect at the next poll, by default 10 s at gateways and 60 s on devices:

# A/B + gated rollout for a CLI upgrade. Builds and signs a candidate release, so it needs a registry
# and key (HALO_REGISTRY / HALO_KEY) and the GA ring's published pointer, or --baseline <digest>.
# --dry-run still reads that pointer.
halo upgrade start claude-code 2.1.300 --registry ghcr.io/acme/halos --key halo.key
halo model switch strong claude-opus-5 --canary
halo enable mcp github --url https://… --for 10%
halo kill <experiment|toggle|rollout> --reason "…"
halo status                                   # rings, rollouts, experiments, toggles
halo explain | halo eject                     # see, or take over, the full policy

A change is a pull request:

  1. CI runs halo validate, halo plan and evals.
  2. On merge, halo release publish builds and signs a release for each ring.
  3. Every environment picks it up: halod on laptops and CI runners, the Dev Container Feature in workspaces, and halo-proxy or Kong for model traffic.
Platform team: policy repo, pull request, CI checks, human merge, signed release. Fleet: rings point at releases; halod applies them on every machine and the gateway routes models; developers keep running their CLI as usual.

examples/simple is the one-file version and examples/acme-corp the full one; make demo runs it locally; halo quickstart is the same stack (about a minute with a warm Docker cache, 2 to 3 minutes cold; one cold run on an arm64 laptop with Docker Desktop took 2:31). Codespaces is UNVERIFIED: CI builds the dev container, but the demo has not been run in a real Codespace. More: how Halos works.

Every rollout technique, as code

Progressive rings, canary ramp, blue-green, dark launch, holdout

A Rollout is an ordered list of steps. Each step sets:

  • a strategy and an exposure
  • a bake time and a minimum sample size
  • gates: metric guardrails, an eval scorecard, a human approval
apiVersion: halos.dev/v1
kind: Rollout
name: opus-5-5-upgrade
axis: traffic                    # client: a CLI/config release · traffic: a model route
experiment: opus-5-5-canary
change: {alias: opus}
steps:
  - name: dark-launch            # mirrored to the candidate, nothing served
    strategy: dark-launch
    percent: 10
    bake: 2d
    gates:
      scorecard: {file: evals/opus-5-5.scorecard.json, variant: opus-5-5, minPass1: 0.75}
  - name: canary-5
    strategy: canary
    percent: 5
    bake: 12h
    minSamples: 500
    gates:
      guardrails: [{metric: halo.api.error_rate, direction: decrease, maxRegression: 0.05}]
  - name: holdout                # 5% stay on the old model for 14 days
    strategy: holdout
    percent: 5
    bake: 14d
    gates: {approval: true}

The controller evaluates every active step on each tick (default every 5 minutes):

  • A guardrail breach measured at the gateway trips the signed kill switch on its own (traffic axis, when halo-server serves a kill list). Any other breach opens a rollback PR and notifies.
  • Progress always opens a PR that a human merges. Nothing auto-promotes.

Commands: halo rollout plan | status | simulate | advance | rollback (docs).

Experiments and feature toggles

A/B on the client axis, canary on the traffic axis, shadow mirrored to a judge, all assigned by one deterministic hash
  • A/B a CLI version or settings change. Each arm is its own signed release channel, and halod picks the arm with the same hash the gateway uses.
  • Canary a model at the gateway, sticky per user and session, so agents never switch model mid-task.
  • Shadow real agent sessions to a candidate model, every step or just the first, and compare its next action with the control and with what production actually did (tool agreement, fidelity vs a measured noise floor, invalid calls, premature stops), plus an LLM judge. Nothing from the candidate is served or executed.
  • Toggles turn one capability (an MCP server, a hook, a model route) on for a ring, an IdP group or a percentage of users. The payload ships inside the signed release. A kill needs no new release and takes effect at the next poll: about 10 s at gateways, 60 s on devices.

halo toggle eval shows which toggles are on for a developer and why; halo gateway routes shows each model alias and the upstream it routes to

Measure, don't guess

Change, offline evals, ring exposure, telemetry, mSPRT verdict, promote PR or auto-rollback
Offline evals Replay real tasks in containers, N trials each. Reports pass@1, pass@k and pass^k, with paired bootstrap CIs on pass rate, cost, tokens and time. Flaky tasks are detected and excluded. Verdict: ship, hold or block.
Matrix Runs one suite across harness × model × provider (Claude Code vs Codex vs Gemini, Anthropic vs Bedrock) and produces a PR-ready report.
Online Shadow pairs are graded against a pinned LLM-judge rubric and land in the same evidence plane as cost, latency and errors.
Sequential stats mSPRT guardrails stop an experiment as soon as a regression is real, not at an arbitrary horizon.
Upgrade watch halo upgrade watch spots a new CLI or model release, pins it on a branch, runs the suite and opens a PR with the scorecard.

Six CLIs, any provider

Claude Code Codex Gemini CLI Copilot CLI Cursor CLI OpenCode
Version pin CLI-enforced halod halod halod not installable by halod halod
Model lock ✓ ✓ ✓ default only - ✓
MCP allowlist ✓ ✓ ✓ ✓ - -
Permissions ✓ ✓ partial partial (UNVERIFIED) - ✓
Gateway ✓ ✓ ✓ - - ✓
Telemetry ✓ ✓ ✓ ✓ - -

A setting a CLI can't enforce produces a warning in the release manifest; it is never silently dropped. halo harnesses prints the capability matrix; the harness reference has every cell and its source.

Traffic goes through halo-proxy to Anthropic, Bedrock (SigV4), Vertex, OpenAI, Azure OpenAI or the Gemini API:

  • Model aliases map to weighted splits and priority failover, with a circuit breaker per target.
  • Moving a model to another provider is a one-line policy change.
  • If you already run Kong, the halo-kong plugin applies the same identity, cohort and experiment decisions. It routes each alias to its first target, with no translation or failover.

Enterprise controls

Control What it does Docs
RBAC IdP groups map to viewer, operator, approver, auditor, admin; role bindings can be scoped to rings and org units; every route is deny-by-default and denials are audited delegated administration
SCIM 2.0 Okta and Entra provisioning; deprovisioning revokes sessions and device tokens at once SCIM
Org units Delegated owners and overlays that can tighten, never loosen, enforced fields org hierarchy
Cost budgets Per user, group, ring or org caps in USD or tokens, warn or enforce, answered as 429 at the gateway budgets
Audit to SIEM Hash-chained audit forwarded to Splunk HEC, signed webhook or syslog TLS, native or OCSF SIEM export
CI and workload identity RFC 8693 exchange of a GitHub, GitLab, Buildkite, CircleCI or cloud OIDC token for a credential of at most 1 h CI and cloud agents
Agent identity Delegated agent credentials with an act chain, down-only model scope and an A2A allowlist agent identity
Extension governance Marketplace, plugin, skill and subagent policy, rendered where the vendor documents a key and warned elsewhere harness reference
OTel GenAI gen_ai.* semantic-convention metrics and opt-in content-free spans from the gateway evidence plane
HA on Postgres Several halo-server replicas behind one load balancer with a fenced controller lease production deployment
Vendor admin sync One policy drives the vendors' cloud admin consoles; halo admin plan fails CI on drift, apply writes what has a public API and never loosens vendor admin sync
Change governance Freeze windows and an incident freeze hold advances and promotions, never rollbacks; N-of-M approvals with separation of duties and tickets; halo plan --diff previews who a change reaches change governance
Credential revocation Revoke one agent or workload credential and everything exchanged from it by jti, or all of a subject's; every replica refuses it, gateways within 30 s agent identity
Egress and sandbox One profile states what the agent's shell may read and write and which hosts it may reach; each adapter renders it natively and warns where a harness cannot egress and sandbox
Gateway DLP halo-proxy and halo-kong scan requests for secrets and tool results for prompt injection, act per ring and unit, and record findings without storing the secret DLP
MCP registry halos.yaml lists approved MCP servers; releases render them into every harness, halod reports unapproved ones, halo-server can authorize your own remote servers MCP registry
Agent supply chain Skills, hooks, commands and subagents pinned by digest, scanned, signed with the release and checked by halod; CycloneDX AI-BOM and SLSA provenance agent supply chain
Cloud agents cloudAgents governs agents no managed machine runs: the Claude Code GitHub Action, Copilot cloud agent, Codex cloud and Cursor cloud agents cloud agents
Session ledger One record per agent session: who (and the delegated chain), release, ring, variant, models, MCP tools, repos, tokens, cost and outcome, from gateway, OTel and vendor audit APIs session ledger
Delivery ROI halo roi joins PR outcomes to randomized experiment arms, so the effect is the change's, not self-selection's; informational, never gates promotion delivery ROI
Policy copilot halo copilot drafts a policy change from an intent, runs validate, plan, impact and stats on it, and commits only to a local branch; a human opens and merges the PR policy copilot
Test a change halo test validates, renders every ring x harness x OS, checks invariants and releases, runs your tests/ cases and simulates rollouts in seconds, offline, before any eval testing a policy change
Admin credentials Service-account API tokens (halo_sat_, always expiring, never stronger than their creator), a sealed break-glass admin, session idle and absolute timeouts, Entra groups overage and acr/amr MFA claims admin access
Signing keys Release, kill-list and artifact signing keys by URI (file://, awskms://, or an exec:// signer for an HSM); ECDSA P-256 and FIPS 140-3 builds key management
Promotion PRs Promotions open a PR or MR through the gh CLI, GitHub REST or GitLab REST; Halos never merges GitLab and GHES
Notifications Slack, Microsoft Teams, PagerDuty and signed-webhook notifiers for rollout, freeze and kill-switch events notifications
HTTP API /api/v1 is described by an OpenAPI 3.1 document generated from the server, with a drift test in CI API reference
Ops kit The Helm chart ships a PrometheusRule, PodDisruptionBudget and HPA, global.imageRegistry, an OCI chart and an air-gap install; scripts/uat-dr.sh runs a restore drill production deployment
Fleet sizing make load-fleet runs simulated halod devices (up to 10,000) against halo-server; the sizing guide turns the results into replica counts sizing
Compliance mapping Controls mapped to SOC 2, ISO 27001 and the EU AI Act, with data-flow and PII documents control mapping
Terraform / OpenTofu The dshakes/halos provider on the Terraform Registry (OpenTofu-compatible) manages service-account tokens and reads status; it never touches policy or approvals Terraform provider

Runs everywhere

macOS, Linux, Windows, Dev Containers, Codespaces and Coder workspaces, CI runners, Kubernetes via Helm

The current release is v0.5.2 (CHANGELOG). Or build from source: git clone https://github.com/dshakes/halos && cd halos && make build (builds halo, halod, halo-shadow, halo-server, halo-proxy and halo-kong into bin/).

brew install dshakes/tap/halo                                                            # macOS / Linux
scoop bucket add dshakes https://github.com/dshakes/scoop-bucket && scoop install halo   # Windows
npx @dshakesnotbot/halo quickstart                                                             # Node 18+, no install

# The script works everywhere; halod runs as root from a root-owned prefix
curl -fsSLO https://raw.githubusercontent.com/dshakes/halos/v0.5.2/install/install.sh
sh install.sh --version v0.5.2                                        # halo into ~/.local/bin
sudo sh install.sh --version v0.5.2 --prefix /usr/local --with-agent  # plus halod

Also available:

Archives are checksummed and carry SBOMs; checksums.txt is cosign-signed and every archive has a GitHub build-provenance attestation. install.sh verifies the checksums, and the cosign signature when cosign is installed (otherwise it warns). The release workflow re-verifies all of it from the published artifacts before a release counts as done (RELEASING.md, install guide).

Agent-native

halo mcp serve exposes these to any MCP client: validate, plan, rollout status, experiment analysis, toggle evaluation and eval scorecards.

The write tools (propose a rollout step, a rollback or a toggle change, kill a change, run an eval) are opt-in and dry-run by default. Proposals commit to a new local branch; propose_promotion and, on request, the rollout proposals push a review branch and open a PR. None pushes to the base branch, merges or publishes a release. The Claude Code plugin, the Codex config, the Gemini CLI extension and the Copilot CLI config drive the same flows: onboarding (doctor → dry run → approve → write → verify) and rollout (edit → validate → eval → experiment → propose).

Architecture

Client plane, traffic plane and evidence plane with their components

Deep dive, traced to the code: tech stack, components and low-level design.

Security by construction

  • Signed everything. Releases, ring pointers and the kill list are ed25519-signed; releases and pointers can also be co-signed with cosign. Ring pointers carry sequence numbers and an expiry, so a registry can't replay an old one.
  • Identity, never headers. The gateway verifies OIDC JWTs (or, in trusted_header mode, accepts identity only from pinned proxy CIDRs), strips client x-halo-* headers and fails closed on unknown models.
  • Guardrails twice. bypassPermissions and danger-full-access are rejected at validate time and again on the rendered output.
  • Humans own the irreversible step. There is no auto-merge, no auto-promote and no agent (MCP) tool that publishes. Privileged actions land in a hash-chained audit log.

Threat model · SECURITY.md · Compliance: control mapping, data flow and PII, security overview

Status

Every component is implemented and covered by unit, race, e2e (make e2e) and evidence-plane (make obs-e2e) tests. Every pull request also runs three acceptance suites against real software:

Suite Runs against Report
make uat-clis the real Claude Code, Codex, Gemini CLI and Copilot CLI (Cursor CLI and OpenCode are not in this run yet), including the eval runner CLI-REPORT.md
make uat-k8s a kind cluster with the Helm chart installed REPORT.md
make uat-kong open-source Kong 3.9.3 with the halo-kong plugin KONG-REPORT.md

Unit tests also run on Windows and macOS in CI. A nightly provider smoke sends real requests through halo-proxy to Anthropic and OpenAI (streaming and non-streaming) and checks the gateway metrics.

Not yet exercised against the real systems:

  • AWS Bedrock, Vertex, Azure OpenAI and Gemini API accounts (fixture-tested only; the nightly smoke covers them once their secrets are set)
  • Kong Enterprise
  • Windows beyond a CI runner: Intune, Authenticode, an interactive logged-in user (CI runs install.ps1, enroll.ps1 and halod as a SYSTEM scheduled task on a hosted Windows runner)
  • MDM-managed devices (Jamf, Kandji, Intune)
  • Codespaces and Coder workspaces (CI builds the dev container and the Feature with the devcontainer CLI)
  • the GitLab CI template on a real GitLab runner (CI runs its script in a container with gitlab-ci-local, an emulation)
  • the Helm chart on a managed cloud cluster

Contributing

CONTRIBUTING.md · AGENTS.md for coding agents · ADRs · Apache-2.0

About

Control plane for AI coding CLIs (Claude Code, Codex, Gemini, Copilot): signed releases, rollout rings, A/B, canary, shadow, toggles, eval-gated promotion. Docs: https://dshakes.github.io/halos/

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages