Skip to content

Commit ce81b90

Browse files
henrikjeclaude
andcommitted
fix(help): add missing examples and normalize option ordering
Add examples to undo (was the only command without any). Fix missing descriptions on example lines in branch rename, rename, repo clone, and list. Fix misleading bare `arb branch rename` example (needs --continue). Normalize option registration order across push, pull, delete, detach, rename, and branch rename to match the canonical pattern established by rebase/merge/retarget: domain-specific flags, fetch pair, --yes, --dry-run, --verbose, scope expansion, --where, --continue/--abort. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 338b16e commit ce81b90

9 files changed

Lines changed: 18 additions & 18 deletions

File tree

src/commands/branch-rename.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -541,16 +541,16 @@ export function registerBranchRenameSubcommand(parent: Command): void {
541541
.option("-r, --delete-remote", "Delete old branch on remote after rename")
542542
.option("--fetch", "Fetch from all remotes before rename (default)")
543543
.option("-N, --no-fetch", "Skip fetching before rename")
544-
.option("--dry-run", "Show what would happen without executing")
545544
.option("-y, --yes", "Skip confirmation prompt")
545+
.option("--dry-run", "Show what would happen without executing")
546546
.option("--include-in-progress", "Rename repos even if they have an in-progress git operation")
547547
.addOption(new Option("--continue", "Resume a partial branch rename").conflicts("abort"))
548548
.addOption(
549549
new Option("--abort", "Cancel the in-progress branch rename and restore pre-rename state").conflicts("continue"),
550550
)
551551
.summary("Rename the workspace branch across all repos")
552552
.description(
553-
"Examples:\n\n arb branch rename feat/PROJ-209 Rename across all repos\n arb branch rename feat/PROJ-209 --delete-remote\n arb branch rename Resume after partial failure\n\nRenames the workspace branch locally across all repos and updates .arbws/config.json. The workspace directory is not renamed — use 'arb rename' to rename both the workspace and branch together.\n\nFetches before assessing to get fresh remote state (use -N/--no-fetch to skip). Shows a plan and asks for confirmation before proceeding. Repos with an in-progress git operation (rebase, merge, cherry-pick) are skipped by default — use --include-in-progress to override.\n\nBranch rename is tracked as an operation in .arbws/operation.json. If it fails partway, use 'arb branch rename --continue' to retry remaining repos, or 'arb branch rename --abort' to roll back. After rename, tracking is cleared so 'arb push' treats the branch as new and pushes under the new name. Use --delete-remote to also delete the old remote branch during rename.",
553+
"Examples:\n\n arb branch rename feat/PROJ-209 Rename across all repos\n arb branch rename feat/PROJ-209 -r Also delete old remote branch\n arb branch rename --continue Resume after partial failure\n\nRenames the workspace branch locally across all repos and updates .arbws/config.json. The workspace directory is not renamed — use 'arb rename' to rename both the workspace and branch together.\n\nFetches before assessing to get fresh remote state (use -N/--no-fetch to skip). Shows a plan and asks for confirmation before proceeding. Repos with an in-progress git operation (rebase, merge, cherry-pick) are skipped by default — use --include-in-progress to override.\n\nBranch rename is tracked as an operation in .arbws/operation.json. If it fails partway, use 'arb branch rename --continue' to retry remaining repos, or 'arb branch rename --abort' to roll back. After rename, tracking is cleared so 'arb push' treats the branch as new and pushes under the new name. Use --delete-remote to also delete the old remote branch during rename.",
554554
)
555555
.action(
556556
arbAction(async (ctx, newNameArg: string | undefined, options: RenameOptions) => {

src/commands/delete.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -465,22 +465,22 @@ function buildConfirmMessage(count: number, deleteRemote: boolean): string {
465465
export function registerDeleteCommand(program: Command): void {
466466
program
467467
.command("delete [names...]")
468-
.option("-y, --yes", "Skip confirmation prompt")
469468
.option("-f, --force", "Force deletion of at-risk workspaces")
470469
.option("-r, --delete-remote", "Delete remote branches")
471470
.option(
472471
"-a, --all-safe",
473472
"Delete all safe workspaces (no uncommitted changes, unpushed commits, or branch drift; behind base is fine)",
474473
)
475-
.option("-w, --where <filter>", "Filter workspaces by repo status flags (comma = OR, + = AND, ^ = negate)")
476474
.option(
477475
"--older-than <duration>",
478476
"Only delete workspaces not touched in the given duration (e.g. 30d, 2w, 3m, 1y)",
479477
)
480478
.option("--newer-than <duration>", "Only delete workspaces touched within the given duration (e.g. 7d, 2w)")
481-
.option("--dry-run", "Show what would happen without executing")
482479
.option("--fetch", "Fetch before assessing workspace status (default)")
483480
.option("-N, --no-fetch", "Skip fetching")
481+
.option("-y, --yes", "Skip confirmation prompt")
482+
.option("--dry-run", "Show what would happen without executing")
483+
.option("-w, --where <filter>", "Filter workspaces by repo status flags (comma = OR, + = AND, ^ = negate)")
484484
.summary("Delete one or more workspaces")
485485
.description(
486486
"Examples:\n\n arb delete PROJ-208 Delete a workspace\n arb delete --all-safe Delete all safe workspaces\n arb delete --where gone --yes Delete all merged workspaces\n\nDelete one or more workspaces and their repos. Fetches workspace repos before assessing for fresh remote state (skip with -N/--no-fetch). Shows the status of each repo (uncommitted changes, unpushed commits) and any modified template files before proceeding. Prompts with a workspace picker when run without arguments.\n\nUse --all-safe to batch-delete all workspaces with safe status (no uncommitted changes, unpushed commits, or branch drift). Use --where <filter> to filter by status flags. Use --older-than/--newer-than to filter by workspace activity age. When used without workspace names, these filters select from all matching workspaces (e.g. arb delete --where gone deletes all gone workspaces). In a TTY, --where, --older-than/--newer-than, and --all-safe show an interactive picker with all matches pre-selected, letting you deselect workspaces to keep. When combined with names, filters narrow the selection further (AND logic). Combine with --all-safe to narrow further (e.g. --all-safe --where gone for merged-and-safe workspaces). See 'arb help filtering' for filter syntax.\n\nUse --yes to skip confirmation (and interactive selection), --force to override at-risk safety checks, --delete-remote to also delete the remote branches.\n\nSee 'arb help stacked' for stacked workspace deletion.",

src/commands/detach.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,10 @@ export function registerDetachCommand(program: Command): void {
7777
.option("-f, --force", "Force detach even with at-risk repos (uncommitted changes, unpushed commits, etc.)")
7878
.option("-a, --all-repos", "Detach all repos from the workspace")
7979
.option("--delete-branch", "Delete the local branch from the canonical repo")
80-
.option("-y, --yes", "Skip confirmation prompt")
81-
.option("--dry-run", "Show what would happen without executing")
8280
.option("--fetch", "Fetch before detaching (default)")
8381
.option("-N, --no-fetch", "Skip pre-fetch")
82+
.option("-y, --yes", "Skip confirmation prompt")
83+
.option("--dry-run", "Show what would happen without executing")
8484
.summary("Detach repos from the workspace")
8585
.description(
8686
"Examples:\n\n arb detach api Detach a single repo\n arb detach api web --delete-branch Detach and delete local branch\n arb detach --all-repos --force Detach all, skip safety checks\n\nDetach one or more repos from the current workspace without deleting the workspace itself. Shows a plan and asks for confirmation before proceeding. Regenerates templates that reference the repo list (those using {% for repo in workspace.repos %}) to reflect the updated repo list. Skips repos with at-risk state (uncommitted changes, unpushed commits, operation in progress, detached HEAD, wrong branch) unless --force is used. Use --all-repos to detach all repos. Use --delete-branch to also delete the local branch from the canonical repo. Fetches the selected repos before detaching for fresh state (skip with -N/--no-fetch). Use --yes to skip the confirmation prompt. Use --dry-run to see what would happen without executing.",

src/commands/list.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export function registerListCommand(program: Command): void {
6060
.command("list")
6161
.summary("List workspaces with status overview")
6262
.description(
63-
"Examples:\n\n arb list List all workspaces\n arb list --where dirty Only dirty workspaces\n arb list -q | xargs -I{} arb status -C {}\n\nList all workspaces in the project with aggregate status. Shows branch, base, repo count, last commit date, and status for each workspace. The last commit date is the most recent author date across all repos, shown as relative time (e.g. '3 days ago'). The active workspace (the one you're currently inside) is marked with *.\n\nUse --dirty / -d to show only workspaces with dirty repos, or --where <filter> to filter by status flags (any workspace with at least one matching repo is shown). See 'arb help filtering' for filter syntax. Use --no-status to skip per-repo status gathering for faster output.\n\nFetches workspace repos by default for fresh remote data (skip with -N/--no-fetch). Press Ctrl+C during the fetch to cancel and use stale data. Quiet mode (-q) skips fetching by default for scripting speed.\n\nUse --json for machine-readable output. See 'arb help scripting' for output modes and piping.",
63+
"Examples:\n\n arb list List all workspaces\n arb list --where dirty Only dirty workspaces\n arb list -q | xargs -I{} arb status -C {} Run status on each workspace\n\nList all workspaces in the project with aggregate status. Shows branch, base, repo count, last commit date, and status for each workspace. The last commit date is the most recent author date across all repos, shown as relative time (e.g. '3 days ago'). The active workspace (the one you're currently inside) is marked with *.\n\nUse --dirty / -d to show only workspaces with dirty repos, or --where <filter> to filter by status flags (any workspace with at least one matching repo is shown). See 'arb help filtering' for filter syntax. Use --no-status to skip per-repo status gathering for faster output.\n\nFetches workspace repos by default for fresh remote data (skip with -N/--no-fetch). Press Ctrl+C during the fetch to cancel and use stale data. Quiet mode (-q) skips fetching by default for scripting speed.\n\nUse --json for machine-readable output. See 'arb help scripting' for output modes and piping.",
6464
)
6565
.option("--fetch", "Fetch workspace repos before listing (default)")
6666
.option("-N, --no-fetch", "Skip fetching")

src/commands/pull.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,13 @@ export function registerPullCommand(program: Command): void {
5555
program
5656
.command("pull [repos...]")
5757
.option("--reset", "Reset to remote tip instead of pulling (overrides rebased-locally skip)")
58-
.option("-y, --yes", "Skip confirmation prompt")
59-
.option("--dry-run", "Show what would happen without executing")
6058
.addOption(new Option("--rebase", "Pull with rebase").conflicts("merge"))
6159
.addOption(new Option("--merge", "Pull with merge").conflicts("rebase"))
60+
.option("-y, --yes", "Skip confirmation prompt")
61+
.option("--dry-run", "Show what would happen without executing")
62+
.option("-v, --verbose", "Show incoming commits in the plan")
6263
.option("--autostash", "Stash uncommitted changes before pull, re-apply after")
6364
.option("--include-wrong-branch", "Include repos on a different branch than the workspace")
64-
.option("-v, --verbose", "Show incoming commits in the plan")
6565
.option("-w, --where <filter>", "Only pull repos matching status filter (comma = OR, + = AND, ^ = negate)")
6666
.addOption(new Option("--continue", "Resume after resolving conflicts").conflicts("abort"))
6767
.addOption(new Option("--abort", "Cancel the in-progress pull and restore pre-pull state").conflicts("continue"))

src/commands/push.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@ export function registerPushCommand(program: Command): void {
3333
.command("push [repos...]")
3434
.option("-f, --force", "Force push with lease")
3535
.option("--include-merged", "Include branches already merged into base")
36-
.option("--include-wrong-branch", "Include repos on a different branch than the workspace")
3736
.option("--fetch", "Fetch from all remotes before push (default)")
3837
.option("-N, --no-fetch", "Skip fetching before push")
3938
.option("-y, --yes", "Skip confirmation prompt")
4039
.option("--dry-run", "Show what would happen without executing")
4140
.option("-v, --verbose", "Show outgoing commits in the plan")
41+
.option("--include-wrong-branch", "Include repos on a different branch than the workspace")
4242
.option("-w, --where <filter>", "Only push repos matching status filter (comma = OR, + = AND, ^ = negate)")
4343
.summary("Push feature branches to the remote")
4444
.description(

src/commands/rename.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -398,16 +398,16 @@ export function registerRenameCommand(program: Command): void {
398398
.option("-r, --delete-remote", "Delete old branch on remote after rename")
399399
.option("--fetch", "Fetch from all remotes before rename (default)")
400400
.option("-N, --no-fetch", "Skip fetching before rename")
401+
.option("-y, --yes", "Skip confirmation prompt")
402+
.option("--dry-run", "Show what would happen without executing")
403+
.option("--include-in-progress", "Rename repos even if they have an in-progress git operation")
401404
.addOption(new Option("--continue", "Resume a partial workspace rename").conflicts("abort"))
402405
.addOption(
403406
new Option("--abort", "Cancel the in-progress rename and restore pre-rename state").conflicts("continue"),
404407
)
405-
.option("--dry-run", "Show what would happen without executing")
406-
.option("-y, --yes", "Skip confirmation prompt")
407-
.option("--include-in-progress", "Rename repos even if they have an in-progress git operation")
408408
.summary("Rename the workspace (directory + branch)")
409409
.description(
410-
"Examples:\n\n arb rename PROJ-209 Rename workspace and branch\n arb rename PROJ-209 --branch feat/PROJ-209\n arb rename --branch feat/PROJ-209 Derive workspace name from branch\n\nRenames the workspace directory and branch across all repos. Completes the create/delete/rename lifecycle triad.\n\nThe positional <new-name> sets the workspace directory name and, by default, the branch name. Use --branch to set the branch name independently (e.g. 'arb rename PROJ-208 --branch feat/PROJ-208'). If only --branch is provided, the workspace name is derived from the last path segment.\n\nUse --base to change the base branch as part of the rename, completing the 'repurpose workspace' workflow.\n\nFetches before assessing to get fresh remote state (use -N/--no-fetch to skip). Shows a plan and asks for confirmation before proceeding. Repos with an in-progress git operation (rebase, merge, cherry-pick) are skipped.\n\nRename is tracked as an operation in .arbws/operation.json. If it fails partway, use 'arb rename --continue' to retry, or 'arb rename --abort' to roll back.",
410+
"Examples:\n\n arb rename PROJ-209 Rename workspace and branch\n arb rename PROJ-209 --branch feat/PROJ-209 Set branch independently\n arb rename --branch feat/PROJ-209 Derive workspace name from branch\n\nRenames the workspace directory and branch across all repos. Completes the create/delete/rename lifecycle triad.\n\nThe positional <new-name> sets the workspace directory name and, by default, the branch name. Use --branch to set the branch name independently (e.g. 'arb rename PROJ-208 --branch feat/PROJ-208'). If only --branch is provided, the workspace name is derived from the last path segment.\n\nUse --base to change the base branch as part of the rename, completing the 'repurpose workspace' workflow.\n\nFetches before assessing to get fresh remote state (use -N/--no-fetch to skip). Shows a plan and asks for confirmation before proceeding. Repos with an in-progress git operation (rebase, merge, cherry-pick) are skipped.\n\nRename is tracked as an operation in .arbws/operation.json. If it fails partway, use 'arb rename --continue' to retry, or 'arb rename --abort' to roll back.",
411411
)
412412
.action(
413413
arbAction(async (ctx, newNameArg: string | undefined, options: RenameCommandOptions) => {

src/commands/repo.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ export function registerRepoCommand(program: Command): void {
8888
.option("--upstream <url>", "Add an upstream remote (for fork workflows)")
8989
.summary("Clone a repo into .arb/repos/")
9090
.description(
91-
"Examples:\n\n arb repo clone git@github.com:org/api\n arb repo clone git@github.com:org/api backend\n arb repo clone git@github.com:me/api --upstream git@github.com:org/api\n\nClone a git repository into .arb/repos/<name> as a canonical copy. These permanent clones are never worked in directly — instead, arb creates worktrees that point back to them. The repo name is derived from the URL if not specified.\n\nFor fork workflows, use --upstream to add the canonical repo as an upstream remote. This sets remote.pushDefault so arb knows to push to origin (your fork) and rebase onto upstream.",
91+
"Examples:\n\n arb repo clone git@github.com:org/api Clone a repo\n arb repo clone git@github.com:org/api backend Clone with custom name\n arb repo clone git@github.com:me/api --upstream git@github.com:org/api Clone fork with upstream\n\nClone a git repository into .arb/repos/<name> as a canonical copy. These permanent clones are never worked in directly — instead, arb creates worktrees that point back to them. The repo name is derived from the URL if not specified.\n\nFor fork workflows, use --upstream to add the canonical repo as an upstream remote. This sets remote.pushDefault so arb knows to push to origin (your fork) and rebase onto upstream.",
9292
)
9393
.action(
9494
arbAction(async (ctx, url: string, nameArg: string | undefined, options) => {

0 commit comments

Comments
 (0)