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.toml before 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.

KeyDefaultTypeScopeDescription
ticketing_system"none"stringBootstrap"jira", "github", or "none". Drives the poller and the dashboard + button.
dry_mode 🔒falseboolBootstrapSkip 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"stringBootstrap (restart)trace, debug, info, warn, error.
worker_image""stringBootstrapDocker image for isolated workflow containers when DinD is enabled. Empty = auto-detect from the running Takuto image.
workflow_definitions_dir"workflows"stringBootstrap (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 🔒trueboolBootstrapWhen 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)stringBootstrapUsername that owns workflows created automatically by the poller. When unset, the lexicographically-first non-suspended admin is used.
migrate_orphan_workflowsfalseboolBootstrapWhen true, restored workflows with no owner (pre-multi-user orphans) are reassigned to the resolved poller owner at startup.
migrate_orphan_repo_associationstrueboolBootstrapWhen true, startup reconciliation links restored workflows to their matching registered repository.
poll_interval_secs60intUI: Item PollingSeconds between Jira/GitHub polls.
pr_merge_poll_interval_secs60intUI: Item PollingSeconds between polls checking whether a workflow’s PR has merged on GitHub. 0 disables.
max_concurrent_workflows1intUI: Item PollingSemaphore size for parallel mise/install/agent sessions. Tune to your CPU and RAM.
max_active_workflows0intUI: Item PollingMax 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_workflows0intUI: Item PollingCap on dashboard + manual starts that are not Done/Stopped/Error. 0 = no limit.
max_parallel_per_userfalseboolUI: Item PollingWhen true, the per-repository parallel-item cap is counted per workflow owner; false counts it globally.
generate_reportfalseboolUI: Item PollingWhen true, each agent step appends findings to a report and a final step consolidates them. Adds tokens.
work_item_log_retention_days7intUI: Item PollingDays of work-item log lines to retain before cleanup. 0 = keep forever.

[jira]

Only used when [general] ticketing_system = "jira".

KeyDefaultTypeScopeDescription
site""stringBootstrapJira host or full https:// URL (e.g. "yourcompany.atlassian.net"). Drives token auth, egress allowlist, and PR-body Jira link.
email""stringBootstrapFallback 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"stringUI: Item PollingStatus 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"stringUI: Item Polling"full" | "summary_only" | "omit" — how linked-issue text appears in {ticket_context}.
ticket_context_max_description_bytes0intUI: Item PollingCap on the main ticket description in {ticket_context}. 0 = unlimited (the default).
linked_issue_description_max_bytes0intUI: Item PollingCap 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 / acli is only a fallback for users who haven’t added their own.

[git]

All [git] keys are Bootstrap settings.

KeyDefaultTypeScopeDescription
base_branch"main"stringBootstrapBranch each worktree is created from.
remote"origin"stringBootstrapGit remote used for fetch, base ref, and push.
repo_path"/workspace"stringBootstrapPath 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).

KeyDefaultTypeScopeDescription
app_id(unset)intBootstrapGitHub App ID.
app_installation_id(unset)intBootstrapApp installation ID for your org/repo.
app_private_key 🔒(unset)stringBootstrapPEM-encoded RSA private key, inline. Mutually exclusive with app_private_key_path. Prefer keeping this in takuto.env.
app_private_key_path 🔒(unset)stringBootstrapPath to a PEM file with the App’s private key.

[web]

The dashboard server.

KeyDefaultTypeScopeDescription
host"0.0.0.0"stringBootstrap (restart)Bind address.
port8080intBootstrap (restart)Bind port.
cors_origins 🔒[]arrayBootstrap (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)boolBootstrapControls 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_logintrueboolBootstrapWhen 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_password have been removed — if present in an old config.toml they 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.

KeyDefaultTypeScopeDescription
connection 🔒""stringBootstrap (restart)Database URL. Empty → SQLite. Schemes: sqlite://…, postgres://… / postgresql://…, mysql://… (also covers MariaDB). The password is redacted in GET /api/config.
local_container(unset)boolBootstrap (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_connections10intBootstrap (restart)Connection pool size.
acquire_timeout_secs30intBootstrap (restart)How long to wait for a pooled connection before timing out.
idle_timeout_secs600intBootstrap (restart)Idle connection lifetime.
fail_fast 🔒trueboolBootstrap (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_sqlitetrueboolBootstrap (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 = true and give the localhost URL you’d use from your host — takuto start wires it onto Takuto’s network for you. Running the engine directly, the connection host must be reachable from inside the Takuto container — use the database container name and its internal port (e.g. takuto_db:5432), not localhost or 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.

KeyDefaultTypeScopeDescription
provider"claude"stringUI: AI Settings"claude", "cursor", "codex", or "opencode". Each reads its own [agent.providers.<name>] sub-table.
available_providersall fourarrayUI: AI SettingsProviders 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_secs1800intUI: AI SettingsPer-step timeout in seconds. Applies to all providers.
improve_timeout_secs300intUI: AI SettingsTimeout in seconds for the AI description-refinement (“improve”) action.
share_conversation_across_stepsfalseboolUI: AI SettingsShare one agent conversation across a flow’s steps vs. a fresh session per step.
max_repeated_output_lines8intUI: AI SettingsNo-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 valueBehavior
"2.1.178" (a specific version)Installs that exact version; never auto-upgrades.
"" or omittedInstalls/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 only latest, so its [jira] acli_version pin is advisory — latest is always installed.

[agent.providers.cursor]

Used only when provider = "cursor".

KeyDefaultTypeScopeDescription
cli"agent"stringUI: AI SettingsCursor Agent executable name or absolute path.
model"Auto"stringUI: AI SettingsCursor Agent --model. "Auto" or empty = automatic selection.
privacy_modetrueboolUI: AI SettingsCursor’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[]arrayUI: AI SettingsExtra CLI flags (deny-list enforced).

[agent.providers.opencode]

The OpenCode (self-hosted, OpenAI-compatible) adapter. Used only when provider = "opencode". See Self-hosted models.

KeyDefaultTypeScopeDescription
model""stringUI: AI SettingsModel id served by the endpoint (the <model> in -m self_hosted/<model>). Required when active.
base_url""stringUI: AI SettingsOpenAI-compatible endpoint URL (e.g. http://lm-studio:1234/v1). Required when active.
extra_args[]arrayUI: AI SettingsExtra CLI flags (deny-list enforced).
allow_shared_defaultfalseboolUI: AI SettingsLet users without a personal bearer fall back to the deployment-default token.
context_limit32768intUI: AI SettingsMax context window (tokens) of the self-hosted model. Match your server’s loaded context length.
output_limit8192intUI: AI SettingsMax output tokens per response.

Claude and Codex use their own [agent.providers.claude] / [agent.providers.codex] sub-tables with model, base_url, and extra_args, all editable from Configuration → AI Settings.

[docker]

All [docker] keys are Bootstrap (consumed at image build / compose up).

KeyDefaultTypeScopeDescription
build_commands[]arrayBootstrapOptional bash -c steps run during image build.
compose_up_commands[]arrayBootstrapOptional 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.

KeyDefaultTypeScopeDescription
ports[]arrayBootstrapApplication 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_ports10intBootstrapSpare ports pre-allocated for automatic dev-server forwarding. 0 disables.
theme""stringBootstrapVS Code colour theme; empty uses the editor’s own default (e.g. "One Dark Pro").
extensions[]arrayBootstrapMarketplace IDs to pre-install (e.g. ["esbenp.prettier-vscode"]).
settings{}tableBootstrapFree-form VS Code settings under [editor.settings].

[terminal]

The web terminal (ttyd) inside the editor container. All [terminal] keys are Bootstrap.

KeyDefaultTypeScopeDescription
git_editor(unset)stringBootstrapapt package (e.g. "nano", "vim") installed in every editor container; git config core.editor is set to it.
setup_commands[]arrayBootstrapShell commands run once per editor container lifetime (guarded by a marker file).
startup_commands[]arrayBootstrapShell 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.

KeyDefaultTypeScopeDescription
extra_egress_hosts 🔒[]arrayBootstrapDomains 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 🔒falseboolBootstrapWhen 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.

KeyDefaultTypeScopeDescription
install_commands[]arrayBootstrapShell 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.

KeyDefaultTypeScopeDescription
mock_agentfalseboolBootstrapWhen 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)stringBootstrapPath to the mock script file. No default — tmp/mock_script.txt is only the suggested example.
mock_agent_line_delay_ms75intBootstrapDelay between mock output lines.
mock_agent_total_ms5000intBootstrapTotal 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 (formerly pre_install, install, pre_workflow, now worktree_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.

VariablePurpose
ANTHROPIC_API_KEY 🔒Claude API key — required for the headless pipeline (Anthropic no longer accepts Pro/Max OAuth unattended).
ANTHROPIC_BASE_URLOverride 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_CONFIGPath to an alternate config.toml.
TAKUTO_DATA_DIROverride the persistent data directory (takuto.db, snapshots).
TAKUTO_HOMEOverride the home base used to compute TAKUTO_DATA_DIR.
TAKUTO_DEV_MOCK_AGENT1 = 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"