The configuration is $XDG_CONFIG_HOME/wloop/config.toml, by default ~/.config/wloop/config.toml, a TOML file like the profile’s manifests; # starts a comment. Every key is optional; a key the loop does not read is an error that names it, and a close key when one exists, and wloop doctor reports it. A value of the wrong kind, or outside its set, is refused the same way: a duration or a date written without quotes, a number where a string goes, inf or nan. A key left out keeps its default. A former config.json is not read; when it is the only file, every command that loads the configuration fails, naming config.toml. wloop config get <key> prints the effective value of one, defaults included (sweep.fast for a nested key). wloop config set <key> <value> writes one key, keeping the file’s comments and layout, and wloop config unset <key> removes one, or a whole table (workflows.<name>); a table an unset leaves with no key, comment or sub-table loses its header too, so an unset undoes a set. Set refuses a key no setting reads, a workflows.<name> key whose name is none of the profile’s workflows (wloop doctor lists them) nor a disabled plugin’s, which can be switched before the plugin is enabled, and a result the loop would refuse; unset removes any key, one no setting reads too, and refuses only a result that would no longer load. Each keeps the previous file as config.toml.loop-<stamp>.bak.
The daemon reads the file when it starts. It follows a change of profile, ui.locale and workflows.<name>.enabled live, the keys its stale warning lists; any other change takes effect after a restart of the daemon, and until then the daemon reports its configuration as stale. The window keys are the app’s: a change applies when the app restarts, and the daemon does not report it. Durations are strings: "2d", "36h", "90m" or "60s". wloop profile schema --config prints the file’s JSON Schema, for an editor whose TOML support reads one.
A plugin’s settings live under its id (github, slack), and <id>.enabled switches it, read at start. workflows.<name> overlays a workflow’s manifest field by field, as Tune workflows shows; its gates.approval takes mode, window and rule, a list of tables with when, mode and window ([[workflows.<name>.gates.approval.rule]]), for every gate the workflow opens, a rule for the kinds its when pins gate.kind to: a rule list replaces the manifest’s rules and [] clears them, a key left out keeps the manifest’s, and a block that does not merge with the manifest’s is named by doctor. intents.<name>.project_settings.when is a predicate over the turn facts of the session’s unit, such as a pull request’s, where the intent’s sessions load the checkout’s own agent settings (.claude/, .mcp.json, CLAUDE.md); elsewhere they start with your settings alone, and an intent it does not name loads them; see Review. Unless the table says otherwise, workspace_managers is ["claude-desktop", "orca"] and agent is "claude".
Settings for the pull requests and the work of matching repositories; the first match wins.
projects[].match
string
An owner/repo pattern, such as acme/* or acme/api.
projects[].projects_dir
string
The project’s projects_dir.
projects[].agent
string
The agent the project’s sessions run.
projects[].agent_home
string
The project’s agent_home.
projects[].workspace_managers
list of strings
The managers a new worktree of the project picks from, in order.
projects[].trust_clones
bool
Trusts a repository of the project in the agent home at the moment the loop clones it, so its settings and hooks run as you; the match must name its owner, such as acme/*.
projects[].github
table
The GitHub settings the project overrides.
projects[].github.trusted_authors
list of strings
The project’s plugins.github.trusted_authors.
projects[].github.followups_without_workspace
bool
The project’s plugins.github.followups_without_workspace.
projects[].github.address_without_workspace
bool
The project’s plugins.github.address_without_workspace.
Each plugin’s table, by id: its switch, its trust and its settings.
plugins.<name>
table
A plugin’s table; the keys besides enabled and trust are the plugin’s own, which only it reads.
plugins.<name>.enabled
bool
Switches the plugin; left out, it is on.
plugins.<name>.trust
one of path
path runs the plugin’s binary whatever its checksum; left out, a bundled plugin runs only with the checksum its install recorded, and any other plugin does not run. Only you write it.
Automated turns per day, all workflows together, on units whose plugin keeps no per-unit count (every provider but GitHub today).
turns.per_unit_per_day
integer
5
Automated turns on one unit per local day, on units whose plugin keeps a per-unit count (GitHub today); every automated turn spends one, whatever its intent declares, and a turn by hand none.
headless
table
The headless turns’ caps; a cost of zero leaves it uncapped.
headless.tier
one of fast, balanced, frontier
balanced
The model tier of their calls.
headless.per_call_usd
number
0.5
What one call may cost, in USD.
headless.per_day_usd
number
5
What they may cost in a day, in USD.
brief
table
The brief: one headless call that previews each unit.
brief.enabled
bool
false
Briefs each unit.
brief.tier
one of fast, balanced, frontier
fast
The brief’s model tier.
brief.max_input_bytes
integer
60000
The most bytes of input a brief reads, between 1000 and 200000.
The thresholds of the session and workspace cleanup workflows.
cleanup.idle
duration
2h
How long a finished session stays idle before it closes.
cleanup.asked_idle
duration
4h
How long a session that asked you stays idle before it closes.
cleanup.workspace_grace
duration
1d
How long, in working time, a workspace stays after its unit finished.
cleanup.manual_idle
duration
1d
How long a session you started stays idle before it closes.
cleanup.stale_workspace
duration
14d
How long an untouched workspace stays.
cleanup.orphan_hold
duration
1d
How long the close of a dormant session waits while its process lingers orphaned, the app showing some terminal throughout, before it closes the session’s record anyway; it ends no process.
cleanup.disposable
list of strings
Ignored files and directories a tool recreates, so removing a workspace that holds them loses nothing.
match is owner/repo or a glob such as owner/*, case-insensitive; the first match wins. An entry may set projects_dir, workspace_managers (replaces the top-level list), agent, agent_home, and under github the project’s trusted_authors (replaces the top-level list), followups_without_workspace and address_without_workspace. Empty fields keep the top-level value. What your profile says for those repositories goes in its organization= and repo= blocks.
workspace_managers = ["orca"] # replaces the top-level list
wloop serves every listed manager at once: it reads their worktrees and sessions and acts on each worktree through its owner. The order matters only for a new worktree, which goes to the first manager that is
enabled: listed here, or in the matching projects entry;
available: installed and reachable;
able to host the project’s agent;
able to honor the session’s launch policy.
Orca honors every launch policy. Claude Desktop honors a session that loads the checkout’s project settings, uses the default agent home, and adds allows and denies, which wloop writes into the worktree’s .claude/settings.local.json. A session that needs your user settings alone (where intents.<name>.project_settings.when does not hold for its intent, and always for a pull request that fails the trust check, whose checkout settings are its author’s), a strict or MCP-free session, or a non-default agent_home falls through to the next manager. When no manager can launch it, the round fails closed and names each manager’s reason. wloop doctor reports whether each manager is available and reachable (one unreachable manager is a note, all of them unreachable is a failure) and a launch <intent> check for each intent no enabled manager can launch.
An empty list is an error. The old workspace_manager key is refused; list the manager in workspace_managers instead.
Only Orca has a board. A workspace Claude Desktop owns has no card; its state shows in the cockpit, the terminal client and the menu bar.
views.orca.columns maps a status to a column: working (while a review round runs, reviewing by default), working-fallback (when the board has no working column, in-review), needs-me (an agent asked or stopped), reviewed (a review published without approving), ready (your approved, green pull request, ready-to-merge), and the author statuses in-progress, in-review and completed. See board columns.
The first rule whose match, a glob over <provider>:<key>, matches gives the repository, the checkout ("" for a new worktree, main, or a path), the role and whether the workspace is shared by several units. A unit no rule, hint or provider default places, such as a Slack DM, runs its sessions in <state>/neutral, an empty repository with no project checked out.