Compatibility and support¶
kubeagent 1.0 is a commitment, not just a version number. This page says exactly what that commitment covers — and, just as importantly, what it does not, because a promise that quietly includes everything is a promise nobody can keep.
kubeagent follows Semantic Versioning. From 1.0 onward, a MAJOR bump is the only release that may break a stable surface listed below. A MINOR adds; a PATCH fixes.
Stable surfaces¶
The command line¶
Every command and flag that kubeagent prints in its own usage text is stable.
Within 1.x:
- No command is removed or renamed.
- No flag is removed, renamed, or given a different meaning.
- No flag's default changes in a way that changes what a run reports.
- A flag that takes a value keeps taking one, and keeps accepting the values it accepted before.
New commands and new flags may arrive in any MINOR. A run that pinned itself to the 1.0 surface keeps working.
The single-dash long-flag spelling is part of this. kubeagent's CLI moved
from the standard library's flag package to Cobra in v0.73.0, and pflag
rejects -kubeconfig where the standard library accepted it. internal/cli
normalizes a leading -longname back to --longname for any name the target
command registers, so command lines written against v0.72 and earlier still run
unchanged. Removing that shim would be a breaking change.
Environment variables¶
Every KUBEAGENT_* variable this site documents is stable in the same sense a
flag is: within 1.x it is not removed, not renamed, and not given a different
meaning. New ones may arrive in any MINOR.
Two things about them are deliberately not promised:
- The tuning defaults.
KUBEAGENT_SCAN_WORKERSdefaults to8andKUBEAGENT_QPS/KUBEAGENT_BURSTdefault to no client-side limit at all. Those numbers are performance behaviour, not contract — they may be retuned in a MINOR. What is stable is that setting them works, that they only affect how fast a scan reads, and that they never change what it reports. See Performance tuning. - What a bad value does beyond staying non-fatal. The tuning variables ignore a value they cannot use and run with the default rather than failing the scan; that tolerance is the contract, the exact clamping is not.
Exit codes¶
kubeagent gate exists to be branched on by a pipeline, so its exit codes are
fixed and may never be reassigned:
| Code | Meaning |
|---|---|
0 |
Pass — nothing at or above --fail-on |
1 |
Fail — findings at or above --fail-on |
2 |
Inconclusive — kubeagent could not see enough to judge |
3 |
Timeout — --wait-for did not settle within --timeout |
4 |
Usage — bad flags or arguments |
Code 2 is the one worth wiring up deliberately: a gate that could not read
what it needed is not a passing gate, and kubeagent refuses to report it as one.
Every other command exits 0 on success and 1 on failure. kubeagent rbac
check exits 1 when the identity is missing a grant the selected features
need — that is a verdict, not an error.
The JSON documents¶
Four surfaces — scan, gate, rbac, and the watch daemon's HTTP endpoints —
each carry their own schemaVersion and their own published JSON Schema, and
each versions independently of the kubeagent release. A new scan field does
not disturb a script reading the gate document.
That contract has its own page: JSON schema contract,
which covers what MINOR and MAJOR mean for a document, how to pin to one, and
what a schemaVersion deliberately does not promise. It is the authority; this
page does not restate it.
The Helm chart's values¶
Documented keys in deploy/helm/kubeagent/values.yaml keep their names and
meanings within 1.x. New keys may be added. The chart's own version moves
independently of the application's appVersion.
The watch daemon's /dashboard endpoint¶
watch --dashboard serves an HTML page at /dashboard on the metrics port.
Within 1.x that endpoint keeps its path, keeps returning HTML when the flag is
set, and keeps returning 404 when it is not. The flag, its
KUBEAGENT_DASHBOARD spelling and the dashboard.enabled chart value are
stable under the three rules above, like every other flag, variable and chart
key. The page's markup is not — it is listed under unstable surfaces below.
The Claude Code plugin manifest¶
.claude-plugin/plugin.json declares the command line that starts the MCP
server. Because that command line is baked into every installation and re-read
on upgrade, changing it changes the behaviour of plugins already installed.
Within 1.x, adding a flag to mcpServers.kubeagent.args is MINOR; removing one,
or changing what an existing flag means, is MAJOR. The plugin's name and the
marketplace entry's name are stable — they are what /plugin install
kubeagent@kubeagent names.
The skill and command text is not stable. It is instruction for a model and will be reworded as the detectors change. Nothing should parse it.
Unstable surfaces — do not build on these¶
- The text report's wording and layout.
internal/report/testdata/golden-scan.txtis a regression guard so a change to the report is always deliberate — it is not a promise to consumers. Parse--output json, never the text. - The HTML report's and the dashboard's markup. Both are artifacts for a
human to look at — a shareable file in one case, a page in a browser in the
other — and their structure will change. Parse
--output jsonor/issues. - Every
internal/package. Go'sinternal/rule already enforces this: nothing outside the module can import them, and the layout is free to move. kubeagent is a binary, not a library. --explainand--investigateoutput. Model-generated prose. It has a shape; its content is not deterministic and never will be.- Any human-readable string —
reason,summary,evidence. Match onissue, which is a stable identifier.
Kubernetes versions¶
kubeagent supports v1.32, v1.33, and v1.34.
This is an evidenced window rather than an asserted one. A nightly GitHub Actions matrix runs the full 23-scenario chaos suite — real injected outages, on a real cluster — against two distributions: kind, once per supported minor, and k3s (via k3d), once at the newest supported minor, each on its own disposable cluster. The kind cells run 134 machine-checked assertions each; the k3s cell runs 110, five scenarios fewer, and names each skip and its reason in its assertion summary — certificate expiry (skipped identically on kind), etcd and kubelet (k3s has no separately stoppable etcd and runs its kubelet inside the single k3s process), NetworkPolicy enforcement (k3s ships Flannel, which does not enforce it), and the metrics-server-absent capacity path (k3s ships metrics-server by default). A minor is listed here because the suite passes against it, and it stops being listed when the suite stops being run against it.
The window moves forward as Kubernetes releases: a new minor is added after the matrix passes against it, and the oldest is dropped once it leaves upstream support. Adding or dropping a minor is a MINOR release, not a MAJOR one — the support window is a statement about what is tested, not a stable API.
What the matrix does not cover: one architecture (amd64), on
ubuntu-latest. kubeagent uses only stable client-go APIs and should work on
any conformant cluster in the window, but EKS, GKE, AKS, OpenShift, and RKE2
are not gated in CI, and nothing on this page claims they are — one
distribution beyond kind is gated, not five. The CNI axis is no longer single
either: Calico enforces NetworkPolicy on the kind cells, Flannel does not on
the k3s cell, and NetworkPolicy enforcement is asserted only where a CNI
enforces it.
The harness itself can also be pointed at a cluster it did not create:
./chaos/run.sh --context <ctx> runs the subset of scenarios whose blast
radius is a namespace it creates and deletes (all but one, which only reads),
refuses every scenario that would write a cluster-scoped object or touch a
node, and names each skipped scenario and its reason in the assertion summary
— so a partial run can never be mistaken for a full one. A second distribution
is now gated nightly (k3s, alongside kind); portable mode remains the way to
point the harness at a distribution the matrix does not gate — EKS, GKE, AKS,
OpenShift, RKE2, or any cluster you already run.
Deprecation policy¶
A stable surface is never removed without warning:
- It is announced as deprecated in the CHANGELOG for the release that deprecates it.
- It keeps working, unchanged, for at least one full MINOR release.
- Using it prints a warning to stderr — never to stdout, so a pipeline parsing JSON is never corrupted by a deprecation notice.
- It is removed only in the next MAJOR.
Nothing is deprecated as of 1.0.
What is read-only, and what is not¶
This is a safety contract rather than a compatibility one, but it is the one most worth being explicit about, and it does not change in 1.x.
kubeagent is read-only toward your cluster by default. scan, watch,
gate, mcp, tui, rbac print, policy validate, policy packs,
schema, version, and completion issue only get, list, and watch
calls. There is no code path from a policy rule, an MCP tool call, or a model
response into a write.
Two documented exceptions:
- Remediation —
scan --fix, andscan --rollbackwhich undoes what a previous--fixrecorded in its audit log. These are the only two flags in kubeagent that write, they are mutually exclusive, and both are opt-in and carry the same guard rails: a fixed allowlist, protected namespaces refused, a permission preflight, a per-action confirmation, an audit-log entry, and a re-verify afterwards. Neither is ever LLM-decided. See Remediation (--fix). kubeagent rbac checkcreatesSelfSubjectAccessReviewobjects — the same virtual resourcekubectl auth can-iuses. The API server evaluates them and never persists them. It is the only path outside remediation that issues a POST, and it changes no cluster state.
kubeagent mcp, kubeagent gate, kubeagent tui, and kubeagent rbac make no
model API call at all, whatever flags you pass. Read-only and makes-no-external-call
are separate promises, and both hold for those four.