Configuration reference
This is the per-key reference for config.toml. The annotated config.toml.example
at the root of the Takuto Core repository is the source of truth —
when this page and that file disagree, the example wins.
Settings are reloaded on file change (a 5-second poller). A few keys are
startup-only and need a restart (noted inline). Secrets belong in takuto.env,
never in config.toml — see Environment variables.
Takuto Core splits config into two kinds:
- Bootstrap — needed before the database/dashboard exist, or applied only at
startup. Hand-edit these in
config.tomlbefore the first boot. - UI-managed — has a sane default and is normally edited from a dashboard
Configuration screen. The UI writes changes back to
config.toml, so the file stays the store; a value set here is only a deploy-time default.
The Scope column marks each key as Bootstrap or names the dashboard surface that manages it. 🔒 marks security-sensitive keys — review before changing in a shared deployment.
[general]
Process-wide behaviour: ticketing mode, polling, concurrency, logging.
| Key | Default | Type | Scope | Description |
|---|---|---|---|---|
ticketing_system | "none" | string | Bootstrap | "jira", "github", or "none". Drives the poller and the dashboard + button. |
dry_mode 🔒 | false | bool | Bootstrap | Skip real Jira/GitHub side effects (no assigns, transitions, or pushes). Local work — worktrees, installs, agent sessions — still runs. Useful for staging a workflow definition before going live. |
log_level | "info" | string | Bootstrap (restart) | trace, debug, info, warn, error. |
worker_image | "" | string | Bootstrap | Docker image for isolated workflow containers when DinD is enabled. Empty = auto-detect from the running Takuto image. |
workflow_definitions_dir | "workflows" | string | Bootstrap (restart) | Path scanned for the *.toml workflows that seed the defaults for a new user/workspace. Live workflows are edited in the dashboard (Configuration → Workflows); editing the TOML later does not change already-seeded workspaces. |
allow_auto_generate_secret_key 🔒 | true | bool | Bootstrap | When true, the server auto-generates {data_dir}/secret.key on first boot if no key is present. Set false to provision the key out of band. |
poller_owner_username | (unset) | string | Bootstrap | Username that owns workflows created automatically by the poller. When unset, the lexicographically-first non-suspended admin is used. |
migrate_orphan_workflows | false | bool | Bootstrap | When true, restored workflows with no owner (pre-multi-user orphans) are reassigned to the resolved poller owner at startup. |
migrate_orphan_repo_associations | true | bool | Bootstrap | When true, startup reconciliation links restored workflows to their matching registered repository. |
poll_interval_secs | 60 | int | UI: Item Polling | Seconds between Jira/GitHub polls. |
pr_merge_poll_interval_secs | 60 | int | UI: Item Polling | Seconds between polls checking whether a workflow’s PR has merged on GitHub. 0 disables. |
max_concurrent_workflows | 1 | int | UI: Item Polling | Semaphore size for parallel mise/install/agent sessions. Tune to your CPU and RAM. |
max_active_workflows | 0 | int | UI: Item Polling | Max workflows visible on the dashboard (every row). The poller will not start new tickets at this limit. 0 mirrors max_concurrent_workflows. |
max_concurrent_manual_workflows | 0 | int | UI: Item Polling | Cap on dashboard + manual starts that are not Done/Stopped/Error. 0 = no limit. |
max_parallel_per_user | false | bool | UI: Item Polling | When true, the per-repository parallel-item cap is counted per workflow owner; false counts it globally. |
generate_report | false | bool | UI: Item Polling | When true, each agent step appends findings to a report and a final step consolidates them. Adds tokens. |
work_item_log_retention_days | 7 | int | UI: Item Polling | Days of work-item log lines to retain before cleanup. 0 = keep forever. |
[jira]
Only used when [general] ticketing_system = "jira".
| Key | Default | Type | Scope | Description |
|---|---|---|---|---|
site | "" | string | Bootstrap | Jira host or full https:// URL (e.g. "yourcompany.atlassian.net"). Drives token auth, egress allowlist, and PR-body Jira link. |
email | "" | string | Bootstrap | Fallback Jira account email — used for the owner/acli token only when a user has not added their own Jira token. Otherwise reads and writes go through each user’s own Jira REST token. |
done_status | "Done" | string | UI: Item Polling | Status that Mark as Done transitions the ticket to. Matched language-independently (by statusCategory), so a localized name like “Terminé(e)” still resolves to “Done”; on failure the error lists the available statuses. |
linked_items_in_prompt | "full" | string | UI: Item Polling | "full" | "summary_only" | "omit" — how linked-issue text appears in {ticket_context}. |
ticket_context_max_description_bytes | 0 | int | UI: Item Polling | Cap on the main ticket description in {ticket_context}. 0 = unlimited (the default). |
linked_issue_description_max_bytes | 0 | int | UI: Item Polling | Cap per linked-issue description when linked_items_in_prompt = "full". 0 = unlimited (the default). |
Now per-user, per-repository: each user’s Jira token (added in Configuration → Ticketing), plus project keys, item types, and the JQL filter — all moved out of
config.toml. The deployment owner token /acliis only a fallback for users who haven’t added their own.
[git]
All [git] keys are Bootstrap settings.
| Key | Default | Type | Scope | Description |
|---|---|---|---|---|
base_branch | "main" | string | Bootstrap | Branch each worktree is created from. |
remote | "origin" | string | Bootstrap | Git remote used for fetch, base ref, and push. |
repo_path | "/workspace" | string | Bootstrap | Path to the cloned repo inside the container. The workspace name is derived from this path’s last component. |
[github]
Optional GitHub App authentication. When configured, commits and PRs are attributed to
the bot account instead of your personal gh user. All three fields (app_id,
app_installation_id, and one private-key source) must be set together; errors are
non-fatal — Takuto Core falls back to personal gh auth and logs a warning. Required
App permissions: contents (write), pull_requests (write), metadata (read).
| Key | Default | Type | Scope | Description |
|---|---|---|---|---|
app_id | (unset) | int | Bootstrap | GitHub App ID. |
app_installation_id | (unset) | int | Bootstrap | App installation ID for your org/repo. |
app_private_key 🔒 | (unset) | string | Bootstrap | PEM-encoded RSA private key, inline. Mutually exclusive with app_private_key_path. Prefer keeping this in takuto.env. |
app_private_key_path 🔒 | (unset) | string | Bootstrap | Path to a PEM file with the App’s private key. |
[web]
The dashboard server.
| Key | Default | Type | Scope | Description |
|---|---|---|---|---|
host | "0.0.0.0" | string | Bootstrap (restart) | Bind address. |
port | 8080 | int | Bootstrap (restart) | Bind port. |
cors_origins 🔒 | [] | array | Bootstrap (restart) | Allowed CORS origins. Empty = auto-compute from host/port. Set explicitly behind a reverse proxy or TLS terminator (e.g. ["https://takuto.example.com"]). |
cookie_secure 🔒 | (auto-detect) | bool | Bootstrap | Controls the Secure flag on the session cookie. Auto-detected from https:// cors_origins or an inbound X-Forwarded-Proto: https. Force true when terminating TLS without that header; false for local plain-HTTP testing only. |
kick_other_sessions_on_login | true | bool | Bootstrap | When true, a successful login deletes prior sessions for the same user. Set false for concurrent desktop + mobile sessions. |
Authentication is multi-user only. On first boot the dashboard prompts you to create the initial admin account. The legacy single-user keys
[web] dashboard_username/dashboard_passwordhave been removed — if present in an oldconfig.tomlthey are silently ignored.
Session policies (not configurable): idle TTL 24 h; absolute TTL 30 days; account
lockout after 5 failed login/recovery attempts in 10 min (admin clears via
POST /api/users/{id}/unlock); per-IP rate limit on /api/auth/login and
/api/auth/recover of 10 / minute.
[database]
Where Takuto stores users, sessions, and snapshots. Omit the section (or leave
connection empty) to keep the zero-config SQLite default at {data_dir}/takuto.db.
Set connection to use an external PostgreSQL / MariaDB / MySQL. Restart-only —
PUT /api/config does not patch this section; backend changes need a process restart.
| Key | Default | Type | Scope | Description |
|---|---|---|---|---|
connection 🔒 | "" | string | Bootstrap (restart) | Database URL. Empty → SQLite. Schemes: sqlite://…, postgres://… / postgresql://…, mysql://… (also covers MariaDB). The password is redacted in GET /api/config. |
local_container | (unset) | bool | Bootstrap (CLI) | CLI-only. Marks connection as a host-facing URL (e.g. localhost:5433) for a database container on this machine. On takuto start the CLI finds that container, attaches it to Takuto’s network as takuto_db, and rewrites the connection. The engine ignores this key. See External database. |
max_connections | 10 | int | Bootstrap (restart) | Connection pool size. |
acquire_timeout_secs | 30 | int | Bootstrap (restart) | How long to wait for a pooled connection before timing out. |
idle_timeout_secs | 600 | int | Bootstrap (restart) | Idle connection lifetime. |
fail_fast 🔒 | true | bool | Bootstrap (restart) | When true, a 5 s SELECT 1 probe runs at startup and aborts if the backend is unreachable. When false, it logs a warning and falls back to local SQLite for that process. |
import_from_sqlite | true | bool | Bootstrap (restart) | On first connect to a fresh external backend, one-shot copy of existing local SQLite data into it (sessions are expired, so users re-authenticate). Skipped on later restarts. |
Running the database in a container? With the CLI, set
local_container = trueand give thelocalhostURL you’d use from your host —takuto startwires it onto Takuto’s network for you. Running the engine directly, theconnectionhost must be reachable from inside the Takuto container — use the database container name and its internal port (e.g.takuto_db:5432), notlocalhostor the host-published port. The full walkthrough is in External database.
[agent]
The AI provider for prompt-bearing workflow steps. Every [agent] key is UI-managed
from Configuration → AI Settings; the values here are deploy-time defaults.
| Key | Default | Type | Scope | Description |
|---|---|---|---|---|
provider | "claude" | string | UI: AI Settings | "claude", "cursor", "codex", or "opencode". Each reads its own [agent.providers.<name>] sub-table. |
available_providers | all four | array | UI: AI Settings | Providers users may authenticate against and switch between. Also determines which agent CLIs are installed at startup and which provider hosts the egress firewall clears — trim it to narrow both. |
step_timeout_secs | 1800 | int | UI: AI Settings | Per-step timeout in seconds. Applies to all providers. |
improve_timeout_secs | 300 | int | UI: AI Settings | Timeout in seconds for the AI description-refinement (“improve”) action. |
share_conversation_across_steps | false | bool | UI: AI Settings | Share one agent conversation across a flow’s steps vs. a fresh session per step. |
max_repeated_output_lines | 8 | int | UI: AI Settings | No-progress guardrail. Abort a step when its output repeats the same substantive line this many times in a row. 0 disables. |
Per-provider settings (model, endpoint, CLI path, extra args) live in
[agent.providers.<name>] sub-tables. Common fields: model, extra_args,
allow_shared_default; Claude/Codex/OpenCode use base_url, Cursor uses cli.
Agent CLI installation & version pinning
Agent CLIs are installed at first startup, not baked into the image. Takuto
installs the CLI (claude / codex / opencode / cursor) into the shared tools volume
the first time a container starts, for each provider in available_providers.
By default each CLI is installed (and refreshed) to latest on every start. To pin a
specific version, set version in that provider’s sub-table:
[agent.providers.claude]
version = "2.1.178" # omit or leave empty to track latest
[agent.providers.codex]
version = "0.9.4"
version value | Behavior |
|---|---|
"2.1.178" (a specific version) | Installs that exact version; never auto-upgrades. |
"" or omitted | Installs/refreshes latest on every container start. |
Pinning works for all four agent providers (claude, codex, opencode, cursor).
The Atlassian CLI (
acli) is installed too, but Atlassian serves onlylatest, so its[jira] acli_versionpin is advisory — latest is always installed.
[agent.providers.cursor]
Used only when provider = "cursor".
| Key | Default | Type | Scope | Description |
|---|---|---|---|---|
cli | "agent" | string | UI: AI Settings | Cursor Agent executable name or absolute path. |
model | "Auto" | string | UI: AI Settings | Cursor Agent --model. "Auto" or empty = automatic selection. |
privacy_mode | true | bool | UI: AI Settings | Cursor’s privacy mode. Left on (true), Cursor does not retain or train on your code. Set it to false only if your Cursor plan and policy allow it — doing so relaxes those guarantees and sends your code to Cursor under their standard data terms. |
extra_args | [] | array | UI: AI Settings | Extra CLI flags (deny-list enforced). |
[agent.providers.opencode]
The OpenCode (self-hosted, OpenAI-compatible) adapter. Used only when
provider = "opencode". See Self-hosted models.
| Key | Default | Type | Scope | Description |
|---|---|---|---|---|
model | "" | string | UI: AI Settings | Model id served by the endpoint (the <model> in -m self_hosted/<model>). Required when active. |
base_url | "" | string | UI: AI Settings | OpenAI-compatible endpoint URL (e.g. http://lm-studio:1234/v1). Required when active. |
extra_args | [] | array | UI: AI Settings | Extra CLI flags (deny-list enforced). |
allow_shared_default | false | bool | UI: AI Settings | Let users without a personal bearer fall back to the deployment-default token. |
context_limit | 32768 | int | UI: AI Settings | Max context window (tokens) of the self-hosted model. Match your server’s loaded context length. |
output_limit | 8192 | int | UI: AI Settings | Max output tokens per response. |
Claude and Codex use their own
[agent.providers.claude]/[agent.providers.codex]sub-tables withmodel,base_url, andextra_args, all editable from Configuration → AI Settings.
[docker]
All [docker] keys are Bootstrap (consumed at image build / compose up).
| Key | Default | Type | Scope | Description |
|---|---|---|---|---|
build_commands | [] | array | Bootstrap | Optional bash -c steps run during image build. |
compose_up_commands | [] | array | Bootstrap | Optional commands run as the takuto user after preflight on every docker compose up. |
[editor]
The in-browser VS Code (openvscode-server) and dynamic port forwarding. All [editor]
keys are Bootstrap.
| Key | Default | Type | Scope | Description |
|---|---|---|---|---|
ports | [] | array | Bootstrap | Application ports to expose when opening the editor (e.g. [3000, 5173, 6006]). Each maps to a host port from the range 9100–9200 and shows on the workflow card. |
dynamic_ports | 10 | int | Bootstrap | Spare ports pre-allocated for automatic dev-server forwarding. 0 disables. |
theme | "" | string | Bootstrap | VS Code colour theme; empty uses the editor’s own default (e.g. "One Dark Pro"). |
extensions | [] | array | Bootstrap | Marketplace IDs to pre-install (e.g. ["esbenp.prettier-vscode"]). |
settings | {} | table | Bootstrap | Free-form VS Code settings under [editor.settings]. |
[terminal]
The web terminal (ttyd) inside the editor container. All [terminal] keys are
Bootstrap.
| Key | Default | Type | Scope | Description |
|---|---|---|---|---|
git_editor | (unset) | string | Bootstrap | apt package (e.g. "nano", "vim") installed in every editor container; git config core.editor is set to it. |
setup_commands | [] | array | Bootstrap | Shell commands run once per editor container lifetime (guarded by a marker file). |
startup_commands | [] | array | Bootstrap | Shell commands run every time a fresh editor container is created. |
[network]
Firewall policy — deploy-time only. All [network] keys are Bootstrap.
The allowlist is provider-aware: the firewall automatically clears the API
hosts of the AI provider(s) you enable — the active [agent].provider plus
every provider in [agent].available_providers (Claude, Codex/OpenAI, Cursor),
and any self-hosted base_url. With the default config (all four providers
available) every supported vendor is reachable out of the box; trim
available_providers to narrow the firewall to just the providers you use. The
exact hosts are resolved at apply time by the core’s takuto egress-hosts command.
| Key | Default | Type | Scope | Description |
|---|---|---|---|---|
extra_egress_hosts 🔒 | [] | array | Bootstrap | Domains added to the egress allowlist on top of the built-in defaults (your AI providers, Atlassian, GitHub, npm registry, registries detected in .npmrc). Each entry expands the attack surface — only add hosts you trust the agent to reach. |
allow_all_https 🔒 | false | bool | Bootstrap | When true, skip the allowlist and permit all outbound HTTPS (443/8443). extra_egress_hosts is ignored. Use only in trusted environments — this disables one of Takuto Core‘s core mitigations. |
[provisioning]
Extra CLI tools installed into the shared tools volume at startup, on top of the ones baked into the image. Use it to pin a tool version, add a tool that was removed from the bake, or skip one entirely. Bootstrap (applied at startup). See Extending Takuto Core.
| Key | Default | Type | Scope | Description |
|---|---|---|---|---|
install_commands | [] | array | Bootstrap | Shell snippets run in order against the tools volume. SHA-gated: re-runs only when the list changes. Each snippet should be idempotent and install into $TAKUTO_TOOLS_BIN. |
[dev]
Dev-only knobs. Leave commented out in production. All [dev] keys are Bootstrap.
| Key | Default | Type | Scope | Description |
|---|---|---|---|---|
mock_agent | false | bool | Bootstrap | When true, agent sessions short-circuit into a scripted mock — no real claude/agent process, no tokens consumed. Honors TAKUTO_DEV_MOCK_AGENT=1. |
mock_agent_script_path | (unset) | string | Bootstrap | Path to the mock script file. No default — tmp/mock_script.txt is only the suggested example. |
mock_agent_line_delay_ms | 75 | int | Bootstrap | Delay between mock output lines. |
mock_agent_total_ms | 5000 | int | Bootstrap | Total mock session duration. |
Ignored sections
The following sections are fully ignored at load — a startup warning is logged so
you notice, but their contents are never read. They moved out of config.toml because
they are per-user and per-workspace, and now live only in the database, edited from the
dashboard:
[commands]— worktree initialisation commands (formerlypre_install,install,pre_workflow, nowworktree_init_commands) live in the database, resolved per(user, workspace)and edited from Configuration → Worktree Settings.[[run_commands]]— long-running dev-server commands surfaced as run/stop buttons are per-user and configured from the same Worktree Settings tab.[polling](and[polling.jira]/[polling.github]) — polling filters, auto-start flow, and the per-repo parallel-item cap are per-user, per-repository, set in Configuration → Ticketing. Deployment-wide limits stay in[general].[jira] project_keys/item_types/jql_filter— also per-user, per-repository (same Ticketing tab).[general] auto_polling— polling is enabled per repository now; the dashboard’s Pause/Resume control is the global master switch.
For [commands] / [[run_commands]] there is no config fallback: if a section is absent
from the database, the workflow simply runs no commands for it.
Environment variables
Secrets and per-host overrides go in takuto.env (mounted at /etc/takuto/env).
Only export VAR=value lines are honoured.
| Variable | Purpose |
|---|---|
ANTHROPIC_API_KEY 🔒 | Claude API key — required for the headless pipeline (Anthropic no longer accepts Pro/Max OAuth unattended). |
ANTHROPIC_BASE_URL | Override the Anthropic API endpoint (proxy / on-prem gateway). |
CLAUDE_CODE_OAUTH_TOKEN 🔒 | Token from an interactive claude login. Not usable for the unattended headless pipeline — use ANTHROPIC_API_KEY there. |
CURSOR_API_KEY 🔒 | Cursor Agent key — skips the interactive agent status preflight. |
GH_TOKEN 🔒 | GitHub PAT (fine-grained, scoped to the target repo). |
TAKUTO_CONFIG | Path to an alternate config.toml. |
TAKUTO_DATA_DIR | Override the persistent data directory (takuto.db, snapshots). |
TAKUTO_HOME | Override the home base used to compute TAKUTO_DATA_DIR. |
TAKUTO_DEV_MOCK_AGENT | 1 = force the mock agent on (overrides [dev] mock_agent). |
Example takuto.env:
export ANTHROPIC_API_KEY="sk-ant-..."
export GH_TOKEN="github_pat_..."
export ANTHROPIC_BASE_URL="https://custom-proxy.example.com/claude"