Skip to content

Config reference ​

Generated from the JSON Schema that awaywork config schema prints, also published at config.schema.json. For autocompletion and hover docs in editors with the YAML language server, start the config with:

yaml
# yaml-language-server: $schema=https://andreaprovenzale.github.io/awaywork/config.schema.json

<key> stands for a map key you choose, [] for a list entry. awaywork doctor validates what the schema cannot, such as where keys and skill names.

Top level ​

KeyTypeDefaultDescription
extendsstringA base config file this one goes on top of, relative to this file: maps merge, this file's keys winning, and a list replaces the base's; relative paths resolve against the file they're in. A base can't extend another
windowsobject[][{"start":"01:00","end":"07:00"}]Local hours a scheduled run may start units in; each opening is one run; [] for none
watchobject{}awaywork watch, the daemon schedule install keeps running
limitsobject{}Unit counts and time per run, for every provider
isolation"none" | "user" | "container""none"Who setup, the agent and the checks run as: none, you; user, the awaywork user (Linux, set up as doctor shows); container, a fresh container of the repo's image each; always user on a GitHub-hosted runner and in awaywork's image
budgetobject{}Quota shares, for every provider
providers (required)("claude" | "codex" | "cursor" | object)[]Providers to use, a name or a map to override; order = routing preference
forge"github" | "bitbucket" | object"github"Where the repos live: github or bitbucket, or github as a map of its settings, e.g. { github: { host: github.acme.com } }
sources (required)objectWhere work comes from: built-in sources or your own commands; at least one
branchstring"away/{key}"Branch name template; {key} or {title} is required, {type} is the conventional-commit type
reposmap{}The repos awaywork works in: each key an owner/name or a * glob such as acme/*, with its settings or nothing. A repo takes the settings of every key naming it, globs in the order written and its own key last, a later one winning; an item in a repo no key names is skipped
gatesmap{}Checks on every slice that publishes commits, run before it's published; one that fires opens a deliver: pr PR as a draft and puts its line in a decision card on top of the PR body
instructionsstring | string[]Instruction files added to every unit
skillsstring[][]Extra skills available to every unit; also looked up in the repo's .claude/skills, .agents/skills and .cursor/skills
mcpmap{}MCP servers a rule or step names in its mcp
queueobject[]Rules mapping items to skills; without any, nothing runs
notifyobjectRuns after each step of a finished unit and with the morning report when a run ends; a failure is only logged
storeobjectWhere awaywork puts the files a post pins, plan.yml, reports and whatever else a step leaves in .away/out/, so a unit on any machine reads them back
keep_runsstring"30d"How long run dirs stay; older ones go when awaywork run or watch starts and daily while watch runs, except those holding an item's latest report

windows[] ​

KeyTypeDefaultDescription
days("sun" | "mon" | "tue" | "wed" | "thu" | "fri" | "sat")[]Weekdays the window opens on; every day when unset
start (required)timeWhen a scheduled run starts, local time
end (required)timeNo unit starts after this

watch ​

awaywork watch, the daemon schedule install keeps running.

KeyTypeDefaultDescription
everystring"5m"How often the daemon polls the sources of run: soon rules; a source's own every can make it less often
debugbooleanfalseAlso write each run's full output to the daemon log

limits ​

Unit counts and time per run, for every provider.

KeyTypeDefaultDescription
unitsintegerAt most this many units per run
units_per_repointegerAt most this many units per run in one repo
unit_minutesintegerStop a worker after this many minutes

budget ​

Quota shares, for every provider.

KeyTypeDefaultDescription
reservepercent"10%"Never go past 1 - reserve of any window
per_runpercentAt most this share of the long window per run
session_maxpercent"90%"Stop a worker past this share of the short window
present_session_maxpercent"40%"Stop a worker past this share of the short window in a run started outside every window
fallbackobject{"units":4,"turns":60}Caps when the provider's quota can't be read

budget.fallback ​

Caps when the provider's quota can't be read.

KeyTypeDefaultDescription
units (required)integerUnits per run
turnsinteger60Turns per unit

providers[] ​

KeyTypeDefaultDescription
claudeobjectclaude settings
codexobjectcodex settings
cursorobjectcursor settings

providers[].claude ​

claude settings.

KeyTypeDefaultDescription
settingsstringSettings file for every worker, relative to the config file; passed as --settings
modelstringModel passed to the provider's binary; default the binary's
config_dirstringFolder of the login it runs on, passed as CLAUDE_CONFIG_DIR, e.g. ~/.claude-work; default the environment's; CLAUDE_CODE_OAUTH_TOKEN wins when set; not with isolation: user or container

providers[].codex ​

codex settings.

KeyTypeDefaultDescription
configmapConfig values for every worker, e.g. { model_reasoning_effort: high }; passed as -c
modelstringModel passed to the provider's binary; default the binary's
config_dirstringFolder of the login it runs on, passed as CODEX_HOME, e.g. ~/.codex-work; default the environment's

providers[].cursor ​

cursor settings.

KeyTypeDefaultDescription
modelstringModel passed to the provider's binary; default the binary's

providers[].<key> ​

A custom provider: any agent CLI, run by a command.

KeyTypeDefaultDescription
command (required)stringShell command that works the clone; the prompt is in the file named by AWAYWORK_PROMPT. Its output goes to worker.log
probestringShell command printing the quota as JSON, { windows: [{ name, span, used, resetsAt, minutes? }] }, with a long window to pace against; runs in the config file's folder once per plan or run, after each unit, and in doctor. Unset, the fallback caps apply
secretsstring[][]Env vars the command reads; withheld from other workers, listed in Actions
skills_dirstring".agents/skills"Where the CLI finds skills in the clone

forge ​

KeyTypeDefaultDescription
github (required)objectGitHub, through gh

forge.github ​

GitHub, through gh.

KeyTypeDefaultDescription
hoststringGitHub Enterprise host, e.g. github.acme.com; github.com by default
userstringThe gh account awaywork acts as, e.g. octocat: its gh auth token becomes GH_TOKEN (GH_ENTERPRISE_TOKEN with a host) for everything awaywork does on GitHub; default gh's active account. A token already in the environment wins

sources ​

Where work comes from: built-in sources or your own commands; at least one.

KeyTypeDefaultDescription
githubobjectMy PRs, PRs awaiting my review and issues assigned to me, in the repos the top-level repos lists, plus any extra searches
asanaobjectMy incomplete Asana tasks
linearobjectMy open Linear issues
jiraobjectMy unresolved Jira Cloud issues
routinesobjectRoutines by name, each an item that comes due on the clock, like a weekly triage

sources.github ​

My PRs, PRs awaiting my review and issues assigned to me, in the repos the top-level repos lists, plus any extra searches.

KeyTypeDefaultDescription
searchstring[]Extra GitHub search qualifiers, each ANDed with is:open archived:false (and with is:closed when a rule reads finished items), e.g. label:awaywork or mentions:@me; items they find are neither mine nor review-requested
contextobjectFetches more context for an item, with secrets kept out of the agent's environment
everystringHow often awaywork watch polls this source for run: soon rules, when that is less often than watch.every

sources.github.context ​

Fetches more context for an item, with secrets kept out of the agent's environment.

KeyTypeDefaultDescription
command (required)stringShell command run per item before the worker, in the config file's folder; AWAYWORK_ITEM_KEY, _ITEM_URL and _ITEM_FILE (the item as JSON) are in its env. Files it writes to $AWAYWORK_CONTEXT_DIR reach the worker in the item's extra/ folder
secretsstring[][]Env vars the command needs; withheld from workers, listed in Actions

sources.asana ​

My incomplete Asana tasks.

KeyTypeDefaultDescription
workspace (required)stringWorkspace gid
projectsstring[]Only tasks in these project gids
repo_mapmapProject gid -> owner/repo where its tasks' code lives
token_envstring"ASANA_TOKEN"Env var holding the Asana token
contextobjectFetches more context for an item, with secrets kept out of the agent's environment
everystringHow often awaywork watch polls this source for run: soon rules, when that is less often than watch.every
linkstringLine awaywork writes into its PR bodies, and finds in yours, to link an item; {key}, {id} and {url} are the item's; default {url}

sources.asana.context ​

Same keys as sources.github.context.

sources.linear ​

My open Linear issues.

KeyTypeDefaultDescription
repo_mapmapTeam key -> owner/repo where its issues' code lives
token_envstring"LINEAR_API_KEY"Env var holding the Linear personal API key
contextobjectFetches more context for an item, with secrets kept out of the agent's environment
everystringHow often awaywork watch polls this source for run: soon rules, when that is less often than watch.every
linkstringLine awaywork writes into its PR bodies, and finds in yours, to link an item; {key}, {id} and {url} are the item's; default Part of {key}

sources.linear.context ​

Same keys as sources.github.context.

sources.jira ​

My unresolved Jira Cloud issues.

KeyTypeDefaultDescription
site (required)stringJira Cloud site host, e.g. acme.atlassian.net
email (required)stringAtlassian account email the API token belongs to
cloud_idstringSite cloud id: set for a scoped token, which calls api.atlassian.com
jqlstringJQL condition ANDed with my unresolved issues
repo_mapmapProject key -> owner/repo where its issues' code lives
token_envstring"JIRA_API_TOKEN"Env var holding the Atlassian API token
contextobjectFetches more context for an item, with secrets kept out of the agent's environment
everystringHow often awaywork watch polls this source for run: soon rules, when that is less often than watch.every
linkstringLine awaywork writes into its PR bodies, and finds in yours, to link an item; {key}, {id} and {url} are the item's; default none

sources.jira.context ​

Same keys as sources.github.context.

sources.routines ​

Routines by name, each an item that comes due on the clock, like a weekly triage.

KeyTypeDefaultDescription
contextobjectFetches more context for an item, with secrets kept out of the agent's environment
everystringHow often awaywork watch polls this source for run: soon rules, when that is less often than watch.every

sources.routines.context ​

Same keys as sources.github.context.

sources.routines.<key> ​

A routine: an item that comes due on the clock.

KeyTypeDefaultDescription
days("sun" | "mon" | "tue" | "wed" | "thu" | "fri" | "sat")[]Weekdays it comes due on; every day when unset
at (required)time | time[]When it comes due, local time: one time or a list
repo (required)stringThe repo its work happens in, owner/name
title (required)stringThe item's title
descriptionstring""The item's description, what the worker reads

sources.<key> ​

A custom source: any command that prints your open items as JSON.

KeyTypeDefaultDescription
command (required)stringShell command printing the items as a JSON array; runs in the config file's folder
fieldsstring[][]Item fields rules may match on
secretsstring[][]Env vars the command reads; the GitHub Actions workflow passes them in
setupstringRuns in the config file's folder before awaywork on GitHub Actions, and at build in awaywork's container image
linkstringLine awaywork writes into its PR bodies, and finds in yours, to link an item; {key}, {id} and {url} are the item's
everystringHow often awaywork watch polls this source for run: soon rules, when that is less often than watch.every
writestringShell command that comments on or moves one of your items, run like command; it reads the write as JSON on stdin, e.g. {"op":"move","item":"ENG-2101","id":"10012","to":"QA"}, and may print the item's updated times as {"before":"…","after":"…"}. Without it, on_done writes nothing to this source
threadbooleanA thread host: a rule's thread may name this source, whose write then also answers {"op":"open","item":"<card key>","title":"…","body":"…"} with {"key":"…","url":"…"}, and command lists the threads it opened as items, their comments the replies

repos.<key> ​

KeyTypeDefaultDescription
branchstringBranch name template for this repo
setupstringSetup command, run in the clone before the worker; a failure skips the unit
secretsstring[][]Env vars setup needs; withheld from workers, listed in Actions
verifystringCommand run in the clone after the worker, before publishing; a failure goes in the PR body or report, and the work is still published
gatesmap{}Gates for this repo's units, on top of the top-level ones; a name both have fires on either's changed, command or skill
teststringTargeted test command, given to the worker in its prompt
instructionsstringInstruction file for units in this repo
imagestringDocker image setup, the agent and the checks run in under isolation: container; it ships the agent CLIs the repo's rules use and its toolchain

repos.<key>.gates.<key> ​

KeyTypeDefaultDescription
changedstring | string[]Git globs from the repo root; fires when the chain's commits change a matching path; not on a plan or report rule's gate, which has no commits
commandstringA shell command awaywork runs in the clone, outside the model, naming its script by its path from the repo root; it diffs from AWAYWORK_FROM, the commit the chain started from, unset on a plan or report, and reads AWAYWORK_OUT_DIR, a read-only copy of what the steps left in .away/out; a non-zero exit fires, with its stdout as the line; so does one that can't run or times out, and, without running, one where a file it names differs from the one the chain started with
skillstringA skill, yours or built in, that a model runs on the chain's commits and a read-only copy of what the steps left in .away/out, a plan's or report's out files alone, after the other gates, routed like the rule's steps; it fires when it writes the verdict fires, its report lines on the card; so does a run that fails or changes the clone, whose changes awaywork drops
instructionsstring | string[]Instruction files a skill gate's judge reads, relative to the config file; never the repo's, and never the rule's

gates.<key> ​

Same keys as repos.<key>.gates.<key>.

mcp.<key> ​

KeyTypeDefaultDescription
commandstringCommand that starts a stdio server
argsstring[]The command's arguments
envmapThe server's env vars, besides its secrets; plain values
urlstringURL of an HTTP server
headersmapHTTP headers; a value may be ${NAME}, or Bearer ${NAME} for Authorization
secretsstring[][]Env vars the server reads, in its env under their own names or in headers; given only to units whose rule names it, listed in Actions
toolsstring[]Tools the worker may call; default all the server's

queue[] ​

First matching rule wins; top = highest priority.

KeyTypeDefaultDescription
skill (required)stringThe skill that does the work
sourcestringMatch only items from this source
whereobject{}Item facts to match: type or a source field; a list means any of, {not} negates, {gt,gte,lt,lte} compare numbers, {older_than,newer_than} compare dates to now, {matches} tests text against a case-insensitive regex, any: [{...}] holds when one entry does; title, description, approved, state (open, merged, closed) and closed (when it finished) are on every source; a where, or an any entry under one, that never names state matches open items only
providerstring | string[]Providers for this rule, in order; default the providers order
modelmapModel per provider for this rule, e.g. { claude: sonnet } or { claude: [sonnet, opus] }; default the provider's
skillsstring[][]Extra skills available to the worker; also looked up in the repo's .claude/skills, .agents/skills and .cursor/skills
mcpstring[]MCP servers the worker gets, by their name under the top-level mcp
instructionsstring | string[]Instruction files added for this rule
withmapParameters for the skill, listed in its prompt; a skill's metadata says which it reads
deliver"draft_pr" | "pr" | "report" | "push" | "pending_review" | "plan"Where the chain's commits go: one draft PR (default), one PR ready for review (a draft when a step fails or the run ends before one runs, a step asks questions with ask in its status file, verify fails, a loop's until never held, or a gate fires), or a push onto your own PR's branch; report makes no step commit, and a chain without commits reports; pending_review reports too, and leaves the last report on the PR it reviews as your pending review, seen by no one until you submit it; plan reports too, and posts the report with the plan.yml a step wrote as one comment on the item, which waits for your reply: approve as its first line approves it, anything else re-plans
waitbooleandeliver: plan or report: the post waits for your reply on the item, approve as its first line letting the next stage take it, anything else running the step again; default true for plan, false for report; a gate of the rule's own that fires makes it wait anyway
gatesmapGates of the rule's own, under names no top-level or repo gate has. On a rule that opens a PR or pushes they run with those, and one that fires does what theirs does; on deliver: plan or report, where those never run, they run on what the step left, without changed, and one that fires puts its line on the post and makes it wait, a planned rule's task holding its card's other tasks until you answer; not on pending_review
post"summary" | "full"deliver: plan, or a report that posts: summary posts the step's .away/out/summary.md, awaywork's facts and a pinned link per file it put in the store; full posts the report inline, plan and contract included; default summary with a store, else full
threadstringWhere its posts go and their replies are read: item (default), the item itself; github, an issue awaywork opens as the item's thread in its repo, assigned to you; or a custom source with thread: true, whose write opens one; for a tracker that can't take them; from then on all of the item's posts go there, its plan's tasks' too, and it closes once its source says the item is done
branchstringBranch name template for this rule
order"oldest" | "newest" | "updated"Which item goes first: oldest, newest or last updated; default the source order
quotaobjectRun this rule's unit only when the quota holds; otherwise skip it
plan_tasksintegerdeliver: plan: at most this many tasks in its plan; default 8
unitsintegerAt most this many units per run from this rule; a chain counts once
thenstring | object | (string | object)[]Steps run in turn after this rule's unit, in its clone; the chain publishes once, when it ends; a {loop} repeats its steps
on_doneobjectWritten to the unit's items that are yours once its chain finished and published; a write that fails is only reported
run"soon" | "window"When its units start: window (default), in the next window run; soon, as soon as awaywork watch sees one due (a new item, or one changed since its last attempt), polling every watch.every

queue[].where ​

Item facts to match: type or a source field; a list means any of, {not} negates, {gt,gte,lt,lte} compare numbers, {older_than,newer_than} compare dates to now, {matches} tests text against a case-insensitive regex, any: [{...}] holds when one entry does; title, description, approved, state (open, merged, closed) and closed (when it finished) are on every source; a where, or an any entry under one, that never names state matches open items only.

KeyTypeDefaultDescription
anyobject[]Matches when at least one of these conditions does; each is a where of its own

queue[].where.<key> ​

Matches items whose field has none of these values.

KeyTypeDefaultDescription
not (required)string | number | boolean | (string | number | boolean)[]

queue[].where.<key> (gt) ​

Matches items whose number field passes every comparison.

KeyTypeDefaultDescription
gtnumberGreater than
gtenumberGreater than or equal to
ltnumberLess than
ltenumberLess than or equal to

queue[].where.<key> (older_than) ​

Matches items whose date field is this long before now, e.g. { older_than: 3d }.

KeyTypeDefaultDescription
older_thanstringLonger ago than this span
newer_thanstringMore recent than this span

queue[].where.<key> (matches) ​

Matches items whose text field contains a match, e.g. { matches: '^\[bug\]' }.

KeyTypeDefaultDescription
matches (required)stringA regular expression, case-insensitive

queue[].gates.<key> ​

Same keys as repos.<key>.gates.<key>.

queue[].quota ​

Run this rule's unit only when the quota holds; otherwise skip it.

KeyTypeDefaultDescription
runs_until_resetintegerHolds when at most this many window openings are left before the provider's long window resets; 1 is the last window
headroompercentHolds when at least this share of the long window is left under this run's ceiling

queue[].then ​

KeyTypeDefaultDescription
skill (required)stringThe skill that does the work
providerstring | string[]Providers for this step, in order; default the rule's, [] the providers order
modelmapModel per provider for this step; default the rule's
skillsstring[]Extra skills available to the worker; default the rule's, [] none
mcpstring[]MCP servers the worker gets, by their name under the top-level mcp; default the rule's, [] none
instructionsstring | string[]Instruction files added for this step; default the rule's, [] none
withmapParameters for the skill, listed in its prompt; a skill's metadata says which it reads
whenobjectRun this step only when every key holds; otherwise skip it

queue[].then.when ​

Run this step only when every key holds; otherwise skip it.

KeyTypeDefaultDescription
verdictstring | string[] | objectThe latest verdict in the chain; a list means any of, {not} negates
commandstringA shell command awaywork runs in the clone, outside the model; exit 0 holds
changedstring | string[]Git globs from the repo root; holds when the chain's commits change a matching path, against where the chain started

queue[].then.when.verdict ​

Matches every verdict but these.

KeyTypeDefaultDescription
not (required)string | string[]

queue[].then (loop) ​

Steps repeated until a condition holds.

KeyTypeDefaultDescription
loop (required)string | object | (string | object)[]Steps run in turn every round, in the chain's clone
until (required)objectEnds the loop as soon as it holds; checked after every step
max (required)integerAt most this many rounds, up to 5

queue[].then.loop ​

Same keys as queue[].then.

queue[].then.loop.when ​

Same keys as queue[].then.when.

queue[].then.loop.when.verdict ​

Same keys as queue[].then.when.verdict.

queue[].then.loop[] ​

Same keys as queue[].then.

queue[].then.loop[].when ​

Same keys as queue[].then.when.

queue[].then.loop[].when.verdict ​

Same keys as queue[].then.when.verdict.

queue[].then.until ​

Ends the loop as soon as it holds; checked after every step.

KeyTypeDefaultDescription
verdictstring | string[] | objectThe latest verdict a loop step wrote; a list means any of, {not} negates
commandstringA shell command awaywork runs in the clone, outside the model; exit 0 holds

queue[].then.until.verdict ​

Same keys as queue[].then.when.verdict.

queue[].then[] ​

Same keys as queue[].then.

queue[].then[].when ​

Same keys as queue[].then.when.

queue[].then[].when.verdict ​

Same keys as queue[].then.when.verdict.

queue[].then[] (loop) ​

Same keys as queue[].then (loop).

queue[].then[].loop ​

Same keys as queue[].then.

queue[].then[].loop.when ​

Same keys as queue[].then.when.

queue[].then[].loop.when.verdict ​

Same keys as queue[].then.when.verdict.

queue[].then[].loop[] ​

Same keys as queue[].then.

queue[].then[].loop[].when ​

Same keys as queue[].then.when.

queue[].then[].loop[].when.verdict ​

Same keys as queue[].then.when.verdict.

queue[].then[].until ​

Same keys as queue[].then.until.

queue[].then[].until.verdict ​

Same keys as queue[].then.when.verdict.

queue[].on_done ​

Written to the unit's items that are yours once its chain finished and published; a write that fails is only reported.

KeyTypeDefaultDescription
movestringWhere the item goes, in its tracker's words: a Jira status, a Linear state, an Asana section, a GitHub label to add
commentstringresult posts the unit's result as awaywork's comment, before any move: a report rule's report, else a link to what it published

notify ​

Runs after each step of a finished unit and with the morning report when a run ends; a failure is only logged.

KeyTypeDefaultDescription
command (required)stringShell command; AWAYWORK_EVENT (unit or run) and AWAYWORK_RUN_ID are in its env, plus AWAYWORK_REPORT for a run, and _UNIT, _SKILL, _STATUS, _ITEM_URL, _ITEM_KEY and _SOURCE (one line per item), _REPO and, when there is one, _VERDICT, _PR_URL, _REPORT or _OUT_DIR for a unit
secretsstring[][]Env vars the command needs; withheld from workers, listed in Actions

store ​

Where awaywork puts the files a post pins, plan.yml, reports and whatever else a step leaves in .away/out/, so a unit on any machine reads them back.

KeyTypeDefaultDescription
command (required)stringShell command run like a custom source's, once per file: it reads {"op":"put","item","unit","path","kind"} on stdin and prints {"url":"…"}, or {"skip":true} to keep the file out of the store, or reads {"op":"get","url"} and prints the file's bytes
secretsstring[][]Env vars the command reads; withheld from workers, listed in Actions
getbooleantruefalse: the command only puts, and awaywork reads a file back with a plain HTTP GET of its URL
readobject{}What comes back into a unit's context when it reads its item's thread

store.read ​

What comes back into a unit's context when it reads its item's thread.

KeyTypeDefaultDescription
max_mbnumber10At most this many MB of a unit's files come back; the rest stay links
filesstring[][]Globs of the file names that come back, e.g. [".md", ".yml"]; default every file