A Rust controller built on
kube-rs
that turns AI agent runs into first-class Kubernetes resources. One CRD per agent — the
operator handles scheduling, RBAC, secrets, persistence, and lifecycle.
apiVersion: thurkube.thurbeen.eu/v1alpha1
kind: AgentJob
metadata:
name: pr-fixer
namespace: agents
spec:
schedule: "0 */6 * * *"
timezone: Europe/Paris
runtimeRef: claude-code
authRef: claude-oauth
roleRef: default
repositoryRefs: [thurkube]
prompt: "Fix any failing PRs on this repository."
persist: true
Eight CRDs, one binary, the full Kubernetes contract
One
AgentJob
resource defines a one-shot or scheduled agent run. The controller emits the matching
Job
or
CronJob
and owns its lifecycle end-to-end.
Runtimes, auth, roles, skills, MCP servers, repositories, and RBAC are separate CRDs. Reference them by name and reuse them across many jobs.
Auth tokens flow from
Secret
keys into the right env var.
ClusterAccess
materializes a ServiceAccount, ClusterRole, and ClusterRoleBinding scoped to the job.
Set
persist: true
and the controller provisions a PVC with sensible defaults — mounted at the runtime's
declared
persistPath
.
A
configHash
in
.status
tracks the rendered ConfigMap. Spec or reference changes redeploy the underlying Job
without manual cleanup.
Bind
McpServer
resources (local
command
or remote
url
) and reusable
AgentSkill
repositories. The controller assembles them into the agent's runtime config.
The controller runs as
runAsNonRoot
with
readOnlyRootFilesystem
, dropped capabilities, and the
RuntimeDefault
seccomp profile.
Single Rust binary with a tokio runtime, server-side apply via field manager
thurkube
, and standard
/healthz
and
/readyz
probes.
Ship the chart from
charts/thurkube
or pull the OCI artifact from GHCR. CRDs install on chart apply (toggle with
crds.install
).
Four steps from cluster to running agent
Deploy the controller and CRDs via Helm.
$ helm install thurkube oci://ghcr.io/thurbeen/charts/thurkube \
--namespace thurkube-system --create-namespace
An
AgentRuntime
points at your container image. An
AgentAuth
wires a Secret key into it.
apiVersion: thurkube.thurbeen.eu/v1alpha1
kind: AgentRuntime
metadata: { name: claude-code }
spec:
image: ghcr.io/thurbeen/claude-code-job:latest
authEnvVar: CLAUDE_CODE_OAUTH_TOKEN
configPath: /etc/claude-code-job
persistPath: /var/lib/claude-code-job
Reference your runtime, auth, role, and any optional repositories or MCP servers.
apiVersion: thurkube.thurbeen.eu/v1alpha1
kind: AgentJob
metadata: { name: summarize }
spec:
runtimeRef: claude-code
authRef: claude-oauth
roleRef: read-only
prompt: "Summarize today's incoming issues."
The controller emits a
Job
or
CronJob
, wires up the ConfigMap, ServiceAccount, and PVC, and reports phase via printer
columns.
$ kubectl get aj -n agents
NAME SCHEDULE SUSPENDED PHASE LAST RUN
summarize <none> false Succeeded 2m
pr-fixer 0 */6 * * * false Running 14s
Helm is the supported path
$ helm install thurkube oci://ghcr.io/thurbeen/charts/thurkube \
--namespace thurkube-system --create-namespace
Installs the eight CRDs and the controller Deployment with locked-down pod security.
Override anything via
--set
or
--values
.
docker run --rm ghcr.io/thurbeen/thurkube:latest --crd | kubectl apply -f -
--set image.tag=v0.1.0
cargo build --release