Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 47 additions & 37 deletions cmd/opencode-worktree/attach.go
Original file line number Diff line number Diff line change
@@ -1,58 +1,68 @@
package main

import (
"flag"
"fmt"
"os"

"github.com/danhenton/opencode-worktree/internal/git"
"github.com/danhenton/opencode-worktree/internal/worktree"
"github.com/spf13/cobra"
)

func runAttach(args []string) error {
fs := flag.NewFlagSet("attach", flag.ContinueOnError)
noMerge := fs.Bool("no-merge", false, "Skip auto-merge after opencode exits")
fs.Usage = func() {
fmt.Fprint(os.Stderr, `Usage: opencode-worktree attach <name> [--no-merge]
func newAttachCmd() *cobra.Command {
var noMerge bool

Reattach to an existing agent worktree session.
cmd := &cobra.Command{
Use: "attach <name>",
Short: "Reattach to an existing agent worktree session",
Long: `Reattach to an existing agent worktree session.

Options:
`)
fs.PrintDefaults()
fmt.Fprint(os.Stderr, `
Examples:
opencode-worktree attach fix-auth-bug
opencode-worktree attach fix-auth-bug --no-merge
`)
}

if err := fs.Parse(reorderKnownBoolFlags(args, "--no-merge")); err != nil {
return errSilent
}
opencode-worktree attach fix-auth-bug --no-merge`,
Args: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return fmt.Errorf("task name is required\n\nUsage: opencode-worktree attach <name> [--no-merge]")
}
if len(args) > 1 {
return fmt.Errorf("unexpected extra argument: %s", args[1])
}
return nil
},
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) != 0 {
return nil, cobra.ShellCompDirectiveNoFileComp
}
repoRoot, err := git.RepoRoot(".")
if err != nil {
return nil, cobra.ShellCompDirectiveNoFileComp
}
names, err := worktree.ActiveTaskNames(repoRoot)
if err != nil {
return nil, cobra.ShellCompDirectiveNoFileComp
}
return names, cobra.ShellCompDirectiveNoFileComp
},
RunE: func(cmd *cobra.Command, args []string) error {
taskName := args[0]

positional := fs.Args()
if len(positional) == 0 {
return fmt.Errorf("task name is required\n\nUsage: opencode-worktree attach <name> [--no-merge]")
}
if len(positional) > 1 {
return fmt.Errorf("unexpected extra argument: %s", positional[1])
}
repoRoot, err := git.RepoRoot(".")
if err != nil {
return fmt.Errorf("not inside a git repository")
}

taskName := positional[0]
worktreeDir, err := worktree.ResolveWorktreeDir(repoRoot, taskName)
if err != nil {
return err
}

repoRoot, err := git.RepoRoot(".")
if err != nil {
return fmt.Errorf("not inside a git repository")
}
fmt.Printf("%sAttaching to agent session: %s\n", emoji("🔗 ", ""), taskName)
fmt.Printf(" Path: %s\n\n", worktreeDir)

worktreeDir, err := worktree.ResolveWorktreeDir(repoRoot, taskName)
if err != nil {
return err
return launchAndMaybeMerge(worktreeDir, "", noMerge)
},
}

fmt.Printf("%sAttaching to agent session: %s\n", emoji("🔗 ", ""), taskName)
fmt.Printf(" Path: %s\n\n", worktreeDir)
cmd.Flags().BoolVarP(&noMerge, "no-merge", "n", false, "Skip auto-merge after opencode exits")

return launchAndMaybeMerge(worktreeDir, "", *noMerge)
return cmd
}
61 changes: 29 additions & 32 deletions cmd/opencode-worktree/cleanup.go
Original file line number Diff line number Diff line change
@@ -1,50 +1,47 @@
package main

import (
"flag"
"fmt"
"os"

"github.com/danhenton/opencode-worktree/internal/git"
"github.com/danhenton/opencode-worktree/internal/worktree"
"github.com/spf13/cobra"
)

func runCleanup(args []string) error {
fs := flag.NewFlagSet("cleanup", flag.ContinueOnError)
dryRun := fs.Bool("dry-run", false, "Show what would be removed without removing anything")
yes := fs.Bool("yes", false, "Skip confirmation prompt")
fs.Usage = func() {
fmt.Fprint(os.Stderr, `Usage: opencode-worktree cleanup [--dry-run] [--yes]
func newCleanupCmd() *cobra.Command {
var dryRun bool
var yes bool

Remove orphaned agent worktrees and branches.
cmd := &cobra.Command{
Use: "cleanup",
Short: "Remove orphaned worktrees and branches",
Long: `Remove orphaned agent worktrees and branches.

Options:
`)
fs.PrintDefaults()
fmt.Fprint(os.Stderr, `
Examples:
opencode-worktree cleanup
opencode-worktree cleanup --dry-run
opencode-worktree cleanup --yes
`)
opencode-worktree cleanup --yes`,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
repoRoot, err := git.RepoRoot(".")
if err != nil {
return fmt.Errorf("not inside a git repository")
}

fmt.Printf("%sCleaning up orphaned agent worktrees and branches...\n", emoji("🧹 ", ""))
opts := worktree.CleanupOptions{DryRun: dryRun, Yes: yes}
if err := worktree.Cleanup(repoRoot, opts); err != nil {
return err
}
if !dryRun {
fmt.Printf("%sCleanup complete.\n", emoji("✅ ", ""))
}
return nil
},
}

if err := fs.Parse(reorderKnownBoolFlags(args, "--dry-run", "--yes")); err != nil {
return errSilent
}

repoRoot, err := git.RepoRoot(".")
if err != nil {
return fmt.Errorf("not inside a git repository")
}
cmd.Flags().BoolVarP(&dryRun, "dry-run", "d", false, "Show what would be removed without removing anything")
cmd.Flags().BoolVarP(&yes, "yes", "y", false, "Skip confirmation prompt")

fmt.Printf("%sCleaning up orphaned agent worktrees and branches...\n", emoji("🧹 ", ""))
opts := worktree.CleanupOptions{DryRun: *dryRun, Yes: *yes}
if err := worktree.Cleanup(repoRoot, opts); err != nil {
return err
}
if !*dryRun {
fmt.Printf("%sCleanup complete.\n", emoji("✅ ", ""))
}
return nil
return cmd
}
35 changes: 0 additions & 35 deletions cmd/opencode-worktree/completions.go

This file was deleted.

24 changes: 0 additions & 24 deletions cmd/opencode-worktree/flags.go

This file was deleted.

Loading