rl-workspaces 0.0.0-stage → 0.5.0

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.
Files changed (87) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +703 -2
  3. package/bin/rl +54 -0
  4. package/config.example.zsh +9 -0
  5. package/dist/access.js +40 -0
  6. package/dist/activity.js +90 -0
  7. package/dist/agent-claude.js +16 -0
  8. package/dist/agent-codex.js +22 -0
  9. package/dist/agent-launch.js +74 -0
  10. package/dist/agent-presets.js +45 -0
  11. package/dist/agent-registry.js +8 -0
  12. package/dist/agent-resume.js +96 -0
  13. package/dist/agent-runner.js +366 -0
  14. package/dist/agent-workflows.js +231 -0
  15. package/dist/agents.js +73 -0
  16. package/dist/automation-config.js +242 -0
  17. package/dist/base.js +66 -0
  18. package/dist/cleanup-path.js +33 -0
  19. package/dist/cli.js +57 -0
  20. package/dist/codex-sessions.js +188 -0
  21. package/dist/command-context.js +67 -0
  22. package/dist/common.js +262 -0
  23. package/dist/delete.js +113 -0
  24. package/dist/display.js +134 -0
  25. package/dist/doctor.js +145 -0
  26. package/dist/git-safety.js +24 -0
  27. package/dist/git-workflow.js +183 -0
  28. package/dist/help.js +726 -0
  29. package/dist/hooks.js +159 -0
  30. package/dist/json.js +34 -0
  31. package/dist/mcp.js +336 -0
  32. package/dist/picker.js +182 -0
  33. package/dist/pr-discovery.js +223 -0
  34. package/dist/pr-update.js +419 -0
  35. package/dist/pr-workflow.js +161 -0
  36. package/dist/repos.js +537 -0
  37. package/dist/review-policy.js +150 -0
  38. package/dist/session-workflows.js +616 -0
  39. package/dist/session.js +12 -0
  40. package/dist/state.js +250 -0
  41. package/dist/storage.js +366 -0
  42. package/dist/store.js +379 -0
  43. package/dist/summary.js +164 -0
  44. package/dist/task-state.js +65 -0
  45. package/dist/task.js +192 -0
  46. package/dist/templates.js +4 -0
  47. package/dist/workflow-config.js +177 -0
  48. package/dist/workflow.js +211 -0
  49. package/lib/rl.zsh +330 -0
  50. package/node_modules/graceful-fs/LICENSE +15 -0
  51. package/node_modules/graceful-fs/README.md +143 -0
  52. package/node_modules/graceful-fs/clone.js +23 -0
  53. package/node_modules/graceful-fs/graceful-fs.js +448 -0
  54. package/node_modules/graceful-fs/legacy-streams.js +118 -0
  55. package/node_modules/graceful-fs/package.json +53 -0
  56. package/node_modules/graceful-fs/polyfills.js +355 -0
  57. package/node_modules/proper-lockfile/LICENSE +21 -0
  58. package/node_modules/proper-lockfile/README.md +183 -0
  59. package/node_modules/proper-lockfile/index.js +40 -0
  60. package/node_modules/proper-lockfile/lib/adapter.js +85 -0
  61. package/node_modules/proper-lockfile/lib/lockfile.js +342 -0
  62. package/node_modules/proper-lockfile/lib/mtime-precision.js +55 -0
  63. package/node_modules/proper-lockfile/package.json +71 -0
  64. package/node_modules/retry/.npmignore +3 -0
  65. package/node_modules/retry/.travis.yml +15 -0
  66. package/node_modules/retry/License +21 -0
  67. package/node_modules/retry/Makefile +18 -0
  68. package/node_modules/retry/README.md +227 -0
  69. package/node_modules/retry/equation.gif +0 -0
  70. package/node_modules/retry/example/dns.js +31 -0
  71. package/node_modules/retry/example/stop.js +40 -0
  72. package/node_modules/retry/index.js +1 -0
  73. package/node_modules/retry/lib/retry.js +100 -0
  74. package/node_modules/retry/lib/retry_operation.js +158 -0
  75. package/node_modules/retry/package.json +32 -0
  76. package/node_modules/retry/test/common.js +10 -0
  77. package/node_modules/retry/test/integration/test-forever.js +24 -0
  78. package/node_modules/retry/test/integration/test-retry-operation.js +258 -0
  79. package/node_modules/retry/test/integration/test-retry-wrap.js +101 -0
  80. package/node_modules/retry/test/integration/test-timeouts.js +69 -0
  81. package/node_modules/signal-exit/LICENSE.txt +16 -0
  82. package/node_modules/signal-exit/README.md +39 -0
  83. package/node_modules/signal-exit/index.js +202 -0
  84. package/node_modules/signal-exit/package.json +38 -0
  85. package/node_modules/signal-exit/signals.js +53 -0
  86. package/package.json +57 -4
  87. package/shell/rl.zsh +11 -0
package/README.md CHANGED
@@ -1,3 +1,704 @@
1
- # Temporary Holding Version
1
+ # rl
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Git workspaces for Codex and Claude Code.
4
+
5
+ Create a workspace, start an agent, and keep task notes and sessions together.
6
+ Switch projects, prepare local dependencies, check PRs, and merge finished work
7
+ without losing your place.
8
+
9
+ Requires macOS or Linux, Git, zsh, and Node.js 22+. Bash users can use the Bash
10
+ integration. Install `fzf` for pickers, `gh` for PR commands, and whichever agent
11
+ you use.
12
+
13
+ ## Install
14
+
15
+ Install from npm:
16
+
17
+ ```sh
18
+ npm install --global rl-workspaces
19
+ ```
20
+
21
+ The first npm release is pending; see Development below to build the unpublished version.
22
+
23
+ Add one line to your shell configuration, then open a new terminal:
24
+
25
+ ```sh
26
+ eval "$(command rl setup shell zsh)" # ~/.zshrc
27
+ # or
28
+ eval "$(command rl setup shell bash)" # ~/.bashrc
29
+ ```
30
+
31
+ Shell integration lets `rl` change your terminal's directory. Direct executable
32
+ calls print the selected path. The integration loads the current runtime on
33
+ each call, so an npm upgrade does not leave you using old commands.
34
+
35
+ ## Get started
36
+
37
+ ```sh
38
+ rl repo add . --base origin/test
39
+ rl switch feature/login -c --agent codex
40
+ # or: rl switch feature/login -c --agent claude
41
+
42
+ rl notes append progress implementation-notes.md
43
+ rl list
44
+ rl switch @ # main checkout
45
+ rl switch - # previous workspace in this shell
46
+ rl switch feature/login
47
+ rl resume codex
48
+ ```
49
+
50
+ The default base is `origin/test`. Use `--base`, `RL_DEFAULT_BASE`, or a registered
51
+ repository's base setting to choose another branch. Creation fetches origin first,
52
+ then branches from the refreshed remote base (including an explicit `--base origin/<branch>`).
53
+ A failed fetch stops creation. This refreshes remote refs without merging into a local
54
+ branch; add `--no-fetch` to work offline using cached refs. Notes and session links
55
+ survive workspace deletion.
56
+
57
+ ## Commands and help
58
+
59
+ `rl help` shows a short list of command families. Arguments, options and examples
60
+ live in command-specific help, which works even outside a configured repository:
61
+
62
+ ```sh
63
+ rl help
64
+ rl help pr
65
+ rl help pr update
66
+ rl workflow run --help
67
+ ```
68
+
69
+ Invalid arguments show usage for that command instead of the full command list.
70
+ Git helpers live under `rl git`, shared documents under `rl notes`, saved sessions
71
+ under `rl agent`, cleanup under `rl storage`, and project/shell setup under
72
+ `rl setup`. Review policies remain separate from agent profiles and workflows.
73
+
74
+ | Command | Use |
75
+ | --- | --- |
76
+ | `rl` | Pick a workspace |
77
+ | `rl checkout` | Switch to a repository |
78
+ | `rl switch` | Open or create a workspace |
79
+ | `rl list` | List workspaces, optionally across repositories |
80
+ | `rl status` | Inspect the selected repository (`--workspace` for workspace details) |
81
+ | `rl delete` | Remove workspaces |
82
+ | `rl storage` | Inspect disk usage and clean generated files |
83
+
84
+ `rl help switch` also documents the specialized `new`, `open`, and `path`
85
+ helpers. `rl help exec` describes running an arbitrary command in a workspace.
86
+
87
+ Switching installs hooks and preserves existing notes. Creation validates names
88
+ and refuses path escapes or an already checked-out branch. `switch -c` requires a
89
+ new checkout; `new` and `open` can reopen an existing checkout. `open` flattens
90
+ slashes in directory names; `new` and `switch -c` retain nested names.
91
+
92
+ Pickers show cached PR state, commits ahead/behind the base, and recent use.
93
+ The `COMMITS + / −` column counts commits ahead/behind, rather than changed lines.
94
+ The picker compares with its displayed base; the status overview compares with the
95
+ displayed upstream. `CHANGES` reports changed files separately.
96
+ PR discovery uses `gh`; `RL_PR_OFFLINE=1` disables it. Status is offline by default.
97
+ `--fetch` explicitly refreshes tracking refs.
98
+
99
+ ## Project setup
100
+
101
+ ```sh
102
+ rl setup init
103
+ # Edit .rl/workflows.json in the main checkout.
104
+ rl setup --dry-run
105
+ rl setup
106
+ # Or: rl switch feature/login -c --setup
107
+ ```
108
+
109
+ Example configuration:
110
+
111
+ ```json
112
+ {
113
+ "copy": [".env", ".cache"],
114
+ "clean": ["node_modules", ".next", ".turbo"],
115
+ "env": { "APP_MODE": "development" },
116
+ "onCreate": [["npm", "ci"]],
117
+ "onOpen": []
118
+ }
119
+ ```
120
+
121
+ Setup runs only when explicitly requested. Commands are argument arrays, executed
122
+ in order without a shell; a failure stops setup and preserves the workspace.
123
+ `rl setup` runs both command lists. `switch --setup` runs `onCreate` for a new
124
+ checkout and `onOpen` whenever it opens one.
125
+
126
+ Copy entries must be ignored, untracked regular files or directories in both
127
+ checkouts. RL validates the complete copy plan before writing, skips existing
128
+ files, and copies independently using filesystem cloning where available.
129
+ Symlinks, tracked files, path escapes, and Git/agent/state configuration paths
130
+ are rejected.
131
+
132
+ Setup, `exec`, and agent launch receive the configured environment,
133
+ `RL_WORKSPACE`, and a stable `RL_PORT` derived from the repository and workspace.
134
+ Use `RL_PORT` in your development server command. It is a suggested port, not a
135
+ reservation; another process can occupy it. Project environment keys are limited
136
+ to `APP_*`, `PUBLIC_*`, `VITE_*`, `NEXT_PUBLIC_*`, `REACT_APP_*`, `PORT`,
137
+ `NODE_ENV`, `DATABASE_URL`, and `REDIS_URL`. Runtime loader, executable search,
138
+ agent configuration, and permission variables cannot be overridden by the project.
139
+
140
+ ## Storage and cleanup
141
+
142
+ These commands operate only on the current adopted RL workspace, including when
143
+ run from a directory inside it. They reject workspace selectors and cross-repository
144
+ routing. They do not scan or clean sibling worktrees.
145
+
146
+ ```sh
147
+ rl storage # disk usage, largest paths, and cleanup suggestions
148
+ rl storage --json # structured usage report
149
+ rl storage clean --dry-run # preview configured generated directories and savings
150
+ rl storage clean # remove those generated directories
151
+ ```
152
+
153
+ Add a `clean` array to `.rl/workflows.json` in the current workspace:
154
+
155
+ ```json
156
+ { "clean": ["node_modules", ".next", ".turbo"] }
157
+ ```
158
+
159
+ The default list is empty. Entries must be literal, ignored directory paths.
160
+ Cleanup validates the complete plan before deleting anything and refuses tracked
161
+ files, credentials such as `.env`, Git/agent/task metadata, and symlink targets.
162
+ Links inside generated directories are unlinked without traversing their targets.
163
+ Code changes, branches, notes, sessions, and task handoffs stay in place. Close
164
+ development servers before cleaning their dependencies; use your project's install
165
+ and build commands to regenerate them later.
166
+
167
+ Storage reports approximate allocated sizes, deduplicating hard links within the
168
+ workspace. Cleanup estimates exclude hard-linked file data retained outside the
169
+ selected directories; filesystem clones and snapshots can also reduce actual
170
+ savings. Suggestions use the current workspace's last-access time (14 days by
171
+ default, configurable with `--older-than 30d`) and its cached PR state. Nothing is
172
+ deleted automatically.
173
+
174
+ ## Finish a feature
175
+
176
+ ```sh
177
+ rl git diff --base origin/test -- --stat
178
+ rl git log --base origin/test -- --graph
179
+ rl git commit -m "Add login" # staged changes
180
+ rl git commit --all -m "Fix login" # tracked changes; untracked files require git add
181
+ rl git rebase --base origin/test
182
+ rl git squash --base origin/test -m "Add login"
183
+ rl git merge test --dry-run
184
+ rl git merge test --cleanup
185
+ ```
186
+
187
+ Git mutation commands also accept `--dry-run`. Rebase and squash require a clean
188
+ workspace. Squash preserves the original HEAD under a printed
189
+ `refs/rl/backups/<UUID>` ref; it rewrites local feature history without pushing.
190
+
191
+ Merge targets a checked-out local branch in the main or a managed checkout.
192
+ It requires clean source and target workspaces and defaults to fast-forward only.
193
+ For an explicit squash merge, use `rl git merge test --squash -m "Add login"`.
194
+ Conflicts are left available for normal Git resolution. Nothing implicitly
195
+ stashes changes or force-pushes.
196
+
197
+ `--cleanup` removes the clean source checkout only after successful integration.
198
+ An unmerged source branch is retained if Git refuses safe branch deletion,
199
+ including after a squash merge. The main checkout cannot be removed.
200
+
201
+ ```sh
202
+ rl delete old-task another-task
203
+ rl delete --dry-run old-task
204
+ rl delete --force abandoned-task
205
+ ```
206
+
207
+ Default deletion refuses dirty workspaces and branches not merged into their
208
+ upstream, or the main checkout when no upstream exists. `--force` explicitly
209
+ discards uncommitted work and unmerged local branches. Remote branches are never
210
+ deleted. Locked worktrees remain protected. Deletion supports the multi-select
211
+ picker and `--jobs 1..32` (default 4), retaining notes and session history.
212
+
213
+ ## Pull requests
214
+
215
+ ```sh
216
+ rl pr # open this branch's PR in your browser
217
+ rl pr sync # save this branch's PR state
218
+ rl pr show # readable saved snapshot with the full PR link
219
+ rl pr show --json # saved metadata for scripts
220
+ rl pr checks [--json] # query checks and preserve gh's exit status
221
+ rl pr checkout 123 # new managed pr-123 workspace
222
+ rl pr checkout 123 --name review/login
223
+ rl pr update --base test # select your RL session PRs behind test, then update them
224
+ rl pr update 123 456 --base test --dry-run # preview an explicit selection
225
+ ```
226
+
227
+ `rl status --workspace` groups Git, PR, session, and task details with aligned labels,
228
+ relative cache times, and terminal colors (`NO_COLOR=1` disables colors);
229
+ use `rl status --workspace --json` for scripts. `rl pr sync --json` keeps machine-readable
230
+ refresh output. `rl pr show` works offline. `rl pr` uses the saved URL when
231
+ available; if the browser cannot open, that link remains in its output. With no
232
+ saved PR, it looks up the current branch through `gh pr view --web`.
233
+
234
+ Opening, refreshing, checks, and checkout require authenticated `gh`. Checkout verifies the origin repository,
235
+ PR identity, and fetched commit before creating a workspace. Fork PR checkout
236
+ is currently rejected. It does not change your current branch, publish, or merge
237
+ a PR. Failed refreshes retain the previous snapshot.
238
+
239
+ `rl pr update` brings selected PR branches up to date by merging the latest base
240
+ branch into them on GitHub. Run it from your current adopted RL workspace; it
241
+ uses that repository's configured base by default, or `--base test` / `origin/test`.
242
+ Only PR branches belonging to your active RL session workspaces in this repository
243
+ are eligible. Deleted session records and unrelated PRs are excluded. Saved Codex
244
+ or Claude conversations and a cached PR link are not required: RL matches the
245
+ live PR's head branch to its workspace records. Explicit PR numbers follow the
246
+ same restriction, and session ownership is checked again before each update.
247
+ PRs remain open. This command updates remote branches and requires authenticated
248
+ `gh` with permission to update those PRs. Local branches, edits, sessions, and
249
+ sibling worktrees are left in place; it creates no additional worktrees.
250
+
251
+ Without PR numbers, `fzf` lets you select multiple open PRs from your RL sessions
252
+ targeting the chosen base and missing some of its commits. Tab selects, Ctrl-A
253
+ selects all displayed rows, and Enter updates the selection. The picker checks up
254
+ to 100 matching session PRs by default;
255
+ `--limit` accepts 1–200, and a single batch accepts at most 50 selections. Explicit
256
+ numbers avoid the picker. `--dry-run` performs read-only checks and reports what
257
+ would be updated. If GitHub hasn't calculated mergeability yet, the preview says so.
258
+
259
+ Each result includes the PR link, branch, behind count in commits, and an outcome:
260
+ updated, already up to date, conflict, changed since selection, failed, pending,
261
+ or skipped. RL continues after individual failures and prints a final summary;
262
+ `--json` provides structured results. GitHub's update request checks the expected
263
+ PR head commit so concurrent changes are rejected. RL verifies that the base is
264
+ included before reporting an update as complete; accepted updates that cannot
265
+ yet be verified stay pending. Conflicts and other incomplete outcomes return a
266
+ nonzero exit status. Closed, retargeted, and fork PRs are skipped.
267
+
268
+ ## Codex and Claude
269
+
270
+ ### Pause a task and continue later
271
+
272
+ Tell your agent “pause this task” once it has RL hooks or the RL MCP tools.
273
+ It saves a handoff containing the current session, concrete changes, reported
274
+ validation results, next steps, and blockers. The hook context tells agents how
275
+ to do this; MCP exposes `rl_task_pause` for a structured save.
276
+
277
+ ```sh
278
+ rl continue # most recently paused task in the selected repository
279
+ rl continue feature/login # choose a specific branch or workspace
280
+ rl continue --no-agent # open it and print the handoff without launching an agent
281
+ ```
282
+
283
+ With shell integration, `continue` changes your terminal's directory. It resumes
284
+ the exact conversation saved in the handoff, including when another session was
285
+ used more recently, and supplies the handoff as the initial prompt. It also points
286
+ the agent to the full shared context/progress documents. Hooks are not required
287
+ to deliver this continuation prompt. A failed launch leaves the task paused;
288
+ a newer handoff saved during the resumed session is retained. When no tasks are
289
+ paused, `continue` opens the most recently continued task. Selection stays within
290
+ the repository chosen by RL's normal routing or `--repo`.
291
+
292
+ An agent can save directly from its shell:
293
+
294
+ ```sh
295
+ rl pause --summary "Login error states" \
296
+ --changes "Added client-side validation in src/login.ts" \
297
+ --validation "Unit tests passed; browser checks not run" \
298
+ --next "Implement the server-error state, then run browser checks" \
299
+ --blockers "Waiting for final copy"
300
+ ```
301
+
302
+ Codex's current UUID is inferred from its environment. Outside Codex, pass
303
+ `--session <UUID>`; Claude also requires `--agent claude --session <UUID>`.
304
+ For automation, `rl pause --file handoff.json` or `rl pause --file -` accepts
305
+ JSON with `summary`, `changes`, `validation`, `next`, optional `blockers`,
306
+ `agent`, and `sessionId`. `--json` prints the saved checkpoint. Required text
307
+ fields cannot be empty; use “Not run” for checks that were not performed.
308
+
309
+ Pausing saves the handoff and session together under the state lock. It does not
310
+ stop the agent or alter Git files. Every checkpoint stays in the workspace's
311
+ `task.handoffs` history, including after workspace deletion. `rl status --workspace` includes
312
+ the saved handoffs, and `rl list` adds a TASK column showing `paused` or `active`.
313
+
314
+ ### Start and resume agents
315
+
316
+ ```sh
317
+ rl agent start codex -- --model <model>
318
+ rl agent start claude
319
+ rl agent run codex --prompt "Review the change" -- --json
320
+ rl agent run claude --prompt "Review the change"
321
+ rl agent handoff claude --output handoff.md
322
+ rl resume # choose among this workspace's Codex and Claude sessions
323
+ rl resume --latest # resume the most recently used session directly (-l / --l)
324
+ rl resume codex # choose only among Codex sessions
325
+ rl resume codex --latest # resume the most recently used Codex session directly
326
+ rl resume claude # choose only among Claude sessions
327
+ rl agent save codex # from inside Codex, if needed
328
+ rl doctor
329
+ rl doctor --repair
330
+ ```
331
+
332
+ Both launch modes preserve agent options after `--`, use the selected workspace,
333
+ and return the agent's exit status. Headless mode uses `codex exec` or
334
+ `claude --print`. RL leaves permissions and authentication to the agent.
335
+
336
+ `rl resume` lists saved Codex and Claude sessions for the current RL workspace.
337
+ If multiple sessions match, an `fzf` picker shows the agent, full session UUID,
338
+ last-used time, and start time, with the most recently used first. If exactly
339
+ one session matches, it resumes automatically. An optional `codex` or `claude`
340
+ argument filters the choices. Escape cancels without launching an agent.
341
+ Use `--latest` (or `-l` / `--l`) to skip the picker and resume the most recently
342
+ used matching session directly.
343
+ `rl continue` still resumes the exact session saved in its task handoff.
344
+
345
+ Run Codex normally in an adopted RL workspace, including in the Codex app.
346
+ `rl status`, `rl list`, `rl instances`, `rl agent sessions`, and `rl resume` / `rl resume codex`
347
+ automatically discover and save matching sessions through Codex's
348
+ [`thread/list` API](https://learn.chatgpt.com/docs/app-server#list-threads-with-pagination--filters).
349
+ Discovery filters by the exact workspace directory, excludes subagents and
350
+ ephemeral sessions, and checks branch metadata and existing ownership. Without
351
+ branch metadata, only sessions created after workspace adoption are imported.
352
+ It reads metadata from Codex's state database, preserves newer saved usage times,
353
+ and leaves saved sessions available if Codex is missing or discovery fails.
354
+ Overview tables show saved session counts in the CODEX and CLAUDE columns.
355
+
356
+ An agent can also run `rl agent save` (Codex by default) or
357
+ `rl agent save codex`; this uses its `CODEX_THREAD_ID`, falling back to
358
+ `CODEX_SESSION_ID`. `rl agent save <agent> <UUID>` explicitly saves a particular conversation.
359
+ Repeated saves update the existing entry. Resume uses the exact recorded UUID.
360
+ Observed Codex `thr_...` IDs are diagnostic only until UUID association is available.
361
+
362
+ Hooks supply shared context/progress at session start, after compaction, and to
363
+ subagents. Prompt submission refreshes changed notes. Codex hooks must be reviewed
364
+ and trusted with `/hooks` before they run; session discovery works independently.
365
+
366
+ | Integration | Codex | Claude Code |
367
+ | --- | --- | --- |
368
+ | Interactive / headless launch | `codex` / `codex exec` | `claude` / `claude --print` |
369
+ | Resume | `codex resume <UUID>` | `claude --resume <UUID>` |
370
+ | Project hooks | `.codex/hooks.json` | `.claude/settings.local.json` |
371
+ | Shared lifecycle | SessionStart, UserPromptSubmit, Stop, SessionEnd, SubagentStart, SubagentStop | Same |
372
+ | Optional extended hooks | Interrupt | StopFailure, Notification |
373
+
374
+ Run `rl setup adopt --extended-hooks` only with agent versions supporting those events.
375
+ Adoption preserves unrelated hooks/settings and excludes generated files locally.
376
+ It never edits global agent configuration. Review agent hook trust and restart
377
+ the agent after adoption or repair.
378
+
379
+ Doctor reports PATH/version/help probes, installed handlers, and observed events.
380
+ Installed help is evidence for launch options; installed files are not proof of
381
+ trusted hook delivery. Activity is `working`, `idle`, `ended`, or `stale` after
382
+ 30 minutes without an event. It describes observations, not process liveness.
383
+
384
+ Compatibility is tested with documented payloads, stub processes, and installed
385
+ CLI help: Codex 0.160.1 and Claude Code 2.1.290. Live model sessions and all older
386
+ versions are not certified. See the official [Codex hooks](https://learn.chatgpt.com/docs/hooks)
387
+ and [Claude hooks](https://code.claude.com/docs/en/hooks) contracts.
388
+
389
+ ## Session-driven agent workflows
390
+
391
+ Your current Codex or Claude session owns its native subagents. RL supplies
392
+ reusable roles, workflow dependencies, trigger rules, policies and durable run
393
+ records. RL never launches a provider CLI, model API or check process for a
394
+ workflow. The parent session claims ready steps, creates native children and
395
+ reports their evidence; it runs configured checks itself.
396
+
397
+ ```sh
398
+ rl workflow init # configure this adopted workspace and refresh hooks
399
+ rl agent add auth --instructions auth-review.md --description "Authentication reviewer"
400
+ rl agent list
401
+ rl agent show auth
402
+ rl workflow add auth-review --file auth-workflow.json
403
+ rl workflow set auth-review --file auth-workflow.json
404
+ rl workflow context --json # discover definitions and trigger rules
405
+ rl workflow status # latest saved run
406
+ rl workflow metrics
407
+ rl policy show review
408
+ ```
409
+
410
+ Configuration stays in this worktree:
411
+
412
+ | File | Owns |
413
+ | --- | --- |
414
+ | `.rl/agents.json` | Roles: description, instructions, optional model/reasoning and `access` preferences; provider defaults to `inherit` |
415
+ | `.rl/agent-workflows.json` | Trigger rules, ordered/parallel steps, concurrency, retry budget, report deadlines and selected policy |
416
+ | `.rl/policies.json` | Criteria, severity deduction weights and acceptance requirements |
417
+
418
+ Each file has `"version": 1` and a named `agents`, `workflows` or `policies` map.
419
+ `rl agent add/set <name> --file profile.json` also saves complete profiles.
420
+ Missing files use preset definitions for discovery, but automatic trigger
421
+ handling requires at least one explicit configuration file. Existing legacy
422
+ provider preferences remain readable; they never authorize starting a separate
423
+ Codex/Claude process. Native model and reasoning options are applied by the
424
+ parent where supported; unavailable settings must be reported explicitly.
425
+
426
+ Session-start hooks detect configuration and teach the parent the protocol.
427
+ Prompt hooks refresh it after configuration changes, including after compaction.
428
+ Tool hooks deliver matching requests as the parent works. Before-edit/tool rules
429
+ deny the pending tool until their request completes or is explicitly dismissed
430
+ (or the user cancels its run), so the parent can delegate before retrying.
431
+ Workflow coordination tools are excluded from this gate. The preset queues
432
+ `triple-review` before finishing changed work: behavior/security, reuse/complexity
433
+ and implementation-quality roles, all read-only. Child hooks do not recursively
434
+ queue workflows. Normal session resume and task checkpoints remain independent.
435
+
436
+ For example, save the following as `auth-workflow.json`, then add it using the
437
+ command above:
438
+
439
+ ```json
440
+ {
441
+ "description": "Review authentication changes before finishing",
442
+ "policy": "review",
443
+ "concurrency": 2,
444
+ "retries": 1,
445
+ "timeoutSeconds": 600,
446
+ "triggers": [
447
+ { "event": "before_edit", "tools": ["Edit", "apply_patch"], "paths": ["src/auth/**"] },
448
+ { "event": "before_finish", "changes": true },
449
+ { "event": "task_planned" }
450
+ ],
451
+ "steps": [
452
+ { "id": "types", "command": ["pnpm", "tsc", "--noEmit"], "after": [] },
453
+ { "id": "auth", "agent": "auth", "after": ["types"] },
454
+ { "id": "quality", "agent": "quality", "after": ["types"] }
455
+ ]
456
+ }
457
+ ```
458
+
459
+ Automatic events are `session_start`, `prompt`, `before_edit`, `after_edit`,
460
+ `before_tool`, `after_tool`, and `before_finish`. Edit events recognize
461
+ Edit/Write/MultiEdit/apply_patch; other tools, including shell commands, use the
462
+ tool events. `tools` matches exact hook tool names; `paths` matches workspace
463
+ relative file paths with `*` (one path segment) and `**` (across segments).
464
+ Path filtering uses structured edit paths/patch headers, not guesses about shell
465
+ commands. `changes: true` requires changes in the locally available comparison
466
+ scope. Semantic events such as `task_planned` are explicitly reported by the
467
+ parent, since RL cannot observe private reasoning. All conditions on a rule
468
+ must match; multiple rules are alternatives.
469
+
470
+ Matching events queue requests for that parent conversation only. Identical
471
+ scope/configuration events are deduplicated; newer changes coalesce into an
472
+ unclaimed request. Before-finish hooks can continue the turn once with the
473
+ request, and guard against repeated Stop-hook loops. They cannot force a client
474
+ to offer or use native delegation. If unavailable or disallowed by current
475
+ instructions, the session must dismiss the request with its concrete reason
476
+ and report that limitation. Current permissions and workspace boundaries apply
477
+ to every child. Read-only roles receive instructions to remain read-only; host
478
+ permissions are enforced by the host, not by RL.
479
+
480
+ The MCP server (`rl agent mcp`) exposes:
481
+
482
+ 1. `rl_workflow_context`: discover roles, workflows, triggers and policies.
483
+ 2. `rl_workflow_pending`: read this parent session's queued requests.
484
+ 3. `rl_workflow_event`: report an explicit milestone and match trigger rules.
485
+ 4. `rl_workflow_start`: create a session-owned run, optionally from a request ID.
486
+ 5. `rl_workflow_claim`: atomically claim one ready stage and receive its prompt,
487
+ dependencies, scope path, output schema and native settings.
488
+ 6. `rl_workflow_report`: submit the claim token and child findings, an actual
489
+ check result, or a failure. RL validates the report and calculates the score.
490
+ 7. `rl_workflow_dismiss`: decline a queued request with a recorded reason.
491
+
492
+ Supply `agent` and the parent conversation's full `sessionId`; Codex may infer
493
+ its ID from the environment, while Claude supplies its UUID explicitly. Observed
494
+ Codex `thr_` IDs also coordinate workflows, but never enter UUID-based resumable
495
+ session history. These are
496
+ coordination identities within the local workspace, not an authentication
497
+ boundary against a process that already has access to its state files.
498
+ CLI equivalents are available when the session has no MCP connection:
499
+
500
+ ```sh
501
+ rl workflow pending --agent claude --session <UUID>
502
+ rl workflow run --request <request-UUID> --agent claude --session <UUID>
503
+ rl workflow event --file event.json --agent claude --session <UUID>
504
+ rl workflow run auth-review --base origin/test --agent claude --session <UUID>
505
+ rl workflow claim <run> --agent claude --session <UUID>
506
+ rl workflow report <run> --file report.json --agent claude --session <UUID>
507
+ ```
508
+
509
+ An event file contains `{ "event": "task_planned" }`; report files contain
510
+ `step`, `claim`, and `result` (the returned schema), or `check` with actual
511
+ `stdout`, `stderr`, `exitCode`, or `error`. Reports may include `childId` and
512
+ parent-reported token/cost usage. Commands and reports return data for the parent;
513
+ `workflow run` prepares work and returns without spawning agents. `--dry-run`
514
+ previews scope without creating a run.
515
+
516
+ Dependencies and concurrency are enforced when stages are claimed. Explicit
517
+ predecessor results are supplied to dependent agents; independent roles receive
518
+ no peer reports. A failed check blocks dependents. Reported agent failures may
519
+ be retried within the configured budget. Routing leads receive one focused
520
+ follow-up by their owning role. Further leads remain coverage limitations.
521
+
522
+ Review scope includes committed branch changes from the merge-base, staged,
523
+ unstaged and non-ignored untracked changes, capped at 4 MiB. The selected base
524
+ uses local refs, without fetching; event detection uses HEAD if the saved base
525
+ is not locally resolvable. RL checks fingerprints before claims and reports.
526
+ Unexpected changed scope requires a new run. Roles default to read-only. A profile with `"access": "workspace-write"` may
527
+ implement its assigned changes within the host's existing permissions. Writing
528
+ stages run exclusively. RL refreshes scope after the writer reports, so later
529
+ reviewers inspect its changes. Earlier checks/reviews remain historical; they
530
+ cannot justify readiness for changed code unless refreshed after writing. Place
531
+ final validation after the writer in the workflow. Unexpected edits during a
532
+ read-only stage still invalidate its result.
533
+
534
+ Policies remain separate. The default deducts 50/20/10/2 for
535
+ critical/high/medium/low findings, deduplicates exact file/line/root-cause matches,
536
+ and blocks readiness on required fixes or coverage gaps. Agents return evidence
537
+ without assigning scores. `rl workflow score --policy review` rescores recorded
538
+ findings and preserves assessment history without agent calls.
539
+
540
+ `workflow pause` stops new claims but accepts reports from already claimed
541
+ children. The parent owns child cancellation and must stop its native agents.
542
+ After existing children have reported, that parent can `workflow resume` using
543
+ the saved configuration. Cancellation rejects further results and requires a
544
+ new run. Neither command sends process signals. Runs retain their parent UUID,
545
+ claim tokens, native child IDs, evidence, scope and policy assessments under the
546
+ current instance's `workflow-runs/` directory. RL measures claim-to-report elapsed
547
+ time; token/cost usage is parent-reported and missing totals remain unknown.
548
+
549
+ After upgrading existing workspaces, run `rl doctor --repair` to add tool hooks,
550
+ and restart/review hooks as required by your host. Native hook integration follows
551
+ the [Codex hooks](https://learn.chatgpt.com/docs/hooks) and
552
+ [Claude hooks](https://code.claude.com/docs/en/hooks) contracts. Automated tests
553
+ exercise hook payloads and MCP/CLI coordination; they do not certify live model
554
+ compliance or native delegation availability in every client.
555
+
556
+ ## Let agents use notes through MCP
557
+
558
+ `rl agent mcp` serves workspace-scoped tools over stdio: `rl_status`, `rl_context`,
559
+ `rl_progress`, `rl_context_append`, `rl_progress_append`, `rl_session_save`,
560
+ `rl_task_pause`, and the seven `rl_workflow_*` coordination tools described above.
561
+ `rl_task_pause` accepts the handoff JSON described above and atomically saves
562
+ the session and task checkpoint. `rl_status` includes task state and handoff history.
563
+ `rl_status` automatically discovers Codex sessions for this workspace.
564
+ `rl_session_save` accepts `{"agent":"codex","sessionId":"<UUID>"}`;
565
+ `agent` defaults to Codex. If `sessionId` is omitted, it uses the MCP server's
566
+ Codex environment when available. Clients should pass their current UUID when
567
+ the server does not inherit it. Claude requires an explicit UUID.
568
+ Append tools take `{"text":"..."}`. They share the same locked document updates
569
+ as the CLI and expose no arbitrary command, deletion, or filesystem tool.
570
+
571
+ In the adopted workspace, add an entry to its trusted `.codex/config.toml`:
572
+
573
+ ```toml
574
+ [mcp_servers.rl]
575
+ command = "rl"
576
+ args = ["agent", "mcp"]
577
+ ```
578
+
579
+ For Claude, merge this entry into the workspace's `.mcp.json`:
580
+
581
+ ```json
582
+ {
583
+ "mcpServers": {
584
+ "rl": { "type": "stdio", "command": "rl", "args": ["agent", "mcp"] }
585
+ }
586
+ }
587
+ ```
588
+
589
+ The client must launch the server in this workspace with `rl` on PATH.
590
+ With custom state settings, pass the same `RL_STATE_DIR` in the server environment.
591
+ Review project trust/server approval normally. Configuration follows the official
592
+ [Codex MCP guide](https://learn.chatgpt.com/docs/extend/mcp?surface=cli) and
593
+ [Claude MCP guide](https://code.claude.com/docs/en/mcp).
594
+ RL does not modify global client settings or relax agent sandbox permissions.
595
+
596
+ ## Notes and reports
597
+
598
+ ```sh
599
+ rl notes show context
600
+ rl notes show progress
601
+ rl notes set context feature-notes.md
602
+ rl notes append progress implementation-notes.md
603
+ printf 'Done: parser. Next: integration tests.\n' | rl notes append progress -
604
+ rl notes summary --stdout
605
+ rl notes summary --output feature-report.md
606
+ ```
607
+
608
+ Context records scope, domain rules, acceptance criteria, and design decisions.
609
+ Progress records completed work, remaining tasks, implementation details, and
610
+ validation. Append preserves concurrent updates; set replaces a document.
611
+ Handoff and summary exports refuse to overwrite existing files; summary also
612
+ supports explicit `--force`. Long injected notes include an excerpt and their path.
613
+
614
+ State lives under `$RL_STATE_DIR/<repository-hash>/<instance-UUID>/`, outside
615
+ the checkout, with `instance.json`, `context.md`, and `progress.md`.
616
+ Deleting a workspace archives its record. Recreating it starts a new instance
617
+ with separate sessions. Back up state alongside your work.
618
+
619
+ ## Multiple repositories and settings
620
+
621
+ ```sh
622
+ rl repo add /path/to/frontend --base origin/test
623
+ rl repo add /path/to/backend --base origin/test
624
+ # Or run `rl repo add .` inside each repository.
625
+ rl checkout frontend
626
+ rl # pick a frontend workspace
627
+ rl checkout backend
628
+ rl checkout # pick a repository
629
+ rl repo list
630
+ rl repo use backend # default when outside registered repositories
631
+ rl --repo backend list # inspect another repo without switching
632
+ ```
633
+
634
+ Registration uses the repository name from `origin`, or the main checkout folder
635
+ name without an origin. An alias is optional: `rl repo add . --alias frontend`.
636
+ The previous `rl repo add frontend /path/to/repository` syntax still works.
637
+ Name collisions require a distinct alias.
638
+
639
+ `rl checkout [repository]` enters that repository's main checkout using shell
640
+ integration (or prints its path when run directly). With no name, it offers a
641
+ repository picker; a single registered repository is selected automatically.
642
+ It preserves Git branches and changes, and leaves the configured default alone.
643
+ Bare `rl` then offers workspaces for the repository you entered. `rl status` shows
644
+ the selected repository, how it was selected, its base, workspaces and saved session
645
+ counts. Use `rl status --workspace` for the detailed current-workspace view;
646
+ `--json` follows the selected view.
647
+
648
+ Repositories are registered explicitly; RL does not scan siblings. Command selection
649
+ uses `--repo`, then `RL_REPO`, the current registered worktree, and the registry
650
+ default. An explicit `RL_REPO` override still applies after changing directories.
651
+ Removing a repository registration retains all worktrees and state.
652
+ Without registered repositories or an explicit `RL_REPO_ROOT`, RL detects the
653
+ main checkout of the current Git repository, including from linked worktrees
654
+ and subdirectories.
655
+
656
+ | Environment setting | Default |
657
+ | --- | --- |
658
+ | `RL_WORKTREE_DIR` | `$HOME/.rl/worktrees` |
659
+ | `RL_STATE_DIR` | `$HOME/.rl/instances` |
660
+ | `RL_REPO` | Optional repository alias |
661
+ | `RL_PR_OFFLINE` | Set to `1` to disable PR queries |
662
+
663
+ Environment variables can also come from trusted zsh configuration selected by
664
+ `RL_CONFIG`, defaulting to `~/.config/rl/config.zsh`. See
665
+ [config.example.zsh](config.example.zsh). Registration supplies repository/base
666
+ settings; `rl help` and individual `--help` show command options.
667
+
668
+ ## Compatibility aliases
669
+
670
+ Existing commands keep their behavior. They are omitted from the main help to
671
+ keep one primary spelling for each operation:
672
+
673
+ | Previous command | Primary command |
674
+ | --- | --- |
675
+ | `rl step commit/rebase/squash`, `rl diff/log/merge` | `rl git commit/rebase/squash/diff/log/merge` |
676
+ | `rl context/progress show/set/append/path` | `rl notes show/set/append/path context/progress` |
677
+ | `rl summary` | `rl notes summary` |
678
+ | `rl session list/save/add` | `rl agent sessions/save` |
679
+ | `rl handoff`, `rl mcp` | `rl agent handoff`, `rl agent mcp` |
680
+ | `rl clean` | `rl storage clean` |
681
+ | `rl config init/show`, `rl adopt`, `rl init` | `rl setup init/show`, `rl setup adopt`, `rl setup shell` |
682
+ | `rl status --list`, `rl status --all` | `rl list`, `rl list --all` |
683
+
684
+ ## Development
685
+
686
+ ```sh
687
+ npm ci
688
+ npm run build
689
+ npm test
690
+ npm run format:check
691
+ npm pack --dry-run
692
+ ```
693
+
694
+ To install an unpublished checkout after building it, run `npm install --global .`
695
+ from that checkout.
696
+
697
+ Strict TypeScript modules share Store, Git execution, workspace resolution, and
698
+ agent adapters. Tests use isolated temporary repositories, representative hook
699
+ payloads, stub agents/GitHub, and a real offline tarball installation. They do
700
+ not modify your global install or launch paid sessions. `npm test` includes
701
+ package and shell smoke checks. No npm install script runs application setup.
702
+
703
+ Issues and pull requests are welcome. Include reproduction steps and validation.
704
+ Licensed under [MIT](LICENSE).