Docs · Templates
Reproducible pods, one file.
A template is a blueprint for a pod - image, tools, repo, connectors, and secret-safety rules - so poddle up gives everyone the exact same environment.
Where they live
- Project -
.poddle/in your repo (checked in, shared with the team). - User -
~/.config/poddle/templates(your personal blueprints).
Use one
poddle up api --template api --identity work
poddle task "fix the failing e2e" --template api --identity workExamples
Compose from a shared base and specialize per project. These are the exact files the docs load - linted against the real parser on every build, so they're always valid.
The foundation .poddle/base.toml
Shared defaults every other template extends - image, size, harness, and safe egress. Put the common bits here and override per project.
# base — shared defaults other templates extend
image = "docker.io/library/debian:stable-slim"
size = "weak"
harness = "claude-code"
secret_scan = "warn"
egress = "redact"A service, built on base .poddle/api.toml
A Node backend that extends base: it clones the repo, installs deps on spin-up, brokers in GitHub and Postgres, and keeps cloud and SSH creds out of the pod.
extends = "base"
image = "docker.io/library/node:22"
size = "strong"
identity = "work"
repo = "git@github.com:acme/api.git"
env = { NODE_ENV = "development" }
setup = ["npm ci"]
connectors = ["github", "postgres-prod"]
# secret-safety
block_paths = ["~/.aws", "~/.ssh"]
secret_scan = "block"
egress = "redact"Data work, locked down .poddle/python-ml.toml
Strong compute, a read-only dataset mount, and egress blocked - the agent can work with your data but cannot send it anywhere.
extends = "base"
image = "docker.io/library/python:3.12"
size = "strong"
setup = [
"pip install -U uv",
"uv pip install --system -r requirements.txt",
]
# a read-only dataset mount — nothing writes back out
mounts = [{ host = "/srv/datasets", container = "/data", ro = true }]
# lock egress down while the agent has your data in the pod
egress = "block"For sensitive repositories .poddle/regulated.toml
Refuses to start if a mount carries a credential file, keeps host secrets out entirely, and blocks outbound leaks - the settings auditors ask about.
extends = "base"
identity = "work"
# host secrets never enter the pod
block_paths = ["~/.aws", "~/.ssh", "~/.config/gcloud", "~/.kube"]
# refuse to start if a mount carries a credential file
secret_scan = "block"
# no outbound leaks
egress = "block"Tuned for headless runs .poddle/nightly.toml
Built on api: it bursts to a strong pod for a poddle task and shrinks back after, so autonomous jobs get horsepower without paying for it while idle.
extends = "api"
identity = "work"
# burst to a strong pod for the run, shrink back to weak if the pod is kept
before_task = "strong"
after_task = "weak"Linted in CI
Every example on this page is parsed and resolved by poddle's own template loader in CI (TestDocExampleTemplates) - rejected if a key is misspelled or an extends chain is broken. What you copy is what the binary accepts.
Fields
| Key | Description |
|---|---|
extends | Inherit from another template - a name or a list. Later values win. |
image | Base container image. |
size | weak (2 vCPU / 4 GB) or strong (8 vCPU / 16 GB). |
harness | Coding-agent runtime (default claude-code). |
identity | Identity to authenticate the harness with. |
repo | Repository to clone into the pod (through a brokered connector). |
env | Environment variables (table). |
mounts | Host paths to mount - each { host, container, ro }. |
setup | Inline commands run once on spin-up. |
scripts | Script files run on spin-up. |
connectors | Connection names to broker into the pod. |
block_paths | Host paths that must never enter the pod. |
secret_scan | Scan mounts for credential files: off · warn (default) · block. |
egress | Broker egress redaction: redact (default) · block · off. |
before_task / after_task | Resize to this size before / after a poddle task run. |
The three that lock a pod down
block_paths, secret_scan, and egress are the safety trio. Set secret_scan = "block" and egress = "block" in a shared base, and every template that extends it inherits a pod that refuses to start on a stray credential file and cannot phone home.