Skip to content

Commit db098e9

Browse files
rohoswaggerclaude
andcommitted
feat: ez branch — list branches with PR numbers and worktree paths
Non-interactive branch listing for agents. Shows all managed branches with current branch marker (*), associated PR number, and worktree path if checked out in a worktree. Agents use `ez branch` to discover branches before `ez checkout <name>`, avoiding the interactive TUI picker. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 3780f93 commit db098e9

9 files changed

Lines changed: 50 additions & 2 deletions

File tree

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ These features exist specifically to make ez useable by AI agents:
129129
| 0.1.12 | `ez update` — self-update command, auto-detects install method (cargo vs script), `--check` for version check without install, `--version` for specific version |
130130
| 0.1.13 | Examples in every `--help`, commit SHA in output, `ez worktree delete --yes` from inside worktree, `worktree_path` fix for linked worktrees |
131131
| 0.1.14 | Phased worktree create/delete: validate→mutate→output with rollback on failure; chdir before worktree remove; prune stale entries; recover from broken worktree state |
132+
| 0.1.15 | `ez branch` — list all branches with PR numbers and worktree paths |
132133

133134
---
134135

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "ez-stack"
3-
version = "0.1.14"
3+
version = "0.1.15"
44
edition = "2024"
55
rust-version = "1.85"
66
description = "A CLI tool for managing stacked PRs with GitHub"

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ Exit codes: 0=ok, 2=gh error, 3=conflict, 4=stale ref, 5=usage error, 6=unstaged
202202
| `ez diff --stat` | Show only the diffstat summary |
203203
| `ez diff --name-only` | Show only changed file names |
204204
| `ez parent` | Print the parent branch name to stdout (pipeable) |
205+
| `ez branch` | List all branches with PR numbers and worktree paths |
205206

206207
### Updating
207208

SKILL.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ ez-stack is a CLI for managing stacked PRs on GitHub. When `.git/ez/stack.json`
8282
| Show stack tree as JSON | `ez log --json` |
8383
| Show current branch info | `ez status` |
8484
| Show status as JSON | `ez status --json` |
85+
| List all branches (with PRs and worktree paths) | `ez branch` |
8586

8687
### Worktrees
8788

src/cli.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,13 @@ Examples:
216216
json: bool,
217217
},
218218

219+
/// List all branches in the stack with PR numbers and worktree paths
220+
#[command(after_help = "\
221+
Examples:
222+
ez branch
223+
ez branch | grep feat/")]
224+
Branch,
225+
219226
/// Show diff of current branch vs its parent (what the PR reviewer sees)
220227
#[command(after_help = "\
221228
Examples:

src/cmd/branch.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use anyhow::Result;
2+
use std::collections::HashMap;
3+
4+
use crate::git;
5+
use crate::stack::StackState;
6+
use crate::ui;
7+
8+
pub fn run() -> Result<()> {
9+
let state = StackState::load()?;
10+
let current = git::current_branch()?;
11+
12+
// Build branch→worktree path map.
13+
let worktree_map: HashMap<String, String> = git::worktree_list()
14+
.unwrap_or_default()
15+
.into_iter()
16+
.filter_map(|wt| wt.branch.map(|b| (b, wt.path)))
17+
.collect();
18+
19+
let order = state.topo_order();
20+
21+
for branch in &order {
22+
let meta = state.get_branch(branch)?;
23+
24+
let marker = if *branch == current { "* " } else { " " };
25+
let pr = meta.pr_number.map(|n| format!(" #{n}")).unwrap_or_default();
26+
let wt = worktree_map
27+
.get(branch.as_str())
28+
.map(|p| format!(" {}", ui::dim(p)))
29+
.unwrap_or_default();
30+
31+
// Machine-readable to stdout: marker, name, PR, worktree path.
32+
println!("{marker}{branch}{pr}{wt}");
33+
}
34+
35+
Ok(())
36+
}

src/cmd/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub mod amend;
2+
pub mod branch;
23
pub mod checkout;
34
pub mod commit;
45
pub mod create;

src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ fn run(cli: Cli) -> Result<()> {
154154
Commands::Top => cmd::navigate::top(),
155155
Commands::Bottom => cmd::navigate::bottom(),
156156
Commands::Checkout { name } => cmd::checkout::run(name.as_deref()),
157+
Commands::Branch => cmd::branch::run(),
157158
Commands::Log { json } => cmd::log::run(json),
158159
Commands::Status { json } => cmd::status::run(json),
159160
Commands::Diff { stat, name_only } => cmd::diff::run(stat, name_only),

0 commit comments

Comments
 (0)