From 82dc06eb84841375f3d1cb3a7fa3c7e71f694bbf Mon Sep 17 00:00:00 2001 From: Steve Yegge Date: Sun, 14 Dec 2025 17:22:42 -0800 Subject: [PATCH] feat(update): add --type flag to bd update command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allows changing issue type (task/epic/bug/feature/chore) via bd update --type. Storage layer already supported it, this adds CLI and RPC support. Fixes GH#522. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- cmd/bd/show.go | 13 +++++++++++++ internal/rpc/protocol.go | 1 + internal/rpc/server_issues_epics.go | 3 +++ 3 files changed, 17 insertions(+) diff --git a/cmd/bd/show.go b/cmd/bd/show.go index ca7fd925..9d5f78ad 100644 --- a/cmd/bd/show.go +++ b/cmd/bd/show.go @@ -514,6 +514,15 @@ var updateCmd = &cobra.Command{ } updates["estimated_minutes"] = estimate } + if cmd.Flags().Changed("type") { + issueType, _ := cmd.Flags().GetString("type") + // Validate issue type + if !types.IssueType(issueType).IsValid() { + fmt.Fprintf(os.Stderr, "Error: invalid issue type %q. Valid types: bug, feature, task, epic, chore\n", issueType) + os.Exit(1) + } + updates["issue_type"] = issueType + } if cmd.Flags().Changed("add-label") { addLabels, _ := cmd.Flags().GetStringSlice("add-label") updates["add_labels"] = addLabels @@ -597,6 +606,9 @@ var updateCmd = &cobra.Command{ if estimate, ok := updates["estimated_minutes"].(int); ok { updateArgs.EstimatedMinutes = &estimate } + if issueType, ok := updates["issue_type"].(string); ok { + updateArgs.IssueType = &issueType + } if addLabels, ok := updates["add_labels"].([]string); ok { updateArgs.AddLabels = addLabels } @@ -1024,6 +1036,7 @@ func init() { updateCmd.Flags().String("acceptance-criteria", "", "DEPRECATED: use --acceptance") _ = updateCmd.Flags().MarkHidden("acceptance-criteria") updateCmd.Flags().IntP("estimate", "e", 0, "Time estimate in minutes (e.g., 60 for 1 hour)") + updateCmd.Flags().StringP("type", "t", "", "Issue type (bug|feature|task|epic|chore)") updateCmd.Flags().StringSlice("add-label", nil, "Add labels (repeatable)") updateCmd.Flags().StringSlice("remove-label", nil, "Remove labels (repeatable)") updateCmd.Flags().StringSlice("set-labels", nil, "Set labels, replacing all existing (repeatable)") diff --git a/internal/rpc/protocol.go b/internal/rpc/protocol.go index 35ded488..76835248 100644 --- a/internal/rpc/protocol.go +++ b/internal/rpc/protocol.go @@ -87,6 +87,7 @@ type UpdateArgs struct { Assignee *string `json:"assignee,omitempty"` ExternalRef *string `json:"external_ref,omitempty"` // Link to external issue trackers EstimatedMinutes *int `json:"estimated_minutes,omitempty"` // Time estimate in minutes + IssueType *string `json:"issue_type,omitempty"` // Issue type (bug|feature|task|epic|chore) AddLabels []string `json:"add_labels,omitempty"` RemoveLabels []string `json:"remove_labels,omitempty"` SetLabels []string `json:"set_labels,omitempty"` diff --git a/internal/rpc/server_issues_epics.go b/internal/rpc/server_issues_epics.go index 737b605a..6617764d 100644 --- a/internal/rpc/server_issues_epics.go +++ b/internal/rpc/server_issues_epics.go @@ -73,6 +73,9 @@ func updatesFromArgs(a UpdateArgs) map[string]interface{} { if a.EstimatedMinutes != nil { u["estimated_minutes"] = *a.EstimatedMinutes } + if a.IssueType != nil { + u["issue_type"] = *a.IssueType + } return u }