From 77dbcaefad3d4b8e96362ddcc2d16cb71d5e68f0 Mon Sep 17 00:00:00 2001 From: Zohar Babin Date: Mon, 13 Apr 2026 00:23:16 -0400 Subject: [PATCH] feat(cli): add --content-stdin flag to issue comment add Allow agents to pipe comment content through stdin instead of the --content flag, avoiding shell escaping issues with backticks, quotes, and other special characters in markdown content. Usage: cat <<'COMMENT' | multica issue comment add --content-stdin Co-Authored-By: Claude Opus 4.6 --- server/cmd/multica/cmd_issue.go | 13 +++++++++++-- server/internal/daemon/execenv/runtime_config.go | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/server/cmd/multica/cmd_issue.go b/server/cmd/multica/cmd_issue.go index c200a94a6..ed751dbcd 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,15 @@ func runIssueCommentList(cmd *cobra.Command, args []string) error { func runIssueCommentAdd(cmd *cobra.Command, args []string) error { content, _ := cmd.Flags().GetString("content") + if useStdin, _ := cmd.Flags().GetBool("content-stdin"); useStdin { + data, err := io.ReadAll(os.Stdin) + if err != nil { + return fmt.Errorf("read stdin: %w", err) + } + content = strings.TrimRight(string(data), "\n") + } 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 dd9a264d5..b3e2d692b 100644 --- a/server/internal/daemon/execenv/runtime_config.go +++ b/server/internal/daemon/execenv/runtime_config.go @@ -61,6 +61,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")