Helmr is a self-hosted runtime for coding agents.
It provides the infrastructure around an agent SDK: an isolated writable workspace, controlled credentials, logs, run history, and approval points before a task writes back. Task code is written in TypeScript and runs inside Firecracker-backed Linux guests managed by your own control plane and workers.
Helmr is in early active development. APIs, deployment shape, and operational defaults may change before a stable release. The current codebase is best suited for contributors, early adopters, and self-hosted evaluation.
- TypeScript tasks that declare images, sandboxes, resources, secrets, inputs, and run logic
- Empty writable workspaces mounted inside isolated Linux guests
- Approval waitpoints before reviews, patches, or other side effects
- Run status, logs, events, payloads, and history in the control plane
- Task-declared secrets injected only at run time
- A runtime boundary you own: your AWS account, your integrations, your workers
- A Go control plane, worker,
helmrCLI, TypeScript SDK, and console UI
cmd/- Go binaries for the CLI, control plane, worker, and guest agentinternal/- Go control-plane, worker, executor, database, and server codesdk/typescript/- public task authoring and runtime client APIsruntime/typescript/- guest-side TypeScript adapterproto/- shared protocol definitions and generated bindingspackages/console/- self-hosted dashboardpackages/web/- public website and documentation siteexamples/- runnable task projectsimages/- Firecracker guest boot image recipesinfra/aws/- OpenTofu/Terraform modules and deployment examplesnix/andscripts/- pinned development, CI, and smoke-test entrypoints
The repository is built around a Nix-pinned toolchain. Use Nix when possible so Go, Bun, Buf, PostgreSQL, and infrastructure tooling match CI.
nix develop
nix run .#doctorWithout Nix, install the versions expected by go.mod, package.json, and the
CI scripts. Firecracker execution requires a Linux host with KVM; macOS is
useful for control-plane, SDK, CLI, and console development but cannot run the
Linux microVM smoke path locally.
Start the local control plane and console:
nix develop
make devThe dev stack starts a disposable PostgreSQL database when HELMR_DATABASE_URL
is not set, runs the control plane, and serves the console at:
http://127.0.0.1:3000/dev/login
Use that URL to create a local owner session and inspect seeded runs.
A task binds a sandbox, TypeScript run logic, declared secrets, and optional human approval points. The code inside the task can call any agent SDK or tool; Helmr owns the adapter protocol around it.
Create a task project with helmr.config.ts and one or more task modules:
import { cache, image, sandbox, source, task } from "@helmr/sdk"
import { writeFile } from "node:fs/promises"
const base = image("repo-agent")
.from("node:24-bookworm-slim")
.workdir("/workspace")
.run(["npm", "install", "-g", "bun@1.3.10"])
.copy("/workspace/package.json", source.file("package.json"))
.run(["bun", "install"], {
cache: [{ mountPath: "/root/.bun/install/cache", cache: cache("repo-agent-bun") }],
})
.run([
"sh",
"-ceu",
"apt-get update && apt-get install -y git ripgrep",
])
const sbx = sandbox("repo-agent")
.image(base)
.resources({ cpu: 2, memory: "4Gi" })
export const reviewPr = task({
id: "review-pr",
sandbox: sbx,
maxDuration: 900,
secrets: {
OPENAI_API_KEY: { env: "OPENAI_API_KEY" },
},
run: async (event: { prNumber: number }, ctx) => {
// Call your agent SDK or review tooling here.
const summary = await reviewPullRequest({
cwd: process.cwd(),
prNumber: event.prNumber,
token: process.env.OPENAI_API_KEY ?? "",
})
const decision = await ctx.wait.human<{ approved: boolean }>({
displayText: "Post this review to GitHub?",
})
if (decision.approved) {
await writeFile("review-summary.txt", `${summary}\n`)
}
},
})import { defineConfig } from "@helmr/sdk"
export default defineConfig({
project: "github-pr-review",
dirs: ["./tasks"],
})Tasks start in the checked-out workspace directory. Use relative paths for workspace files; absolute paths keep normal Linux container semantics.
See examples/ for deployable task projects, including dependency caching, CLI tooling, human input waitpoints, vault secrets, and GitHub PR review flows.
Remote runs execute a deployed task with an empty writable workspace:
helmr deploy PATH/TO/TASK_PROJECT
helmr run review-pr \
--payload-json '{"owner":"OWNER","repo":"REPO","prNumber":123}' \
--secret OPENAI_API_KEY=vault:OPENAI_API_KEYIf a task needs repository files, clone or fetch them from inside the task using payload fields and declared secrets. Helmr keeps the runtime substrate generic; GitHub is a task integration, not a required run source.
Payload is audit data. Helmr persists it in plaintext in the database, run events, and event streams. Do not put tokens, API keys, credentials, or sensitive personal data in payloads.
Tasks declare where secrets appear inside the guest, such as an environment variable. Remote runs bind those declarations to vault references:
printf '%s' "$OPENAI_API_KEY" | helmr secret set OPENAI_API_KEY
helmr run my-task --secret OPENAI_API_KEY=vault:OPENAI_API_KEYRemote runs reject local-only secret sources such as env: and file:.
Checkpoint artifacts are encrypted before leaving the worker staging directory.
Workers require HELMR_CHECKPOINT_ENCRYPTION_KEY, a base64-encoded 32-byte key.
Use the same key for workers that must restore the same checkpoint state:
head -c 32 /dev/urandom | base64Common local checks:
make test
make lint
make build
bun run typecheckCI parity and platform-specific checks:
nix flake check
nix run .#ci-checks
nix run .#ci-postgres
nix run .#ci-buildkit
make test-linux-compileLinux Firecracker smoke tests need a Linux host with KVM:
nix run .#smoke-linux- SDK - TypeScript SDK and runtime client notes
- Runtime - guest-side runtime adapter responsibilities
- Examples - runnable task projects
- AWS infrastructure - self-hosted AWS modules and dev smoke flow
- Scripts - maintenance and CI helper entrypoints
- Images - guest boot artifact recipes
- Proto - protocol definitions and generated bindings
Licensed under the Apache License, Version 2.0. See LICENSE.