Plan, run, report
awaywork plan shows what a run would do, awaywork run does it, and awaywork report reads back what it did.
Preview the next run
awaywork plan shows each source and provider as it loads (Getting started), then becomes a view to browse:
☾ >_ awaywork You're away, your agents work
Providers
present run (outside the windows): present_session_max
provider window used ceiling set by resets in session / stop at
claude seven_day 5% 25.7% pacing 5 runs 2% / 40%
other limits: reserve cap 90%
▾ Needs you 1
▾ tracker T 1
T-4 Export invoices as CSV add repo
▾ Units 3
item rule skill provider deliver title
▾ acme/api 2
1 #1 #1 fix (built-in) claude draft_pr Add rate limits to the public API
+ api#5: same feature, matched #3
3 #2 #2 review (built-in) claude report Cache user sessions
▾ acme/web 1
2 #3 #1 fix (built-in) claude draft_pr WIP: new billing page
▾ Skipped 2: 1 no_rule, 1 over_cap
▾ tracker T 1
T-7 Onboarding emails no rule
closest #3 implement: type is task, wants issue
▸ acme/api 1
⏎ unfold o open s skip a approve ? help q quit- Units name the item (
api#1is acme/api#1; a tracker key stays as is), the rule it matched, the skill, provider and delivery. - Needs you is the skipped items only you can unblock, each ending on what to do:
add repofor a task with no repo. - Skipped is the config doing its job, counted by kind.
⏎pages why an item is planned or skipped,oopens it,sskips it in the coming runs,?lists the rest (key table).
Piped or in CI it prints the same as text, the skipped items only counted, and ends on the commands that dig in:
awaywork plan --skipped [kind] lists them
awaywork plan --why <key> says why an item is planned or notplan --skipped lists the skipped items with their reason, Needs you first; plan --skipped no_rule lists one kind. plan --why <key> explains one item, with the queue when it matched no rule:
$ awaywork plan --why T-7
tracker T-7 Onboarding emails
https://tracker.acme.dev/T-7
skipped: no_rule
matched no rule; closest #3 implement: type is task, wants issue
Queue
#1 fix type=pr mine=true
#2 review type=pr review_requested=true
#3 implement type=issue
#4 fix column=QAA planned item shows its unit, rule, skill, provider and branch instead. With no queue in your config, plan says Nothing will run: the config has no queue; /away or awaywork init writes one.
awaywork plan --rules shows what each rule takes now, without probing quota:
Queue
#1 fix source=github type=pr mine=true checks=failing
1 taken: acme/api#1
#2 fix source=github type=pr mine=true unresolved_threads!=0
0 taken
[...]
#4 review source=github type=pr review_requested=true trusted=true
1 taken: acme/api#2
1 unmatched: acme/api#3An item goes to the first rule it matches; a later rule that matches it too shows 1 taken by #1: acme/api#1. To reorder, move the rules in the config.
Why a unit waits
awaywork plan says why a unit makes no work this run:
- Waiting for review: it links an open awaywork PR. awaywork doesn't add to work you haven't read.
- Waiting for your answer: the item's newest comment is awaywork's questions.
- Waiting for your approval: of awaywork's plan on it, or of a report rule's result that waits.
- Unchanged since run
<id>: no item changed (updated, and for asyncits base's head) since a worker last finished this skill on it, so a review isn't redone every run. Acontinueis exempt. - Gave up after 3 attempts; next try on
<date>: its chain didn't finish 3 runs in a row. It retries a week later, changed or not, and again a week after each failed try, so an error that fires nightly isn't retried nightly. - Skipped by you:
awaywork skip <source:key>(e.g.github:acme/api#5) holds an item, and any unit it joins, untilawaywork unskipor the--untildate.plan --skipped skipped_by_youlists it with the--reason. Skips live in~/.local/state/awaywork/skips.json.
run --unit runs a unit anyway, unchanged, skipped or given up; a given-up one runs as its one try.
Details:
- An awaywork PR matches only rules whose
wherenamesours, like the defaultfixon threads you left on it. That rule takes the unit even over a better-ranked linked item, and its draft stacks on the awaywork PR. - A GitHub issue's draft PR into the default branch says
Closesit, which links them, so the issue waits with the draft. - awaywork's draft whose footer says it goes on there doesn't wait: the unit continues on it.
- A PR awaywork pushed onto waits while its head is awaywork's push, unless that was a
sync's clean merge. - An attempt is one chain, finished when every step that ran was done and no publish left anything behind. A failure, an error, a
unit_minutestimeout or unpushed commits don't finish it; a plan report then a failed implement is one failure. - A finished attempt clears the count; another skill starts a new one. Skipped, dry-run and aborted units don't count, nor do stops the item didn't or may not have caused (quota, session limit, window end, a watchdog stop for low memory or disk). Attempts live in
~/.local/state/awaywork/attempts.json.
Run one unit
awaywork run --unit api#1 # one unit, as plan names it
awaywork run --repo 'acme/*' # only units in matching repos
awaywork run --rule 4 # only units of queue rule #4
awaywork report --list # recent runs, to pick an id for report <id>
awaywork report --unit 2 # one unit in full: its files, PR body or report--unit takes the item as plan shows it (api#1), its key (acme/api#1, github:acme/api#1) or the unit id (acme-api-1), in any case. It holds your terminal until the unit ends, hours sometimes; --detach hands it back at once, the output going to the run's run.log:
$ awaywork run --unit api#1 --detach
Started api#1 as run 20261109-095329; awaywork report 20261109-095329 shows it once it endsTo stop a detached unit, kill the pid in ~/.local/state/awaywork/run.lock: it ends as Ctrl-C would, report included.
- A unit you name goes past
limits.units,limits.units_per_repoand its rule'sunits; the rest of the plan stays capped. - A step of a rule's
thenruns its whole chain, from the first step. - It plans first, so a unit that can't start exits 1 saying why: not in the plan, the run lock taken, or no provider.
- An item no rule takes needs a skill:
--skill, detached too. - Outside your windows it's a present run with a lower session limit, and a provider whose quota awaywork can't read (a command provider without a
probe) sits it out: run inside a window or add a probe.
--repo <glob> and --rule <n> (counting from 1, as plan shows) work on plan and run, and together both must hold. Caps and ceilings stay the full run's, but only matching units count: with limits.units: 3, --repo acme/api plans up to three acme/api units.
The run directory, ~/.local/state/awaywork/runs/<id>/, keeps the plan, the worker's log, its context files and the report. The id is the run's start time in UTC; old ones go after keep_runs.
The morning report
awaywork report opens the last run from its report.json: each provider's long window before and after against the ceiling, a row per unit with its result and a line of what it concluded, then Needs you and the skipped items. Here web#3 is selected and d just said why it did nothing:
☾ >_ awaywork You're away, your agents work
Run 20261019-220012: 1 draft PR, 1 report, 3 units
2026-10-19 22:00:12 to 2026-10-19 23:47:40
away run (inside a window): session_max
claude: seven_day 5% to 17%, ceiling 42.9%; session 2% to 31%, stop at 90%
▾ Needs you 1
▾ tracker T 1
T-4 Export invoices as CSV add repo
▾ Units 3
item skill status result
▾ acme/api 2
1 #1 fix done, 14 turns https://github.com/acme/api/pull/14
Rate limits the public API with a token bucket per client key; bursts get a 429 instead of a…
3 #2 review done, 6 turns report, verdict approve
Approve: the session cache keys on the user id and expires with the token.
▾ acme/web 1
2 #3 fix done, 9 turns nothing
No code changes: the red check is the visual diff job, which fails on main too since #212.
▾ Skipped 2: 1 no_rule, 1 over_cap
▸ tracker T 1
▸ acme/api 1
⏎ read o open l log d diff s skip a approve ? help q quit
diff: this unit left no diffplan is the same view without l and d, since a plan has no logs or diffs. report opens at once too, a line per loading step, such as the run fetched from GitHub.
- Items sit under their repo, or tracker and project key, so a row shows just
#3. - A skipped item ends on what it asks of you (
review PR,answer question,approve,add repo, ...) or why it waits (no rule,over cap, ...). Needs you sorts a repo's items by that, so PRs to review sit together. - The line under a skipped item is the rest of its reason, without the closest rule in Needs you;
⏎has all of it. Rows run to the terminal's width, keeping that word on screen. - It opens on the first Needs you item, else the first unit, else the first skip, and leaves out empty sections; with nothing at all, it says why.
- The footer dims keys with nothing behind them:
don a unit that committed nothing,lon a run from the runner, which keeps no logs.
| Key | Does |
|---|---|
↑ ↓, j k | move |
g G, Home End | first, last row |
| PgDn PgUp, Ctrl-D Ctrl-U | a screen down, up |
→ ← Space | unfold, fold, as ⏎ on a heading; ← on a row goes to its section |
⏎ | page the unit in full (report --unit), or why an item is planned or skipped (plan --why), in $PAGER, else (or if it's cat) less -R -c -+F -+X, which repaints from the top and stays open on a short text |
o | open the unit's PR, else its item; a skip waiting for review opens the PR it waits on |
l | page the worker.log of the chain's last step |
d | page the diff: the commits the unit published, else the step's own |
s | awaywork skip the item, after a y |
a | awaywork approve the item, after a y; there's no undo |
? | the keys |
q, Esc, Ctrl-C | quit, also while it loads |
Piped, in CI (CI set), or with --json, --list, --unit or --skipped, it prints text, so awaywork report | cat prints the view, then the quota and how to dig in:
$ awaywork report | cat
Run 20261019-220012: 1 draft PR, 1 report, 3 units
[...]
Quota
away run (inside a window): session_max
claude: seven_day 5% to 17%, ceiling 42.9%; session 2% to 31%, stop at 90%
awaywork report 20261019-220012 --unit <n|key> shows one
awaywork report 20261019-220012 --skipped [kind] lists the skipped itemsreport --unit <n> prints one unit in full, as ⏎ pages it: links, each step with its provider and what it left when there are several, the files still there (none on a run from the runner), then its PR body or report. It takes the row number, the unit id (a step's gives its chain) or an item:
$ awaywork report --unit 2
2 web#3 WIP: new billing page
skill fix
status done, 9 turns
result nothing
item https://github.com/acme/web/pull/3
files ~/.local/state/awaywork/runs/20261019-220012/units/acme-web-3/1-fix/worker.log
~/.local/state/awaywork/runs/20261019-220012/units/acme-web-3/out/pr.md
Fix the billing page build
[...]- An all-digit item key, like an Asana gid, wins over a row number.
- A name that fits two units (
api#1under two owners) is refused with each one'ssource:key, here and inrun --unitandplan --why. - A long reason, like a failed setup's output, gets its first line in the row, all of it under
--unit. - A unit with
thensteps is one row, its chain in the skill column.
Also:
report --skipped [kind]lists the skipped items asplan --skippeddoes;report --jsonprints the run as JSON.report --listlists recent runs with their units, PRs and reports, andreport <id>prints one; inside a control repo they include the runs GitHub Actions uploaded.- During a run there's no report yet:
reportlists the steps done, the one working and itsworker.logpath, totail -f. - The run dir also keeps
report.md, the run as markdown: units with every step under its chain and a summary line each, Needs you, the skips folded by kind, each report folded under its unit. GitHub Actions puts it in the job summary andnotifygets it. A run from beforereport.jsonprints itsreport.md.
Stats
awaywork stats adds up every run that kept a units.json, per rule (by its place in that run's queue), skill and provider: units, how many were done, failed or stopped, the share of the long quota window their workers used, and PRs opened. --json prints the same.
- The quota share is an estimate: it starts at the reading before the unit (the plan's probe, then that provider's previous unit), includes other use of the account meanwhile, and is
-when the window reset mid-unit or the worker read no quota. - A chain's steps count one by one, and only the first carries the chain's PR, so later skills' rows show no PRs.
units.jsonis written when the run ends, so a killed run, or an older one, has none and is left out.