Commit c3d2636048ba

Vincent Demeester <vincent@sbr.pm>
2026-01-27 16:19:05
feat(lazyworktree): add tmux integration and dynamic alias discovery
- Add custom tmux command with emacs, shell, lazygit, claude windows - Add discoverDirs option for auto-discovering repo aliases - Scans configured directories for repos with main/ or .git - Creates wt<prefix><short> aliases with collision detection - Configure tektoncd, osp, github.com, gitlab.com as discover dirs Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent ba0cb9b
Changed files (2)
home/common/dev/lazyworktree.nix
@@ -34,13 +34,51 @@
       # Branch naming
       issue_branch_name_template = "{{.IssueNumber}}-{{.Slug}}";
       pr_branch_name_template = "pr-{{.PRNumber}}-{{.Slug}}";
+
+      # Custom commands
+      custom_commands = {
+        t = {
+          description = "Tmux session";
+          show_help = true;
+          tmux = {
+            session_name = "wt:$WORKTREE_NAME";
+            attach = true;
+            on_exists = "switch";
+            windows = [
+              {
+                name = "emacs";
+                command = "emacs";
+              }
+              {
+                name = "shell";
+                command = "zsh";
+              }
+              {
+                name = "lazygit";
+                command = "lazygit";
+              }
+              {
+                name = "claude";
+                command = "cr";
+              }
+            ];
+          };
+        };
+      };
     };
 
-    # Quick aliases for commonly used repositories
+    # Explicit aliases for commonly used repositories
     aliases = {
-      # Home configuration
       wh = "${config.home.homeDirectory}/src/home";
-      wtp = "${config.home.homeDirectory}/src/tektoncd/pipeline/main";
+    };
+
+    # Auto-discover repos from these directories
+    # Creates wt<prefix><repo> aliases (e.g., wttpi for tektoncd/pipeline)
+    discoverDirs = {
+      t = "${config.home.homeDirectory}/src/tektoncd";
+      o = "${config.home.homeDirectory}/src/osp";
+      g = "${config.home.homeDirectory}/src/github.com";
+      l = "${config.home.homeDirectory}/src/gitlab.com";
     };
   };
 }
home/modules/lazyworktree.nix
@@ -67,6 +67,23 @@ in
         Each key becomes a shell function that jumps to that repository's worktrees.
       '';
     };
+
+    discoverDirs = lib.mkOption {
+      type = types.attrsOf types.str;
+      default = { };
+      example = lib.literalExpression ''
+        {
+          t = "~/src/tektoncd";    # wtt<repo>
+          o = "~/src/osp";         # wto<repo>
+          g = "~/src/github.com";  # wtg<repo>
+        }
+      '';
+      description = ''
+        Directories to scan for automatic worktree alias discovery.
+        Key is the prefix (wt<prefix><repo>), value is the directory path.
+        Repos with a 'main' subdirectory or .git are detected automatically.
+      '';
+    };
   };
 
   config = mkIf cfg.enable {
@@ -100,6 +117,71 @@ in
           '') cfg.aliases
         );
 
+        # Dynamic aliases: auto-discover repos from source directories
+        # Creates wt<prefix><repo> aliases for each repo found
+        discoverDirsArray = lib.concatStringsSep "\n" (
+          lib.mapAttrsToList (prefix: dir: ''
+            "${dir}:${prefix}"
+          '') cfg.discoverDirs
+        );
+
+        dynamicAliasesSetup =
+          if cfg.discoverDirs == { } then
+            ""
+          else
+            ''
+              # Auto-discover worktree aliases from source directories
+              # Format: wt<prefix><short> → worktree_jump <path>
+              # Uses first 2 letters, extends if collision detected
+              _lazyworktree_discover_aliases() {
+                local -A alias_map  # Track aliases to detect collisions
+                local base_dirs=(
+                  ${lib.concatStringsSep "\n    " (
+                    lib.mapAttrsToList (prefix: dir: ''"${dir}:${prefix}"'') cfg.discoverDirs
+                  )}
+                )
+
+                for entry in "''${base_dirs[@]}"; do
+                  local base_dir="''${entry%%:*}"
+                  local prefix="''${entry##*:}"
+
+                  [[ -d "$base_dir" ]] || continue
+
+                  for repo_dir in "$base_dir"/*/; do
+                    [[ -d "$repo_dir" ]] || continue
+                    local repo_name=$(basename "$repo_dir")
+                    local target_dir=""
+
+                    # Determine target (main worktree or repo root)
+                    if [[ -d "$repo_dir/main" ]]; then
+                      target_dir="$repo_dir/main"
+                    elif [[ -d "$repo_dir/.git" ]]; then
+                      target_dir="$repo_dir"
+                    else
+                      continue
+                    fi
+
+                    # Generate short name: start with 2 chars, extend if needed
+                    local len=2
+                    local short alias_name
+                    while (( len <= ''${#repo_name} )); do
+                      short="''${repo_name:0:$len}"
+                      alias_name="wt''${prefix}''${short}"
+                      # Check if alias already exists or conflicts
+                      if [[ -z "''${alias_map[$alias_name]}" ]] || [[ "''${alias_map[$alias_name]}" == "$target_dir" ]]; then
+                        break
+                      fi
+                      (( len++ ))
+                    done
+
+                    alias_map[$alias_name]="$target_dir"
+                    eval "''${alias_name}() { worktree_jump \"$target_dir\" \"\$@\"; }"
+                  done
+                done
+              }
+              _lazyworktree_discover_aliases
+            '';
+
       in
       {
         bash.initExtra = mkIf cfg.enableBashIntegration ''
@@ -111,6 +193,7 @@ in
           ${sourceUpstream}
           ${aliasDefinitions}
           ${zshAliasCompletions}
+          ${dynamicAliasesSetup}
         '';
       };
   };