cawdev-cli 1.0.5-beta → 1.0.7-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/runner/README.md CHANGED
@@ -68,6 +68,13 @@ page and waits for you to approve a code; after that it is remembered, and
68
68
  `/login` does it again on demand. No password is ever typed into the terminal —
69
69
  that belongs on a page your browser has told you the origin of.
70
70
 
71
+ When the platform stops honouring that session — it expired, you signed out in
72
+ the console, or your account went — the first request answered 401 says so
73
+ once, the footer pins `session expired — /login to sign in again`, and the
74
+ terminal drops to watching only until `/login` succeeds. The polls pick up again
75
+ on their own after it. In advanced mode `/login` stays in advanced mode: the URL
76
+ and the code are printed in the prompt window.
77
+
71
78
  ```
72
79
  cawdev the runner here, starting one if there is none
73
80
  cawdev --runner <name> when this machine runs more than one
@@ -101,8 +108,8 @@ with the window — there `q` stops it, and asks first when sessions are live.
101
108
  machine is configured, most changes are smaller than that. **Inside the
102
109
  terminal, press `c`** (or type `/config`): a picker over what this machine does
103
110
  — add a project, add a workspace, each agent with its current state ("Disable
104
- claude", "Enable codex"), the console-rules switch, and the config itself with the
105
- token cut short. Every row is one of the shell commands below, driven through
111
+ claude", "Enable codex"), the console-rules switch, **Stop serving** each
112
+ project, and the config itself with the token cut short. Every row is one of the shell commands below, driven through
106
113
  the terminal's own line editor and picker; `esc` anywhere in a step changes
107
114
  nothing. The screen edits the file the daemon says it booted from (the hello
108
115
  carries `configPath` since R288), so an older daemon is told to restart rather
@@ -126,6 +133,7 @@ is for scripts and for a machine with no daemon to attach to:
126
133
  cawdev config a menu, the same Select widget as everywhere else
127
134
  cawdev config add-project serve one more project you can write to
128
135
  cawdev config add-workspace another checkout for a project already served
136
+ cawdev config remove-project <slug> stop serving a project; its checkouts stay on disk
129
137
  cawdev config agent enable|disable <claude|agy|codex>
130
138
  cawdev config rules on|off accept permission rules from the console — R126
131
139
  cawdev config show this machine's config, token redacted
@@ -221,7 +229,10 @@ move through the command list while one is open.
221
229
  | `/quit` | leave |
222
230
 
223
231
  **Typing `/` filters that list as you go**, each row with its description; arrows
224
- and `enter` pick one and `tab` completes as far as the matches agree. Guessing a
232
+ and `enter` pick one and `tab` completes as far as the matches agree — then
233
+ moves down the list, so `/lo` `tab` `tab` reaches `/login` past `/log`. A name
234
+ typed in full is the first row, so `/log` `enter` runs `/log`. Advanced mode
235
+ draws the same list above its prompt, six rows at a time. Guessing a
225
236
  command name and being told `no such command` is a step, and it is the step this
226
237
  removes.
227
238
 
@@ -230,7 +241,8 @@ removes.
230
241
  `/logout` forgets it along with the session.
231
242
 
232
243
  **A paste stays one line.** Paste four hundred lines and the input shows
233
- `[pasted, 342 lines]`; all of it is sent. A paste that scrolled the transcript
244
+ `[pasted, 342 lines]`; all of it is sent — into a prompt or into a command alike
245
+ (`/new plan <paste>`, `/card <paste>`), its line breaks kept (`commandWords`). A paste that scrolled the transcript
234
246
  away would bury the thing this program exists to keep.
235
247
 
236
248
  Under `NO_COLOR` it is the same terminal without the colour: the picker still
@@ -359,8 +371,17 @@ project this machine serves included ("nothing planned" is an answer) — one
359
371
  small box each, titled with the card and its status — `R3 (Planned)` — the cards of
360
372
  every project this machine serves that are ready to be developed, read again
361
373
  every thirty seconds. **`d`** lists them and develops the one you pick, on this
362
- machine and on the card's own branch; `/new dev` with nothing after it does the
363
- same anywhere, and `/new dev R3` goes straight to one.
374
+ machine and on the card's own branch — except on a finished plan's window, where
375
+ it is that plan's `/develop` (below) with no list; `/new dev` with nothing after it does the
376
+ same anywhere, and `/new dev R3` goes straight to one. A full-width rule
377
+ under the strip separates the board from the session windows; it comes out of
378
+ the strip's own rows, never the windows'.
379
+
380
+ **`/refresh`** reads the cards again now rather than on the next tick, and
381
+ says what it found per project — `saasng: 5 considering · 2 planned · 1 in
382
+ development` — and which project could not be read, and why. A project that
383
+ cannot be read keeps its last cards and no other's: one unreadable slug used
384
+ to leave every column of every project at 0, silently.
364
385
 
365
386
  **Four windows at most.** Past four, the rest are named on one line above the
366
387
  prompt — number, kind, state, card, in the state's colour — and `tab` (or the
@@ -371,8 +392,15 @@ recently looked at first.
371
392
  A window stays up when its session ends, and its last line says what can be
372
393
  done next:
373
394
 
374
- - **`/develop`** on a finished plan starts the development of its card, on
375
- this machine (the branch is the card's own).
395
+ - **`d`** or **`/develop`** on a finished plan — the window says `d develops R2
396
+ here, in place of this plan` — starts the development of its card, on
397
+ this machine (the branch is the card's own). `/develop R30` names another
398
+ card, `@slug` its project, and `--codex`/`--claude`/`--agy` the agent —
399
+ otherwise the agent that PLANNED the card when its finished plan has a
400
+ window here, else `/agent`'s choice, exactly as `/new dev R30` does, because
401
+ it IS that command. Once the development has started the plan's window
402
+ closes, and the development's window takes its focus when this machine
403
+ takes the run; a start the platform refused leaves the plan's window up.
376
404
  - **`/pr`** on a finished session that wrote a branch opens its pull request
377
405
  (`POST runs/{id}/pull-request` — through the card's work item, or from the
378
406
  run itself for a session started from a sentence): this machine pushes the
@@ -395,7 +423,18 @@ done next:
395
423
  project's runs, kept when `carriesOnHere` — yours, `canCarryOn`, and its
396
424
  checkout on this machine or none), listed in the scrollback, and given a
397
425
  window that opens on why it stopped.
398
- - **`/open`** opens the pull request in your browser.
426
+ - **Finished, having built nothing** — a dev session that ended FINISHED
427
+ with no commit (IMPLEMENT stopped on a plan it would not follow, say) —
428
+ reads `finished · nothing built`, in amber rather than green, offers no
429
+ `/pr` but the re-plan instead, and its window shows its summary, where it
430
+ said why (`builtNothing`; the terminal reads the run's commits once it
431
+ ends, and claims nothing until it has).
432
+ - **`/open`** opens the pull request in your browser. It reads the run again
433
+ first — the runner records the link after the run is FINISHED, so the copy
434
+ taken at that moment has none — and falls back to the card's work item.
435
+ On a finished PLAN, which opens no pull request, it opens the card on cawdev
436
+ instead — `roadmap/R2?show=plan` (`issues/…` for an issue) — with the plan
437
+ of record unfolded and scrolled to: that plan is what the session produced.
399
438
  - **`/drop`** deletes the checkout the session was cloned into, when it was one
400
439
  made on demand (below): asked first, naming the path, and refused while a
401
440
  run is in it or holds it, with uncommitted files, or with a commit origin
@@ -424,6 +463,21 @@ sentence; `--anyway` starts it regardless, the same decision the console's
424
463
  panel asks for. All four commands need you signed in (`/login`), and they work
425
464
  outside advanced mode too, on the session you are watching.
426
465
 
466
+ **The prompt says which window it acts on.** In advanced mode the line at the
467
+ bottom leads with the focused window's number — `[2] cawdev ▸ /pr`, `[2]
468
+ enter prompts “…”` — and a command's answer keeps the number of the window it
469
+ was about (`[2] A session on … is running`), so a note left on screen after
470
+ the focus moved still says whose it was.
471
+
472
+ **A project deleted in the console is not offered.** The config on this
473
+ machine still names it, and nothing on the platform can change that file, so
474
+ the terminal asks: a served project whose roadmap read answers 404 — deleted,
475
+ or your access went — is left out of the picker, the strip, `/new` and `/card`,
476
+ and one line says so, once, after the mode is on screen. `c` → **Stop serving
477
+ ngsign** (`cawdev config remove-project ngsign`) takes it out of the config;
478
+ the checkouts stay where they are, and the daemon stops polling for it at its
479
+ next restart, because `projects` is read at boot.
480
+
427
481
  **Which projects it shows is yours to pick.** `/advanced-mode` on a machine
428
482
  serving several projects opens a picker with every one ticked — space (or a
429
483
  digit) ticks and unticks, `a` all or none, enter confirms — and only the
@@ -432,16 +486,73 @@ projects ticked are drawn: their windows, their roadmap on top, and the ones
432
486
  nothing; `/projects` asks again from inside the mode; `/reload` keeps the
433
487
  pick. A prompt never talks to a session of a project that is not shown.
434
488
 
489
+ **↑ is history, as in a shell.** On a line nothing has been typed on yet —
490
+ empty, or the bare `/` a command line opens with — ↑ and ↓ walk what was
491
+ typed before (kept across launches, `history.mjs`); a command line walks only
492
+ the commands. Once something is typed, the arrows move in the list of
493
+ commands instead, and enter sends a recalled line as it is. Outside advanced
494
+ mode ↑ with no line open recalls the last entry onto the line it belongs to;
495
+ in advanced mode the wheel arrives as arrows, so there it is `/` or enter,
496
+ then ↑.
497
+
498
+ **`/view`** opens the focused session's page on cawdev — transcript, stages,
499
+ card — in the browser, on the console this terminal signed in to.
500
+
501
+ **`/view R29`** prints a card here instead: its status, section, tags, branch,
502
+ work item and pull request, who is coding or reviewing it, what it is related
503
+ to, its page on the web, and the first thirty lines of its body (`cardLines`,
504
+ pure). `/view <words>` finds it by its title among the cards of the projects on
505
+ screen and offers a list when several match; `@slug` names the project;
506
+ **`/view card`** is the focused session's own card.
507
+
508
+ **Which agent `/new` asks for.** `--claude`, `--codex` or `--agy` on a `/new`
509
+ names that session's agent (`/new dev R12 --codex`); `/agent codex` makes it
510
+ the terminal's choice for every `/new` after it, kept across launches
511
+ (`prefs.mjs`, `~/.cawdev/terminal.json`) and shown in advanced mode's prompt
512
+ title; `/agent default` hands the choice back to the project. A flag beats
513
+ `/agent`, and with neither nothing is named — the project's default decides,
514
+ as it always has. A name no runner spawns is refused, by `/agent` and by the
515
+ platform alike, rather than spawned as Claude Code; `/agent codex` on a
516
+ machine that does not list codex says so (`c` → Enable codex). The window's
517
+ `Codex · GPT-5-codex` line says which one actually ran.
518
+
519
+ **A stage asks rather than stops.** A decision that is the person's — a scope
520
+ the card leaves open, a plan the code has moved away from — is asked with
521
+ `ask_user`, and the stage carries on with the answer; PLAN asks before it
522
+ writes, so a plan never hands IMPLEMENT an open question, and IMPLEMENT asks
523
+ when its plan is wrong or incomplete instead of stopping (`ASK_DONT_STOP`).
524
+ Codex is given the time to: cawdev's MCP server gets `tool_timeout_sec` 660 on
525
+ its side, longer than `ask_user`'s ten-minute wait — Codex's own default of
526
+ 60 s cut every question off before anybody could answer it.
527
+
528
+ **Codex and Antigravity write only on a machine that allows everything.**
529
+ Neither has per-command permissions — Codex's sandbox is read-only, blocks the
530
+ network (no push) or is off — so a session of theirs that writes is refused,
531
+ unspawned, until the machine accepts console rules AND "Allow everything" is
532
+ ticked on it. The refusal says so in steps, for this machine
533
+ (`needsEverything`, lib/agents.mjs): which of the two is done, the Runners page
534
+ on this console, the command to start it again — and it is written on the
535
+ run's transcript as well as its summary, so the window shows it; a failed
536
+ window prints its run's summary (`sayWhyItFailed`) rather than just "failed".
537
+
538
+ **`/card <the idea in words>`** writes a card in **Considering** and starts
539
+ nothing — no session, no branch, nothing spent: the roadmap's first column
540
+ is where an idea waits to be decided on, and writing one down does not need
541
+ a model. Titled by its words (`cardTitleFor`), the whole text in its body;
542
+ the project chosen exactly as `/new` chooses it (`@project`, else advanced
543
+ mode narrowed to one, else asked).
544
+
435
545
  **Across the top, the roadmap** (`roadmapStrip`): every project this machine
436
- serves as a small board — Considering, Planned, In development, Merged side
437
- by side, one line per card, `●` on a card with a session running now;
438
- Shipped and Declined, which only grow, are counts beside the project's name,
439
- as on the console's board. As tall as the fullest column, never more than a
546
+ serves as a small board — Considering, Planned and In development side by
547
+ side, one line per card, `●` on a card with a session running now; Merged,
548
+ Shipped and Declined — work that is over, and only grows — are counts beside
549
+ the project's name (`1 merged · 2 shipped`), as the console's board folds its
550
+ own last columns. As tall as the fullest column, never more than a
440
551
  third of the screen, and gone before the windows are on a short terminal.
441
552
  When the room runs out it is SAID: a column ends in `+N more`, empty columns
442
- go first when the width does, then whole columns (Merged, then Considering,
443
- then Planned — In development stays longest), named in the header as
444
- `merged 3 hidden`, then projects, counted as `+N projects`. Read every 30 s.
553
+ go first when the width does, then whole columns (Considering, then Planned —
554
+ In development stays longest), named in the header as `considering 3
555
+ hidden`, then projects, counted as `+N projects`. Read every 30 s.
445
556
 
446
557
  **A window says which agent and which model** — `Claude · Opus 5.5`,
447
558
  `Codex · GPT-5-codex` — bold and underlined at the head of its second line
@@ -451,16 +562,25 @@ announces on `init`, and per STAGE on a walked run, since each stage is its
451
562
  own process. An ended one's is the platform's. No model named reads
452
563
  `default model` — the CLI's own choice — rather than a guess.
453
564
 
454
- **A dev window says where it is working**: its second line is the project and
455
- the absolute path of the checkout (`subtitleFor`) — on a machine with
456
- `saasng` and its `-auto-N` clones, the one directory to open. Cut from the
457
- left when narrow, so the end of the path survives.
565
+ **A window's project has a line of its own**, the second, under the title
566
+ (`subtitleFor`) — at the end of the title a long card name pushed it out of
567
+ sight. **A dev window adds where it is working**: the project and the absolute
568
+ path of the checkout — on a machine with `saasng` and its `-auto-N` clones, the
569
+ one directory to open. Cut from the left when narrow, so the end of the path
570
+ survives.
458
571
 
459
572
  **The prompt shows what is open, not what was.** A question is the prompt's
460
573
  banner alone, whole and wrapped between words, and it goes the moment it is
461
574
  answered — here or in the console. A permission request's lines are tagged
462
575
  with it (`sayAbout`) and leave when it is decided.
463
576
 
577
+ **A question says which window it came from.** With four sessions on screen,
578
+ "waiting for an answer" is not enough to know whose. A question or a
579
+ permission request names its session (`sessionTag`) — `2 · dev · R3 Client
580
+ mail… — saasng`: the window's number, its kind, its card and its project — in
581
+ the line announcing it, in the title of the picker that answers it, and above
582
+ the banner. The card is cut to 32 columns so the question itself still fits.
583
+
464
584
  ### Checkouts made on demand: `autoWorkspaces`
465
585
 
466
586
  `"autoWorkspaces": 3` in the machine's config lets the daemon CLONE up to three
@@ -853,6 +973,19 @@ files at all. R47 removes the need for this by giving each run a workspace.
853
973
  writes to git: no merging, no branch deletion, no pushing. (A project's own
854
974
  rules can ask for all three — see below — but that is a queued action with a
855
975
  name on it, not something the survey does in passing.)
976
+ 7b. **A stage is not done while its commands are still running.** A stage is
977
+ one turn, closed the moment the turn ends, so a test suite started with
978
+ `run_in_background` and never waited for is a result lost. The daemon
979
+ follows the session's background shells (`lib/background-shells.mjs`:
980
+ `Bash` with `run_in_background`, `BashOutput`, `KillShell`); a stage whose
981
+ turn ends with one still running, or finished and never read, is reported
982
+ FAILED with the commands named, and the run fails with it — keeping its
983
+ checkout and its session (R80), so **`/continue` picks it up**. Where it
984
+ resumes is the platform's (R263: the claim's lifecycle starts at the first
985
+ stage not DONE, with what the DONE ones said); what the daemon adds is WHY
986
+ the stage stopped — the re-run is handed that and told to run its commands
987
+ in the foreground. IMPLEMENT and TEST are also told up front to
988
+ wait for every command, and TEST to commit — no stage after it writes code.
856
989
  8. **Reports the lifecycle back** and, if the session dies without saying
857
990
  anything, ends the run rather than leaving it `RUNNING` forever.
858
991
 
@@ -1077,6 +1210,39 @@ A run **`WAITING_ON_USER` is never swept.** That is the one state where nothing
1077
1210
  happening is correct: it is stalled on a person, who may reasonably take a day.
1078
1211
  Nor is a `PAUSED` or `USAGE_LIMITED` one (below) — there is no process to lose.
1079
1212
 
1213
+ ### When the daemon itself was killed (R339)
1214
+
1215
+ A daemon that dies and is restarted — by systemd, by `cawdev`, by hand — comes
1216
+ back with nothing in its hands, and the platform could only infer that five
1217
+ minutes later, as "its runner is alive but stopped driving it". So the daemon
1218
+ keeps a note of the runs it is driving (`~/.cawdev/driving/<runner id>.json`,
1219
+ rewritten when the set changes), and on boot the next one reads it: every run
1220
+ the dead daemon was driving that the platform still believes in is failed **at
1221
+ once** as `DAEMON_RESTARTED`, with the old and new pids and where to look for the
1222
+ cause. A session the old daemon left running is stopped first — only when its
1223
+ pid still runs the command it was spawned with. The workspace is held exactly as
1224
+ for a vanished runner, and a machine with **auto-resume** on carries such a run
1225
+ on by itself **once**; a second restart on the same run waits for a person,
1226
+ because a test suite that killed the daemon twice will kill it a third time.
1227
+
1228
+ The usual cause on a small Linux box is memory: the session runs a test suite,
1229
+ the kernel's OOM killer picks the biggest process, and that is sometimes the
1230
+ daemon. `journalctl -k | grep -i "killed process"` says so. Two fixes, both on
1231
+ the machine:
1232
+
1233
+ - **`"sessionMemoryMax": "6G"`** in `runner.config.json` spawns each agent
1234
+ session under `systemd-run --scope -p MemoryMax=…` (a size systemd reads —
1235
+ `6G`, `512M`, `75%`). A session that blows through it is killed on its own,
1236
+ the ordinary "agent was terminated" failure, and the daemon stays up. Linux
1237
+ only, and it needs a systemd manager for the user (`loginctl enable-linger
1238
+ <user>` on a box with nobody logged in) or a daemon running as root; the
1239
+ daemon probes once at boot and says in its log whether it applied. Needs a
1240
+ restart to change.
1241
+ - **Protect the daemon and give the box room**: in the daemon's systemd unit,
1242
+ `OOMScoreAdjust=-800` makes the kernel pick a test worker over the daemon;
1243
+ and add swap (`fallocate -l 4G /swapfile && chmod 600 /swapfile && mkswap
1244
+ /swapfile && swapon /swapfile`, plus its `/etc/fstab` line).
1245
+
1080
1246
  ## When the usage limit hits (R73)
1081
1247
 
1082
1248
  Claude Code stops with a message naming the window — the five-hour one or the
@@ -1186,8 +1352,11 @@ your inbox and on the run, and waits for an answer. Allow it once, or allow it
1186
1352
  always here — which writes a rule on the project that every runner serving it
1187
1353
  inherits.
1188
1354
 
1189
- Nobody answering is a decision too: after fifteen minutes the request expires
1190
- and the session is told to report blocked rather than wait for ever.
1355
+ Nobody answering is a decision too: after the project's wait — fifteen minutes
1356
+ unless its Rules page says otherwise, and possibly never (R339) — the request
1357
+ expires and the session is told to carry on without it. Allowing it later still
1358
+ works: the grant lasts the rest of the run and the session is sent a message to
1359
+ try again. A stage gate never expires.
1191
1360
 
1192
1361
  You can still say in advance what a project may do, and for anything a session
1193
1362
  needs on every run that is the better answer — with `allowedTools`, which