Config in code (Starlark)
Use tarjan.star for loops, conditionals and computed values.
YAML is the default and right for most setups. When a config has logic —
many near-identical services, per-environment conditionals, computed ports/URLs
— write tarjan.star in Starlark (a
small, sandboxed Python-like language) instead. It produces the same config,
so every feature works unchanged; the interpreter is pure Go, so tarjan stays a
single binary with no extra toolchain.
# N near-identical services become a loop, not N copy-pasted blocks
services = [
service(
name = "db",
docker = docker(image = "postgres:16", ports = ["5432:5432"]),
health = health(tcp = "localhost:5432"),
),
]
for i, name in enumerate(["catalog", "orders", "gateway"]):
services.append(service(
name = name,
workdir = name,
command = "go run ./cmd/server",
env = {"PORT": str(8080 + i)},
depends_on = ["db"],
restart = "on-failure",
))
tarjan = config(name = "shop", services = services, workspace = workspace(vscode = True))tarjan auto-detects tarjan.star (preferred) or tarjan.yaml. The builtins mirror the
YAML schema: config, repo, tool, service, docker, health, watch,
hooks, remote, workspace. Keyword arguments are snake_case (e.g.
depends_on, min_version, identity_file). Pass remotes = {...} to
config(...) and remote = "name" to service(...) to run a service on a
remote target. The script must assign its result to a top-level
tarjan. tarjan reload works with Starlark too.