From 67ef76a1efd3fd69da3d0148c17be1879cf67022 Mon Sep 17 00:00:00 2001 From: Will Pote Date: Tue, 24 Mar 2026 16:15:49 -0500 Subject: [PATCH 1/7] Add list ignore support for worktree paths and branch names Hide worktrees and branches from `wt list` using glob patterns in user config. Patterns match against canonical worktree paths and branch names, with `--ignored` flag to bypass filtering. Configure in ~/.config/worktrunk/config.toml: [list] ignore = "*/tmp-*" # single pattern ignore = ["*/tmp-*", "*/scratch-*"] # multiple patterns --- Cargo.lock | 1 + Cargo.toml | 1 + docs/content/list.md | 20 ++ skills/worktrunk/reference/list.md | 20 ++ src/cli/mod.rs | 21 ++ src/commands/list/collect/mod.rs | 183 +++++++++++++----- src/commands/list/mod.rs | 34 +++- src/config/user/sections.rs | 6 + src/config/user/tests.rs | 4 + src/main.rs | 6 +- tests/integration_tests/list_config.rs | 145 +++++++++++++- ...tegration_tests__help__help_list_long.snap | 18 ++ ...tion_tests__help__help_list_narrow_80.snap | 22 +++ ...egration_tests__help__help_list_short.snap | 1 + ...onfig__list_config_ignore_array_globs.snap | 51 +++++ ...ig__list_config_ignore_by_parent_path.snap | 51 +++++ ...nfig__list_config_ignore_local_branch.snap | 49 +++++ ...onfig__list_config_ignore_single_glob.snap | 51 +++++ ...config_ignore_worktree_by_branch_name.snap | 51 +++++ ...list_ignored_flag_shows_all_worktrees.snap | 53 +++++ 20 files changed, 732 insertions(+), 56 deletions(-) create mode 100644 tests/snapshots/integration__integration_tests__list_config__list_config_ignore_array_globs.snap create mode 100644 tests/snapshots/integration__integration_tests__list_config__list_config_ignore_by_parent_path.snap create mode 100644 tests/snapshots/integration__integration_tests__list_config__list_config_ignore_local_branch.snap create mode 100644 tests/snapshots/integration__integration_tests__list_config__list_config_ignore_single_glob.snap create mode 100644 tests/snapshots/integration__integration_tests__list_config__list_config_ignore_worktree_by_branch_name.snap create mode 100644 tests/snapshots/integration__integration_tests__list_config__list_ignored_flag_shows_all_worktrees.snap diff --git a/Cargo.lock b/Cargo.lock index b7c9b8e279..be0b47a436 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3224,6 +3224,7 @@ dependencies = [ "env_logger", "etcetera", "fs2", + "glob", "home", "humantime", "ignore", diff --git a/Cargo.toml b/Cargo.toml index cdaf390ce3..f81bd91c0e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -126,6 +126,7 @@ schemars = { version = "1.2.1", features = ["derive"] } tempfile = "3.27" wait-timeout = "0.2" +glob = "0.3.3" [target.'cfg(unix)'.dependencies] skim = "0.20" diff --git a/docs/content/list.md b/docs/content/list.md index 8451ecb497..32e7654cc5 100644 --- a/docs/content/list.md +++ b/docs/content/list.md @@ -164,6 +164,21 @@ These appear across all columns while the table is loading: --- +## Filtering with ignore patterns + +The `[list].ignore` config hides worktrees and branches from output. Patterns are matched against both the canonical worktree path and the branch name: + +```toml +[list] +ignore = ["tmp-*", "*/scratch/*"] +``` + +A worktree or branch is hidden if any pattern matches its path or branch name. Filtering applies to worktrees, local branches (`--branches`), and remote branches (`--remotes`). The summary line shows how many items were filtered (e.g. `Showing 3 worktrees, 1 ignored`). + +Use `--ignored` to bypass filtering and show everything. + +--- + ## JSON output Query structured data with `--format=json`: @@ -319,6 +334,11 @@ Usage: wt list [OPTIONS] --full Show CI, diff analysis, and LLM summaries + --ignored + Show all items, including ignored ones + + Disables filtering by [list].ignore patterns, showing all items. + --progressive Show fast info immediately, update with slow info diff --git a/skills/worktrunk/reference/list.md b/skills/worktrunk/reference/list.md index e3818217f1..e7f90cb9e7 100644 --- a/skills/worktrunk/reference/list.md +++ b/skills/worktrunk/reference/list.md @@ -136,6 +136,21 @@ These appear across all columns while the table is loading: --- +## Filtering with ignore patterns + +The `[list].ignore` config hides worktrees and branches from output. Patterns are matched against both the canonical worktree path and the branch name: + +```toml +[list] +ignore = ["tmp-*", "*/scratch/*"] +``` + +A worktree or branch is hidden if any pattern matches its path or branch name. Filtering applies to worktrees, local branches (`--branches`), and remote branches (`--remotes`). The summary line shows how many items were filtered (e.g. `Showing 3 worktrees, 1 ignored`). + +Use `--ignored` to bypass filtering and show everything. + +--- + ## JSON output Query structured data with `--format=json`: @@ -286,6 +301,11 @@ Usage: wt list [OPTIONS] --full Show CI, diff analysis, and LLM summaries + --ignored + Show all items, including ignored ones + + Disables filtering by [list].ignore patterns, showing all items. + --progressive Show fast info immediately, update with slow info diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 0d4ceaa53d..cc4412360a 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -578,6 +578,21 @@ These appear across all columns while the table is loading: --- +## Filtering with ignore patterns + +The `[list].ignore` config hides worktrees and branches from output. Patterns are matched against both the canonical worktree path and the branch name: + +```toml +[list] +ignore = ["tmp-*", "*/scratch/*"] +``` + +A worktree or branch is hidden if any pattern matches its path or branch name. Filtering applies to worktrees, local branches (`--branches`), and remote branches (`--remotes`). The summary line shows how many items were filtered (e.g. `Showing 3 worktrees, 1 ignored`). + +Use `--ignored` to bypass filtering and show everything. + +--- + ## JSON output Query structured data with `--format=json`: @@ -733,6 +748,12 @@ Missing a field that would be generally useful? Open an issue at https://github. #[arg(long)] full: bool, + /// Show all items, including ignored ones + /// + /// Disables filtering by [list].ignore patterns, showing all items. + #[arg(long)] + ignored: bool, + /// Show fast info immediately, update with slow info /// /// Displays local data (branches, paths, status) first, then updates diff --git a/src/commands/list/collect/mod.rs b/src/commands/list/collect/mod.rs index b5a7aea8ae..1c1fb2899c 100644 --- a/src/commands/list/collect/mod.rs +++ b/src/commands/list/collect/mod.rs @@ -219,6 +219,7 @@ pub enum ShowConfig { cli_branches: bool, cli_remotes: bool, cli_full: bool, + cli_ignored: bool, }, } @@ -330,59 +331,116 @@ pub fn collect( let url_template = url_template_cell.into_inner().unwrap(); // Resolve show flags: merge CLI overrides with config (warmed in parallel phase) - let (show_branches, show_remotes, skip_tasks, command_timeout, collect_deadline) = - match show_config { - ShowConfig::Resolved { - show_branches, - show_remotes, - skip_tasks, - command_timeout, - collect_deadline, - } => ( + let ( + show_branches, + show_remotes, + skip_tasks, + command_timeout, + collect_deadline, + show_ignored, + ignore_patterns, + ) = match show_config { + ShowConfig::Resolved { + show_branches, + show_remotes, + skip_tasks, + command_timeout, + collect_deadline, + } => ( + show_branches, + show_remotes, + skip_tasks, + command_timeout, + collect_deadline, + false, + None, + ), + ShowConfig::DeferredToParallel { + cli_branches, + cli_remotes, + cli_full, + cli_ignored, + } => { + let config = repo.config(); + let show_branches = cli_branches || config.list.branches(); + let show_remotes = cli_remotes || config.list.remotes(); + let show_full = cli_full || config.list.full(); + let skip_tasks: HashSet = if show_full { + HashSet::new() + } else { + [ + TaskKind::BranchDiff, + TaskKind::CiStatus, + TaskKind::WorkingTreeConflicts, + TaskKind::SummaryGenerate, + ] + .into_iter() + .collect() + }; + // Resolve timeouts from merged config (--full disables both) + let (command_timeout, collect_deadline) = if show_full { + (None, None) + } else { + let task_timeout = config.list.task_timeout(); + let deadline = config.list.timeout().map(|d| std::time::Instant::now() + d); + (task_timeout, deadline) + }; + let ignore_patterns = config.list.ignore.clone(); + ( show_branches, show_remotes, skip_tasks, command_timeout, collect_deadline, - ), - ShowConfig::DeferredToParallel { - cli_branches, - cli_remotes, - cli_full, - } => { - let config = repo.config(); - let show_branches = cli_branches || config.list.branches(); - let show_remotes = cli_remotes || config.list.remotes(); - let show_full = cli_full || config.list.full(); - let skip_tasks: HashSet = if show_full { - HashSet::new() - } else { - [ - TaskKind::BranchDiff, - TaskKind::CiStatus, - TaskKind::WorkingTreeConflicts, - TaskKind::SummaryGenerate, - ] - .into_iter() + cli_ignored, + ignore_patterns, + ) + } + }; + + // Compile ignore patterns once for use across worktrees, branches, and remotes. + // Uses string matching (not path matching) for branch names since they contain + // `/` separators but aren't filesystem paths. + let compiled_ignore: Vec = if show_ignored { + Vec::new() + } else { + ignore_patterns + .as_ref() + .map(|p| { + p.iter() + .filter_map(|s| match glob::Pattern::new(s) { + Ok(pat) => Some(pat), + Err(e) => { + log::warn!("Invalid [list].ignore pattern {:?}: {}", s, e); + None + } + }) .collect() - }; - // Resolve timeouts from merged config (--full disables both) - let (command_timeout, collect_deadline) = if show_full { - (None, None) - } else { - let task_timeout = config.list.task_timeout(); - let deadline = config.list.timeout().map(|d| std::time::Instant::now() + d); - (task_timeout, deadline) - }; - ( - show_branches, - show_remotes, - skip_tasks, - command_timeout, - collect_deadline, - ) - } - }; + }) + .unwrap_or_default() + }; + let branch_ignored = + |name: &str| -> bool { compiled_ignore.iter().any(|pat| pat.matches(name)) }; + + // Filter out ignored worktrees by path or branch name + let (worktrees, ignored_worktree_count) = if compiled_ignore.is_empty() { + (worktrees, 0) + } else { + let before = worktrees.len(); + let filtered: Vec<_> = worktrees + .into_iter() + .filter(|wt| { + let path = canonicalize(&wt.path) + .ok() + .unwrap_or_else(|| wt.path.clone()); + let path_matches = compiled_ignore.iter().any(|pat| pat.matches_path(&path)); + let name_matches = wt.branch.as_deref().is_some_and(&branch_ignored); + !(path_matches || name_matches) + }) + .collect(); + let ignored = before - filtered.len(); + (filtered, ignored) + }; // Filter local branches to those without worktrees (CPU-only, no git commands) let branches_without_worktrees = if show_branches { @@ -400,6 +458,20 @@ pub fn collect( } else { Vec::new() }; + + // Filter ignored local branches + let (branches_without_worktrees, ignored_branch_count) = if compiled_ignore.is_empty() { + (branches_without_worktrees, 0) + } else { + let before = branches_without_worktrees.len(); + let filtered: Vec<_> = branches_without_worktrees + .into_iter() + .filter(|(name, _)| !branch_ignored(name)) + .collect(); + let ignored = before - filtered.len(); + (filtered, ignored) + }; + let remote_branches = if show_remotes { if let Some(result) = remote_branches_cell.into_inner() { result? @@ -411,6 +483,21 @@ pub fn collect( Vec::new() }; + // Filter ignored remote branches + let (remote_branches, ignored_remote_count) = if compiled_ignore.is_empty() { + (remote_branches, 0) + } else { + let before = remote_branches.len(); + let filtered: Vec<_> = remote_branches + .into_iter() + .filter(|(name, _)| !branch_ignored(name)) + .collect(); + let ignored = before - filtered.len(); + (filtered, ignored) + }; + + let total_ignored = ignored_worktree_count + ignored_branch_count + ignored_remote_count; + // Detect current worktree using git rev-parse --show-toplevel (via WorkingTree::root). // This correctly handles worktrees placed inside other worktrees (e.g., .worktrees/ layout) // by letting git resolve the actual worktree root rather than using prefix matching. @@ -948,6 +1035,7 @@ pub fn collect( &all_items, show_branches || show_remotes, layout.hidden_column_count, + total_ignored, error_count, timed_out_count, ); @@ -975,6 +1063,7 @@ pub fn collect( &all_items, show_branches || show_remotes, layout.hidden_column_count, + total_ignored, error_count, timed_out_count, ); diff --git a/src/commands/list/mod.rs b/src/commands/list/mod.rs index 452372ddde..5df17eb1e8 100644 --- a/src/commands/list/mod.rs +++ b/src/commands/list/mod.rs @@ -149,6 +149,7 @@ pub fn handle_list( cli_branches: bool, cli_remotes: bool, cli_full: bool, + cli_ignored: bool, render_mode: RenderMode, ) -> anyhow::Result<()> { // Progressive rendering only for table format with Progressive mode @@ -174,6 +175,7 @@ pub fn handle_list( cli_branches, cli_remotes, cli_full, + cli_ignored, }, show_progress, render_table, @@ -206,6 +208,7 @@ pub(super) struct SummaryMetrics { worktrees: usize, local_branches: usize, remote_branches: usize, + ignored: usize, dirty_worktrees: usize, ahead_items: usize, } @@ -266,6 +269,10 @@ impl SummaryMetrics { parts.push(format!("{} worktree{}", self.worktrees, plural)); } + if self.ignored > 0 { + parts.push(format!("{} ignored", self.ignored)); + } + if self.dirty_worktrees > 0 { parts.push(format!("{} with changes", self.dirty_worktrees)); } @@ -292,10 +299,12 @@ pub(crate) fn format_summary_message( items: &[ListItem], show_branches: bool, hidden_column_count: usize, + ignored_count: usize, error_count: usize, timed_out_count: usize, ) -> String { - let metrics = SummaryMetrics::from_items(items); + let mut metrics = SummaryMetrics::from_items(items); + metrics.ignored = ignored_count; let dim = Style::new().dimmed(); let summary = metrics .summary_parts(show_branches, hidden_column_count) @@ -331,6 +340,7 @@ mod tests { assert_eq!(metrics.worktrees, 0); assert_eq!(metrics.local_branches, 0); assert_eq!(metrics.remote_branches, 0); + assert_eq!(metrics.ignored, 0); assert_eq!(metrics.dirty_worktrees, 0); assert_eq!(metrics.ahead_items, 0); } @@ -341,6 +351,7 @@ mod tests { worktrees: 1, local_branches: 0, remote_branches: 0, + ignored: 0, dirty_worktrees: 0, ahead_items: 0, }; @@ -354,6 +365,7 @@ mod tests { worktrees: 3, local_branches: 0, remote_branches: 0, + ignored: 0, dirty_worktrees: 0, ahead_items: 0, }; @@ -367,6 +379,7 @@ mod tests { worktrees: 2, local_branches: 5, remote_branches: 10, + ignored: 0, dirty_worktrees: 0, ahead_items: 0, }; @@ -383,6 +396,7 @@ mod tests { worktrees: 3, local_branches: 0, remote_branches: 0, + ignored: 0, dirty_worktrees: 2, ahead_items: 0, }; @@ -396,6 +410,7 @@ mod tests { worktrees: 2, local_branches: 0, remote_branches: 0, + ignored: 0, dirty_worktrees: 0, ahead_items: 1, }; @@ -409,6 +424,7 @@ mod tests { worktrees: 1, local_branches: 0, remote_branches: 0, + ignored: 0, dirty_worktrees: 0, ahead_items: 0, }; @@ -425,6 +441,7 @@ mod tests { worktrees: 2, local_branches: 0, remote_branches: 5, + ignored: 0, dirty_worktrees: 0, ahead_items: 0, }; @@ -438,6 +455,7 @@ mod tests { worktrees: 5, local_branches: 3, remote_branches: 8, + ignored: 0, dirty_worktrees: 2, ahead_items: 4, }; @@ -460,16 +478,18 @@ mod tests { use insta::assert_snapshot; // No errors - assert_snapshot!(format_summary_message(&[], false, 0, 0, 0), @"β—‹ Showing 0 worktrees"); + assert_snapshot!(format_summary_message(&[], false, 0, 0, 0, 0), @"β—‹ Showing 0 worktrees"); // All timeouts - assert_snapshot!(format_summary_message(&[], false, 0, 3, 3), @"β—‹ Showing 0 worktrees. 3 tasks timed out"); + assert_snapshot!(format_summary_message(&[], false, 0, 0, 3, 3), @"β—‹ Showing 0 worktrees. 3 tasks timed out"); // Mixed errors and timeouts - assert_snapshot!(format_summary_message(&[], false, 0, 5, 3), @"β—‹ Showing 0 worktrees. 5 tasks failed (3 timed out)"); + assert_snapshot!(format_summary_message(&[], false, 0, 0, 5, 3), @"β—‹ Showing 0 worktrees. 5 tasks failed (3 timed out)"); // Only failures, no timeouts - assert_snapshot!(format_summary_message(&[], false, 0, 2, 0), @"β—‹ Showing 0 worktrees. 2 tasks failed"); + assert_snapshot!(format_summary_message(&[], false, 0, 0, 2, 0), @"β—‹ Showing 0 worktrees. 2 tasks failed"); // Single error - assert_snapshot!(format_summary_message(&[], false, 0, 1, 0), @"β—‹ Showing 0 worktrees. 1 task failed"); + assert_snapshot!(format_summary_message(&[], false, 0, 0, 1, 0), @"β—‹ Showing 0 worktrees. 1 task failed"); + // With ignored items + assert_snapshot!(format_summary_message(&[], false, 0, 3, 0, 0), @"β—‹ Showing 0 worktrees, 3 ignored"); // Single timeout - assert_snapshot!(format_summary_message(&[], false, 0, 1, 1), @"β—‹ Showing 0 worktrees. 1 task timed out"); + assert_snapshot!(format_summary_message(&[], false, 0, 0, 1, 1), @"β—‹ Showing 0 worktrees. 1 task timed out"); } } diff --git a/src/config/user/sections.rs b/src/config/user/sections.rs index 457ac5af53..2eced3e4aa 100644 --- a/src/config/user/sections.rs +++ b/src/config/user/sections.rs @@ -148,6 +148,11 @@ pub struct ListConfig { /// Disabled when --full is used. Default: no budget (wait for all results). #[serde(rename = "timeout-ms", skip_serializing_if = "Option::is_none")] pub timeout_ms: Option, + + /// Glob patterns for items to hide from list output. + /// Matches against worktree paths and branch names. Use `--ignored` flag to view hidden items. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub ignore: Option>, } impl ListConfig { @@ -197,6 +202,7 @@ impl Merge for ListConfig { summary: other.summary.or(self.summary), task_timeout_ms: other.task_timeout_ms.or(self.task_timeout_ms), timeout_ms: other.timeout_ms.or(self.timeout_ms), + ignore: other.ignore.clone().or_else(|| self.ignore.clone()), } } } diff --git a/src/config/user/tests.rs b/src/config/user/tests.rs index a844a84439..9aae445db0 100644 --- a/src/config/user/tests.rs +++ b/src/config/user/tests.rs @@ -311,6 +311,7 @@ fn test_list_config_serde() { summary: None, task_timeout_ms: Some(500), timeout_ms: None, + ignore: None, }; let json = serde_json::to_string(&config).unwrap(); let parsed: ListConfig = serde_json::from_str(&json).unwrap(); @@ -553,6 +554,7 @@ fn test_merge_list_config() { summary: Some(true), task_timeout_ms: Some(1000), timeout_ms: Some(2000), + ignore: None, }; let override_config = ListConfig { full: None, // Should fall back to base @@ -561,6 +563,7 @@ fn test_merge_list_config() { summary: None, // Should fall back to base task_timeout_ms: None, // Should fall back to base timeout_ms: None, // Should fall back to base + ignore: None, }; let merged = base.merge_with(&override_config); @@ -1006,6 +1009,7 @@ fn test_list_config_accessor_methods_with_values() { summary: Some(true), task_timeout_ms: Some(5000), timeout_ms: Some(3000), + ignore: None, }; assert!(config.full()); assert!(config.branches()); diff --git a/src/main.rs b/src/main.rs index f34d0e906d..2da75b2be4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -459,12 +459,14 @@ fn handle_config_command(action: ConfigCommand) -> anyhow::Result<()> { } } +#[allow(clippy::too_many_arguments)] fn handle_list_command( subcommand: Option, format: OutputFormat, branches: bool, remotes: bool, full: bool, + ignored: bool, progressive: bool, no_progressive: bool, ) -> anyhow::Result<()> { @@ -485,7 +487,7 @@ fn handle_list_command( None => { let (repo, _recovered) = current_or_recover()?; let render_mode = RenderMode::detect(flag_pair(progressive, no_progressive)); - handle_list(repo, format, branches, remotes, full, render_mode) + handle_list(repo, format, branches, remotes, full, ignored, render_mode) } } } @@ -942,6 +944,7 @@ fn main() { branches, remotes, full, + ignored, progressive, no_progressive, } => handle_list_command( @@ -950,6 +953,7 @@ fn main() { branches, remotes, full, + ignored, progressive, no_progressive, ), diff --git a/tests/integration_tests/list_config.rs b/tests/integration_tests/list_config.rs index fc13f5a5f4..d4f52663a5 100644 --- a/tests/integration_tests/list_config.rs +++ b/tests/integration_tests/list_config.rs @@ -1,7 +1,8 @@ //! Tests for `wt list` command with user config use crate::common::{ - TestRepo, repo, set_temp_home_env, setup_snapshot_settings_with_home, temp_home, wt_command, + TestRepo, list_snapshots, repo, set_temp_home_env, setup_snapshot_settings_with_home, + temp_home, wt_command, }; use insta_cmd::assert_cmd_snapshot; use rstest::rstest; @@ -473,3 +474,145 @@ task-timeout-ms = 1 stderr ); } + +#[rstest] +fn test_list_config_ignore_single_glob(mut repo: TestRepo) { + // Create worktrees: one matching the ignore pattern, one not + repo.add_worktree("feature"); + repo.add_worktree("tmp-scratch"); + + // Write config with ignore pattern to the test config path + // Pattern matches worktree directory names containing "tmp-" + repo.write_test_config( + r#"worktree-path = "../{{ repo }}.{{ branch }}" + +[list] +ignore = ["*/repo.tmp-*"] +"#, + ); + + assert_cmd_snapshot!(list_snapshots::command(&repo, repo.root_path())); +} + +#[rstest] +fn test_list_config_ignore_array_globs(mut repo: TestRepo) { + // Create worktrees matching different patterns + repo.add_worktree("feature"); + repo.add_worktree("tmp-one"); + repo.add_worktree("scratch-two"); + + // Write config with multiple ignore patterns + // Patterns match worktree directory names containing "tmp-" or "scratch-" + repo.write_test_config( + r#"worktree-path = "../{{ repo }}.{{ branch }}" + +[list] +ignore = ["*/repo.tmp-*", "*/repo.scratch-*"] +"#, + ); + + assert_cmd_snapshot!(list_snapshots::command(&repo, repo.root_path())); +} + +#[rstest] +fn test_list_ignored_flag_shows_all_worktrees(mut repo: TestRepo) { + // Create worktrees: one matching the ignore pattern, one not + repo.add_worktree("feature"); + repo.add_worktree("tmp-scratch"); + + // Write config with ignore pattern + repo.write_test_config( + r#"worktree-path = "../{{ repo }}.{{ branch }}" + +[list] +ignore = ["*/repo.tmp-*"] +"#, + ); + + // Use --ignored flag to show ALL worktrees (disables filtering) + let mut cmd = list_snapshots::command(&repo, repo.root_path()); + cmd.arg("--ignored"); + assert_cmd_snapshot!(cmd); +} + +#[rstest] +fn test_list_config_ignore_by_parent_path(mut repo: TestRepo) { + // Create worktrees in different parent directories + let temp_dir = repo.root_path().parent().unwrap(); + let scratch_dir = temp_dir.join("scratch"); + let keep_dir = temp_dir.join("keep"); + + // Worktree in "scratch" folder (should be ignored) + repo.add_worktree_at_path("feature-scratch", &scratch_dir.join("repo.feature-scratch")); + + // Worktree in "keep" folder (should be kept) + repo.add_worktree_at_path("feature-keep", &keep_dir.join("repo.feature-keep")); + + // Configure ignore pattern matching the parent directory + repo.write_test_config( + r#"worktree-path = "{{ branch }}" + +[list] +ignore = ["*/scratch/*"] +"#, + ); + + assert_cmd_snapshot!(list_snapshots::command(&repo, repo.root_path())); +} + +#[rstest] +fn test_list_config_ignore_worktree_by_branch_name(mut repo: TestRepo) { + repo.add_worktree("feature"); + repo.add_worktree("tmp-scratch"); + + // Pattern matches branch name directly (no path glob needed) + repo.write_test_config( + r#"worktree-path = "../{{ repo }}.{{ branch }}" + +[list] +ignore = ["tmp-*"] +"#, + ); + + assert_cmd_snapshot!(list_snapshots::command(&repo, repo.root_path())); +} + +#[rstest] +fn test_list_config_ignore_local_branch(repo: TestRepo) { + // Remove fixture worktrees to isolate test (keep only main worktree) + for branch in &["feature-a", "feature-b", "feature-c"] { + let worktree_path = repo + .root_path() + .parent() + .unwrap() + .join(format!("repo.{}", branch)); + if worktree_path.exists() { + let _ = repo + .git_command() + .args([ + "worktree", + "remove", + "--force", + worktree_path.to_str().unwrap(), + ]) + .output(); + } + let _ = repo.git_command().args(["branch", "-D", branch]).output(); + } + + // Create branches without worktrees + repo.run_git(&["branch", "feature"]); + repo.run_git(&["branch", "tmp-experiment"]); + + repo.write_test_config( + r#"worktree-path = "../{{ repo }}.{{ branch }}" + +[list] +ignore = ["tmp-*"] +"#, + ); + + let mut cmd = list_snapshots::command(&repo, repo.root_path()); + cmd.arg("--branches"); + assert_cmd_snapshot!(cmd); +} diff --git a/tests/snapshots/integration__integration_tests__help__help_list_long.snap b/tests/snapshots/integration__integration_tests__help__help_list_long.snap index e29e17e1e3..19bf313144 100644 --- a/tests/snapshots/integration__integration_tests__help__help_list_long.snap +++ b/tests/snapshots/integration__integration_tests__help__help_list_long.snap @@ -54,6 +54,11 @@ Usage: wt list [OPTIONS] --full Show CI, diff analysis, and LLM summaries + --ignored + Show all items, including ignored ones + + Disables filtering by [list].ignore patterns, showing all items. + --progressive Show fast info immediately, update with slow info @@ -181,6 +186,19 @@ These appear across all columns while the table is loading: ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── +Filtering with ignore patterns + +The [list].ignore config hides worktrees and branches from output. Patterns are matched against both the canonical worktree path and the branch name: + +  [list] +  ignore = ["tmp-*", "*/scratch/*"] + +A worktree or branch is hidden if any pattern matches its path or branch name. Filtering applies to worktrees, local branches (--branches), and remote branches (--remotes). The summary line shows how many items were filtered (e.g. Showing 3 worktrees, 1 ignored). + +Use --ignored to bypass filtering and show everything. + +──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + JSON output Query structured data with --format=json: diff --git a/tests/snapshots/integration__integration_tests__help__help_list_narrow_80.snap b/tests/snapshots/integration__integration_tests__help__help_list_narrow_80.snap index 4b3a44219e..89129f2616 100644 --- a/tests/snapshots/integration__integration_tests__help__help_list_narrow_80.snap +++ b/tests/snapshots/integration__integration_tests__help__help_list_narrow_80.snap @@ -54,6 +54,11 @@ Usage: wt list [OPTIONS] --full Show CI, diff analysis, and LLM summaries + --ignored + Show all items, including ignored ones + + Disables filtering by [list].ignore patterns, showing all items. + --progressive Show fast info immediately, update with slow info @@ -203,6 +208,23 @@ These appear across all columns while the table is loading: ──────────────────────────────────────────────────────────────────────────────── +Filtering with ignore patterns + +The [list].ignore config hides worktrees and branches from output. Patterns are +matched against both the canonical worktree path and the branch name: + +  [list] +  ignore = ["tmp-*", "*/scratch/*"] + +A worktree or branch is hidden if any pattern matches its path or branch name. +Filtering applies to worktrees, local branches (--branches), and remote branches + (--remotes). The summary line shows how many items were filtered (e.g. Showing +3 worktrees, 1 ignored). + +Use --ignored to bypass filtering and show everything. + +──────────────────────────────────────────────────────────────────────────────── + JSON output Query structured data with --format=json: diff --git a/tests/snapshots/integration__integration_tests__help__help_list_short.snap b/tests/snapshots/integration__integration_tests__help__help_list_short.snap index 986b35eea7..67c9dc6b5a 100644 --- a/tests/snapshots/integration__integration_tests__help__help_list_short.snap +++ b/tests/snapshots/integration__integration_tests__help__help_list_short.snap @@ -44,6 +44,7 @@ Usage: wt list [OPTIONS] --branches Include branches without worktrees --remotes Include remote branches --full Show CI, diff analysis, and LLM summaries + --ignored Show all items, including ignored ones --progressive Show fast info immediately, update with slow info -h, --help Print help (see more with '--help') diff --git a/tests/snapshots/integration__integration_tests__list_config__list_config_ignore_array_globs.snap b/tests/snapshots/integration__integration_tests__list_config__list_config_ignore_array_globs.snap new file mode 100644 index 0000000000..83b65e1982 --- /dev/null +++ b/tests/snapshots/integration__integration_tests__list_config__list_config_ignore_array_globs.snap @@ -0,0 +1,51 @@ +--- +source: tests/integration_tests/list_config.rs +info: + program: wt + args: + - list + env: + APPDATA: "[TEST_CONFIG_HOME]" + CLICOLOR_FORCE: "1" + COLUMNS: "500" + GIT_AUTHOR_DATE: "2025-01-01T00:00:00Z" + GIT_COMMITTER_DATE: "2025-01-01T00:00:00Z" + GIT_CONFIG_GLOBAL: "[TEST_GIT_CONFIG]" + GIT_CONFIG_SYSTEM: /dev/null + GIT_EDITOR: "" + GIT_TERMINAL_PROMPT: "0" + HOME: "[TEST_HOME]" + LANG: C + LC_ALL: C + MOCK_CONFIG_DIR: "[MOCK_CONFIG_DIR]" + NO_COLOR: "" + PATH: "[PATH]" + PSModulePath: "" + RUST_LOG: warn + SHELL: "" + TERM: alacritty + USERPROFILE: "[TEST_HOME]" + WORKTRUNK_APPROVALS_PATH: "[TEST_APPROVALS]" + WORKTRUNK_CONFIG_PATH: "[TEST_CONFIG]" + WORKTRUNK_SYSTEM_CONFIG_PATH: "[TEST_SYSTEM_CONFIG]" + WORKTRUNK_TEST_CLAUDE_INSTALLED: "0" + WORKTRUNK_TEST_DELAYED_STREAM_MS: "-1" + WORKTRUNK_TEST_EPOCH: "1735776000" + WORKTRUNK_TEST_NUSHELL_ENV: "0" + WORKTRUNK_TEST_POWERSHELL_ENV: "0" + WORKTRUNK_TEST_SKIP_URL_HEALTH_CHECK: "1" + XDG_CONFIG_HOME: "[TEST_CONFIG_HOME]" +--- +success: true +exit_code: 0 +----- stdout ----- + Branch Status HEADΒ± main↕ Remoteβ‡… Path Commit Age Message +@ main ^| | . 05a4a45d 16h Initial commit ++ feature _ ../repo.feature 05a4a45d 16h Initial commit ++ feature-a ↑ ↑1 ../repo.feature-a 1b87d473 16h Add feature-a file ++ feature-b ↑ ↑1 ../repo.feature-b f62940fc 16h Add feature-b file ++ feature-c ↑ ↑1 ../repo.feature-c 345c7c93 16h Add feature-c file + +β—‹ Showing 5 worktrees, 2 ignored, 3 ahead + +----- stderr ----- diff --git a/tests/snapshots/integration__integration_tests__list_config__list_config_ignore_by_parent_path.snap b/tests/snapshots/integration__integration_tests__list_config__list_config_ignore_by_parent_path.snap new file mode 100644 index 0000000000..e2141b5055 --- /dev/null +++ b/tests/snapshots/integration__integration_tests__list_config__list_config_ignore_by_parent_path.snap @@ -0,0 +1,51 @@ +--- +source: tests/integration_tests/list_config.rs +info: + program: wt + args: + - list + env: + APPDATA: "[TEST_CONFIG_HOME]" + CLICOLOR_FORCE: "1" + COLUMNS: "500" + GIT_AUTHOR_DATE: "2025-01-01T00:00:00Z" + GIT_COMMITTER_DATE: "2025-01-01T00:00:00Z" + GIT_CONFIG_GLOBAL: "[TEST_GIT_CONFIG]" + GIT_CONFIG_SYSTEM: /dev/null + GIT_EDITOR: "" + GIT_TERMINAL_PROMPT: "0" + HOME: "[TEST_HOME]" + LANG: C + LC_ALL: C + MOCK_CONFIG_DIR: "[MOCK_CONFIG_DIR]" + NO_COLOR: "" + PATH: "[PATH]" + PSModulePath: "" + RUST_LOG: warn + SHELL: "" + TERM: alacritty + USERPROFILE: "[TEST_HOME]" + WORKTRUNK_APPROVALS_PATH: "[TEST_APPROVALS]" + WORKTRUNK_CONFIG_PATH: "[TEST_CONFIG]" + WORKTRUNK_SYSTEM_CONFIG_PATH: "[TEST_SYSTEM_CONFIG]" + WORKTRUNK_TEST_CLAUDE_INSTALLED: "0" + WORKTRUNK_TEST_DELAYED_STREAM_MS: "-1" + WORKTRUNK_TEST_EPOCH: "1735776000" + WORKTRUNK_TEST_NUSHELL_ENV: "0" + WORKTRUNK_TEST_POWERSHELL_ENV: "0" + WORKTRUNK_TEST_SKIP_URL_HEALTH_CHECK: "1" + XDG_CONFIG_HOME: "[TEST_CONFIG_HOME]" +--- +success: true +exit_code: 0 +----- stdout ----- + Branch Status HEADΒ± main↕ Remoteβ‡… Path Commit Age Message +@ main ^| | . 05a4a45d 16h Initial commit ++ feature-keep βš‘_ ../keep/repo.feature-keep 05a4a45d 16h Initial commit ++ feature-a βš‘↑ ↑1 ../repo.feature-a 1b87d473 16h Add feature-a file ++ feature-b βš‘↑ ↑1 ../repo.feature-b f62940fc 16h Add feature-b file ++ feature-c βš‘↑ ↑1 ../repo.feature-c 345c7c93 16h Add feature-c file + +β—‹ Showing 5 worktrees, 1 ignored, 3 ahead + +----- stderr ----- diff --git a/tests/snapshots/integration__integration_tests__list_config__list_config_ignore_local_branch.snap b/tests/snapshots/integration__integration_tests__list_config__list_config_ignore_local_branch.snap new file mode 100644 index 0000000000..c45d500c7a --- /dev/null +++ b/tests/snapshots/integration__integration_tests__list_config__list_config_ignore_local_branch.snap @@ -0,0 +1,49 @@ +--- +source: tests/integration_tests/list_config.rs +info: + program: wt + args: + - list + - "--branches" + env: + APPDATA: "[TEST_CONFIG_HOME]" + CLICOLOR_FORCE: "1" + COLUMNS: "500" + GIT_AUTHOR_DATE: "2025-01-01T00:00:00Z" + GIT_COMMITTER_DATE: "2025-01-01T00:00:00Z" + GIT_CONFIG_GLOBAL: "[TEST_GIT_CONFIG]" + GIT_CONFIG_SYSTEM: /dev/null + GIT_EDITOR: "" + GIT_TERMINAL_PROMPT: "0" + HOME: "[TEST_HOME]" + LANG: C + LC_ALL: C + MOCK_CONFIG_DIR: "[MOCK_CONFIG_DIR]" + NO_COLOR: "" + PATH: "[PATH]" + PSModulePath: "" + RUST_LOG: warn + SHELL: "" + TERM: alacritty + USERPROFILE: "[TEST_HOME]" + WORKTRUNK_APPROVALS_PATH: "[TEST_APPROVALS]" + WORKTRUNK_CONFIG_PATH: "[TEST_CONFIG]" + WORKTRUNK_SYSTEM_CONFIG_PATH: "[TEST_SYSTEM_CONFIG]" + WORKTRUNK_TEST_CLAUDE_INSTALLED: "0" + WORKTRUNK_TEST_DELAYED_STREAM_MS: "-1" + WORKTRUNK_TEST_EPOCH: "1735776000" + WORKTRUNK_TEST_NUSHELL_ENV: "0" + WORKTRUNK_TEST_POWERSHELL_ENV: "0" + WORKTRUNK_TEST_SKIP_URL_HEALTH_CHECK: "1" + XDG_CONFIG_HOME: "[TEST_CONFIG_HOME]" +--- +success: true +exit_code: 0 +----- stdout ----- + Branch Status HEADΒ± main↕ Remoteβ‡… Path Commit Age Message +@ main ^| | . 05a4a45d 16h Initial commit + feature /_ 05a4a45d 16h Initial commit + +β—‹ Showing 1 worktrees, 1 branches, 1 ignored + +----- stderr ----- diff --git a/tests/snapshots/integration__integration_tests__list_config__list_config_ignore_single_glob.snap b/tests/snapshots/integration__integration_tests__list_config__list_config_ignore_single_glob.snap new file mode 100644 index 0000000000..b818f531b8 --- /dev/null +++ b/tests/snapshots/integration__integration_tests__list_config__list_config_ignore_single_glob.snap @@ -0,0 +1,51 @@ +--- +source: tests/integration_tests/list_config.rs +info: + program: wt + args: + - list + env: + APPDATA: "[TEST_CONFIG_HOME]" + CLICOLOR_FORCE: "1" + COLUMNS: "500" + GIT_AUTHOR_DATE: "2025-01-01T00:00:00Z" + GIT_COMMITTER_DATE: "2025-01-01T00:00:00Z" + GIT_CONFIG_GLOBAL: "[TEST_GIT_CONFIG]" + GIT_CONFIG_SYSTEM: /dev/null + GIT_EDITOR: "" + GIT_TERMINAL_PROMPT: "0" + HOME: "[TEST_HOME]" + LANG: C + LC_ALL: C + MOCK_CONFIG_DIR: "[MOCK_CONFIG_DIR]" + NO_COLOR: "" + PATH: "[PATH]" + PSModulePath: "" + RUST_LOG: warn + SHELL: "" + TERM: alacritty + USERPROFILE: "[TEST_HOME]" + WORKTRUNK_APPROVALS_PATH: "[TEST_APPROVALS]" + WORKTRUNK_CONFIG_PATH: "[TEST_CONFIG]" + WORKTRUNK_SYSTEM_CONFIG_PATH: "[TEST_SYSTEM_CONFIG]" + WORKTRUNK_TEST_CLAUDE_INSTALLED: "0" + WORKTRUNK_TEST_DELAYED_STREAM_MS: "-1" + WORKTRUNK_TEST_EPOCH: "1735776000" + WORKTRUNK_TEST_NUSHELL_ENV: "0" + WORKTRUNK_TEST_POWERSHELL_ENV: "0" + WORKTRUNK_TEST_SKIP_URL_HEALTH_CHECK: "1" + XDG_CONFIG_HOME: "[TEST_CONFIG_HOME]" +--- +success: true +exit_code: 0 +----- stdout ----- + Branch Status HEADΒ± main↕ Remoteβ‡… Path Commit Age Message +@ main ^| | . 05a4a45d 16h Initial commit ++ feature _ ../repo.feature 05a4a45d 16h Initial commit ++ feature-a ↑ ↑1 ../repo.feature-a 1b87d473 16h Add feature-a file ++ feature-b ↑ ↑1 ../repo.feature-b f62940fc 16h Add feature-b file ++ feature-c ↑ ↑1 ../repo.feature-c 345c7c93 16h Add feature-c file + +β—‹ Showing 5 worktrees, 1 ignored, 3 ahead + +----- stderr ----- diff --git a/tests/snapshots/integration__integration_tests__list_config__list_config_ignore_worktree_by_branch_name.snap b/tests/snapshots/integration__integration_tests__list_config__list_config_ignore_worktree_by_branch_name.snap new file mode 100644 index 0000000000..b818f531b8 --- /dev/null +++ b/tests/snapshots/integration__integration_tests__list_config__list_config_ignore_worktree_by_branch_name.snap @@ -0,0 +1,51 @@ +--- +source: tests/integration_tests/list_config.rs +info: + program: wt + args: + - list + env: + APPDATA: "[TEST_CONFIG_HOME]" + CLICOLOR_FORCE: "1" + COLUMNS: "500" + GIT_AUTHOR_DATE: "2025-01-01T00:00:00Z" + GIT_COMMITTER_DATE: "2025-01-01T00:00:00Z" + GIT_CONFIG_GLOBAL: "[TEST_GIT_CONFIG]" + GIT_CONFIG_SYSTEM: /dev/null + GIT_EDITOR: "" + GIT_TERMINAL_PROMPT: "0" + HOME: "[TEST_HOME]" + LANG: C + LC_ALL: C + MOCK_CONFIG_DIR: "[MOCK_CONFIG_DIR]" + NO_COLOR: "" + PATH: "[PATH]" + PSModulePath: "" + RUST_LOG: warn + SHELL: "" + TERM: alacritty + USERPROFILE: "[TEST_HOME]" + WORKTRUNK_APPROVALS_PATH: "[TEST_APPROVALS]" + WORKTRUNK_CONFIG_PATH: "[TEST_CONFIG]" + WORKTRUNK_SYSTEM_CONFIG_PATH: "[TEST_SYSTEM_CONFIG]" + WORKTRUNK_TEST_CLAUDE_INSTALLED: "0" + WORKTRUNK_TEST_DELAYED_STREAM_MS: "-1" + WORKTRUNK_TEST_EPOCH: "1735776000" + WORKTRUNK_TEST_NUSHELL_ENV: "0" + WORKTRUNK_TEST_POWERSHELL_ENV: "0" + WORKTRUNK_TEST_SKIP_URL_HEALTH_CHECK: "1" + XDG_CONFIG_HOME: "[TEST_CONFIG_HOME]" +--- +success: true +exit_code: 0 +----- stdout ----- + Branch Status HEADΒ± main↕ Remoteβ‡… Path Commit Age Message +@ main ^| | . 05a4a45d 16h Initial commit ++ feature _ ../repo.feature 05a4a45d 16h Initial commit ++ feature-a ↑ ↑1 ../repo.feature-a 1b87d473 16h Add feature-a file ++ feature-b ↑ ↑1 ../repo.feature-b f62940fc 16h Add feature-b file ++ feature-c ↑ ↑1 ../repo.feature-c 345c7c93 16h Add feature-c file + +β—‹ Showing 5 worktrees, 1 ignored, 3 ahead + +----- stderr ----- diff --git a/tests/snapshots/integration__integration_tests__list_config__list_ignored_flag_shows_all_worktrees.snap b/tests/snapshots/integration__integration_tests__list_config__list_ignored_flag_shows_all_worktrees.snap new file mode 100644 index 0000000000..14cdd84871 --- /dev/null +++ b/tests/snapshots/integration__integration_tests__list_config__list_ignored_flag_shows_all_worktrees.snap @@ -0,0 +1,53 @@ +--- +source: tests/integration_tests/list_config.rs +info: + program: wt + args: + - list + - "--ignored" + env: + APPDATA: "[TEST_CONFIG_HOME]" + CLICOLOR_FORCE: "1" + COLUMNS: "500" + GIT_AUTHOR_DATE: "2025-01-01T00:00:00Z" + GIT_COMMITTER_DATE: "2025-01-01T00:00:00Z" + GIT_CONFIG_GLOBAL: "[TEST_GIT_CONFIG]" + GIT_CONFIG_SYSTEM: /dev/null + GIT_EDITOR: "" + GIT_TERMINAL_PROMPT: "0" + HOME: "[TEST_HOME]" + LANG: C + LC_ALL: C + MOCK_CONFIG_DIR: "[MOCK_CONFIG_DIR]" + NO_COLOR: "" + PATH: "[PATH]" + PSModulePath: "" + RUST_LOG: warn + SHELL: "" + TERM: alacritty + USERPROFILE: "[TEST_HOME]" + WORKTRUNK_APPROVALS_PATH: "[TEST_APPROVALS]" + WORKTRUNK_CONFIG_PATH: "[TEST_CONFIG]" + WORKTRUNK_SYSTEM_CONFIG_PATH: "[TEST_SYSTEM_CONFIG]" + WORKTRUNK_TEST_CLAUDE_INSTALLED: "0" + WORKTRUNK_TEST_DELAYED_STREAM_MS: "-1" + WORKTRUNK_TEST_EPOCH: "1735776000" + WORKTRUNK_TEST_NUSHELL_ENV: "0" + WORKTRUNK_TEST_POWERSHELL_ENV: "0" + WORKTRUNK_TEST_SKIP_URL_HEALTH_CHECK: "1" + XDG_CONFIG_HOME: "[TEST_CONFIG_HOME]" +--- +success: true +exit_code: 0 +----- stdout ----- + Branch Status HEADΒ± main↕ Remoteβ‡… Path Commit Age Message +@ main ^| | . 05a4a45d 16h Initial commit ++ feature _ ../repo.feature 05a4a45d 16h Initial commit ++ feature-a ↑ ↑1 ../repo.feature-a 1b87d473 16h Add feature-a file ++ feature-b ↑ ↑1 ../repo.feature-b f62940fc 16h Add feature-b file ++ feature-c ↑ ↑1 ../repo.feature-c 345c7c93 16h Add feature-c file ++ tmp-scratch _ ../repo.tmp-scratch 05a4a45d 16h Initial commit + +β—‹ Showing 6 worktrees, 3 ahead + +----- stderr ----- From a238dba90f3142223531c34f17047cf1c621947d Mon Sep 17 00:00:00 2001 From: Will Pote Date: Sat, 4 Apr 2026 16:48:55 -0500 Subject: [PATCH 2/7] chore: gitignore .DS_Store Made-with: Cursor --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index d0b9f14d10..2c348dec72 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /target +.DS_Store docs/static/assets/ docs/demos/out/ From 39ad8f1609ba5754c0f1bdc874ae50850b3c8ef6 Mon Sep 17 00:00:00 2001 From: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com> Date: Mon, 6 Apr 2026 00:37:52 +0000 Subject: [PATCH 3/7] docs: add [list].ignore to example config and help text Co-Authored-By: Claude Opus 4.6 --- dev/config.example.toml | 1 + docs/content/config.md | 1 + skills/worktrunk/reference/config.md | 1 + src/cli/mod.rs | 1 + ...integration__integration_tests__help__help_config_create.snap | 1 + .../integration__integration_tests__help__help_config_long.snap | 1 + 6 files changed, 6 insertions(+) diff --git a/dev/config.example.toml b/dev/config.example.toml index 9c7f5c8886..7e31447280 100644 --- a/dev/config.example.toml +++ b/dev/config.example.toml @@ -85,6 +85,7 @@ # # task-timeout-ms = 0 # Kill individual git commands after N ms; 0 disables # timeout-ms = 0 # Wall-clock budget for the entire collect phase; 0 disables +# ignore = ["tmp-*"] # Glob patterns to hide from output; use --ignored to show all # # ### Commit # diff --git a/docs/content/config.md b/docs/content/config.md index 5f90b08ac3..7acde0b713 100644 --- a/docs/content/config.md +++ b/docs/content/config.md @@ -166,6 +166,7 @@ remotes = false # Include remote-only branches (--remotes) task-timeout-ms = 0 # Kill individual git commands after N ms; 0 disables timeout-ms = 0 # Wall-clock budget for the entire collect phase; 0 disables +ignore = ["tmp-*"] # Glob patterns to hide from output; use --ignored to show all ``` ### Commit diff --git a/skills/worktrunk/reference/config.md b/skills/worktrunk/reference/config.md index 0f40593088..3bde07f4ee 100644 --- a/skills/worktrunk/reference/config.md +++ b/skills/worktrunk/reference/config.md @@ -165,6 +165,7 @@ remotes = false # Include remote-only branches (--remotes) task-timeout-ms = 0 # Kill individual git commands after N ms; 0 disables timeout-ms = 0 # Wall-clock budget for the entire collect phase; 0 disables +ignore = ["tmp-*"] # Glob patterns to hide from output; use --ignored to show all ``` ### Commit diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 733694cc39..9ebe0c8deb 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -1758,6 +1758,7 @@ remotes = false # Include remote-only branches (--remotes) task-timeout-ms = 0 # Kill individual git commands after N ms; 0 disables timeout-ms = 0 # Wall-clock budget for the entire collect phase; 0 disables +ignore = ["tmp-*"] # Glob patterns to hide from output; use --ignored to show all ``` ### Commit diff --git a/tests/snapshots/integration__integration_tests__help__help_config_create.snap b/tests/snapshots/integration__integration_tests__help__help_config_create.snap index fa50c61156..7511dfd135 100644 --- a/tests/snapshots/integration__integration_tests__help__help_config_create.snap +++ b/tests/snapshots/integration__integration_tests__help__help_config_create.snap @@ -144,6 +144,7 @@ Creates ~/.config/worktrunk/config.toml with the following content:   #   # task-timeout-ms = 0 # Kill individual git commands after N ms; 0 disables   # timeout-ms = 0 # Wall-clock budget for the entire collect phase; 0 disables +  # ignore = ["tmp-*"] # Glob patterns to hide from output; use --ignored to show all   #   # ### Commit   # diff --git a/tests/snapshots/integration__integration_tests__help__help_config_long.snap b/tests/snapshots/integration__integration_tests__help__help_config_long.snap index 6a001b105f..93c71abe96 100644 --- a/tests/snapshots/integration__integration_tests__help__help_config_long.snap +++ b/tests/snapshots/integration__integration_tests__help__help_config_long.snap @@ -190,6 +190,7 @@ Persistent flag values for wt list. Override on command line as needed.     task-timeout-ms = 0 # Kill individual git commands after N ms; 0 disables   timeout-ms = 0 # Wall-clock budget for the entire collect phase; 0 disables +  ignore = ["tmp-*"] # Glob patterns to hide from output; use --ignored to show all Commit From 386b8effc7304d28554091929ac448646c40c449 Mon Sep 17 00:00:00 2001 From: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com> Date: Mon, 6 Apr 2026 01:25:56 +0000 Subject: [PATCH 4/7] docs: label [list].ignore as experimental Mark the ignore filtering feature (config field, --ignored flag, and docs section) with [experimental] tags to signal the interface may change. Co-Authored-By: Claude Opus 4.6 --- dev/config.example.toml | 2 +- docs/content/config.md | 2 +- docs/content/list.md | 4 +++- skills/worktrunk/reference/config.md | 2 +- skills/worktrunk/reference/list.md | 4 ++-- src/cli/mod.rs | 6 +++--- ...ration__integration_tests__help__help_config_create.snap | 2 +- ...egration__integration_tests__help__help_config_long.snap | 2 +- ...ntegration__integration_tests__help__help_list_long.snap | 4 ++-- ...ation__integration_tests__help__help_list_narrow_80.snap | 4 ++-- ...tegration__integration_tests__help__help_list_short.snap | 2 +- 11 files changed, 18 insertions(+), 16 deletions(-) diff --git a/dev/config.example.toml b/dev/config.example.toml index 7e31447280..b4210cf3fe 100644 --- a/dev/config.example.toml +++ b/dev/config.example.toml @@ -85,7 +85,7 @@ # # task-timeout-ms = 0 # Kill individual git commands after N ms; 0 disables # timeout-ms = 0 # Wall-clock budget for the entire collect phase; 0 disables -# ignore = ["tmp-*"] # Glob patterns to hide from output; use --ignored to show all +# ignore = ["tmp-*"] # [experimental] Glob patterns to hide from output; use --ignored to show all # # ### Commit # diff --git a/docs/content/config.md b/docs/content/config.md index 7acde0b713..2691473d59 100644 --- a/docs/content/config.md +++ b/docs/content/config.md @@ -166,7 +166,7 @@ remotes = false # Include remote-only branches (--remotes) task-timeout-ms = 0 # Kill individual git commands after N ms; 0 disables timeout-ms = 0 # Wall-clock budget for the entire collect phase; 0 disables -ignore = ["tmp-*"] # Glob patterns to hide from output; use --ignored to show all +ignore = ["tmp-*"] # Glob patterns to hide from output; use --ignored to show all ``` ### Commit diff --git a/docs/content/list.md b/docs/content/list.md index 4ec11f3633..bc192debdb 100644 --- a/docs/content/list.md +++ b/docs/content/list.md @@ -134,6 +134,8 @@ These appear across all columns while the table is loading: ## Filtering with ignore patterns + + The `[list].ignore` config hides worktrees and branches from output. Patterns are matched against both the canonical worktree path and the branch name: ```toml @@ -280,7 +282,7 @@ Usage: wt list [OPTIONS] Show CI, diff analysis, and LLM summaries --ignored - Show all items, including ignored ones + [experimental] Show all items, including ignored ones Disables filtering by [list].ignore patterns, showing all items. diff --git a/skills/worktrunk/reference/config.md b/skills/worktrunk/reference/config.md index 3bde07f4ee..8fc243a2a1 100644 --- a/skills/worktrunk/reference/config.md +++ b/skills/worktrunk/reference/config.md @@ -165,7 +165,7 @@ remotes = false # Include remote-only branches (--remotes) task-timeout-ms = 0 # Kill individual git commands after N ms; 0 disables timeout-ms = 0 # Wall-clock budget for the entire collect phase; 0 disables -ignore = ["tmp-*"] # Glob patterns to hide from output; use --ignored to show all +ignore = ["tmp-*"] # [experimental] Glob patterns to hide from output; use --ignored to show all ``` ### Commit diff --git a/skills/worktrunk/reference/list.md b/skills/worktrunk/reference/list.md index ff73d5ea78..db7c4c4253 100644 --- a/skills/worktrunk/reference/list.md +++ b/skills/worktrunk/reference/list.md @@ -122,7 +122,7 @@ These appear across all columns while the table is loading: --- -## Filtering with ignore patterns +## Filtering with ignore patterns [experimental] The `[list].ignore` config hides worktrees and branches from output. Patterns are matched against both the canonical worktree path and the branch name: @@ -290,7 +290,7 @@ Options: Show CI, diff analysis, and LLM summaries --ignored - Show all items, including ignored ones + [experimental] Show all items, including ignored ones Disables filtering by [list].ignore patterns, showing all items. diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 9ebe0c8deb..e0211f0352 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -590,7 +590,7 @@ These appear across all columns while the table is loading: --- -## Filtering with ignore patterns +## Filtering with ignore patterns [experimental] The `[list].ignore` config hides worktrees and branches from output. Patterns are matched against both the canonical worktree path and the branch name: @@ -761,7 +761,7 @@ Missing a field that would be generally useful? Open an issue at https://github. #[arg(long)] full: bool, - /// Show all items, including ignored ones + /// \[experimental\] Show all items, including ignored ones /// /// Disables filtering by [list].ignore patterns, showing all items. #[arg(long)] @@ -1758,7 +1758,7 @@ remotes = false # Include remote-only branches (--remotes) task-timeout-ms = 0 # Kill individual git commands after N ms; 0 disables timeout-ms = 0 # Wall-clock budget for the entire collect phase; 0 disables -ignore = ["tmp-*"] # Glob patterns to hide from output; use --ignored to show all +ignore = ["tmp-*"] # [experimental] Glob patterns to hide from output; use --ignored to show all ``` ### Commit diff --git a/tests/snapshots/integration__integration_tests__help__help_config_create.snap b/tests/snapshots/integration__integration_tests__help__help_config_create.snap index 7511dfd135..cb4f0c6729 100644 --- a/tests/snapshots/integration__integration_tests__help__help_config_create.snap +++ b/tests/snapshots/integration__integration_tests__help__help_config_create.snap @@ -144,7 +144,7 @@ Creates ~/.config/worktrunk/config.toml with the following content:   #   # task-timeout-ms = 0 # Kill individual git commands after N ms; 0 disables   # timeout-ms = 0 # Wall-clock budget for the entire collect phase; 0 disables -  # ignore = ["tmp-*"] # Glob patterns to hide from output; use --ignored to show all +  # ignore = ["tmp-*"] # [experimental] Glob patterns to hide from output; use --ignored to show all   #   # ### Commit   # diff --git a/tests/snapshots/integration__integration_tests__help__help_config_long.snap b/tests/snapshots/integration__integration_tests__help__help_config_long.snap index 93c71abe96..58f9941354 100644 --- a/tests/snapshots/integration__integration_tests__help__help_config_long.snap +++ b/tests/snapshots/integration__integration_tests__help__help_config_long.snap @@ -190,7 +190,7 @@ Persistent flag values for wt list. Override on command line as needed.     task-timeout-ms = 0 # Kill individual git commands after N ms; 0 disables   timeout-ms = 0 # Wall-clock budget for the entire collect phase; 0 disables -  ignore = ["tmp-*"] # Glob patterns to hide from output; use --ignored to show all +  ignore = ["tmp-*"] # [experimental] Glob patterns to hide from output; use --ignored to show all Commit diff --git a/tests/snapshots/integration__integration_tests__help__help_list_long.snap b/tests/snapshots/integration__integration_tests__help__help_list_long.snap index e008541627..98c0472c99 100644 --- a/tests/snapshots/integration__integration_tests__help__help_list_long.snap +++ b/tests/snapshots/integration__integration_tests__help__help_list_long.snap @@ -55,7 +55,7 @@ Usage: wt list [OPTIONS] Show CI, diff analysis, and LLM summaries --ignored - Show all items, including ignored ones + [experimental] Show all items, including ignored ones Disables filtering by [list].ignore patterns, showing all items. @@ -186,7 +186,7 @@ These appear across all columns while the table is loading: ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── -Filtering with ignore patterns +Filtering with ignore patterns [experimental] The [list].ignore config hides worktrees and branches from output. Patterns are matched against both the canonical worktree path and the branch name: diff --git a/tests/snapshots/integration__integration_tests__help__help_list_narrow_80.snap b/tests/snapshots/integration__integration_tests__help__help_list_narrow_80.snap index 120ec604a7..8bfc20a370 100644 --- a/tests/snapshots/integration__integration_tests__help__help_list_narrow_80.snap +++ b/tests/snapshots/integration__integration_tests__help__help_list_narrow_80.snap @@ -55,7 +55,7 @@ Usage: wt list [OPTIONS] Show CI, diff analysis, and LLM summaries --ignored - Show all items, including ignored ones + [experimental] Show all items, including ignored ones Disables filtering by [list].ignore patterns, showing all items. @@ -208,7 +208,7 @@ These appear across all columns while the table is loading: ──────────────────────────────────────────────────────────────────────────────── -Filtering with ignore patterns +Filtering with ignore patterns [experimental] The [list].ignore config hides worktrees and branches from output. Patterns are matched against both the canonical worktree path and the branch name: diff --git a/tests/snapshots/integration__integration_tests__help__help_list_short.snap b/tests/snapshots/integration__integration_tests__help__help_list_short.snap index 67c9dc6b5a..eb9598260e 100644 --- a/tests/snapshots/integration__integration_tests__help__help_list_short.snap +++ b/tests/snapshots/integration__integration_tests__help__help_list_short.snap @@ -44,7 +44,7 @@ Usage: wt list [OPTIONS] --branches Include branches without worktrees --remotes Include remote branches --full Show CI, diff analysis, and LLM summaries - --ignored Show all items, including ignored ones + --ignored [experimental] Show all items, including ignored ones --progressive Show fast info immediately, update with slow info -h, --help Print help (see more with '--help') From 1afaa9c127725ae2c8ab9fe4623a1e762ec10471 Mon Sep 17 00:00:00 2001 From: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com> Date: Mon, 6 Apr 2026 02:00:48 +0000 Subject: [PATCH 5/7] =?UTF-8?q?rename:=20[list].ignore=20=E2=86=92=20[list?= =?UTF-8?q?].hidden?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The filtering only applies to `wt list` display β€” hidden worktrees are still accessible to switch, merge, remove, etc. "Hidden" better describes this display-level behavior than "ignore" (which implies the items are functionally excluded). Renames config field, CLI flag (--ignored β†’ --hidden), all internal variables, tests, docs, and snapshots. Co-Authored-By: Claude Opus 4.6 --- dev/config.example.toml | 2 +- docs/content/config.md | 2 +- docs/content/list.md | 16 ++--- skills/worktrunk/reference/config.md | 2 +- skills/worktrunk/reference/list.md | 16 ++--- src/cli/mod.rs | 18 +++--- src/commands/list/collect/mod.rs | 62 +++++++++---------- src/commands/list/mod.rs | 36 +++++------ src/config/user/sections.rs | 6 +- src/config/user/tests.rs | 8 +-- src/main.rs | 8 +-- tests/integration_tests/list_config.rs | 40 ++++++------ ...ation_tests__help__help_config_create.snap | 2 +- ...gration_tests__help__help_config_long.snap | 2 +- ...tegration_tests__help__help_list_long.snap | 16 ++--- ...tion_tests__help__help_list_narrow_80.snap | 16 ++--- ...egration_tests__help__help_list_short.snap | 2 +- ...nfig__list_config_hidden_array_globs.snap} | 2 +- ...g__list_config_hidden_by_parent_path.snap} | 2 +- ...fig__list_config_hidden_local_branch.snap} | 2 +- ...nfig__list_config_hidden_single_glob.snap} | 2 +- ...onfig_hidden_worktree_by_branch_name.snap} | 2 +- ...list_hidden_flag_shows_all_worktrees.snap} | 2 +- 23 files changed, 133 insertions(+), 133 deletions(-) rename tests/snapshots/{integration__integration_tests__list_config__list_config_ignore_array_globs.snap => integration__integration_tests__list_config__list_config_hidden_array_globs.snap} (97%) rename tests/snapshots/{integration__integration_tests__list_config__list_config_ignore_by_parent_path.snap => integration__integration_tests__list_config__list_config_hidden_by_parent_path.snap} (97%) rename tests/snapshots/{integration__integration_tests__list_config__list_config_ignore_local_branch.snap => integration__integration_tests__list_config__list_config_hidden_local_branch.snap} (96%) rename tests/snapshots/{integration__integration_tests__list_config__list_config_ignore_worktree_by_branch_name.snap => integration__integration_tests__list_config__list_config_hidden_single_glob.snap} (97%) rename tests/snapshots/{integration__integration_tests__list_config__list_config_ignore_single_glob.snap => integration__integration_tests__list_config__list_config_hidden_worktree_by_branch_name.snap} (97%) rename tests/snapshots/{integration__integration_tests__list_config__list_ignored_flag_shows_all_worktrees.snap => integration__integration_tests__list_config__list_hidden_flag_shows_all_worktrees.snap} (99%) diff --git a/dev/config.example.toml b/dev/config.example.toml index b4210cf3fe..c816a48c7b 100644 --- a/dev/config.example.toml +++ b/dev/config.example.toml @@ -85,7 +85,7 @@ # # task-timeout-ms = 0 # Kill individual git commands after N ms; 0 disables # timeout-ms = 0 # Wall-clock budget for the entire collect phase; 0 disables -# ignore = ["tmp-*"] # [experimental] Glob patterns to hide from output; use --ignored to show all +# hidden = ["tmp-*"] # [experimental] Glob patterns to hide from output; use --hidden to show all # # ### Commit # diff --git a/docs/content/config.md b/docs/content/config.md index 2691473d59..c6c3476d1d 100644 --- a/docs/content/config.md +++ b/docs/content/config.md @@ -166,7 +166,7 @@ remotes = false # Include remote-only branches (--remotes) task-timeout-ms = 0 # Kill individual git commands after N ms; 0 disables timeout-ms = 0 # Wall-clock budget for the entire collect phase; 0 disables -ignore = ["tmp-*"] # Glob patterns to hide from output; use --ignored to show all +hidden = ["tmp-*"] # Glob patterns to hide from output; use --hidden to show all ``` ### Commit diff --git a/docs/content/list.md b/docs/content/list.md index bc192debdb..9c61b3f175 100644 --- a/docs/content/list.md +++ b/docs/content/list.md @@ -132,20 +132,20 @@ These appear across all columns while the table is loading: --- -## Filtering with ignore patterns +## Filtering with hidden patterns -The `[list].ignore` config hides worktrees and branches from output. Patterns are matched against both the canonical worktree path and the branch name: +The `[list].hidden` config hides worktrees and branches from output. Patterns are matched against both the canonical worktree path and the branch name: ```toml [list] -ignore = ["tmp-*", "*/scratch/*"] +hidden = ["tmp-*", "*/scratch/*"] ``` -A worktree or branch is hidden if any pattern matches its path or branch name. Filtering applies to worktrees, local branches (`--branches`), and remote branches (`--remotes`). The summary line shows how many items were filtered (e.g. `Showing 3 worktrees, 1 ignored`). +A worktree or branch is hidden if any pattern matches its path or branch name. Filtering applies to worktrees, local branches (`--branches`), and remote branches (`--remotes`). The summary line shows how many items were filtered (e.g. `Showing 3 worktrees, 1 hidden`). -Use `--ignored` to bypass filtering and show everything. +Use `--hidden` to bypass filtering and show everything. --- @@ -281,10 +281,10 @@ Usage: wt list [OPTIONS] --full Show CI, diff analysis, and LLM summaries - --ignored - [experimental] Show all items, including ignored ones + --hidden + [experimental] Show all items, including hidden ones - Disables filtering by [list].ignore patterns, showing all items. + Disables filtering by [list].hidden patterns, showing all items. --progressive Show fast info immediately, update with slow info diff --git a/skills/worktrunk/reference/config.md b/skills/worktrunk/reference/config.md index 8fc243a2a1..0da82f4dca 100644 --- a/skills/worktrunk/reference/config.md +++ b/skills/worktrunk/reference/config.md @@ -165,7 +165,7 @@ remotes = false # Include remote-only branches (--remotes) task-timeout-ms = 0 # Kill individual git commands after N ms; 0 disables timeout-ms = 0 # Wall-clock budget for the entire collect phase; 0 disables -ignore = ["tmp-*"] # [experimental] Glob patterns to hide from output; use --ignored to show all +hidden = ["tmp-*"] # [experimental] Glob patterns to hide from output; use --hidden to show all ``` ### Commit diff --git a/skills/worktrunk/reference/list.md b/skills/worktrunk/reference/list.md index db7c4c4253..ce2efcb6be 100644 --- a/skills/worktrunk/reference/list.md +++ b/skills/worktrunk/reference/list.md @@ -122,18 +122,18 @@ These appear across all columns while the table is loading: --- -## Filtering with ignore patterns [experimental] +## Filtering with hidden patterns [experimental] -The `[list].ignore` config hides worktrees and branches from output. Patterns are matched against both the canonical worktree path and the branch name: +The `[list].hidden` config hides worktrees and branches from output. Patterns are matched against both the canonical worktree path and the branch name: ```toml [list] -ignore = ["tmp-*", "*/scratch/*"] +hidden = ["tmp-*", "*/scratch/*"] ``` -A worktree or branch is hidden if any pattern matches its path or branch name. Filtering applies to worktrees, local branches (`--branches`), and remote branches (`--remotes`). The summary line shows how many items were filtered (e.g. `Showing 3 worktrees, 1 ignored`). +A worktree or branch is hidden if any pattern matches its path or branch name. Filtering applies to worktrees, local branches (`--branches`), and remote branches (`--remotes`). The summary line shows how many items were filtered (e.g. `Showing 3 worktrees, 1 hidden`). -Use `--ignored` to bypass filtering and show everything. +Use `--hidden` to bypass filtering and show everything. --- @@ -289,10 +289,10 @@ Options: --full Show CI, diff analysis, and LLM summaries - --ignored - [experimental] Show all items, including ignored ones + --hidden + [experimental] Show all items, including hidden ones - Disables filtering by [list].ignore patterns, showing all items. + Disables filtering by [list].hidden patterns, showing all items. --progressive Show fast info immediately, update with slow info diff --git a/src/cli/mod.rs b/src/cli/mod.rs index e0211f0352..029a5bd0a5 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -590,18 +590,18 @@ These appear across all columns while the table is loading: --- -## Filtering with ignore patterns [experimental] +## Filtering with hidden patterns [experimental] -The `[list].ignore` config hides worktrees and branches from output. Patterns are matched against both the canonical worktree path and the branch name: +The `[list].hidden` config hides worktrees and branches from output. Patterns are matched against both the canonical worktree path and the branch name: ```toml [list] -ignore = ["tmp-*", "*/scratch/*"] +hidden = ["tmp-*", "*/scratch/*"] ``` -A worktree or branch is hidden if any pattern matches its path or branch name. Filtering applies to worktrees, local branches (`--branches`), and remote branches (`--remotes`). The summary line shows how many items were filtered (e.g. `Showing 3 worktrees, 1 ignored`). +A worktree or branch is hidden if any pattern matches its path or branch name. Filtering applies to worktrees, local branches (`--branches`), and remote branches (`--remotes`). The summary line shows how many items were filtered (e.g. `Showing 3 worktrees, 1 hidden`). -Use `--ignored` to bypass filtering and show everything. +Use `--hidden` to bypass filtering and show everything. --- @@ -761,11 +761,11 @@ Missing a field that would be generally useful? Open an issue at https://github. #[arg(long)] full: bool, - /// \[experimental\] Show all items, including ignored ones + /// \[experimental\] Show all items, including hidden ones /// - /// Disables filtering by [list].ignore patterns, showing all items. + /// Disables filtering by [list].hidden patterns, showing all items. #[arg(long)] - ignored: bool, + hidden: bool, /// Show fast info immediately, update with slow info /// @@ -1758,7 +1758,7 @@ remotes = false # Include remote-only branches (--remotes) task-timeout-ms = 0 # Kill individual git commands after N ms; 0 disables timeout-ms = 0 # Wall-clock budget for the entire collect phase; 0 disables -ignore = ["tmp-*"] # [experimental] Glob patterns to hide from output; use --ignored to show all +hidden = ["tmp-*"] # [experimental] Glob patterns to hide from output; use --hidden to show all ``` ### Commit diff --git a/src/commands/list/collect/mod.rs b/src/commands/list/collect/mod.rs index ab8a6ce1fc..6c3746df06 100644 --- a/src/commands/list/collect/mod.rs +++ b/src/commands/list/collect/mod.rs @@ -251,7 +251,7 @@ pub enum ShowConfig { cli_branches: bool, cli_remotes: bool, cli_full: bool, - cli_ignored: bool, + cli_hidden: bool, }, } @@ -368,8 +368,8 @@ pub fn collect( skip_tasks, command_timeout, collect_deadline, - show_ignored, - ignore_patterns, + show_hidden, + hidden_patterns, ) = match show_config { ShowConfig::Resolved { show_branches, @@ -390,7 +390,7 @@ pub fn collect( cli_branches, cli_remotes, cli_full, - cli_ignored, + cli_hidden, } => { let config = repo.config(); let show_branches = cli_branches || config.list.branches(); @@ -416,33 +416,33 @@ pub fn collect( let deadline = config.list.timeout().map(|d| std::time::Instant::now() + d); (task_timeout, deadline) }; - let ignore_patterns = config.list.ignore.clone(); + let hidden_patterns = config.list.hidden.clone(); ( show_branches, show_remotes, skip_tasks, command_timeout, collect_deadline, - cli_ignored, - ignore_patterns, + cli_hidden, + hidden_patterns, ) } }; - // Compile ignore patterns once for use across worktrees, branches, and remotes. + // Compile hidden patterns once for use across worktrees, branches, and remotes. // Uses string matching (not path matching) for branch names since they contain // `/` separators but aren't filesystem paths. - let compiled_ignore: Vec = if show_ignored { + let compiled_hidden: Vec = if show_hidden { Vec::new() } else { - ignore_patterns + hidden_patterns .as_ref() .map(|p| { p.iter() .filter_map(|s| match glob::Pattern::new(s) { Ok(pat) => Some(pat), Err(e) => { - log::warn!("Invalid [list].ignore pattern {:?}: {}", s, e); + log::warn!("Invalid [list].hidden pattern {:?}: {}", s, e); None } }) @@ -450,11 +450,11 @@ pub fn collect( }) .unwrap_or_default() }; - let branch_ignored = - |name: &str| -> bool { compiled_ignore.iter().any(|pat| pat.matches(name)) }; + let branch_hidden = + |name: &str| -> bool { compiled_hidden.iter().any(|pat| pat.matches(name)) }; - // Filter out ignored worktrees by path or branch name - let (worktrees, ignored_worktree_count) = if compiled_ignore.is_empty() { + // Filter out hidden worktrees by path or branch name + let (worktrees, hidden_worktree_count) = if compiled_hidden.is_empty() { (worktrees, 0) } else { let before = worktrees.len(); @@ -464,13 +464,13 @@ pub fn collect( let path = canonicalize(&wt.path) .ok() .unwrap_or_else(|| wt.path.clone()); - let path_matches = compiled_ignore.iter().any(|pat| pat.matches_path(&path)); - let name_matches = wt.branch.as_deref().is_some_and(&branch_ignored); + let path_matches = compiled_hidden.iter().any(|pat| pat.matches_path(&path)); + let name_matches = wt.branch.as_deref().is_some_and(&branch_hidden); !(path_matches || name_matches) }) .collect(); - let ignored = before - filtered.len(); - (filtered, ignored) + let hidden = before - filtered.len(); + (filtered, hidden) }; // Filter local branches to those without worktrees (CPU-only, no git commands) @@ -490,17 +490,17 @@ pub fn collect( Vec::new() }; - // Filter ignored local branches - let (branches_without_worktrees, ignored_branch_count) = if compiled_ignore.is_empty() { + // Filter hidden local branches + let (branches_without_worktrees, hidden_branch_count) = if compiled_hidden.is_empty() { (branches_without_worktrees, 0) } else { let before = branches_without_worktrees.len(); let filtered: Vec<_> = branches_without_worktrees .into_iter() - .filter(|(name, _)| !branch_ignored(name)) + .filter(|(name, _)| !branch_hidden(name)) .collect(); - let ignored = before - filtered.len(); - (filtered, ignored) + let hidden = before - filtered.len(); + (filtered, hidden) }; let remote_branches = if show_remotes { @@ -514,20 +514,20 @@ pub fn collect( Vec::new() }; - // Filter ignored remote branches - let (remote_branches, ignored_remote_count) = if compiled_ignore.is_empty() { + // Filter hidden remote branches + let (remote_branches, hidden_remote_count) = if compiled_hidden.is_empty() { (remote_branches, 0) } else { let before = remote_branches.len(); let filtered: Vec<_> = remote_branches .into_iter() - .filter(|(name, _)| !branch_ignored(name)) + .filter(|(name, _)| !branch_hidden(name)) .collect(); - let ignored = before - filtered.len(); - (filtered, ignored) + let hidden = before - filtered.len(); + (filtered, hidden) }; - let total_ignored = ignored_worktree_count + ignored_branch_count + ignored_remote_count; + let total_hidden = hidden_worktree_count + hidden_branch_count + hidden_remote_count; // Detect current worktree using git rev-parse --show-toplevel (via WorkingTree::root). // This correctly handles worktrees placed inside other worktrees (e.g., .worktrees/ layout) @@ -1072,7 +1072,7 @@ pub fn collect( &all_items, show_branches || show_remotes, layout.hidden_column_count, - total_ignored, + total_hidden, error_count, timed_out_count, ), diff --git a/src/commands/list/mod.rs b/src/commands/list/mod.rs index c381af1579..bebcad2e13 100644 --- a/src/commands/list/mod.rs +++ b/src/commands/list/mod.rs @@ -149,7 +149,7 @@ pub fn handle_list( cli_branches: bool, cli_remotes: bool, cli_full: bool, - cli_ignored: bool, + cli_hidden: bool, render_mode: RenderMode, ) -> anyhow::Result<()> { // Progressive rendering only for table format with Progressive mode @@ -175,7 +175,7 @@ pub fn handle_list( cli_branches, cli_remotes, cli_full, - cli_ignored, + cli_hidden, }, show_progress, render_table, @@ -208,7 +208,7 @@ pub(super) struct SummaryMetrics { worktrees: usize, local_branches: usize, remote_branches: usize, - ignored: usize, + hidden: usize, dirty_worktrees: usize, ahead_items: usize, } @@ -269,8 +269,8 @@ impl SummaryMetrics { parts.push(format!("{} worktree{}", self.worktrees, plural)); } - if self.ignored > 0 { - parts.push(format!("{} ignored", self.ignored)); + if self.hidden > 0 { + parts.push(format!("{} hidden", self.hidden)); } if self.dirty_worktrees > 0 { @@ -299,12 +299,12 @@ pub(crate) fn format_summary_message( items: &[ListItem], show_branches: bool, hidden_column_count: usize, - ignored_count: usize, + hidden_count: usize, error_count: usize, timed_out_count: usize, ) -> String { let mut metrics = SummaryMetrics::from_items(items); - metrics.ignored = ignored_count; + metrics.hidden = hidden_count; let dim = Style::new().dimmed(); let summary = metrics .summary_parts(show_branches, hidden_column_count) @@ -340,7 +340,7 @@ mod tests { assert_eq!(metrics.worktrees, 0); assert_eq!(metrics.local_branches, 0); assert_eq!(metrics.remote_branches, 0); - assert_eq!(metrics.ignored, 0); + assert_eq!(metrics.hidden, 0); assert_eq!(metrics.dirty_worktrees, 0); assert_eq!(metrics.ahead_items, 0); } @@ -351,7 +351,7 @@ mod tests { worktrees: 1, local_branches: 0, remote_branches: 0, - ignored: 0, + hidden: 0, dirty_worktrees: 0, ahead_items: 0, }; @@ -365,7 +365,7 @@ mod tests { worktrees: 3, local_branches: 0, remote_branches: 0, - ignored: 0, + hidden: 0, dirty_worktrees: 0, ahead_items: 0, }; @@ -379,7 +379,7 @@ mod tests { worktrees: 2, local_branches: 5, remote_branches: 10, - ignored: 0, + hidden: 0, dirty_worktrees: 0, ahead_items: 0, }; @@ -396,7 +396,7 @@ mod tests { worktrees: 3, local_branches: 0, remote_branches: 0, - ignored: 0, + hidden: 0, dirty_worktrees: 2, ahead_items: 0, }; @@ -410,7 +410,7 @@ mod tests { worktrees: 2, local_branches: 0, remote_branches: 0, - ignored: 0, + hidden: 0, dirty_worktrees: 0, ahead_items: 1, }; @@ -424,7 +424,7 @@ mod tests { worktrees: 1, local_branches: 0, remote_branches: 0, - ignored: 0, + hidden: 0, dirty_worktrees: 0, ahead_items: 0, }; @@ -441,7 +441,7 @@ mod tests { worktrees: 2, local_branches: 0, remote_branches: 5, - ignored: 0, + hidden: 0, dirty_worktrees: 0, ahead_items: 0, }; @@ -455,7 +455,7 @@ mod tests { worktrees: 5, local_branches: 3, remote_branches: 8, - ignored: 0, + hidden: 0, dirty_worktrees: 2, ahead_items: 4, }; @@ -487,8 +487,8 @@ mod tests { assert_snapshot!(format_summary_message(&[], false, 0, 0, 2, 0), @"β—‹ Showing 0 worktrees. 2 tasks failed"); // Single error assert_snapshot!(format_summary_message(&[], false, 0, 0, 1, 0), @"β—‹ Showing 0 worktrees. 1 task failed"); - // With ignored items - assert_snapshot!(format_summary_message(&[], false, 0, 3, 0, 0), @"β—‹ Showing 0 worktrees, 3 ignored"); + // With hidden items + assert_snapshot!(format_summary_message(&[], false, 0, 3, 0, 0), @"β—‹ Showing 0 worktrees, 3 hidden"); // Single timeout assert_snapshot!(format_summary_message(&[], false, 0, 0, 1, 1), @"β—‹ Showing 0 worktrees. 1 task timed out"); } diff --git a/src/config/user/sections.rs b/src/config/user/sections.rs index 02f6925c95..d89a24f82d 100644 --- a/src/config/user/sections.rs +++ b/src/config/user/sections.rs @@ -151,9 +151,9 @@ pub struct ListConfig { pub timeout_ms: Option, /// Glob patterns for items to hide from list output. - /// Matches against worktree paths and branch names. Use `--ignored` flag to view hidden items. + /// Matches against worktree paths and branch names. Use `--hidden` flag to view hidden items. #[serde(default, skip_serializing_if = "Option::is_none")] - pub ignore: Option>, + pub hidden: Option>, } impl ListConfig { @@ -203,7 +203,7 @@ impl Merge for ListConfig { summary: other.summary.or(self.summary), task_timeout_ms: other.task_timeout_ms.or(self.task_timeout_ms), timeout_ms: other.timeout_ms.or(self.timeout_ms), - ignore: other.ignore.clone().or_else(|| self.ignore.clone()), + hidden: other.hidden.clone().or_else(|| self.hidden.clone()), } } } diff --git a/src/config/user/tests.rs b/src/config/user/tests.rs index 1872edd33a..cb39c7b3aa 100644 --- a/src/config/user/tests.rs +++ b/src/config/user/tests.rs @@ -311,7 +311,7 @@ fn test_list_config_serde() { summary: None, task_timeout_ms: Some(500), timeout_ms: None, - ignore: None, + hidden: None, }; let json = serde_json::to_string(&config).unwrap(); let parsed: ListConfig = serde_json::from_str(&json).unwrap(); @@ -553,7 +553,7 @@ fn test_merge_list_config() { summary: Some(true), task_timeout_ms: Some(1000), timeout_ms: Some(2000), - ignore: None, + hidden: None, }; let override_config = ListConfig { full: None, // Should fall back to base @@ -562,7 +562,7 @@ fn test_merge_list_config() { summary: None, // Should fall back to base task_timeout_ms: None, // Should fall back to base timeout_ms: None, // Should fall back to base - ignore: None, + hidden: None, }; let merged = base.merge_with(&override_config); @@ -969,7 +969,7 @@ fn test_list_config_accessor_methods_with_values() { summary: Some(true), task_timeout_ms: Some(5000), timeout_ms: Some(3000), - ignore: None, + hidden: None, }; assert!(config.full()); assert!(config.branches()); diff --git a/src/main.rs b/src/main.rs index 9bea6d87f9..c3e6eba0d8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -495,7 +495,7 @@ fn handle_list_command( branches: bool, remotes: bool, full: bool, - ignored: bool, + hidden: bool, progressive: bool, no_progressive: bool, ) -> anyhow::Result<()> { @@ -516,7 +516,7 @@ fn handle_list_command( None => { let (repo, _recovered) = current_or_recover()?; let render_mode = RenderMode::detect(flag_pair(progressive, no_progressive)); - handle_list(repo, format, branches, remotes, full, ignored, render_mode) + handle_list(repo, format, branches, remotes, full, hidden, render_mode) } } } @@ -983,7 +983,7 @@ fn dispatch_command(command: Commands) -> anyhow::Result<()> { branches, remotes, full, - ignored, + hidden, progressive, no_progressive, } => handle_list_command( @@ -992,7 +992,7 @@ fn dispatch_command(command: Commands) -> anyhow::Result<()> { branches, remotes, full, - ignored, + hidden, progressive, no_progressive, ), diff --git a/tests/integration_tests/list_config.rs b/tests/integration_tests/list_config.rs index dbe4f4deb9..9ac0e55571 100644 --- a/tests/integration_tests/list_config.rs +++ b/tests/integration_tests/list_config.rs @@ -476,18 +476,18 @@ task-timeout-ms = 1 } #[rstest] -fn test_list_config_ignore_single_glob(mut repo: TestRepo) { - // Create worktrees: one matching the ignore pattern, one not +fn test_list_config_hidden_single_glob(mut repo: TestRepo) { + // Create worktrees: one matching the hidden pattern, one not repo.add_worktree("feature"); repo.add_worktree("tmp-scratch"); - // Write config with ignore pattern to the test config path + // Write config with hidden pattern to the test config path // Pattern matches worktree directory names containing "tmp-" repo.write_test_config( r#"worktree-path = "../{{ repo }}.{{ branch }}" [list] -ignore = ["*/repo.tmp-*"] +hidden = ["*/repo.tmp-*"] "#, ); @@ -495,19 +495,19 @@ ignore = ["*/repo.tmp-*"] } #[rstest] -fn test_list_config_ignore_array_globs(mut repo: TestRepo) { +fn test_list_config_hidden_array_globs(mut repo: TestRepo) { // Create worktrees matching different patterns repo.add_worktree("feature"); repo.add_worktree("tmp-one"); repo.add_worktree("scratch-two"); - // Write config with multiple ignore patterns + // Write config with multiple hidden patterns // Patterns match worktree directory names containing "tmp-" or "scratch-" repo.write_test_config( r#"worktree-path = "../{{ repo }}.{{ branch }}" [list] -ignore = ["*/repo.tmp-*", "*/repo.scratch-*"] +hidden = ["*/repo.tmp-*", "*/repo.scratch-*"] "#, ); @@ -515,28 +515,28 @@ ignore = ["*/repo.tmp-*", "*/repo.scratch-*"] } #[rstest] -fn test_list_ignored_flag_shows_all_worktrees(mut repo: TestRepo) { - // Create worktrees: one matching the ignore pattern, one not +fn test_list_hidden_flag_shows_all_worktrees(mut repo: TestRepo) { + // Create worktrees: one matching the hidden pattern, one not repo.add_worktree("feature"); repo.add_worktree("tmp-scratch"); - // Write config with ignore pattern + // Write config with hidden pattern repo.write_test_config( r#"worktree-path = "../{{ repo }}.{{ branch }}" [list] -ignore = ["*/repo.tmp-*"] +hidden = ["*/repo.tmp-*"] "#, ); - // Use --ignored flag to show ALL worktrees (disables filtering) + // Use --hidden flag to show ALL worktrees (disables filtering) let mut cmd = list_snapshots::command(&repo, repo.root_path()); - cmd.arg("--ignored"); + cmd.arg("--hidden"); assert_cmd_snapshot!(cmd); } #[rstest] -fn test_list_config_ignore_by_parent_path(mut repo: TestRepo) { +fn test_list_config_hidden_by_parent_path(mut repo: TestRepo) { // Create worktrees in different parent directories let temp_dir = repo.root_path().parent().unwrap(); let scratch_dir = temp_dir.join("scratch"); @@ -548,12 +548,12 @@ fn test_list_config_ignore_by_parent_path(mut repo: TestRepo) { // Worktree in "keep" folder (should be kept) repo.add_worktree_at_path("feature-keep", &keep_dir.join("repo.feature-keep")); - // Configure ignore pattern matching the parent directory + // Configure hidden pattern matching the parent directory repo.write_test_config( r#"worktree-path = "{{ branch }}" [list] -ignore = ["*/scratch/*"] +hidden = ["*/scratch/*"] "#, ); @@ -561,7 +561,7 @@ ignore = ["*/scratch/*"] } #[rstest] -fn test_list_config_ignore_worktree_by_branch_name(mut repo: TestRepo) { +fn test_list_config_hidden_worktree_by_branch_name(mut repo: TestRepo) { repo.add_worktree("feature"); repo.add_worktree("tmp-scratch"); @@ -570,7 +570,7 @@ fn test_list_config_ignore_worktree_by_branch_name(mut repo: TestRepo) { r#"worktree-path = "../{{ repo }}.{{ branch }}" [list] -ignore = ["tmp-*"] +hidden = ["tmp-*"] "#, ); @@ -578,7 +578,7 @@ ignore = ["tmp-*"] } #[rstest] -fn test_list_config_ignore_local_branch(repo: TestRepo) { +fn test_list_config_hidden_local_branch(repo: TestRepo) { // Remove fixture worktrees to isolate test (keep only main worktree) for branch in &["feature-a", "feature-b", "feature-c"] { let worktree_path = repo @@ -608,7 +608,7 @@ fn test_list_config_ignore_local_branch(repo: TestRepo) { r#"worktree-path = "../{{ repo }}.{{ branch }}" [list] -ignore = ["tmp-*"] +hidden = ["tmp-*"] "#, ); diff --git a/tests/snapshots/integration__integration_tests__help__help_config_create.snap b/tests/snapshots/integration__integration_tests__help__help_config_create.snap index cb4f0c6729..5a37716703 100644 --- a/tests/snapshots/integration__integration_tests__help__help_config_create.snap +++ b/tests/snapshots/integration__integration_tests__help__help_config_create.snap @@ -144,7 +144,7 @@ Creates ~/.config/worktrunk/config.toml with the following content:   #   # task-timeout-ms = 0 # Kill individual git commands after N ms; 0 disables   # timeout-ms = 0 # Wall-clock budget for the entire collect phase; 0 disables -  # ignore = ["tmp-*"] # [experimental] Glob patterns to hide from output; use --ignored to show all +  # hidden = ["tmp-*"] # [experimental] Glob patterns to hide from output; use --hidden to show all   #   # ### Commit   # diff --git a/tests/snapshots/integration__integration_tests__help__help_config_long.snap b/tests/snapshots/integration__integration_tests__help__help_config_long.snap index 58f9941354..e913fd77bb 100644 --- a/tests/snapshots/integration__integration_tests__help__help_config_long.snap +++ b/tests/snapshots/integration__integration_tests__help__help_config_long.snap @@ -190,7 +190,7 @@ Persistent flag values for wt list. Override on command line as needed.     task-timeout-ms = 0 # Kill individual git commands after N ms; 0 disables   timeout-ms = 0 # Wall-clock budget for the entire collect phase; 0 disables -  ignore = ["tmp-*"] # [experimental] Glob patterns to hide from output; use --ignored to show all +  hidden = ["tmp-*"] # [experimental] Glob patterns to hide from output; use --hidden to show all Commit diff --git a/tests/snapshots/integration__integration_tests__help__help_list_long.snap b/tests/snapshots/integration__integration_tests__help__help_list_long.snap index 98c0472c99..c59e4c9b64 100644 --- a/tests/snapshots/integration__integration_tests__help__help_list_long.snap +++ b/tests/snapshots/integration__integration_tests__help__help_list_long.snap @@ -54,10 +54,10 @@ Usage: wt list [OPTIONS] --full Show CI, diff analysis, and LLM summaries - --ignored - [experimental] Show all items, including ignored ones + --hidden + [experimental] Show all items, including hidden ones - Disables filtering by [list].ignore patterns, showing all items. + Disables filtering by [list].hidden patterns, showing all items. --progressive Show fast info immediately, update with slow info @@ -186,16 +186,16 @@ These appear across all columns while the table is loading: ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── -Filtering with ignore patterns [experimental] +Filtering with hidden patterns [experimental] -The [list].ignore config hides worktrees and branches from output. Patterns are matched against both the canonical worktree path and the branch name: +The [list].hidden config hides worktrees and branches from output. Patterns are matched against both the canonical worktree path and the branch name:   [list] -  ignore = ["tmp-*", "*/scratch/*"] +  hidden = ["tmp-*", "*/scratch/*"] -A worktree or branch is hidden if any pattern matches its path or branch name. Filtering applies to worktrees, local branches (--branches), and remote branches (--remotes). The summary line shows how many items were filtered (e.g. Showing 3 worktrees, 1 ignored). +A worktree or branch is hidden if any pattern matches its path or branch name. Filtering applies to worktrees, local branches (--branches), and remote branches (--remotes). The summary line shows how many items were filtered (e.g. Showing 3 worktrees, 1 hidden). -Use --ignored to bypass filtering and show everything. +Use --hidden to bypass filtering and show everything. ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── diff --git a/tests/snapshots/integration__integration_tests__help__help_list_narrow_80.snap b/tests/snapshots/integration__integration_tests__help__help_list_narrow_80.snap index 8bfc20a370..a82af54275 100644 --- a/tests/snapshots/integration__integration_tests__help__help_list_narrow_80.snap +++ b/tests/snapshots/integration__integration_tests__help__help_list_narrow_80.snap @@ -54,10 +54,10 @@ Usage: wt list [OPTIONS] --full Show CI, diff analysis, and LLM summaries - --ignored - [experimental] Show all items, including ignored ones + --hidden + [experimental] Show all items, including hidden ones - Disables filtering by [list].ignore patterns, showing all items. + Disables filtering by [list].hidden patterns, showing all items. --progressive Show fast info immediately, update with slow info @@ -208,20 +208,20 @@ These appear across all columns while the table is loading: ──────────────────────────────────────────────────────────────────────────────── -Filtering with ignore patterns [experimental] +Filtering with hidden patterns [experimental] -The [list].ignore config hides worktrees and branches from output. Patterns are +The [list].hidden config hides worktrees and branches from output. Patterns are matched against both the canonical worktree path and the branch name:   [list] -  ignore = ["tmp-*", "*/scratch/*"] +  hidden = ["tmp-*", "*/scratch/*"] A worktree or branch is hidden if any pattern matches its path or branch name. Filtering applies to worktrees, local branches (--branches), and remote branches (--remotes). The summary line shows how many items were filtered (e.g. Showing -3 worktrees, 1 ignored). +3 worktrees, 1 hidden). -Use --ignored to bypass filtering and show everything. +Use --hidden to bypass filtering and show everything. ──────────────────────────────────────────────────────────────────────────────── diff --git a/tests/snapshots/integration__integration_tests__help__help_list_short.snap b/tests/snapshots/integration__integration_tests__help__help_list_short.snap index eb9598260e..73fb36fcbd 100644 --- a/tests/snapshots/integration__integration_tests__help__help_list_short.snap +++ b/tests/snapshots/integration__integration_tests__help__help_list_short.snap @@ -44,7 +44,7 @@ Usage: wt list [OPTIONS] --branches Include branches without worktrees --remotes Include remote branches --full Show CI, diff analysis, and LLM summaries - --ignored [experimental] Show all items, including ignored ones + --hidden [experimental] Show all items, including hidden ones --progressive Show fast info immediately, update with slow info -h, --help Print help (see more with '--help') diff --git a/tests/snapshots/integration__integration_tests__list_config__list_config_ignore_array_globs.snap b/tests/snapshots/integration__integration_tests__list_config__list_config_hidden_array_globs.snap similarity index 97% rename from tests/snapshots/integration__integration_tests__list_config__list_config_ignore_array_globs.snap rename to tests/snapshots/integration__integration_tests__list_config__list_config_hidden_array_globs.snap index 83b65e1982..919454d996 100644 --- a/tests/snapshots/integration__integration_tests__list_config__list_config_ignore_array_globs.snap +++ b/tests/snapshots/integration__integration_tests__list_config__list_config_hidden_array_globs.snap @@ -46,6 +46,6 @@ exit_code: 0 + feature-b ↑ ↑1 ../repo.feature-b f62940fc 16h Add feature-b file + feature-c ↑ ↑1 ../repo.feature-c 345c7c93 16h Add feature-c file -β—‹ Showing 5 worktrees, 2 ignored, 3 ahead +β—‹ Showing 5 worktrees, 2 hidden, 3 ahead ----- stderr ----- diff --git a/tests/snapshots/integration__integration_tests__list_config__list_config_ignore_by_parent_path.snap b/tests/snapshots/integration__integration_tests__list_config__list_config_hidden_by_parent_path.snap similarity index 97% rename from tests/snapshots/integration__integration_tests__list_config__list_config_ignore_by_parent_path.snap rename to tests/snapshots/integration__integration_tests__list_config__list_config_hidden_by_parent_path.snap index e2141b5055..9efdaac5e1 100644 --- a/tests/snapshots/integration__integration_tests__list_config__list_config_ignore_by_parent_path.snap +++ b/tests/snapshots/integration__integration_tests__list_config__list_config_hidden_by_parent_path.snap @@ -46,6 +46,6 @@ exit_code: 0 + feature-b βš‘↑ ↑1 ../repo.feature-b f62940fc 16h Add feature-b file + feature-c βš‘↑ ↑1 ../repo.feature-c 345c7c93 16h Add feature-c file -β—‹ Showing 5 worktrees, 1 ignored, 3 ahead +β—‹ Showing 5 worktrees, 1 hidden, 3 ahead ----- stderr ----- diff --git a/tests/snapshots/integration__integration_tests__list_config__list_config_ignore_local_branch.snap b/tests/snapshots/integration__integration_tests__list_config__list_config_hidden_local_branch.snap similarity index 96% rename from tests/snapshots/integration__integration_tests__list_config__list_config_ignore_local_branch.snap rename to tests/snapshots/integration__integration_tests__list_config__list_config_hidden_local_branch.snap index c45d500c7a..2c768dead0 100644 --- a/tests/snapshots/integration__integration_tests__list_config__list_config_ignore_local_branch.snap +++ b/tests/snapshots/integration__integration_tests__list_config__list_config_hidden_local_branch.snap @@ -44,6 +44,6 @@ exit_code: 0 @ main ^| | . 05a4a45d 16h Initial commit feature /_ 05a4a45d 16h Initial commit -β—‹ Showing 1 worktrees, 1 branches, 1 ignored +β—‹ Showing 1 worktrees, 1 branches, 1 hidden ----- stderr ----- diff --git a/tests/snapshots/integration__integration_tests__list_config__list_config_ignore_worktree_by_branch_name.snap b/tests/snapshots/integration__integration_tests__list_config__list_config_hidden_single_glob.snap similarity index 97% rename from tests/snapshots/integration__integration_tests__list_config__list_config_ignore_worktree_by_branch_name.snap rename to tests/snapshots/integration__integration_tests__list_config__list_config_hidden_single_glob.snap index b818f531b8..b55c07641c 100644 --- a/tests/snapshots/integration__integration_tests__list_config__list_config_ignore_worktree_by_branch_name.snap +++ b/tests/snapshots/integration__integration_tests__list_config__list_config_hidden_single_glob.snap @@ -46,6 +46,6 @@ exit_code: 0 + feature-b ↑ ↑1 ../repo.feature-b f62940fc 16h Add feature-b file + feature-c ↑ ↑1 ../repo.feature-c 345c7c93 16h Add feature-c file -β—‹ Showing 5 worktrees, 1 ignored, 3 ahead +β—‹ Showing 5 worktrees, 1 hidden, 3 ahead ----- stderr ----- diff --git a/tests/snapshots/integration__integration_tests__list_config__list_config_ignore_single_glob.snap b/tests/snapshots/integration__integration_tests__list_config__list_config_hidden_worktree_by_branch_name.snap similarity index 97% rename from tests/snapshots/integration__integration_tests__list_config__list_config_ignore_single_glob.snap rename to tests/snapshots/integration__integration_tests__list_config__list_config_hidden_worktree_by_branch_name.snap index b818f531b8..b55c07641c 100644 --- a/tests/snapshots/integration__integration_tests__list_config__list_config_ignore_single_glob.snap +++ b/tests/snapshots/integration__integration_tests__list_config__list_config_hidden_worktree_by_branch_name.snap @@ -46,6 +46,6 @@ exit_code: 0 + feature-b ↑ ↑1 ../repo.feature-b f62940fc 16h Add feature-b file + feature-c ↑ ↑1 ../repo.feature-c 345c7c93 16h Add feature-c file -β—‹ Showing 5 worktrees, 1 ignored, 3 ahead +β—‹ Showing 5 worktrees, 1 hidden, 3 ahead ----- stderr ----- diff --git a/tests/snapshots/integration__integration_tests__list_config__list_ignored_flag_shows_all_worktrees.snap b/tests/snapshots/integration__integration_tests__list_config__list_hidden_flag_shows_all_worktrees.snap similarity index 99% rename from tests/snapshots/integration__integration_tests__list_config__list_ignored_flag_shows_all_worktrees.snap rename to tests/snapshots/integration__integration_tests__list_config__list_hidden_flag_shows_all_worktrees.snap index 14cdd84871..06801e85ea 100644 --- a/tests/snapshots/integration__integration_tests__list_config__list_ignored_flag_shows_all_worktrees.snap +++ b/tests/snapshots/integration__integration_tests__list_config__list_hidden_flag_shows_all_worktrees.snap @@ -4,7 +4,7 @@ info: program: wt args: - list - - "--ignored" + - "--hidden" env: APPDATA: "[TEST_CONFIG_HOME]" CLICOLOR_FORCE: "1" From f9276f0befd148689967a1b049cf77e6fcf01027 Mon Sep 17 00:00:00 2001 From: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com> Date: Wed, 8 Apr 2026 04:50:31 +0000 Subject: [PATCH 6/7] Remove `--hidden` CLI flag, add TODO for future addition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The flag name and whether it should be a flag at all is TBD. The `[list].hidden` config functionality remains β€” only the CLI override is removed. Co-Authored-By: Claude Opus 4.6 --- dev/config.example.toml | 2 +- docs/content/config.md | 2 +- docs/content/list.md | 7 --- skills/worktrunk/reference/config.md | 2 +- skills/worktrunk/reference/list.md | 7 --- src/cli/mod.rs | 10 +--- src/commands/list/collect/mod.rs | 37 +++++-------- src/commands/list/mod.rs | 2 - src/config/user/sections.rs | 2 +- src/main.rs | 1 - tests/integration_tests/list_config.rs | 21 -------- ...ation_tests__help__help_config_create.snap | 2 +- ...gration_tests__help__help_config_long.snap | 2 +- ...tegration_tests__help__help_list_long.snap | 7 --- ...tion_tests__help__help_list_narrow_80.snap | 7 --- ...egration_tests__help__help_list_short.snap | 1 - ..._list_hidden_flag_shows_all_worktrees.snap | 53 ------------------- 17 files changed, 22 insertions(+), 143 deletions(-) delete mode 100644 tests/snapshots/integration__integration_tests__list_config__list_hidden_flag_shows_all_worktrees.snap diff --git a/dev/config.example.toml b/dev/config.example.toml index f8072d027b..5c051cc9a6 100644 --- a/dev/config.example.toml +++ b/dev/config.example.toml @@ -85,7 +85,7 @@ # # task-timeout-ms = 0 # Kill individual git commands after N ms; 0 disables # timeout-ms = 0 # Wall-clock budget for the entire collect phase; 0 disables -# hidden = ["tmp-*"] # [experimental] Glob patterns to hide from output; use --hidden to show all +# hidden = ["tmp-*"] # [experimental] Glob patterns to hide from output # # ### Commit # diff --git a/docs/content/config.md b/docs/content/config.md index 5c121fb693..59d4d7f6f8 100644 --- a/docs/content/config.md +++ b/docs/content/config.md @@ -166,7 +166,7 @@ remotes = false # Include remote-only branches (--remotes) task-timeout-ms = 0 # Kill individual git commands after N ms; 0 disables timeout-ms = 0 # Wall-clock budget for the entire collect phase; 0 disables -hidden = ["tmp-*"] # Glob patterns to hide from output; use --hidden to show all +hidden = ["tmp-*"] # Glob patterns to hide from output ``` ### Commit diff --git a/docs/content/list.md b/docs/content/list.md index 9c61b3f175..da971c46e5 100644 --- a/docs/content/list.md +++ b/docs/content/list.md @@ -145,8 +145,6 @@ hidden = ["tmp-*", "*/scratch/*"] A worktree or branch is hidden if any pattern matches its path or branch name. Filtering applies to worktrees, local branches (`--branches`), and remote branches (`--remotes`). The summary line shows how many items were filtered (e.g. `Showing 3 worktrees, 1 hidden`). -Use `--hidden` to bypass filtering and show everything. - --- ## JSON output @@ -281,11 +279,6 @@ Usage: wt list [OPTIONS] --full Show CI, diff analysis, and LLM summaries - --hidden - [experimental] Show all items, including hidden ones - - Disables filtering by [list].hidden patterns, showing all items. - --progressive Show fast info immediately, update with slow info diff --git a/skills/worktrunk/reference/config.md b/skills/worktrunk/reference/config.md index eb8a3aa631..b1d1476760 100644 --- a/skills/worktrunk/reference/config.md +++ b/skills/worktrunk/reference/config.md @@ -165,7 +165,7 @@ remotes = false # Include remote-only branches (--remotes) task-timeout-ms = 0 # Kill individual git commands after N ms; 0 disables timeout-ms = 0 # Wall-clock budget for the entire collect phase; 0 disables -hidden = ["tmp-*"] # [experimental] Glob patterns to hide from output; use --hidden to show all +hidden = ["tmp-*"] # [experimental] Glob patterns to hide from output ``` ### Commit diff --git a/skills/worktrunk/reference/list.md b/skills/worktrunk/reference/list.md index ce2efcb6be..29ab2d7965 100644 --- a/skills/worktrunk/reference/list.md +++ b/skills/worktrunk/reference/list.md @@ -133,8 +133,6 @@ hidden = ["tmp-*", "*/scratch/*"] A worktree or branch is hidden if any pattern matches its path or branch name. Filtering applies to worktrees, local branches (`--branches`), and remote branches (`--remotes`). The summary line shows how many items were filtered (e.g. `Showing 3 worktrees, 1 hidden`). -Use `--hidden` to bypass filtering and show everything. - --- ## JSON output @@ -289,11 +287,6 @@ Options: --full Show CI, diff analysis, and LLM summaries - --hidden - [experimental] Show all items, including hidden ones - - Disables filtering by [list].hidden patterns, showing all items. - --progressive Show fast info immediately, update with slow info diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 70feb7752a..ee0e829a15 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -390,11 +390,7 @@ pub(crate) struct ListArgs { #[arg(long)] pub(crate) full: bool, - /// \[experimental\] Show all items, including hidden ones - /// - /// Disables filtering by [list].hidden patterns, showing all items. - #[arg(long)] - pub(crate) hidden: bool, + // TODO: consider adding a flag to show hidden items (name TBD β€” `--hidden`, `--all`, etc.) /// Show fast info immediately, update with slow info /// @@ -788,8 +784,6 @@ hidden = ["tmp-*", "*/scratch/*"] A worktree or branch is hidden if any pattern matches its path or branch name. Filtering applies to worktrees, local branches (`--branches`), and remote branches (`--remotes`). The summary line shows how many items were filtered (e.g. `Showing 3 worktrees, 1 hidden`). -Use `--hidden` to bypass filtering and show everything. - --- ## JSON output @@ -1811,7 +1805,7 @@ remotes = false # Include remote-only branches (--remotes) task-timeout-ms = 0 # Kill individual git commands after N ms; 0 disables timeout-ms = 0 # Wall-clock budget for the entire collect phase; 0 disables -hidden = ["tmp-*"] # [experimental] Glob patterns to hide from output; use --hidden to show all +hidden = ["tmp-*"] # [experimental] Glob patterns to hide from output ``` ### Commit diff --git a/src/commands/list/collect/mod.rs b/src/commands/list/collect/mod.rs index 6c3746df06..7fb9108e11 100644 --- a/src/commands/list/collect/mod.rs +++ b/src/commands/list/collect/mod.rs @@ -251,7 +251,6 @@ pub enum ShowConfig { cli_branches: bool, cli_remotes: bool, cli_full: bool, - cli_hidden: bool, }, } @@ -368,7 +367,6 @@ pub fn collect( skip_tasks, command_timeout, collect_deadline, - show_hidden, hidden_patterns, ) = match show_config { ShowConfig::Resolved { @@ -383,14 +381,12 @@ pub fn collect( skip_tasks, command_timeout, collect_deadline, - false, None, ), ShowConfig::DeferredToParallel { cli_branches, cli_remotes, cli_full, - cli_hidden, } => { let config = repo.config(); let show_branches = cli_branches || config.list.branches(); @@ -423,7 +419,6 @@ pub fn collect( skip_tasks, command_timeout, collect_deadline, - cli_hidden, hidden_patterns, ) } @@ -432,24 +427,20 @@ pub fn collect( // Compile hidden patterns once for use across worktrees, branches, and remotes. // Uses string matching (not path matching) for branch names since they contain // `/` separators but aren't filesystem paths. - let compiled_hidden: Vec = if show_hidden { - Vec::new() - } else { - hidden_patterns - .as_ref() - .map(|p| { - p.iter() - .filter_map(|s| match glob::Pattern::new(s) { - Ok(pat) => Some(pat), - Err(e) => { - log::warn!("Invalid [list].hidden pattern {:?}: {}", s, e); - None - } - }) - .collect() - }) - .unwrap_or_default() - }; + let compiled_hidden: Vec = hidden_patterns + .as_ref() + .map(|p| { + p.iter() + .filter_map(|s| match glob::Pattern::new(s) { + Ok(pat) => Some(pat), + Err(e) => { + log::warn!("Invalid [list].hidden pattern {:?}: {}", s, e); + None + } + }) + .collect() + }) + .unwrap_or_default(); let branch_hidden = |name: &str| -> bool { compiled_hidden.iter().any(|pat| pat.matches(name)) }; diff --git a/src/commands/list/mod.rs b/src/commands/list/mod.rs index ea307e23c0..0c37b5aec8 100644 --- a/src/commands/list/mod.rs +++ b/src/commands/list/mod.rs @@ -149,7 +149,6 @@ pub fn handle_list( cli_branches: bool, cli_remotes: bool, cli_full: bool, - cli_hidden: bool, render_mode: RenderMode, ) -> anyhow::Result<()> { // Progressive rendering only for table format with Progressive mode @@ -175,7 +174,6 @@ pub fn handle_list( cli_branches, cli_remotes, cli_full, - cli_hidden, }, show_progress, render_table, diff --git a/src/config/user/sections.rs b/src/config/user/sections.rs index d89a24f82d..f8d7e85b11 100644 --- a/src/config/user/sections.rs +++ b/src/config/user/sections.rs @@ -151,7 +151,7 @@ pub struct ListConfig { pub timeout_ms: Option, /// Glob patterns for items to hide from list output. - /// Matches against worktree paths and branch names. Use `--hidden` flag to view hidden items. + /// Matches against worktree paths and branch names. #[serde(default, skip_serializing_if = "Option::is_none")] pub hidden: Option>, } diff --git a/src/main.rs b/src/main.rs index fdc67a3f76..30faf60065 100644 --- a/src/main.rs +++ b/src/main.rs @@ -540,7 +540,6 @@ fn handle_list_command(args: ListArgs) -> anyhow::Result<()> { args.branches, args.remotes, args.full, - args.hidden, render_mode, ) } diff --git a/tests/integration_tests/list_config.rs b/tests/integration_tests/list_config.rs index 9ac0e55571..bd9bce98f9 100644 --- a/tests/integration_tests/list_config.rs +++ b/tests/integration_tests/list_config.rs @@ -514,27 +514,6 @@ hidden = ["*/repo.tmp-*", "*/repo.scratch-*"] assert_cmd_snapshot!(list_snapshots::command(&repo, repo.root_path())); } -#[rstest] -fn test_list_hidden_flag_shows_all_worktrees(mut repo: TestRepo) { - // Create worktrees: one matching the hidden pattern, one not - repo.add_worktree("feature"); - repo.add_worktree("tmp-scratch"); - - // Write config with hidden pattern - repo.write_test_config( - r#"worktree-path = "../{{ repo }}.{{ branch }}" - -[list] -hidden = ["*/repo.tmp-*"] -"#, - ); - - // Use --hidden flag to show ALL worktrees (disables filtering) - let mut cmd = list_snapshots::command(&repo, repo.root_path()); - cmd.arg("--hidden"); - assert_cmd_snapshot!(cmd); -} - #[rstest] fn test_list_config_hidden_by_parent_path(mut repo: TestRepo) { // Create worktrees in different parent directories diff --git a/tests/snapshots/integration__integration_tests__help__help_config_create.snap b/tests/snapshots/integration__integration_tests__help__help_config_create.snap index 6fe3052e46..af29cfb470 100644 --- a/tests/snapshots/integration__integration_tests__help__help_config_create.snap +++ b/tests/snapshots/integration__integration_tests__help__help_config_create.snap @@ -145,7 +145,7 @@ Creates ~/.config/worktrunk/config.toml with the following content:   #   # task-timeout-ms = 0 # Kill individual git commands after N ms; 0 disables   # timeout-ms = 0 # Wall-clock budget for the entire collect phase; 0 disables -  # hidden = ["tmp-*"] # [experimental] Glob patterns to hide from output; use --hidden to show all +  # hidden = ["tmp-*"] # [experimental] Glob patterns to hide from output   #   # ### Commit   # diff --git a/tests/snapshots/integration__integration_tests__help__help_config_long.snap b/tests/snapshots/integration__integration_tests__help__help_config_long.snap index 1e31db6029..43f55cbc11 100644 --- a/tests/snapshots/integration__integration_tests__help__help_config_long.snap +++ b/tests/snapshots/integration__integration_tests__help__help_config_long.snap @@ -191,7 +191,7 @@ Persistent flag values for wt list. Override on command line as needed.     task-timeout-ms = 0 # Kill individual git commands after N ms; 0 disables   timeout-ms = 0 # Wall-clock budget for the entire collect phase; 0 disables -  hidden = ["tmp-*"] # [experimental] Glob patterns to hide from output; use --hidden to show all +  hidden = ["tmp-*"] # [experimental] Glob patterns to hide from output Commit diff --git a/tests/snapshots/integration__integration_tests__help__help_list_long.snap b/tests/snapshots/integration__integration_tests__help__help_list_long.snap index 0fd7b29c42..320203d5de 100644 --- a/tests/snapshots/integration__integration_tests__help__help_list_long.snap +++ b/tests/snapshots/integration__integration_tests__help__help_list_long.snap @@ -55,11 +55,6 @@ Usage: wt list [OPTIONS] --full Show CI, diff analysis, and LLM summaries - --hidden - [experimental] Show all items, including hidden ones - - Disables filtering by [list].hidden patterns, showing all items. - --progressive Show fast info immediately, update with slow info @@ -196,8 +191,6 @@ The [list].hidden config hides worktrees and branches from output. Patte A worktree or branch is hidden if any pattern matches its path or branch name. Filtering applies to worktrees, local branches (--branches), and remote branches (--remotes). The summary line shows how many items were filtered (e.g. Showing 3 worktrees, 1 hidden). -Use --hidden to bypass filtering and show everything. - ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── JSON output diff --git a/tests/snapshots/integration__integration_tests__help__help_list_narrow_80.snap b/tests/snapshots/integration__integration_tests__help__help_list_narrow_80.snap index 9c7c204174..940a022e5d 100644 --- a/tests/snapshots/integration__integration_tests__help__help_list_narrow_80.snap +++ b/tests/snapshots/integration__integration_tests__help__help_list_narrow_80.snap @@ -55,11 +55,6 @@ Usage: wt list [OPTIONS] --full Show CI, diff analysis, and LLM summaries - --hidden - [experimental] Show all items, including hidden ones - - Disables filtering by [list].hidden patterns, showing all items. - --progressive Show fast info immediately, update with slow info @@ -222,8 +217,6 @@ Filtering applies to worktrees, local branches (--branches), and remote (--remotes). The summary line shows how many items were filtered (e.g. Showing 3 worktrees, 1 hidden). -Use --hidden to bypass filtering and show everything. - ──────────────────────────────────────────────────────────────────────────────── JSON output diff --git a/tests/snapshots/integration__integration_tests__help__help_list_short.snap b/tests/snapshots/integration__integration_tests__help__help_list_short.snap index c3a443d43d..5a06070891 100644 --- a/tests/snapshots/integration__integration_tests__help__help_list_short.snap +++ b/tests/snapshots/integration__integration_tests__help__help_list_short.snap @@ -45,7 +45,6 @@ Usage: wt list [OPTIONS] --branches Include branches without worktrees --remotes Include remote branches --full Show CI, diff analysis, and LLM summaries - --hidden [experimental] Show all items, including hidden ones --progressive Show fast info immediately, update with slow info -h, --help Print help (see more with '--help') diff --git a/tests/snapshots/integration__integration_tests__list_config__list_hidden_flag_shows_all_worktrees.snap b/tests/snapshots/integration__integration_tests__list_config__list_hidden_flag_shows_all_worktrees.snap deleted file mode 100644 index 06801e85ea..0000000000 --- a/tests/snapshots/integration__integration_tests__list_config__list_hidden_flag_shows_all_worktrees.snap +++ /dev/null @@ -1,53 +0,0 @@ ---- -source: tests/integration_tests/list_config.rs -info: - program: wt - args: - - list - - "--hidden" - env: - APPDATA: "[TEST_CONFIG_HOME]" - CLICOLOR_FORCE: "1" - COLUMNS: "500" - GIT_AUTHOR_DATE: "2025-01-01T00:00:00Z" - GIT_COMMITTER_DATE: "2025-01-01T00:00:00Z" - GIT_CONFIG_GLOBAL: "[TEST_GIT_CONFIG]" - GIT_CONFIG_SYSTEM: /dev/null - GIT_EDITOR: "" - GIT_TERMINAL_PROMPT: "0" - HOME: "[TEST_HOME]" - LANG: C - LC_ALL: C - MOCK_CONFIG_DIR: "[MOCK_CONFIG_DIR]" - NO_COLOR: "" - PATH: "[PATH]" - PSModulePath: "" - RUST_LOG: warn - SHELL: "" - TERM: alacritty - USERPROFILE: "[TEST_HOME]" - WORKTRUNK_APPROVALS_PATH: "[TEST_APPROVALS]" - WORKTRUNK_CONFIG_PATH: "[TEST_CONFIG]" - WORKTRUNK_SYSTEM_CONFIG_PATH: "[TEST_SYSTEM_CONFIG]" - WORKTRUNK_TEST_CLAUDE_INSTALLED: "0" - WORKTRUNK_TEST_DELAYED_STREAM_MS: "-1" - WORKTRUNK_TEST_EPOCH: "1735776000" - WORKTRUNK_TEST_NUSHELL_ENV: "0" - WORKTRUNK_TEST_POWERSHELL_ENV: "0" - WORKTRUNK_TEST_SKIP_URL_HEALTH_CHECK: "1" - XDG_CONFIG_HOME: "[TEST_CONFIG_HOME]" ---- -success: true -exit_code: 0 ------ stdout ----- - Branch Status HEADΒ± main↕ Remoteβ‡… Path Commit Age Message -@ main ^| | . 05a4a45d 16h Initial commit -+ feature _ ../repo.feature 05a4a45d 16h Initial commit -+ feature-a ↑ ↑1 ../repo.feature-a 1b87d473 16h Add feature-a file -+ feature-b ↑ ↑1 ../repo.feature-b f62940fc 16h Add feature-b file -+ feature-c ↑ ↑1 ../repo.feature-c 345c7c93 16h Add feature-c file -+ tmp-scratch _ ../repo.tmp-scratch 05a4a45d 16h Initial commit - -β—‹ Showing 6 worktrees, 3 ahead - ------ stderr ----- From 8dba427ce0e7e977b65cd122e6e63a6afa56fee3 Mon Sep 17 00:00:00 2001 From: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com> Date: Wed, 8 Apr 2026 04:56:14 +0000 Subject: [PATCH 7/7] fix: formatting Co-Authored-By: Claude Opus 4.6 --- src/cli/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cli/mod.rs b/src/cli/mod.rs index ee0e829a15..efce9f5751 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -391,7 +391,6 @@ pub(crate) struct ListArgs { pub(crate) full: bool, // TODO: consider adding a flag to show hidden items (name TBD β€” `--hidden`, `--all`, etc.) - /// Show fast info immediately, update with slow info /// /// Displays local data (branches, paths, status) first, then updates