Skip to content
This repository was archived by the owner on Apr 15, 2026. It is now read-only.
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
30 changes: 8 additions & 22 deletions internal/cmd/attach.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package cmd
import (
"errors"
"fmt"
"os"

"github.com/spf13/cobra"

Expand Down Expand Up @@ -39,7 +38,10 @@ session continues running.`,
}

func runAttachCmd(cmd *cobra.Command, args []string) error {
mgr := ManagerFromContext(cmd.Context())
mgr, err := requireManager(cmd.Context())
if err != nil {
return err
}

switch len(args) {
case 0:
Expand All @@ -66,17 +68,9 @@ func attachGlobalMRU(cmd *cobra.Command, mgr *instance.Manager) error {

// attachInstanceMRU attaches to the most recently accessed session for a specific instance.
func attachInstanceMRU(cmd *cobra.Command, mgr *instance.Manager, branch string) error {
repoPath, err := os.Getwd()
if err != nil {
return fmt.Errorf("get working directory: %w", err)
}

inst, err := mgr.GetByBranch(cmd.Context(), repoPath, branch)
inst, err := getInstanceByBranch(cmd.Context(), mgr, branch, "no instance found for branch %q (use 'hjk run' to create one)")
if err != nil {
if errors.Is(err, instance.ErrNotFound) {
return fmt.Errorf("no instance found for branch %q (use 'hjk run' to create one)", branch)
}
return fmt.Errorf("get instance: %w", err)
return err
}

session, err := mgr.GetMRUSession(cmd.Context(), inst.ID)
Expand All @@ -92,17 +86,9 @@ func attachInstanceMRU(cmd *cobra.Command, mgr *instance.Manager, branch string)

// attachExplicitSession attaches to a specific session by name.
func attachExplicitSession(cmd *cobra.Command, mgr *instance.Manager, branch, sessionName string) error {
repoPath, err := os.Getwd()
inst, err := getInstanceByBranch(cmd.Context(), mgr, branch, "no instance found for branch %q (use 'hjk run' to create one)")
if err != nil {
return fmt.Errorf("get working directory: %w", err)
}

inst, err := mgr.GetByBranch(cmd.Context(), repoPath, branch)
if err != nil {
if errors.Is(err, instance.ErrNotFound) {
return fmt.Errorf("no instance found for branch %q (use 'hjk run' to create one)", branch)
}
return fmt.Errorf("get instance: %w", err)
return err
}

// Verify session exists
Expand Down
43 changes: 43 additions & 0 deletions internal/cmd/helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package cmd

import (
"context"
"errors"
"fmt"
"os"

"github.com/jmgilman/headjack/internal/instance"
)

func requireManager(ctx context.Context) (*instance.Manager, error) {
mgr := ManagerFromContext(ctx)
if mgr == nil {
return nil, errors.New("instance manager not initialized")
}
return mgr, nil
}

func repoPath() (string, error) {
path, err := os.Getwd()
if err != nil {
return "", fmt.Errorf("get working directory: %w", err)
}
return path, nil
}

func getInstanceByBranch(ctx context.Context, mgr *instance.Manager, branch, notFoundMsg string) (*instance.Instance, error) {
repoPath, err := repoPath()
if err != nil {
return nil, err
}

inst, err := mgr.GetByBranch(ctx, repoPath, branch)
if err != nil {
if errors.Is(err, instance.ErrNotFound) && notFoundMsg != "" {
return nil, fmt.Errorf(notFoundMsg, branch)
}
return nil, fmt.Errorf("get instance: %w", err)
}

return inst, nil
}
11 changes: 4 additions & 7 deletions internal/cmd/kill.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package cmd
import (
"errors"
"fmt"
"os"
"strings"

"github.com/spf13/cobra"
Expand Down Expand Up @@ -32,16 +31,14 @@ func runKillCmd(cmd *cobra.Command, args []string) error {
return err
}

// Get the instance for this branch
repoPath, err := os.Getwd()
mgr, err := requireManager(cmd.Context())
if err != nil {
return fmt.Errorf("get working directory: %w", err)
return err
}

mgr := ManagerFromContext(cmd.Context())
inst, err := mgr.GetByBranch(cmd.Context(), repoPath, branch)
inst, err := getInstanceByBranch(cmd.Context(), mgr, branch, "")
if err != nil {
return fmt.Errorf("get instance: %w", err)
return err
}

// Kill the session
Expand Down
9 changes: 4 additions & 5 deletions internal/cmd/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,14 @@ func runLogsCmd(cmd *cobra.Command, args []string) error {
}

// Get the instance for this branch
repoPath, err := os.Getwd()
mgr, err := requireManager(cmd.Context())
if err != nil {
return fmt.Errorf("get working directory: %w", err)
return err
}

mgr := ManagerFromContext(cmd.Context())
inst, err := mgr.GetByBranch(cmd.Context(), repoPath, branch)
inst, err := getInstanceByBranch(cmd.Context(), mgr, branch, "")
if err != nil {
return fmt.Errorf("get instance: %w", err)
return err
}

// Get the session to verify it exists and get its ID
Expand Down
23 changes: 13 additions & 10 deletions internal/cmd/ps.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,25 +52,29 @@ func listInstances(cmd *cobra.Command) error {
return fmt.Errorf("get all flag: %w", err)
}

mgr, err := requireManager(cmd.Context())
if err != nil {
return err
}

filter := instance.ListFilter{}

// If not showing all, filter by current repo
if !all {
repoPath, wdErr := os.Getwd()
if wdErr != nil {
return fmt.Errorf("get working directory: %w", wdErr)
repoPathValue, pathErr := repoPath()
if pathErr != nil {
return pathErr
}

opener := git.NewOpener(exec.New())
repo, openErr := opener.Open(cmd.Context(), repoPath)
repo, openErr := opener.Open(cmd.Context(), repoPathValue)
if openErr != nil {
return fmt.Errorf("open repository: %w", openErr)
}

filter.RepoID = repo.Identifier()
}

mgr := ManagerFromContext(cmd.Context())
instances, err := mgr.List(cmd.Context(), filter)
if err != nil {
return fmt.Errorf("list instances: %w", err)
Expand Down Expand Up @@ -113,15 +117,14 @@ func listInstances(cmd *cobra.Command) error {
}

func listSessions(cmd *cobra.Command, branch string) error {
repoPath, err := os.Getwd()
mgr, err := requireManager(cmd.Context())
if err != nil {
return fmt.Errorf("get working directory: %w", err)
return err
}

mgr := ManagerFromContext(cmd.Context())
inst, err := mgr.GetByBranch(cmd.Context(), repoPath, branch)
inst, err := getInstanceByBranch(cmd.Context(), mgr, branch, "")
if err != nil {
return fmt.Errorf("get instance: %w", err)
return err
}

sessions, err := mgr.ListSessions(cmd.Context(), inst.ID)
Expand Down
18 changes: 4 additions & 14 deletions internal/cmd/recreate.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
package cmd

import (
"errors"
"fmt"
"os"

"github.com/spf13/cobra"

"github.com/jmgilman/headjack/internal/instance"
)

var recreateCmd = &cobra.Command{
Expand All @@ -30,20 +26,14 @@ The worktree (and all git-tracked and untracked files) is preserved.`,
RunE: func(cmd *cobra.Command, args []string) error {
branch := args[0]

// Get current working directory as repo path
repoPath, err := os.Getwd()
mgr, err := requireManager(cmd.Context())
if err != nil {
return fmt.Errorf("get working directory: %w", err)
return err
}

// Get instance by branch
mgr := ManagerFromContext(cmd.Context())
inst, err := mgr.GetByBranch(cmd.Context(), repoPath, branch)
inst, err := getInstanceByBranch(cmd.Context(), mgr, branch, "no instance found for branch %q")
if err != nil {
if errors.Is(err, instance.ErrNotFound) {
return fmt.Errorf("no instance found for branch %q", branch)
}
return fmt.Errorf("get instance: %w", err)
return err
}

// Determine image to use (precedence: flag > config)
Expand Down
17 changes: 4 additions & 13 deletions internal/cmd/rm.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,11 @@ package cmd

import (
"bufio"
"errors"
"fmt"
"os"
"strings"

"github.com/spf13/cobra"

"github.com/jmgilman/headjack/internal/instance"
)

var rmCmd = &cobra.Command{
Expand Down Expand Up @@ -37,20 +34,14 @@ WARNING: This deletes uncommitted work in the worktree.`,
return fmt.Errorf("get force flag: %w", err)
}

// Get current working directory as repo path
repoPath, err := os.Getwd()
mgr, err := requireManager(cmd.Context())
if err != nil {
return fmt.Errorf("get working directory: %w", err)
return err
}

// Get instance by branch
mgr := ManagerFromContext(cmd.Context())
inst, err := mgr.GetByBranch(cmd.Context(), repoPath, branch)
inst, err := getInstanceByBranch(cmd.Context(), mgr, branch, "no instance found for branch %q")
if err != nil {
if errors.Is(err, instance.ErrNotFound) {
return fmt.Errorf("no instance found for branch %q", branch)
}
return fmt.Errorf("get instance: %w", err)
return err
}

// Confirm removal unless --force
Expand Down
11 changes: 7 additions & 4 deletions internal/cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package cmd
import (
"errors"
"fmt"
"os"

"github.com/spf13/cobra"

Expand Down Expand Up @@ -173,17 +172,21 @@ func injectAuthToken(agent string, cfg *instance.CreateSessionConfig) error {
func runRunCmd(cmd *cobra.Command, args []string) error {
branch := args[0]

repoPath, err := os.Getwd()
mgr, err := requireManager(cmd.Context())
if err != nil {
return fmt.Errorf("get working directory: %w", err)
return err
}

flags, err := parseRunFlags(cmd)
if err != nil {
return err
}

mgr := ManagerFromContext(cmd.Context())
repoPath, err := repoPath()
if err != nil {
return err
}

inst, err := getOrCreateInstance(cmd, mgr, repoPath, branch, flags.image)
if err != nil {
return err
Expand Down
18 changes: 4 additions & 14 deletions internal/cmd/stop.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
package cmd

import (
"errors"
"fmt"
"os"

"github.com/spf13/cobra"

"github.com/jmgilman/headjack/internal/instance"
)

var stopCmd = &cobra.Command{
Expand All @@ -21,20 +17,14 @@ The worktree is preserved and the instance can be resumed later with 'hjk run'.`
RunE: func(cmd *cobra.Command, args []string) error {
branch := args[0]

// Get current working directory as repo path
repoPath, err := os.Getwd()
mgr, err := requireManager(cmd.Context())
if err != nil {
return fmt.Errorf("get working directory: %w", err)
return err
}

// Get instance by branch
mgr := ManagerFromContext(cmd.Context())
inst, err := mgr.GetByBranch(cmd.Context(), repoPath, branch)
inst, err := getInstanceByBranch(cmd.Context(), mgr, branch, "no instance found for branch %q")
if err != nil {
if errors.Is(err, instance.ErrNotFound) {
return fmt.Errorf("no instance found for branch %q", branch)
}
return fmt.Errorf("get instance: %w", err)
return err
}

// Stop the instance
Expand Down