From 47b5480f8b37ead918312bb6aed1f93f9d0368c0 Mon Sep 17 00:00:00 2001 From: Steven Hood Date: Fri, 10 Apr 2026 09:23:17 -0700 Subject: [PATCH 1/2] fix: auto-detect non-TTY stdin in issue edit to prevent segfault `issue edit` panics with a segfault in the survey library when stdin is not a terminal (e.g. piped input, CI, scripted agents) because survey assumes interactive TTY input. `issue create` and `epic create` already handle this by checking `cmdutil.StdinHasData()` and implicitly setting noInput=true. Apply the same guard to `issue edit` for consistency. Co-Authored-By: Claude Opus 4.6 (1M context) --- internal/cmd/issue/edit/edit.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/cmd/issue/edit/edit.go b/internal/cmd/issue/edit/edit.go index 5dfa5d97..36d71135 100644 --- a/internal/cmd/issue/edit/edit.go +++ b/internal/cmd/issue/edit/edit.go @@ -60,6 +60,9 @@ func edit(cmd *cobra.Command, args []string) { project := viper.GetString("project.key") params := parseArgsAndFlags(cmd.Flags(), args, project) + if !params.noInput && cmdutil.StdinHasData() { + params.noInput = true + } client := api.DefaultClient(params.debug) ec := editCmd{ client: client, From 7f9411672b6ff9176ad70e272c8e775d334acaf3 Mon Sep 17 00:00:00 2001 From: Steven Hood Date: Fri, 10 Apr 2026 16:47:00 -0700 Subject: [PATCH 2/2] fix: add non-TTY guards to issue move and issue delete MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same pattern as the edit fix — these commands use survey prompts for missing arguments but don't check for a TTY first. In non-TTY contexts (CI, agents, scripts), this causes a segfault when the required arguments aren't provided. - issue move: guard setIssueKey and setDesiredState - issue delete: guard setIssueKey When stdin is not a terminal and required args are missing, fail with a clear error message instead of crashing. Co-Authored-By: Claude Opus 4.6 (1M context) --- internal/cmd/issue/delete/delete.go | 4 ++++ internal/cmd/issue/move/move.go | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/internal/cmd/issue/delete/delete.go b/internal/cmd/issue/delete/delete.go index 28630c7d..071fb47a 100644 --- a/internal/cmd/issue/delete/delete.go +++ b/internal/cmd/issue/delete/delete.go @@ -101,6 +101,10 @@ func (mc *deleteCmd) setIssueKey(project string) error { return nil } + if cmdutil.StdinHasData() { + return fmt.Errorf("ISSUE-KEY argument is required in non-interactive mode") + } + var ans string qs := &survey.Question{ diff --git a/internal/cmd/issue/move/move.go b/internal/cmd/issue/move/move.go index 49d6c304..f611cb08 100644 --- a/internal/cmd/issue/move/move.go +++ b/internal/cmd/issue/move/move.go @@ -180,6 +180,10 @@ func (mc *moveCmd) setIssueKey(project string) error { return nil } + if cmdutil.StdinHasData() { + return fmt.Errorf("ISSUE-KEY argument is required in non-interactive mode") + } + var ans string qs := &survey.Question{ @@ -200,6 +204,10 @@ func (mc *moveCmd) setDesiredState(it string) error { return nil } + if cmdutil.StdinHasData() { + return fmt.Errorf("desired state argument is required in non-interactive mode") + } + var ( options = make([]string, 0, len(mc.transitions)) ans string