Kitaru
Guides

Configuration

Kitaru config directory, execution defaults, environment variables, and precedence

This guide covers Kitaru's configuration system: where settings live on disk, how to set execution defaults, how headless environments are bootstrapped, and how precedence is resolved.

Config directory

Kitaru stores all of its state — settings, database, credentials, and local stores — in a single directory. By default this is your platform's standard application config directory:

Linux:   ~/.config/kitaru/
macOS:   ~/Library/Application Support/kitaru/
Windows: %APPDATA%\\kitaru\\

Inside that directory you will find:

kitaru.yaml    # Log-store, model aliases, and other Kitaru settings
config.yaml    # Internal runtime configuration (managed automatically)
local_stores/  # SQLite database and local artifact storage

You can see the active config directory by running kitaru status or kitaru info.

If you want to relocate that directory, set:

export KITARU_CONFIG_PATH=/app/.kitaru

This moves everything — settings, database, and credentials — to the new location. Kitaru reads that path immediately, but it only creates the directory on first write.

Configure runtime defaults in Python

Use kitaru.configure(...) to set process-local defaults:

import kitaru

kitaru.configure(
    stack="local",
    cache=False,
    retries=1,
    image=kitaru.ImageSettings(
        base_image="python:3.12-slim",
        environment={"OPENAI_API_KEY": "{{ OPENAI_KEY }}"},
    ),
)

These defaults apply to flows started in the current Python process.

Flow-level and invocation-level overrides

Flow defaults can override configured runtime defaults, and invocation-time arguments can override both.

from kitaru import flow

@flow(cache=True, retries=2, stack="gpu-cluster")
def my_flow(topic: str) -> str:
    ...

handle = my_flow.run("kitaru", retries=3, stack="prod-cluster")

In this example, resolved retries are 3, and the execution runs on prod-cluster for that one submission.

The important distinction is:

  • kitaru.configure(stack="...") sets a process-local default
  • @flow(stack="...") sets a default for one flow definition
  • my_flow.run(stack="...") overrides both for one execution
  • none of those change the persisted active stack selected by kitaru stack use ...

Environment variables

Kitaru's public env-var surface uses KITARU_* names.

Connection

These are the key env vars for non-interactive setup:

  • KITARU_SERVER_URL
  • KITARU_AUTH_TOKEN
  • KITARU_PROJECT

For normal interactive use:

  • kitaru login starts and connects to a local server
  • kitaru login <server> connects to a remote server

The KITARU_* connection variables are mainly for Docker, CI, and other headless environments.

Use them together for Docker, CI, or any other headless environment:

export KITARU_SERVER_URL=https://my-server.example.com
export KITARU_AUTH_TOKEN=kat_abc123...
export KITARU_PROJECT=my-project

There are two guardrails:

  1. KITARU_SERVER_URL and KITARU_AUTH_TOKEN must be set together.
  2. If a remote server is configured via env vars, KITARU_PROJECT is required at first use (KitaruClient(), my_flow.run(), replay, etc.).

Internally, Kitaru translates these public env vars into the ZenML env vars the runtime already understands. That means you should configure KITARU_*, not ZENML_*, in normal Kitaru docs and examples.

Execution

Execution settings:

  • KITARU_STACK
  • KITARU_CACHE
  • KITARU_RETRIES
  • KITARU_IMAGE (JSON object or plain image string)

LLM

  • KITARU_DEFAULT_MODEL sets the default model for kitaru.llm() when no explicit model= argument is provided.
  • KITARU_LLM_MOCK_RESPONSE remains available for tests and demos.

KITARU_DEFAULT_MODEL first tries local alias lookup. If the value is not a registered alias, Kitaru passes it straight through as a raw LiteLLM model string. This lookup happens before Kitaru falls back to the locally configured default alias.

If you want the full secret-backed setup path for kitaru.llm(), see Secrets + Model Registration.

Housekeeping

  • KITARU_CONFIG_PATH
  • KITARU_DEBUG
  • KITARU_ANALYTICS_OPT_IN

kitaru status

kitaru status shows an Environment section when KITARU_* vars are active. Secret values such as KITARU_AUTH_TOKEN and KITARU_LOG_STORE_API_KEY are masked.

Precedence (highest to lowest)

  1. Invocation-time overrides (my_flow.run(..., stack="prod"))
  2. Flow decorator defaults (@flow(stack="prod"))
  3. kitaru.configure(...)
  4. Environment variables (KITARU_STACK, KITARU_SERVER_URL, etc.)
  5. Project config (pyproject.toml under [tool.kitaru])
  6. Persisted active stack fallback plus global user config (for example connection defaults)
  7. Built-in defaults (cache=True, retries=0)

In practice, stack starts unset in the built-in defaults and is then resolved from the persisted active stack when one is available.

For connection-specific resolution, Kitaru uses this lower-to-higher order:

  1. Persisted global connection (kitaru login)
  2. Direct ZENML_* env vars for compatibility
  3. KITARU_* env vars
  4. Runtime overrides from kitaru.configure(...)

Project config in pyproject.toml

[tool.kitaru]
stack = "prod"
cache = false
retries = 2

[tool.kitaru.image]
base_image = "python:3.12-slim"

[tool.kitaru.image.environment]
OPENAI_API_KEY = "{{ OPENAI_KEY }}"

Automatic package injection

Kitaru automatically adds itself to the container image requirements for remote execution when Kitaru is assembling the image from requirements. You usually do not need to add kitaru to your requirements list manually.

If you specify your own requirements, Kitaru appends itself without duplicating:

kitaru.configure(
    image=kitaru.ImageSettings(
        requirements=["httpx", "pydantic"],
    ),
)
# Remote container installs: httpx, pydantic, kitaru

If you already include kitaru (with or without a version pin), it is not added again:

kitaru.configure(
    image=kitaru.ImageSettings(
        requirements=["kitaru>=0.2.0", "httpx"],
    ),
)
# Remote container installs: kitaru>=0.2.0, httpx (no duplicate)

If you specify a custom base_image or dockerfile, you control the image contents yourself. In that case, Kitaru does not auto-inject the SDK, so your image must already include kitaru.

Replicating your local environment

During development, you can replicate your entire local Python environment into the remote container. This installs all locally installed packages (via pip freeze) so the remote container matches your dev setup exactly:

from kitaru import flow

@flow(image={"replicate_local_python_environment": True})
def my_flow(topic: str) -> str:
    ...

System packages

If your flow needs system-level dependencies (e.g., git, ffmpeg), use apt_packages:

from kitaru import flow
import kitaru

@flow(
    image=kitaru.ImageSettings(
        apt_packages=["git", "ffmpeg"],
        requirements=["httpx"],
    ),
)
def my_flow(topic: str) -> str:
    ...

Project selection

There are really two different stories here:

  1. Persisted login / default setup — if you connect with kitaru login <server>, Kitaru can usually just follow the server-side default project and you do not need to think about it much.
  2. Env-driven remote bootstrap — if you connect with KITARU_SERVER_URL / KITARU_AUTH_TOKEN, then KITARU_PROJECT is required at first use.

Bare kitaru login is the local-server path instead: it does not use KITARU_SERVER_URL or KITARU_AUTH_TOKEN, and it warns instead of failing if those remote auth env vars are already set in your shell.

You can set the project explicitly with either:

  • Environment variable (preferred): KITARU_PROJECT=my-project
  • SDK call (advanced/internal): kitaru.configure(project="my-project")

configure(project=...) is an internal/testing escape hatch, not a normal user-facing setting. Prefer KITARU_PROJECT for standard usage.

When an explicit project override is set, it appears in kitaru info output as "Project override". It does not appear in kitaru status except as part of the raw Environment section when KITARU_PROJECT itself is active.

Headless / Docker / CI recipe

# Connection
export KITARU_SERVER_URL=https://my-server.example.com
export KITARU_AUTH_TOKEN=kat_abc123...
export KITARU_PROJECT=my-project

# Execution
export KITARU_STACK=my-remote-stack
export KITARU_CACHE=true
export KITARU_RETRIES=2

# LLM
export OPENAI_API_KEY=sk-...
export KITARU_DEFAULT_MODEL=openai/gpt-4o

# Observability
export KITARU_LOG_STORE_BACKEND=datadog
export KITARU_LOG_STORE_ENDPOINT=https://http-intake.logs.datadoghq.com
export KITARU_LOG_STORE_API_KEY=...

# Housekeeping
export KITARU_CONFIG_PATH=/app/.kitaru
export KITARU_DEBUG=false
export KITARU_ANALYTICS_OPT_IN=false

Compatibility note

Direct ZENML_* env vars still work because the underlying runtime understands them, but Kitaru docs use KITARU_* as the public interface.

Frozen execution spec

At flow start, Kitaru computes a fully resolved execution config and persists it with the execution metadata (kitaru_execution_spec). This keeps execution behavior stable even if config changes later.

Example in this repository

uv sync --extra local
uv run examples/basic_flow/flow_with_configuration.py
uv run pytest tests/test_phase10_configuration_example.py

For the broader catalog, see Examples.

On this page