@exla/rudder 0.0.0-stage → 3.4.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 (181) hide show
  1. package/LICENSE +100 -0
  2. package/README.md +733 -2
  3. package/assets/rudder.icns +0 -0
  4. package/assets/sounds/NOTICE.md +8 -0
  5. package/assets/sounds/ping.mp3 +0 -0
  6. package/dist/agent-attention.d.ts +5 -0
  7. package/dist/agent-attention.js +54 -0
  8. package/dist/agent-attention.js.map +1 -0
  9. package/dist/analytics.d.ts +36 -0
  10. package/dist/analytics.js +178 -0
  11. package/dist/analytics.js.map +1 -0
  12. package/dist/attach-session.d.ts +91 -0
  13. package/dist/attach-session.js +290 -0
  14. package/dist/attach-session.js.map +1 -0
  15. package/dist/auth.d.ts +36 -0
  16. package/dist/auth.js +392 -0
  17. package/dist/auth.js.map +1 -0
  18. package/dist/backends.d.ts +3 -0
  19. package/dist/backends.js +638 -0
  20. package/dist/backends.js.map +1 -0
  21. package/dist/board/board.css +1 -0
  22. package/dist/board/board.js +2 -0
  23. package/dist/board/daemon.d.ts +39 -0
  24. package/dist/board/daemon.js +1510 -0
  25. package/dist/board/daemon.js.map +1 -0
  26. package/dist/brain.d.ts +24 -0
  27. package/dist/brain.js +244 -0
  28. package/dist/brain.js.map +1 -0
  29. package/dist/bus.d.ts +9 -0
  30. package/dist/bus.js +23 -0
  31. package/dist/bus.js.map +1 -0
  32. package/dist/checkout-sync.d.ts +35 -0
  33. package/dist/checkout-sync.js +247 -0
  34. package/dist/checkout-sync.js.map +1 -0
  35. package/dist/cloud.d.ts +48 -0
  36. package/dist/cloud.js +4596 -0
  37. package/dist/cloud.js.map +1 -0
  38. package/dist/codex-binary.d.ts +12 -0
  39. package/dist/codex-binary.js +184 -0
  40. package/dist/codex-binary.js.map +1 -0
  41. package/dist/context-audit.d.ts +21 -0
  42. package/dist/context-audit.js +109 -0
  43. package/dist/context-audit.js.map +1 -0
  44. package/dist/daemon.d.ts +27 -0
  45. package/dist/daemon.js +203 -0
  46. package/dist/daemon.js.map +1 -0
  47. package/dist/effort.d.ts +9 -0
  48. package/dist/effort.js +72 -0
  49. package/dist/effort.js.map +1 -0
  50. package/dist/feedback.d.ts +46 -0
  51. package/dist/feedback.js +173 -0
  52. package/dist/feedback.js.map +1 -0
  53. package/dist/gc.d.ts +3 -0
  54. package/dist/gc.js +262 -0
  55. package/dist/gc.js.map +1 -0
  56. package/dist/git.d.ts +31 -0
  57. package/dist/git.js +455 -0
  58. package/dist/git.js.map +1 -0
  59. package/dist/goal.d.ts +33 -0
  60. package/dist/goal.js +95 -0
  61. package/dist/goal.js.map +1 -0
  62. package/dist/graph.d.ts +93 -0
  63. package/dist/graph.js +372 -0
  64. package/dist/graph.js.map +1 -0
  65. package/dist/handoff.d.ts +110 -0
  66. package/dist/handoff.js +565 -0
  67. package/dist/handoff.js.map +1 -0
  68. package/dist/improve/advisor.d.ts +10 -0
  69. package/dist/improve/advisor.js +115 -0
  70. package/dist/improve/advisor.js.map +1 -0
  71. package/dist/improve/collect.d.ts +49 -0
  72. package/dist/improve/collect.js +274 -0
  73. package/dist/improve/collect.js.map +1 -0
  74. package/dist/improve/gate.d.ts +17 -0
  75. package/dist/improve/gate.js +60 -0
  76. package/dist/improve/gate.js.map +1 -0
  77. package/dist/improve/index.d.ts +9 -0
  78. package/dist/improve/index.js +376 -0
  79. package/dist/improve/index.js.map +1 -0
  80. package/dist/improve/judge.d.ts +32 -0
  81. package/dist/improve/judge.js +114 -0
  82. package/dist/improve/judge.js.map +1 -0
  83. package/dist/improve/mine.d.ts +31 -0
  84. package/dist/improve/mine.js +192 -0
  85. package/dist/improve/mine.js.map +1 -0
  86. package/dist/improve/propose.d.ts +51 -0
  87. package/dist/improve/propose.js +150 -0
  88. package/dist/improve/propose.js.map +1 -0
  89. package/dist/improve/rank.d.ts +16 -0
  90. package/dist/improve/rank.js +49 -0
  91. package/dist/improve/rank.js.map +1 -0
  92. package/dist/improve/schedule.d.ts +1 -0
  93. package/dist/improve/schedule.js +95 -0
  94. package/dist/improve/schedule.js.map +1 -0
  95. package/dist/improve/ship.d.ts +25 -0
  96. package/dist/improve/ship.js +82 -0
  97. package/dist/improve/ship.js.map +1 -0
  98. package/dist/improve/state.d.ts +157 -0
  99. package/dist/improve/state.js +264 -0
  100. package/dist/improve/state.js.map +1 -0
  101. package/dist/index.d.ts +2 -0
  102. package/dist/index.js +88 -0
  103. package/dist/index.js.map +1 -0
  104. package/dist/jj-binary.d.ts +36 -0
  105. package/dist/jj-binary.js +143 -0
  106. package/dist/jj-binary.js.map +1 -0
  107. package/dist/jj.d.ts +163 -0
  108. package/dist/jj.js +926 -0
  109. package/dist/jj.js.map +1 -0
  110. package/dist/logger.d.ts +22 -0
  111. package/dist/logger.js +110 -0
  112. package/dist/logger.js.map +1 -0
  113. package/dist/main.d.ts +3 -0
  114. package/dist/main.js +1366 -0
  115. package/dist/main.js.map +1 -0
  116. package/dist/migration.d.ts +82 -0
  117. package/dist/migration.js +198 -0
  118. package/dist/migration.js.map +1 -0
  119. package/dist/models.d.ts +9 -0
  120. package/dist/models.js +623 -0
  121. package/dist/models.js.map +1 -0
  122. package/dist/move-home.d.ts +82 -0
  123. package/dist/move-home.js +472 -0
  124. package/dist/move-home.js.map +1 -0
  125. package/dist/native/darwin-arm64/rudder-native +0 -0
  126. package/dist/native/darwin-x64/rudder-native +0 -0
  127. package/dist/native/linux-x64/rudder-native +0 -0
  128. package/dist/native-agents.d.ts +8 -0
  129. package/dist/native-agents.js +178 -0
  130. package/dist/native-agents.js.map +1 -0
  131. package/dist/native-binary.d.ts +4 -0
  132. package/dist/native-binary.js +140 -0
  133. package/dist/native-binary.js.map +1 -0
  134. package/dist/paste-bridge.d.ts +36 -0
  135. package/dist/paste-bridge.js +279 -0
  136. package/dist/paste-bridge.js.map +1 -0
  137. package/dist/plan-mode.d.ts +2 -0
  138. package/dist/plan-mode.js +22 -0
  139. package/dist/plan-mode.js.map +1 -0
  140. package/dist/planner.d.ts +27 -0
  141. package/dist/planner.js +587 -0
  142. package/dist/planner.js.map +1 -0
  143. package/dist/predict.d.ts +67 -0
  144. package/dist/predict.js +369 -0
  145. package/dist/predict.js.map +1 -0
  146. package/dist/report.d.ts +74 -0
  147. package/dist/report.js +412 -0
  148. package/dist/report.js.map +1 -0
  149. package/dist/rudder-md.d.ts +33 -0
  150. package/dist/rudder-md.js +142 -0
  151. package/dist/rudder-md.js.map +1 -0
  152. package/dist/run-manager.d.ts +62 -0
  153. package/dist/run-manager.js +1400 -0
  154. package/dist/run-manager.js.map +1 -0
  155. package/dist/scheduler.d.ts +128 -0
  156. package/dist/scheduler.js +955 -0
  157. package/dist/scheduler.js.map +1 -0
  158. package/dist/state.d.ts +127 -0
  159. package/dist/state.js +704 -0
  160. package/dist/state.js.map +1 -0
  161. package/dist/surfaces.d.ts +91 -0
  162. package/dist/surfaces.js +460 -0
  163. package/dist/surfaces.js.map +1 -0
  164. package/dist/task-summary.d.ts +30 -0
  165. package/dist/task-summary.js +472 -0
  166. package/dist/task-summary.js.map +1 -0
  167. package/dist/types.d.ts +492 -0
  168. package/dist/types.js +2 -0
  169. package/dist/types.js.map +1 -0
  170. package/dist/usage.d.ts +198 -0
  171. package/dist/usage.js +830 -0
  172. package/dist/usage.js.map +1 -0
  173. package/dist/util.d.ts +73 -0
  174. package/dist/util.js +399 -0
  175. package/dist/util.js.map +1 -0
  176. package/dist/version-check.d.ts +16 -0
  177. package/dist/version-check.js +269 -0
  178. package/dist/version-check.js.map +1 -0
  179. package/package.json +68 -4
  180. package/scripts/copy-native.mjs +89 -0
  181. package/scripts/postinstall.mjs +34 -0
package/README.md CHANGED
@@ -1,3 +1,734 @@
1
- # Temporary Holding Version
1
+ # rudder
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
+ <p>
4
+ <a href="https://rudder.exla.ai">
5
+ <img src="https://rudder.exla.ai/favicon.svg" width="36" height="36" alt="Rudder logo" />
6
+ </a>
7
+ </p>
8
+
9
+ [![TUI e2e](https://github.com/exla-ai/rudder/actions/workflows/tui.yml/badge.svg)](https://github.com/exla-ai/rudder/actions/workflows/tui.yml)
10
+ [![npm version](https://img.shields.io/npm/v/@exla/rudder.svg)](https://www.npmjs.com/package/@exla/rudder)
11
+ [![Node >=22](https://img.shields.io/badge/node-%3E%3D22-43853d.svg)](https://nodejs.org/)
12
+ [![Website](https://img.shields.io/badge/site-rudder.exla.ai-111111.svg)](https://rudder.exla.ai)
13
+
14
+ Rudder is a TUI for managing coding agents. Run Claude Code, Codex and opencode
15
+ side by side in one native dashboard: every task you type gets its own isolated
16
+ jj workspace, so agents never step on each other. See which agent needs you,
17
+ approve prompts, steer any agent mid-turn, and merge the results back with one
18
+ key. `/main` puts an agent in the main checkout when you want one there, and
19
+ `/plan` turns a bigger goal into a reviewed multi-agent DAG.
20
+
21
+ > **AI agents and contributors:** this README is for using Rudder. If you are
22
+ > an AI agent (or a human) working on the Rudder codebase itself, read
23
+ > [`AGENTS.md`](./AGENTS.md) first; it is the engineering reference and the
24
+ > source of truth for architecture, conventions, and release rules.
25
+
26
+ ## Install
27
+
28
+ ```bash
29
+ npm install -g @exla/rudder@latest
30
+ rudder
31
+ ```
32
+
33
+ After the global install, every user-facing `rudder` launch checks npm and
34
+ auto-updates itself before running when a newer version is available. Set
35
+ `RUDDER_DISABLE_AUTO_UPDATE=1` to opt out. Run without a global install using
36
+ `npx @exla/rudder@latest`.
37
+
38
+ Rudder used to be published as `@viraatdas/rudder`. Existing installs move
39
+ themselves to `@exla/rudder` on their next update; nothing to do by hand.
40
+
41
+ ## Requirements
42
+
43
+ - Node.js 22 or newer
44
+ - Git
45
+ - Claude Code and/or Codex installed and logged in
46
+ - macOS (Apple Silicon or Intel) or Linux x64; the dashboard binary for each
47
+ ships in the package
48
+
49
+ Rudder runs agents in isolated [jj (Jujutsu)](https://jj-vcs.github.io)
50
+ workspaces; your repo stays plain git. You do not need to install jj: if it is
51
+ not already on your PATH, Rudder sets up its own copy in `~/.rudder/bin` during
52
+ install (or on first run). A jj you installed yourself is always used instead.
53
+
54
+ Check your setup at any time:
55
+
56
+ ```bash
57
+ rudder doctor
58
+ ```
59
+
60
+ ## Quick start
61
+
62
+ ```bash
63
+ rudder
64
+ ```
65
+
66
+ With no arguments, `rudder` opens the dashboard. Type a task in the bottom input
67
+ and press `Enter`: Rudder starts one worker for it in its own jj workspace. It
68
+ lands in Review when done and merges back with `m`. Use `/main <task>` for an
69
+ agent that works directly in the main checkout (for release, push and deploy
70
+ work), `/gam <task>` to pair a builder with a reviewer from another model, or
71
+ `/plan <task>` when you want a reviewed multi-agent DAG.
72
+
73
+ If a task needs shared local context like API tokens, private URLs, account ids,
74
+ or environment values, save it with `/share <text>` in the task input. Rudder
75
+ also captures obvious token-looking lines like `APIFY_TOKEN=...` from task-bar
76
+ messages. The text is written to `RUDDER_SHARED.md`, which is gitignored and
77
+ mirrored into worker workspaces; all agents are explicitly told to read it when
78
+ present.
79
+
80
+ You can also start a task directly from the shell:
81
+
82
+ ```bash
83
+ rudder "fix the failing tests"
84
+ rudder claude "fix the auth redirect bug"
85
+ rudder codex --model gpt-6.1-sol "refactor the parser"
86
+ ```
87
+
88
+ ## Onboarding and auth
89
+
90
+ ```bash
91
+ rudder onboard
92
+ ```
93
+
94
+ Onboarding uses the auth you already have, so you usually do not need API keys:
95
+
96
+ - Claude Code auth from the macOS Keychain or `~/.claude/.credentials.json`
97
+ - Codex auth from `~/.codex/auth.json`
98
+ - `ANTHROPIC_API_KEY` / `OPENAI_API_KEY` if you prefer keys
99
+
100
+ If auth is missing you can skip it and set up a backend later. Config is written
101
+ to `~/.rudder/config.json`.
102
+
103
+ ## The dashboard
104
+
105
+ ```text
106
+ ┌───────────────┬────────────────────────────────────────────┐
107
+ │ agents │ worker │
108
+ │ task list │ live Claude Code or Codex terminal │
109
+ │ status/model │ DAG-over-orchestrator, scrollback, review │
110
+ ├───────────────┴────────────────────────────────────────────┤
111
+ │ task input: main owner by default, /plan DAG, /run isolated │
112
+ └──────────────────────────────────────────────────────────────┘
113
+ ```
114
+
115
+ - **agents** (left): one row per task with its backend, model, effort, and status.
116
+ - **worker** (right): the real Claude Code or Codex terminal. When it is focused,
117
+ your keystrokes go straight to the agent, so its prompts, slash commands,
118
+ selection, and `Tab` all work normally.
119
+ - **orchestrator** (right, when selected): a Claude Code PTY with the live DAG
120
+ rendered above it. For planned work, use it to inspect/refine the plan while
121
+ the bottom task input remains the primary place to type new requests.
122
+ - **task** (bottom): the entry point for fresh requests, slash commands, plan
123
+ refinements, and approval with empty `Enter`.
124
+
125
+ Mouse wheel and trackpad scroll the pane under the pointer. Over the worker or
126
+ review pane they scroll Rudder's captured scrollback.
127
+
128
+ ### Usage dashboard
129
+
130
+ Press `U` in the agents pane (or type `/usage web`) for a machine-wide usage
131
+ page in your browser: subscription quota meters for every signed-in Claude Code
132
+ and Codex account (session and weekly windows with time to reset, read from the
133
+ providers' own usage endpoints using the sign-ins the CLIs already hold), token
134
+ costs estimated at API list rates from the CLIs' local session logs (per day,
135
+ provider, model, and workspace, with the top sessions per workspace and a
136
+ click-to-copy id for `--resume`), and a live view of CPU and memory for Rudder
137
+ and every agent process. Bare `/usage` keeps the one-line summary for the
138
+ current session.
139
+
140
+ ### Diff panel
141
+
142
+ Press `⌥d` (or type `/diff`) to open a diff panel beside the worker pane, or
143
+ `⌥4` (also `^W 4`) to jump straight to it as the fourth pane: the
144
+ selected agent's change set parsed from `jj diff` (or `git diff` against HEAD
145
+ plus untracked files in a plain checkout), with per-file `+`/`−` counts, line
146
+ numbers, and the run's token usage and estimated API-rate cost in the header.
147
+ It refreshes as the agent edits. `j`/`k` and the wheel scroll, `n`/`p` jump
148
+ between files, `r` refreshes, `Esc` or `⌥d` closes it, and `⌥h` solos it like
149
+ any other pane. On a narrow terminal it takes the worker's place instead of
150
+ squeezing both. `v` opens the same panel.
151
+
152
+ ### God's view
153
+
154
+ Press `⌥g` (also `^W g`) to see every running agent at once: the screen turns
155
+ into a grid with one tile per agent showing the bottom of its terminal, titled
156
+ with its id, task, model and whether it is working, needs you, or is done.
157
+ Arrows or `h`/`j`/`k`/`l` move the highlight, `Enter` or a click opens that
158
+ agent in the worker pane, and `⌥g` or `Esc` closes the grid. Agents are never
159
+ resized for it, so their scrollback is untouched. With more agents than fit,
160
+ the grid pages.
161
+
162
+ ### Web board
163
+
164
+ Press `o` in the agents pane (or type `/web`) to open the live project board in
165
+ your browser. The board is a second control surface, not just a monitor: open a
166
+ task to send an update while it runs, or request changes from Review to resume
167
+ the same agent in the same workspace. The task's update thread records your
168
+ directions alongside the latest worker activity. `+ Task` follows the same
169
+ end-to-end main-owner path as typing in the dashboard task pane; use `/plan` in
170
+ the native dashboard for an explicit DAG.
171
+
172
+ The board also works on its own with `rudder board`: in that mode updates
173
+ redirect or resume the detached worker directly and move revised work back
174
+ through Review before it can merge.
175
+
176
+ ## Keyboard shortcuts
177
+
178
+ **Direct (work from any pane):**
179
+
180
+ | Key | Action |
181
+ | --- | --- |
182
+ | `Option-1` / `Option-2` / `Option-3` | Focus the agents, worker, or task pane |
183
+ | `Option-[` / `Option-]` | Step to the previous / next agent, staying in the pane you are in |
184
+ | `Option-h` | Full screen: the focused pane takes the whole terminal; press again to bring the panes back |
185
+ | `Option-g` | God's view: every agent tiled on one screen; press again to close |
186
+ | `Option-d` | Diff panel for the selected agent |
187
+ | `Ctrl-V` | Paste a screenshot or copied files into an agent (works in `rudder cloud` too) |
188
+ | `Option-v` / `Option-b` | Previous question in the selected worker / back to its latest message (Claude Code and Codex) |
189
+ | `Cmd-C` | Copy the active Rudder selection |
190
+ | `Ctrl-C` | Quit (asks to confirm if agents are still running) |
191
+
192
+ `Option-1/2/3` and `Option-[`/`Option-]` work out of the box on macOS terminals,
193
+ whether or not "Use Option as Meta" is enabled. `Cmd-[` / `Cmd-]` also step agents
194
+ in terminals that forward Cmd to the app (Ghostty and other terminals that speak
195
+ the kitty keyboard protocol, and only if the terminal has not bound those keys
196
+ itself). `Option-[`/`Option-]` are the ones that always work.
197
+
198
+ ## More tabs on the same session
199
+
200
+ One dashboard owns the session. Run `rudder` again in another tab or split of
201
+ the same checkout and you get a second full view of it: the same agents, plans
202
+ and panes, with its own selection, focused pane and task bar. Start agents,
203
+ `/plan`, merge or type into a worker from either tab; both see the result.
204
+ `Ctrl-C` in a second view closes only that tab.
205
+
206
+ A pane has one size, so the tab you typed in last sets it; the other tab shows
207
+ that pane at the same size.
208
+
209
+ To mirror a single agent at full size instead (three agents side by side in
210
+ three splits, say), attach to it:
211
+
212
+ ```bash
213
+ rudder attach # pick from the live agents
214
+ rudder attach n2 # a plan node
215
+ rudder attach parser # part of the title
216
+ ```
217
+
218
+ The attached tab mirrors that agent's pane: same output, same scrollback,
219
+ `Option-v` / `Option-b` step through messages, the wheel scrolls, and every
220
+ other key goes to the agent. `Ctrl-W q` detaches; the agent keeps running in
221
+ the dashboard. While a tab is attached, that agent's pane is sized to the tab
222
+ rather than to the dashboard layout, and its row in the dashboard reads
223
+ `attached`.
224
+
225
+ Stepping agents is the shortcut worth learning: the worker pane hands every
226
+ keystroke to the agent's own TUI, so `j`/`k` only select from the agents list —
227
+ these move between agents without leaving the conversation you are reading.
228
+
229
+ **Leader: press `Ctrl-W`, then one key.** A reliable way to run a dashboard
230
+ command, even while typing inside the worker pane:
231
+
232
+ | Then press | Action |
233
+ | --- | --- |
234
+ | `1` / `2` / `3` | Focus agents / worker / task |
235
+ | `v` | Toggle review |
236
+ | `m` | Merge the selected completed workspace |
237
+ | `M` | Merge all completed workspaces |
238
+ | `R` | Review all completed workspaces (Codex review-all agent) |
239
+ | `r` | Rename the selected agent |
240
+ | `b` | Branch the selected agent's chat into a new worker |
241
+ | `u` | Undo the selected row's merge (restores the jj operation it ran as) |
242
+ | `d` | Delete the selected agent and its workspace |
243
+ | `j` / `k` | Move the agent selection |
244
+ | `q` | Quit |
245
+ | `Esc` | Cancel the leader |
246
+
247
+ `Ctrl-G` toggles the same command set as a sticky "nav mode" (`Esc` exits) if you
248
+ prefer a held mode over the one-shot leader.
249
+
250
+ **In the task pane:** `Enter` runs the draft. A newline is `Option+Enter`,
251
+ `Shift+Enter`, `Ctrl+Enter`, `Cmd+Enter`, or `Ctrl-J` — they all mean the same
252
+ thing, because only some terminals pass each of them through, and a trailing
253
+ `\` before `Enter` works even in the ones that pass none. Once the draft has
254
+ more than one line, `Up` / `Down` move between its lines and only reach task
255
+ history from the top or bottom line; `Home` / `End`, `Ctrl-A` / `Ctrl-E` and
256
+ `Ctrl-K` act on the current line, and `Ctrl`/`Cmd` with `Home` / `End` jumps to
257
+ the ends of the whole draft.
258
+
259
+ **In the worker pane:** keystrokes go to the agent. `Tab` / `Shift+Tab` are
260
+ forwarded to it, `Shift+Enter` inserts a newline, and `PageUp` / `PageDown`
261
+ scroll the pane.
262
+
263
+ **In the agents pane:** `j` / `k` or arrows move the selection, `Enter` focuses
264
+ the worker, `m` / `M` / `R` / `r` / `d` act on the selection, `x` stops a running
265
+ agent (keeping its workspace), `c` clears all merged agents from the list (press
266
+ twice to confirm), `g` toggles the nested DAG view, `o` opens the web board, and
267
+ `U` opens the usage dashboard, and `⌥d` toggles the diff panel.
268
+
269
+ **Finished work collapses.** A long session ends with dozens of merged and failed
270
+ rows, which bury the two or three still moving, so `done` and `closed` each render
271
+ as a single row with a count and a chevron (`done 27 ›`). `j` / `k` walk onto that
272
+ row and `Enter` opens the drawer: the finished runs list in the worker pane with
273
+ the highlighted one's result below it, and `Esc` backs out. `review` stays inline
274
+ up to five rows — merge-ready work should be one keystroke away — and collapses the
275
+ same way past that, because a 25-row review section is not scannable either.
276
+
277
+ ## Commands and Orchestrator Skills
278
+
279
+ Type these in the bottom task input. When an interactive Claude orchestrator is
280
+ running, Rudder also exposes matching project skills; the orchestrator can write
281
+ `RUDDER_*` control markers in `RUDDER.md` and Rudder consumes them.
282
+
283
+ | Command | Action |
284
+ | --- | --- |
285
+ | `/model` | Pick provider, then model, then effort |
286
+ | `/fast` | Fast mode for new agents: flagship model at low effort (Claude opus / Codex gpt-6.1-sol); `/model` switches back |
287
+ | `/plan <text>` | Start the orchestrator / DAG planner |
288
+ | `/gam [main] [<model>] <task>` | Generator + adversarial reviewer pair: split panes, the reviewer questions every round, steers the generator mid-turn, and can stop the run; only the generator edits. `^W t` shows the dialogue between them |
289
+ | `/share <text>` | Save gitignored shared context for all agents in `RUDDER_SHARED.md` |
290
+ | `/main [task]` or `/m` | Start an agent in the main checkout instead of its own workspace |
291
+ | `/review-all` | Combine completed workspaces and start a Codex review-all agent |
292
+ | `/merge-all` | Merge all completed workspaces |
293
+ | `/verify` | Re-run the final repository checks after every DAG node is integrated |
294
+ | `/color terminal\|paper` | Choose the native dashboard color mode; `terminal` uses your terminal foreground/background, `paper` restores the white canvas |
295
+ | `$ <command>` | Open a shell pane in this checkout running the command (`$` alone opens a shell) |
296
+ | `/login` | Browser login for Rudder Cloud |
297
+ | `/cloud` | Toggle cloud mode: tasks you type start in Rudder Cloud and keep running when you disconnect (`/cloud off` goes local) |
298
+ | `/cloud list` | List cloud workers |
299
+ | `/help` | Show the keybinding + command cheat sheet |
300
+
301
+ Finding a DAG task's worker: every plan node id (`n0`, `n1`, …) appears on the
302
+ orchestrator DAG row, on the matching worker's row in the agents pane (`run n1`),
303
+ and in the worker pane title, so the three panes cross-reference by id. A finished
304
+ Planned DAG workers integrate automatically after completion; manually started
305
+ workers remain ready for `m`/`M`. Only locally merged nodes unblock dependents.
306
+ Merged rows show the target branch, jj/Git revision, and whether the remote contains it.
307
+
308
+ ## Models
309
+
310
+ Use `/model [provider] [model] [effort]` in the task input. Claude offers the
311
+ same current aliases as Claude Code (`opus`, `fable`, `sonnet`, and `haiku`);
312
+ the picker labels context windows such as Opus's 1M context without inventing a
313
+ different model name. Codex offers `gpt-6.1-sol`, `gpt-5.6-sol`, and other
314
+ discovered models. `auto` effort means Rudder passes no override.
315
+
316
+ `opencode` is available as a third backend: `/model opencode <provider/model>`
317
+ (its ids are provider-qualified, e.g. `anthropic/claude-sonnet-4-5`), and the
318
+ picker lists whatever `opencode models` reports for your authenticated providers.
319
+ opencode has no reasoning-effort flag, so Rudder offers no effort choice for it
320
+ rather than a dead control, and `/fast` says so instead of pretending. Turn-end is
321
+ reported by a small plugin Rudder generates per run (loaded through
322
+ `OPENCODE_CONFIG`, never written into your workspace), so opencode rows reach
323
+ Review deterministically like the other two. Token/cost accounting for opencode
324
+ rows is not wired up yet and reports zero.
325
+
326
+ Your last provider, model, and effort are saved in `~/.rudder/config.json` and
327
+ reused next time. Rudder refreshes model metadata from
328
+ `https://models.dev/api.json` and falls back to local caches when offline.
329
+ The native Codex picker also reads `~/.codex/models_cache.json`, so account-specific
330
+ models such as the GPT-5.6 Sol/Terra/Luna family appear as soon as Codex exposes them.
331
+ Implementation, review, resume, and shipping Codex sessions keep Codex plugins and
332
+ Computer Use enabled, matching a direct Codex session. Read-only planner sessions
333
+ disable both capabilities so planning cannot cause external side effects.
334
+
335
+ ## One-Off and Planning
336
+
337
+ Type a task in the bottom input and Rudder starts one worker for it in its own
338
+ jj workspace. The same thing happens no matter what else is on screen: a
339
+ standalone worker that touches nothing but its workspace, lands in Review when
340
+ done, and merges back with `m` or `/merge-all`. A slash command Rudder does not
341
+ know is reported as unknown instead of being sent to an agent as a task.
342
+
343
+ Use `/main <task>` for an agent in the main checkout itself, for work that has to
344
+ happen there (release, push, deploy). Several may run there at once; they edit
345
+ the same tree, so they can overwrite each other, and Rudder says so in the
346
+ activity log rather than stopping you. Use `/plan <text>` when you want the
347
+ orchestrator / DAG path: the read-only planner decomposes the task, then separate
348
+ isolated workers implement its nodes. To change a running plan, talk to that
349
+ orchestrator's own pane.
350
+
351
+ For planned work, Rudder runs a dedicated Claude Code orchestrator PTY with a DAG
352
+ pane above it. The flow stays inside Rudder: the orchestrator researches
353
+ read-only, writes the DAG to `RUDDER.md`, and separate workers do the
354
+ implementation.
355
+
356
+ 1. **It asks when it needs to.** The planner inspects the repo first. If something
357
+ material is missing (scope, approach, a key decision), it asks before the first
358
+ DAG, shown as a numbered prompt; a clear request goes straight to a DAG with the
359
+ planner's assumptions listed under it:
360
+
361
+ ```
362
+ ❓ The planner needs your input
363
+ 1. Which time range: last 4 weeks, 6 months, or all time?
364
+ 2. Reuse the existing module contract, or rebuild from scratch?
365
+
366
+ ↳ answer in the task input (e.g. "1: ..., 2: ...")
367
+ ```
368
+
369
+ Type your answer in the task input; Rudder resumes the same planning
370
+ conversation with your answer. The focused orchestrator pane can also accept
371
+ a follow-up when it is showing the planner chat.
372
+ 2. **It lays out a DAG.** When it is ready it shows the task DAG (a tree of worker tasks
373
+ with their dependencies) above the orchestrator terminal. Type feedback in the
374
+ task input to refine it, or press empty `Enter` to approve/launch.
375
+ 3. **The fleet runs.** The scheduler drains the DAG (todo → in-progress → review → done) as
376
+ dependencies merge, each task in its own isolated jj workspace.
377
+
378
+ After launch, typing a new task folds it into the running DAG as a new node. When a worker
379
+ finishes, Rudder reads back what it did and what work it found remaining (reconstructing it
380
+ from the diff if the agent did not say), so the plan keeps growing on its own. Type a
381
+ sweeping change ("rewrite this in Rust instead") and the plan re-plans around the work
382
+ already done. The queued plan and workspaces survive a restart. Closing the dashboard
383
+ marks owned live PTYs `paused` and removes their dead process ids; select a paused row
384
+ and press `Enter` to resume it (reusing its backend session when available).
385
+
386
+ The orchestrator also handles worker operations in natural language. For example, tell it
387
+ "pause the current tasks and resume them on Codex gpt-5.6 at max effort." It resolves the
388
+ live node ids from `RUDDER.md`, pauses each matching worker without deleting its jj
389
+ workspace, and resumes it on the requested provider/model. A same-provider switch keeps
390
+ the agent conversation; a provider switch keeps the workspace and starts a fresh session
391
+ with a handoff to inspect and continue the existing diff.
392
+
393
+ ## Continuing a conversation you already started
394
+
395
+ The chat you are already having in a terminal — a plain `claude`, `codex`, or
396
+ `opencode` session — holds the context you would otherwise retype: the files you
397
+ looked at, the decisions you made, the plan you agreed on. Rudder can pick that
398
+ conversation up and keep it going as an agent.
399
+
400
+ Two directions, same result:
401
+
402
+ - **From the dashboard:** type `/resume`. The palette lists this repository's
403
+ recent conversations — Claude, Codex, and opencode in one list, newest first —
404
+ showing what each was about, which model it was running, how long ago, and its
405
+ session id. Pick one, optionally type the next step after it, and press Enter. It
406
+ opens as an isolated worker that merges with `m` like any other.
407
+ - **From inside the chat:** run `rudder handoff "<next step>"`. That queues the
408
+ conversation you are in; the dashboard picks it up within a second (start it with
409
+ `rudder` if it is not open). `--here` continues in the main checkout instead of an
410
+ isolated workspace, `--list` shows the conversations Rudder can see, and
411
+ `--codex` / `--opencode` pick a different source CLI.
412
+
413
+ Handoffs always FORK the conversation. The chat in your terminal is untouched and
414
+ keeps working; the Rudder agent continues from a copy. The fork is told it is now
415
+ running in a different workspace, so it re-reads files instead of trusting its
416
+ memory of the checkout it came from.
417
+
418
+ `/handoff` still works as an alias for `/resume` (it is what the CLI half is
419
+ called). `b` on a worker row does the same thing for a conversation already inside
420
+ Rudder, and `/restore <claude|codex> <id>` continues a session IN PLACE (same
421
+ session, main checkout) instead of forking it into a worker.
422
+
423
+ ## Worktrees and merging
424
+
425
+ **Who merges what:** planned `/plan` DAG nodes integrate into your checkout
426
+ **automatically** as soon as they finish — no per-node confirmation — so
427
+ dependent nodes unblock and the chain keeps flowing (their row shows
428
+ `done · auto-merging`, then `merged locally`; the final gate runs the repo's
429
+ checks after the last node lands). Workers started from the task bar never
430
+ auto-merge: they wait in Review (`done · press m to merge`) until you merge
431
+ them yourself. There is no `/automerge` command or config flag — this split is
432
+ the behavior.
433
+
434
+ Planned and task-bar workers run in their own jj workspaces under a sibling
435
+ `.rudder-workspaces` area, so parallel agents never edit the same checkout.
436
+ `/main` agents intentionally run in the main checkout. Run records
437
+ live under `.rudder/runs/`. If you quit Rudder, live workers become `paused`, keep
438
+ their workspace/session metadata, and stay listed when you reopen the repo.
439
+
440
+ - Press `m` to merge the selected completed agent back into its branch.
441
+ - Press `M` (or `/merge-all`) to merge all completed agents.
442
+ - Both ask for a `y`/`n` confirmation first, and the prompt warns when your own
443
+ uncommitted changes in the main checkout would ride along in the merge.
444
+
445
+ Clean merges become merge commits. If git reports conflicts, Rudder leaves the
446
+ conflicted state in place and can open an agent in the main checkout to help
447
+ resolve it.
448
+
449
+ Choose the merge behavior in `~/.rudder/config.json`:
450
+
451
+ ```json
452
+ { "mergeStrategy": "rebase" }
453
+ ```
454
+
455
+ - `"merge"` (default): `git merge --no-ff`.
456
+ - `"rebase"`: rebase the workspace onto the latest base, then `git merge --ff-only`.
457
+
458
+ Command-line equivalents:
459
+
460
+ ```bash
461
+ rudder merge <runId>
462
+ rudder sync <runId>
463
+ rudder cleanup
464
+ ```
465
+
466
+ `rudder stop` records a durable cancellation request and terminates the native PTY process
467
+ group. Cancellation is terminal: a resulting signal exit cannot be relabeled as a failure.
468
+
469
+ ## Shipping and delivery evidence
470
+
471
+ Rudder treats these as different facts: an agent finished, changes merged locally,
472
+ a revision was pushed, and a product was deployed. A task that explicitly asks to
473
+ deploy, publish, release, install, or launch remains `delivery proof needed` until
474
+ its completion report records the target, delivery kind, verification time, and at
475
+ least one real smoke check. Verified web URLs, installed macOS app paths, provider
476
+ deployment ids, revisions, and versions are persisted in `.rudder/runs/<id>/run.json`
477
+ and shown in the native dashboard, web board, and generated `RUDDER.md`.
478
+
479
+ Pushing a commit is never presented as proof that a host deployed it. Likewise,
480
+ building a macOS app is not the same as replacing and launching the installed app.
481
+ If delivery fails or needs credentials/user input, the row says `delivery blocked`
482
+ instead of incorrectly moving to deployed.
483
+
484
+ ## Review
485
+
486
+ Press `v` on an agent to toggle a review of its workspace, showing the run's diff.
487
+ Press `v` or `Esc` to return to the worker.
488
+
489
+ Press `R` to review all completed workspaces as one bundle: Rudder builds an
490
+ aggregate branch and starts a Codex review-all agent over the combined diff. When
491
+ that row is done, press `m` on it to merge the reviewed bundle into your checkout.
492
+
493
+ ## Rudder Cloud
494
+
495
+ Rudder Cloud is an optional hosted worker mode. The local dashboard stays your
496
+ control surface; you decide whether a task runs locally or is handed to the cloud.
497
+
498
+ ```bash
499
+ rudder login # sign in with Google (opens straight to the account picker)
500
+ rudder cloud # open this repo on your home machine and attach to it
501
+ rudder cloud home # home machine status: projects, agents, previews
502
+ rudder cloud move # move this repo's running agents to the home machine
503
+ rudder cloud sync [repo] # bring this checkout and the cloud's clone level (/sync)
504
+ rudder cloud app # the phone app link
505
+ rudder cloud list # list cloud workers
506
+ rudder cloud logs <id> # worker status
507
+ rudder cloud onload [runId] # hand one agent off to the cloud (or upload the workspace)
508
+ rudder cloud workspace attach # migrate all live isolated agents into one cloud workspace
509
+ rudder sail <name> # short alias for starting a cloud worker
510
+ ```
511
+
512
+ **Your home machine.** `rudder cloud` in a repo with a GitHub origin opens it on
513
+ your one cloud machine (4 CPU / 16 GB, persistent disk), cloning it into
514
+ `~/code/<repo>` the first time. Every repo you open lives on that same machine,
515
+ each with its own Rudder dashboard, so agents can read your other repos at the
516
+ paths you are used to. GitHub is the source of truth: the cloud clones from it,
517
+ and finished work comes back as a pushed branch and a draft PR (`m` in a cloud
518
+ dashboard publishes instead of merging locally). Before attaching, Rudder warns
519
+ about uncommitted or unpushed work it can't see, and offers to copy the repo's
520
+ `.env` files into the encrypted vault. The machine stops after two quiet hours
521
+ and starts again on the next `rudder cloud` or phone visit; conversations and
522
+ agent state live on its disk, so agents resume where they were.
523
+ `rudder cloud --snapshot` keeps the old behavior: upload this folder to a
524
+ machine of its own.
525
+
526
+ **Same repo on the laptop and the cloud (`/sync`).** `/sync` in the dashboard
527
+ (or `rudder cloud sync`) brings this checkout and the cloud machine's clone of
528
+ it up to the newest default branch, and carries the work GitHub does not have
529
+ yet, uncommitted edits included, from one side to the other directly. Nothing is
530
+ pushed to your repo, and gitignored files such as `.env` never travel. The side
531
+ receiving work only takes it when nothing of its own would be lost; when both
532
+ sides changed, both versions are kept and the other one waits as the jj bookmark
533
+ `rudder-sync/cloud` (or `rudder-sync/laptop`). `rudder cloud sync <repo>` with a
534
+ name clones a repo that so far exists only on the cloud into `~/code/<repo>`.
535
+ `/sync all` covers every repo, and `/sync move` hands this laptop's running
536
+ agents to the cloud.
537
+
538
+ **Screenshots and files.** In `rudder cloud`, `Ctrl-V` with a screenshot or
539
+ files copied in Finder, or dragging a file into the terminal, uploads it to the
540
+ cloud machine and gives the agent its path there: Claude Code attaches an image
541
+ as `[Image #1]` exactly as it does locally. Up to 25 MB per file.
542
+
543
+ **Updates.** After a release the cloud machine updates itself once its agents
544
+ have been idle for five minutes, so you never restart it by hand.
545
+
546
+ **Phone.** Open `rudder cloud app` on your phone and sign in with the same
547
+ Google account. You see every project and agent, read conversations as they
548
+ happen, text any agent, start tasks (`/model` picks Claude or Codex for new ones),
549
+ stop, merge or delete agents (swipe left), and open previews. A message that can't
550
+ reach an agent (a menu is open in its pane) says so instead of vanishing. Claude
551
+ panes in the cloud also run with Remote Control, so they appear in the Claude
552
+ app too.
553
+
554
+ **Previews.** Put a Tailscale auth key in the vault
555
+ (`rudder cloud secrets set TS_AUTHKEY`) and the home machine joins your tailnet
556
+ as `rudder-home`. Any dev server an agent starts there shows up as an HTTPS link
557
+ (`https://rudder-home.<tailnet>.ts.net:<port>`) in `rudder cloud home` and the
558
+ phone app.
559
+
560
+ Inside the dashboard, `/login` starts browser auth and `/cloud` toggles cloud
561
+ mode: while it is on, tasks you type start as workers in Rudder Cloud and keep
562
+ running when this laptop disconnects (`/cloud off` returns to local workers).
563
+ `rudder cloud` from a shell onloads the current workspace (repo snapshot plus
564
+ selected auth/config) so the whole dashboard runs on a cloud machine. Completed
565
+ cloud work returns through the same review and merge path as local work.
566
+
567
+ **Taking agents with you.** About to close the laptop? Press `H` in the
568
+ dashboard and every running agent moves to your home machine: its work so far
569
+ (the jj change, including unpushed local changes it builds on) and its
570
+ conversation go along, nothing is pushed to GitHub, and the conversation resumes
571
+ there, so it keeps going with the laptop closed. Quitting with agents running
572
+ offers the same thing ("3 agents are running here. Move them to the home
573
+ machine?"), and `rudder cloud` in a repo with agents asks too. Bare `/handoff`
574
+ moves just the selected agent. (`/handoff <session-id>` still adopts an outside
575
+ CLI chat, like `/resume`.) Delete an agent anywhere (`dd` here, swipe left on the
576
+ phone) and it is gone everywhere.
577
+
578
+ Cloud comes in two shapes: a **sail** is an ephemeral, task-scoped worker (it goes away
579
+ when the task is done; idle sails pause and can resume), while a **workspace** is a
580
+ persistent, volume-backed dev environment you can come back to. Both restore the same
581
+ workspace snapshot.
582
+
583
+ An active workspace agent keeps running when you close the terminal or lose the
584
+ connection; the idle sweeper only stops a workspace after its reported active-agent
585
+ count reaches zero. Re-running `rudder cloud` reconnects to the same volume and saved
586
+ sessions. If several terminals attach, the first remains the input and resize
587
+ controller; additional terminals are read-only observers until the controller leaves.
588
+ This prevents another terminal's dimensions or disconnect keys from disrupting the
589
+ shared remote dashboard.
590
+
591
+ You can also tell the live orchestrator: "take the current agents and run them on
592
+ Rudder Cloud." Rudder freezes the local worker PTYs first, then migrates every live
593
+ isolated workspace. Claude sessions resume from their transcript when available;
594
+ Codex and missing-session workers restart from a context-rich handoff over the existing
595
+ diff. The explicit fleet-migration snapshot includes all inherited environment variables
596
+ (except OS/Rudder control variables),
597
+ agent auth/config, shell and cloud CLI configuration, and project `.env*` files (including
598
+ nested package dotenv files) in each restored worker workspace.
599
+
600
+ Cloud workers use Fly Machines by default. To use your own server over SSH (Docker over
601
+ SSH; bring-your-own-compute can be stopped but not paused/resumed):
602
+
603
+ ```bash
604
+ rudder cloud byoc <ssh-host> # an entry from ~/.ssh/config, key auth + Docker
605
+ rudder cloud vm "task" # run on that host
606
+ rudder cloud runtime [fly|byoc]
607
+ ```
608
+
609
+ The CLI points at the hosted control plane `https://rudder-cloud-control.fly.dev`.
610
+ Set `RUDDER_CLOUD_URL` to use your own deployment. Rudder Cloud login is separate
611
+ from Claude Code and Codex login; provider auth stays in the official CLIs.
612
+
613
+ ## Run management
614
+
615
+ ```bash
616
+ rudder status
617
+ rudder runs
618
+ rudder watch <runId>
619
+ rudder logs <runId> --follow
620
+ rudder stop <runId>
621
+ rudder delete <runId>
622
+ rudder merge <runId>
623
+ rudder sync <runId>
624
+ rudder cleanup
625
+ ```
626
+
627
+ ## Troubleshooting
628
+
629
+ - Stale behavior after an upgrade: restart any already-running Rudder dashboards
630
+ so no old `rudder-native` process lingers. New `rudder` launches auto-update
631
+ unless `RUDDER_DISABLE_AUTO_UPDATE=1` is set.
632
+ - Sustained CPU/redraw load: version 2.12.9 and newer cache Codex plan-output scans,
633
+ avoid reparsing unchanged planner JSON, throttle background PTY drains, and redraw
634
+ only dirty frames. Upgrade and restart any dashboard launched by 2.12.8 or older.
635
+ - Trackpad scrolling: confirm your terminal sends scroll events with
636
+ `rudder mouse-test parsed`. Set `RUDDER_WHEEL_SCROLL_ROWS=<n>` to change the
637
+ scroll step, or `RUDDER_MOUSE_DEBUG=1` to inspect routing.
638
+
639
+ ## Continual improvement loop
640
+
641
+ Rudder improves itself from its own telemetry. Every run already leaves a
642
+ record on disk (`.rudder/runs/`, event logs, verifier results, steer history,
643
+ token usage). The improvement loop, `rudder improve`, is a scheduled local
644
+ batch job (launchd on macOS, not a resident daemon) that:
645
+
646
+ 1. **Collects** recent session telemetry across your registered projects,
647
+ redacting secrets at the source.
648
+ 2. **Mines** it into ranked friction findings (failed runs, user redirects,
649
+ merge conflicts, verifier misses) using the advisor pattern: a Sonnet
650
+ executor consults a Fable 5 advisor mid-generation, so most tokens bill at
651
+ the executor rate.
652
+ 3. **Proposes** fixes with headless agents in isolated git worktrees of the
653
+ rudder repo, each briefed with a rich context pack (finding, evidence,
654
+ surface map, prior failed attempts, repo conventions).
655
+ 4. **Judges** each candidate with the repo's full test gates plus a
656
+ three-lens adversarial LLM panel that fails closed.
657
+ 5. **Prepares** survivors as pushed review branches by default. If you
658
+ explicitly opt into `ship` autonomy, Rudder instead rebases onto
659
+ `origin/main`, runs `npm version patch`, and pushes main + tag for the normal
660
+ tag-driven npm release. Later cycles verify whether the targeted metric
661
+ improved and record regressions for review.
662
+
663
+ ```bash
664
+ rudder improve run --dry-run # see what it would do, propose nothing
665
+ rudder improve schedule install # nightly cycle at 03:30 via launchd
666
+ rudder improve status # shipped versions, metrics trend, ledger
667
+ ```
668
+
669
+ Everything stays on your machine. Estimated model/agent spend is bounded per
670
+ cycle (`improve.budgetUsd`, default $5), and autonomy is configurable:
671
+ `observe` only reports, `propose` (the default) pushes a review branch, and
672
+ `ship` is an explicit opt-in to unattended releases. `RUDDER_IMPROVE=0`
673
+ disables the loop. The full harness spec is in
674
+ [`docs/continual-improvement.md`](./docs/continual-improvement.md);
675
+ implementation details live in [`AGENTS.md`](./AGENTS.md) section 15.
676
+
677
+ ## What Rudder derives rather than remembers
678
+
679
+ A status that can be checked is checked, on a slow tick, against whatever actually
680
+ knows: jj for "is this work in main", the process handle for "is this agent
681
+ alive", the filesystem for "does this workspace exist", each backend's own session
682
+ store for "which conversation is this". Anything that changed is written to
683
+ `.rudder/activity.jsonl` with the ids it touched — change id, bookmark, commit,
684
+ jj operation — so it can be lined up against `jj op log` afterwards.
685
+
686
+ This is why a merged row can say **`merged · NOT in main`**: the merge landed, and
687
+ then something rewrote history under it. Rudder used to keep claiming success.
688
+
689
+ ## Telemetry and feedback
690
+
691
+ Rudder sends a small set of **anonymous usage events** so the parts people get
692
+ stuck on are visible: how many installs ever start an agent, how many ever merge,
693
+ which backend and model get picked, which errors fire most. It is on by default,
694
+ disclosed the first time you run anything, and off in one command:
695
+
696
+ ```bash
697
+ rudder telemetry status
698
+ rudder telemetry off # or RUDDER_TELEMETRY=0 in your shell
699
+ ```
700
+
701
+ What is sent: the event name, rudder version, platform, backend/model, agent and
702
+ merge counts, slash-command *names*, and a hashed project id (a digest of the
703
+ repo path — it counts projects without naming them). What is never sent: your
704
+ prompts, code, diffs, file contents, paths, repo names, branch names, or session
705
+ ids. Events are anonymous (no person profile), keyed to a random id minted per
706
+ install. Implementation and the rules it enforces: `src/analytics.ts`.
707
+
708
+ **`/feedback <what broke>`** in the task pane (or `rudder feedback "..."`) sends a
709
+ report with the message plus what was on screen in structure: version, platform,
710
+ backend/model, how many agents were running, the last few notices and the last
711
+ error — with paths stripped. It lands in three places, in order of durability: a
712
+ local JSON copy under `.rudder/feedback/` (always, so nothing is lost offline), a
713
+ usage event, and a GitHub issue when `gh` is installed and authenticated. Add
714
+ `--no-issue` to keep it out of the public tracker.
715
+
716
+ ## Building from source
717
+
718
+ ```bash
719
+ git clone https://github.com/exla-ai/rudder.git
720
+ cd rudder
721
+ ./setup.sh
722
+ ```
723
+
724
+ `setup.sh` checks prerequisites (Node >=20, git, npm, Rust/`cargo`), installs
725
+ dependencies, builds (`tsc` + `cargo build --release`), typechecks, and smoke
726
+ tests the CLI. It is safe to re-run after pulling. For architecture and
727
+ implementation details, see [`AGENTS.md`](./AGENTS.md).
728
+
729
+ ## License
730
+
731
+ [Elastic License 2.0](LICENSE) (ELv2). Source-available: you can use, modify and
732
+ redistribute Rudder, but you may not offer it to others as a hosted or managed
733
+ service. Versions published before 2.16.6 were released under MIT and remain
734
+ available under those terms.