diff --git a/server/cmd/multica/cmd_issue.go b/server/cmd/multica/cmd_issue.go index c200a94a6..5e153241d 100644 --- a/server/cmd/multica/cmd_issue.go +++ b/server/cmd/multica/cmd_issue.go @@ -3,6 +3,7 @@ package main import ( "context" "fmt" + "io" "net/url" "os" "strings" @@ -185,7 +186,8 @@ func init() { issueRunMessagesCmd.Flags().Int("since", 0, "Only return messages after this sequence number") // issue comment add - issueCommentAddCmd.Flags().String("content", "", "Comment content (required)") + issueCommentAddCmd.Flags().String("content", "", "Comment content (required unless --content-stdin)") + issueCommentAddCmd.Flags().Bool("content-stdin", false, "Read comment content from stdin (avoids shell escaping issues)") issueCommentAddCmd.Flags().String("parent", "", "Parent comment ID (reply to a specific comment)") issueCommentAddCmd.Flags().StringSlice("attachment", nil, "File path(s) to attach (can be specified multiple times)") issueCommentAddCmd.Flags().String("output", "json", "Output format: table or json") @@ -637,8 +639,25 @@ func runIssueCommentList(cmd *cobra.Command, args []string) error { func runIssueCommentAdd(cmd *cobra.Command, args []string) error { content, _ := cmd.Flags().GetString("content") + useStdin, _ := cmd.Flags().GetBool("content-stdin") + + if content != "" && useStdin { + return fmt.Errorf("--content and --content-stdin are mutually exclusive") + } + + if useStdin { + data, err := io.ReadAll(os.Stdin) + if err != nil { + return fmt.Errorf("read stdin: %w", err) + } + content = strings.TrimSuffix(string(data), "\n") + if content == "" { + return fmt.Errorf("stdin content is empty") + } + } + if content == "" { - return fmt.Errorf("--content is required") + return fmt.Errorf("--content or --content-stdin is required") } client, err := newAPIClient(cmd) diff --git a/server/internal/daemon/execenv/runtime_config.go b/server/internal/daemon/execenv/runtime_config.go index b0e0cb8aa..6ea1b0a83 100644 --- a/server/internal/daemon/execenv/runtime_config.go +++ b/server/internal/daemon/execenv/runtime_config.go @@ -78,6 +78,7 @@ func buildMetaSkillContent(provider string, ctx TaskContextForEnv) string { b.WriteString("- `multica issue create --title \"...\" [--description \"...\"] [--priority X] [--assignee X] [--parent ] [--status X]` — Create a new issue\n") b.WriteString("- `multica issue assign --to ` — Assign an issue to a member or agent by name (use --unassign to remove assignee)\n") b.WriteString("- `multica issue comment add --content \"...\" [--parent ]` — Post a comment (use --parent to reply to a specific comment)\n") + b.WriteString(" - For content with special characters (backticks, quotes), pipe via stdin: `cat <<'COMMENT' | multica issue comment add --content-stdin`\n") b.WriteString("- `multica issue comment delete ` — Delete a comment\n") b.WriteString("- `multica issue status ` — Update issue status (todo, in_progress, in_review, done, blocked)\n") b.WriteString("- `multica issue update [--title X] [--description X] [--priority X]` — Update issue fields\n\n")