Osmia is a Kubernetes-native AI coding agent harness that orchestrates autonomous developer agents (Claude Code, OpenAI Codex, Aider) to perform maintenance and development tasks on codebases at scale. It is Apache 2.0 licensed, enterprise-grade, and security-first.
The full technical plan, including the product requirements, is in oss-plan.md. Refer to it when you need architectural context or implementation details.
- Controller: Go (>= 1.23) using controller-runtime, client-go, hashicorp/go-plugin
- Plugin interfaces: Protobuf/gRPC (source of truth in
proto/) - Plugin SDKs: Generated from protobufs — Python, Go, TypeScript
- Build: Makefile targets for build, test, lint, proto-gen, sdk-gen
- Container images: Multi-stage Docker builds, distroless base images
- Deployment: Helm chart in
charts/osmia/
- Run
gofumpton all Go files before committing (stricter superset of gofmt) - Use
golangci-lint runto check for issues — fix all warnings - Use British English in all comments, documentation, error messages, and user-facing strings (e.g. "colour" not "color", "organisation" not "organization", "licence" not "license")
- Use Go's
slog(standard library) for all logging — structured, JSON output - Follow standard Go project layout:
cmd/,internal/,pkg/ internal/is for packages only used by the controllerpkg/is for packages that external consumers (plugins, SDKs) may import- Prefer table-driven tests
- All exported types, functions, and methods must have doc comments
- Error messages should be lowercase, no trailing punctuation (Go convention)
Follow the structure defined in section 8 of oss-plan.md. The key packages are:
cmd/osmia/ — Main entrypoint
internal/controller/ — controller-runtime reconciler
internal/jobbuilder/ — ExecutionSpec -> K8s Job translation
internal/sandboxbuilder/ — Sandbox CR builder (gVisor/Kata)
internal/taskrun/ — TaskRun state machine + idempotency + store
internal/watchdog/ — Progress watchdog loop
internal/agentstream/ — Real-time NDJSON streaming from agent pods
internal/config/ — Configuration loading
internal/metrics/ — Prometheus metrics
internal/webhook/ — Webhook receiver (GitHub/GitLab/Slack/Shortcut/generic)
internal/secretresolver/ — Task-scoped secret resolution + policy
internal/promptbuilder/ — Prompt construction with task profiles + workflows
pkg/engine/ — ExecutionEngine interface + built-in engines
pkg/plugin/ — gRPC plugin host + all plugin interfaces
proto/ — Protobuf definitions (source of truth for all interfaces)
- Write unit tests for every package (
*_test.goalongside the source) - Use table-driven tests with subtests (
t.Run) - Use
testify/assertandtestify/requirefor assertions - Integration tests go in
tests/integration/ - E2E tests (requiring a kind cluster) go in
tests/e2e/ - Run
go test ./...to execute all unit tests - Aim for meaningful coverage of core logic — state machines, builders, reconciliation loops
- All plugin interfaces are defined as protobuf services in
proto/ - The Go interfaces in
pkg/plugin/*/must match the protobuf definitions - Use
buffor linting and generating protobuf code - Every service must include a
HandshakeRPC withinterface_version
- This is a security-first project. Every design decision should consider the threat model in section 10 of
oss-plan.md - Never log secrets or API keys
- Validate all external input (ticket descriptions, plugin responses, webhook payloads)
- Use context.Context for cancellation and timeouts on all I/O operations
- All container specs must include restrictive securityContext (runAsNonRoot, readOnlyRootFilesystem, drop ALL capabilities)
- Prefer workload identity (IRSA/WIF) patterns over static credentials where applicable
- Use Go modules. Run
go mod tidyafter adding/removing imports - Prefer standard library where possible
- Key dependencies: controller-runtime, client-go, hashicorp/go-plugin, grpc-go, prometheus/client_golang
- Do not add dependencies without good reason — this is an OSS project and every dependency is an attack surface
- Use conventional commits:
feat:,fix:,docs:,test:,refactor:,chore: - Keep commits focused — one logical change per commit
- Write descriptive commit messages explaining why, not just what
- Do not modify
oss-plan.md(it is a reference document) - Do not introduce Python into the controller — the controller is Go only
- Do not bypass the plugin interface abstraction — all external integrations go through the defined interfaces
- Do not hard-code configuration values — use
osmia-config.yamland environment variables - Do not add Kubernetes CRD types until explicitly decided (see open question 7 in the plan)
- Never edit
CHANGELOG.mddirectly. It is assembled bytowncrierat release time from the fragments inchangelog.d/. - Add one fragment per user-visible change:
changelog.d/+<slug>.<category>.md, category being one ofadded,changed,deprecated,removed,fixed,security. The contents are the entry as prose, with no leading-. - See
changelog.d/README.mdfor conventions andtowncrier.tomlfor config.