build
build
¶
Container image building and build-context staging.
Owns the L0 (base dev) and L1 (agent CLI) Dockerfile templates, resource
staging, image naming, and podman build invocation.
Image layer architecture::
L0 (base) — Ubuntu + dev tools + init script + dev user
L1 (agent) — All AI agent CLIs, shell environment, ACP wrappers
L1 is self-sufficient for standalone use — all user
config (repo URL, SSH, branch, gate) is runtime.
─── boundary: above owned by terok-agent, below by terok ───
L2 (project)— Optional: user Dockerfile snippet (custom packages)
Only built when project has docker snippet config.
terok-agent run claude . launches directly on the L1 image — no L2
build needed. terok adds L2 only for project-specific image customisation.
Usage as a library::
from terok_agent.build import build_base_images
images = build_base_images("ubuntu:24.04")
# images.l0 = "terok-l0:ubuntu-24.04"
# images.l1 = "terok-l1-cli:ubuntu-24.04"
The templates currently use Dockerfile ARG/${VAR} syntax.
Jinja2 is wired in for future use — converting L1 install blocks to
registry-driven {% for agent %} loops.
DEFAULT_BASE_IMAGE = 'ubuntu:24.04'
module-attribute
¶
Default base OS image when none is specified.
BuildError
¶
Bases: RuntimeError
Raised when base-image construction cannot complete.
The CLI maps this to a user-facing error message; library callers
can catch it without being terminated by SystemExit.
ImageSet(l0, l1, l1_sidecar=None)
dataclass
¶
L0 + L1 image tags produced by a build.
l0_image_tag(base_image)
¶
l1_image_tag(base_image)
¶
l1_sidecar_image_tag(base_image)
¶
stage_scripts(dest)
¶
Stage container helper scripts into dest.
Copies all files from terok_agent/resources/scripts/ into the given
directory, replacing any existing contents. Python bytecode caches and
__init__.py markers are excluded.
Source code in src/terok_agent/build.py
stage_toad_agents(dest)
¶
Stage Toad ACP agent TOML definitions into dest.
These describe OpenCode-based agents (Blablador, KISSKI, etc.) that are injected into Toad's bundled agent directory at container build time.
Source code in src/terok_agent/build.py
stage_tmux_config(dest)
¶
Stage the container tmux configuration into dest.
Copies container-tmux.conf — the green-status-bar config that
distinguishes container tmux sessions from host tmux.
Source code in src/terok_agent/build.py
render_l0(base_image=DEFAULT_BASE_IMAGE)
¶
Render the L0 (base dev) Dockerfile.
The base_image is normalised before rendering so that blank or whitespace-only values produce a valid Dockerfile.
Source code in src/terok_agent/build.py
render_l1(l0_image, *, cache_bust='0')
¶
Render the L1 (agent CLI) Dockerfile.
l0_image is the tag of the L0 image to build on top of. cache_bust invalidates the agent-install layers when changed (typically set to a Unix timestamp).
Source code in src/terok_agent/build.py
render_l1_sidecar(l0_image, *, tool_name='coderabbit', cache_bust='0')
¶
Render the L1 sidecar (tool-only) Dockerfile.
The sidecar image is built FROM L0 (not L1) and installs a single tool binary — no agent CLIs, no LLMs. The tool_name selects which tool install block to activate via Jinja2 conditional.
Source code in src/terok_agent/build.py
prepare_build_context(dest)
¶
Stage auxiliary resources into a build context directory.
After calling this, dest contains the resources that Dockerfile
COPY directives reference:
scripts/— container helper scripts (init, env, ACP wrappers)toad-agents/— ACP agent TOML definitionstmux/— container tmux config
Dockerfiles themselves are not written here — they are rendered
and placed by :func:build_base_images (which calls this function
internally).
Source code in src/terok_agent/build.py
build_base_images(base_image=DEFAULT_BASE_IMAGE, *, rebuild=False, full_rebuild=False, build_dir=None)
¶
Build L0 + L1 container images and return their tags.
Skips building if images already exist locally (unless rebuild or full_rebuild is set). Uses a temporary directory for the build context by default; pass build_dir to use a specific (empty or non-existent) directory instead.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
base_image
|
str
|
Base OS image (e.g. |
DEFAULT_BASE_IMAGE
|
rebuild
|
bool
|
Force rebuild with cache bust (refreshes agent installs). |
False
|
full_rebuild
|
bool
|
Force rebuild with |
False
|
build_dir
|
Path | None
|
Build context directory (must be empty or absent). |
None
|
Returns:
| Type | Description |
|---|---|
ImageSet
|
class: |
Raises:
| Type | Description |
|---|---|
BuildError
|
If podman is missing or a build step fails. |
ValueError
|
If build_dir exists and is non-empty. |
Source code in src/terok_agent/build.py
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 | |
build_sidecar_image(base_image=DEFAULT_BASE_IMAGE, *, tool_name='coderabbit', rebuild=False, full_rebuild=False, build_dir=None)
¶
Build the L1 sidecar image for a specific tool. Returns the image tag.
Ensures L0 exists first (builds it if missing), then builds the sidecar image FROM L0. The sidecar contains only the named tool — no agent CLIs, no LLMs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
base_image
|
str
|
Base OS image (passed through to L0 build). |
DEFAULT_BASE_IMAGE
|
tool_name
|
str
|
Tool to install (selects Jinja2 conditional in template). |
'coderabbit'
|
rebuild
|
bool
|
Force rebuild with cache bust. |
False
|
full_rebuild
|
bool
|
Force rebuild with |
False
|
build_dir
|
Path | None
|
Build context directory (must be empty or absent). |
None
|
Returns:
| Type | Description |
|---|---|
str
|
The sidecar image tag (e.g. |
Raises:
| Type | Description |
|---|---|
BuildError
|
If podman is missing or a build step fails. |