You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The command does not provide enough value over `arb exec git diff` to
justify its maintenance cost and CLI surface area. Its only meaningful
coordination value is merge-base resolution, which is a single
well-known git command. See DR-0096.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: GUIDELINES.md
+6-6Lines changed: 6 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -24,7 +24,7 @@ Beyond showing honest state, Arborist actively watches for conditions that signa
24
24
25
25
### Coordination and overview, not authoring
26
26
27
-
Arborist coordinates multi-repo operations (push, rebase, merge) and provides workspace-level overview (status, log, diff). It does not replace Git for authoring operations. Committing, staging, interactive rebase, and PR creation belong to direct interaction with each repository. `arb exec` bridges the gap for anything Arborist doesn't cover.
27
+
Arborist coordinates multi-repo operations (push, rebase, merge) and provides workspace-level overview (status, log). It does not replace Git for authoring operations. Committing, staging, interactive rebase, and PR creation belong to direct interaction with each repository. `arb exec` bridges the gap for anything Arborist doesn't cover.
28
28
29
29
### Do one thing and do it well
30
30
@@ -95,7 +95,7 @@ Tell the user *what happened*, not just *that it happened*. Use descriptive per-
95
95
96
96
**State-changing commands** (`push`, `pull`, `rebase`, `merge`, `reset`, `retarget`): accept optional `[repos...]` to narrow scope; default to all repos. Follow the five-phase workflow: assess → plan → confirm → execute → summarize. Each defines a typed assessment interface classifying repos into will-operate / up-to-date / skip-with-reason.
97
97
98
-
**Overview commands** (`status`, `log`, `diff`) are read-only. They scope to the feature branch via base branch resolution, skip detached/drifted repos with explanation, and support `[repos...]` filtering, `--json`, and `--verbose`.
98
+
**Overview commands** (`status`, `log`) are read-only. They scope to the feature branch via base branch resolution, skip detached/drifted repos with explanation, and support `[repos...]` filtering, `--json`, and `--verbose`.
|`--all-repos` (`-a`) | Select all repos (scripting) |
123
123
| Interactive picker | When no args and TTY |
124
124
125
-
**Overview commands** (`status`, `log`, `diff`):
125
+
**Overview commands** (`status`, `log`):
126
126
127
127
| Flag | Purpose |
128
128
|------|---------|
@@ -142,7 +142,7 @@ When multiple operations manage the same `.arb/` subsystem (repos, templates), g
142
142
143
143
**`pull`** always fetches — it inherently needs fresh remote state to assess what to pull. It does not offer `--no-fetch`.
144
144
145
-
**Content commands** (`log`, `diff`) do not fetch by default — stale content is less confusing. `--fetch` opts in.
145
+
**`log`** does not fetch by default — stale content is less confusing. `--fetch` opts in.
146
146
147
147
The `ARB_NO_FETCH` environment variable globally suppresses automatic fetching — equivalent to passing `-N` to every command. Explicit `--fetch` overrides it. `pull` is unaffected (it always fetches). See `decisions/0045-universal-fetch-flags.md` and `decisions/0087-arb-no-fetch-env-var.md`.
148
148
@@ -174,9 +174,9 @@ When repos are the command's primary target, they are positional arguments (`arb
174
174
175
175
### Status-based filtering: `--where` and `--dirty`
176
176
177
-
`--where` (`-w`) filters repos by `RepoFlags`. Supported on every command that gathers workspace status: `status`, `diff`, `log`, `exec`, `open`, `list`, `delete`, `push`, `pull`, `rebase`, `merge`, `reset`. Commands that don't gather status (e.g. `attach`, `create`, `branch rename`) do not get `--where`.
177
+
`--where` (`-w`) filters repos by `RepoFlags`. Supported on every command that gathers workspace status: `status`, `log`, `exec`, `open`, `list`, `delete`, `push`, `pull`, `rebase`, `merge`, `reset`. Commands that don't gather status (e.g. `attach`, `create`, `branch rename`) do not get `--where`.
178
178
179
-
`--dirty` (`-d`) is a shorthand for `--where dirty`, mutually exclusive with `--where`. Only offered where "dirty" is a natural filter: `status`, `diff`, `log`, `exec`, `open`, `list`. Omitted from sync commands and `delete`.
179
+
`--dirty` (`-d`) is a shorthand for `--where dirty`, mutually exclusive with `--where`. Only offered where "dirty" is a natural filter: `status`, `log`, `exec`, `open`, `list`. Omitted from sync commands and `delete`.
180
180
181
181
Filter terms are organized by orthogonal dimension (see ARCHITECTURE.md). Positional terms use the `<position>-<axis>` pattern (`ahead-share`, `behind-base`) so axis relationships are obvious. Filter names describe state, not suggested action — whether a repo "needs rebase" depends on the user's intent; the filter just says `behind-base`. Named positive terms exist only where they provide non-trivial composition (`pushed` = `^ahead-share+^no-share`) or are natural vocabulary (`clean`, `safe`); trivially-derivable positives use `^` negation instead (`^behind-base` rather than a named `synced-base`).
- Overview commands (`status`, `log`, `diff`) handle `--fetch`/`--no-fetch`, `--json`, `[repos...]` consistently. They must not fetch by default.
61
+
- Overview commands (`status`, `log`) handle `--fetch`/`--no-fetch`, `--json`, `[repos...]` consistently. They must not fetch by default.
62
62
- Mutation commands (`push`, `rebase`, `merge`) must fetch by default. `exec` and `open` must not have fetch flags.
63
63
-`--where` filtering works the same everywhere it appears. Filter terms must be anchored to `FILTER_TERMS` in `status.ts` — no ad-hoc string comparisons.
64
64
-`--force` has per-command semantics (plan modifier in `push`, safety bypass in `delete`). Verify that help text and behavior match each command's specific contract.
Copy file name to clipboardExpand all lines: README.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -352,7 +352,7 @@ arb exec npm install # run a command in every repo
352
352
arb status -w dirty,unpushed # filter repos by status flags
353
353
```
354
354
355
-
All state-changing commands support `--dry-run` to preview the plan and `--yes` to skip confirmation prompts. `status`, `branch`, `list`, `log`, `diff`, and `repo list` support `--json` for structured output and `--quiet` for one name per line — useful for feeding into other commands. `arb exec` runs any command in each repo; `--where` (`-w`) filters repos by status flags like `dirty`, `behind-base`, or `ahead-share` and works across most commands. Exit codes are meaningful: 0 for success, 1 for issues, 130 for user abort. Human-facing output goes to stderr, machine-parsable data to stdout — so piping works naturally.
355
+
All state-changing commands support `--dry-run` to preview the plan and `--yes` to skip confirmation prompts. `status`, `branch`, `list`, `log`, and `repo list` support `--json` for structured output and `--quiet` for one name per line — useful for feeding into other commands. `arb exec` runs any command in each repo; `--where` (`-w`) filters repos by status flags like `dirty`, `behind-base`, or `ahead-share` and works across most commands. Exit codes are meaningful: 0 for success, 1 for issues, 130 for user abort. Human-facing output goes to stderr, machine-parsable data to stdout — so piping works naturally.
DR-0023 introduced `arb diff` as the third overview command alongside `status` and `log`, forming a coherent triad. The command shows the cumulative diff of the feature branch since diverging from the base branch across all repos, with TTY, pipe, and JSON output modes.
8
+
9
+
After using the command in practice, the value proposition turned out to be thin. In a workspace with multiple repos, the full diff across all repos is overwhelming and rarely useful — developers diff interactively in their editor or one repo at a time. The `--stat` summary mode was the most useful output, but it remains a thin wrapper around `git diff --stat` with merge-base resolution.
10
+
11
+
## Options
12
+
13
+
### A: Remove `arb diff` entirely
14
+
15
+
Users who need the diff use `arb exec -- git diff --stat $(git merge-base origin/main HEAD)` or work in individual repos.
16
+
17
+
-**Pros:** Maximum surface area reduction (~500 lines of command code, ~587 lines of integration tests). Simplifies the overview layer. One fewer command to learn, document, test, and maintain.
18
+
-**Cons:** Breaks the "overview triad" from DR-0023. Loses cross-repo summary stats and JSON output.
19
+
20
+
### B: Fold diff into `arb log --diff`
21
+
22
+
Add a `--diff` flag to `arb log` that shows per-commit patches or cumulative diffstat.
23
+
24
+
-**Pros:** Retains some diff capability.
25
+
-**Cons:** Cumulative changeset and per-commit patches are fundamentally different operations. Expands log's scope beyond its core question, violating "do one thing well." `--verbose` already shows per-commit changed files.
26
+
27
+
### C: Keep `arb diff` (status quo)
28
+
29
+
No changes.
30
+
31
+
-**Pros:** The triad remains complete.
32
+
-**Cons:** Maintaining a command with thin value.
33
+
34
+
## Decision
35
+
36
+
Option A: remove `arb diff` entirely.
37
+
38
+
## Reasoning
39
+
40
+
The "Evaluating new operations" framework in GUIDELINES.md asks: "Would `arb exec` leave users meaningfully worse off?" For diff, the answer is no. The command does not involve conflict prediction, divergence analysis, plan/confirm flows, or state machines — the hallmarks of commands that earn their place per the "Minimal, semantic CLI" principle. Its only meaningful coordination value is merge-base resolution, which is a single well-known git command.
41
+
42
+
Option B was rejected because grafting cumulative-diff semantics onto `arb log` creates conceptual confusion. If the command does not earn its place as a standalone, attaching it to another command does not change that.
43
+
44
+
## Consequences
45
+
46
+
- The overview command layer is now `status` and `log`. GUIDELINES.md references are updated accordingly.
47
+
- DR-0023 remains unchanged as a historical record. Its reasoning about the authoring boundary (`arb commit`, `arb pr`) still holds; only the diff inclusion is reversed.
48
+
- DR-0031 (diff merge-base against working tree) is now historical context with no active code.
49
+
- Users who relied on `arb diff --json` for scripting need to adapt. This is acceptable during pre-release per "Prefer correctness over backwards compatibility."
For workspace-level commands (`list`, `delete`), AND applies per-repo: a workspace matches `dirty+ahead-share` only if a _single_ repo is both dirty and ahead-share, not if one repo is dirty and a different repo is ahead-share.
48
48
49
-
`--where` is supported on `status`, `exec`, `open`, `diff`, `log`, `list`, `delete`, `push`, `pull`, `rebase`, `merge`, and `reset`. On `status`, `exec`, `open`, `diff`, `log`, and `list`, the shorthand `--dirty` (`-d`) is equivalent to `--where dirty`.
49
+
`--where` is supported on `status`, `exec`, `open`, `log`, `list`, `delete`, `push`, `pull`, `rebase`, `merge`, and `reset`. On `status`, `exec`, `open`, `log`, and `list`, the shorthand `--dirty` (`-d`) is equivalent to `--where dirty`.
50
50
51
51
The full list of filter terms:
52
52
@@ -120,7 +120,7 @@ Commands that accept `[repos...]` or `[names...]` also read names from stdin whe
120
120
121
121
```bash
122
122
arb status -q --where dirty | arb exec git stash # stash only dirty repos (exec doesn't read stdin)
123
-
arb status -q --where ahead-share | arb diff# diff only ahead-share repos
123
+
arb status -q --where ahead-share | arb log# log only ahead-share repos
Set `ARB_NO_FETCH` to disable automatic fetching globally — equivalent to passing `-N` to every command. Explicit `--fetch` overrides the env var. `pull` always fetches regardless, since it inherently needs fresh remote state.
local topics="filtering remotes stacked templates scripting"
660
-
local commands="init repo create delete rename list path cd attach detach status watch branch pull push rebase retarget merge reset undo log diff exec open template"
646
+
local commands="init repo create delete rename list path cd attach detach status watch branch pull push rebase retarget merge reset undo log exec open template"
local commands="init repo create delete rename list path cd attach detach status watch branch pull push rebase retarget merge reset log diff exec open template help"
672
+
local commands="init repo create delete rename list path cd attach detach status watch branch pull push rebase retarget merge reset log exec open template help"
0 commit comments