code-review skill posts comments with literal \n instead of newlines (intermittent)
Summary
The \code-review\ skill intermittently posts PR comments where newlines appear as literal \\\n\ (backslash + n) characters rather than being rendered as actual newlines, making the review unreadable in the GitHub UI.
Reproduction
The skill is invoked via \anthropics/claude-code-action@v1\ workflow:
\\\`yaml
- uses: anthropics/claude-code-action@v1
with:
plugin_marketplaces: 'https://github.com/anthropics/claude-code.git'
plugins: 'code-review@claude-code-plugins'
prompt: '/code-review:code-review --comment ${{ github.repository }}/pull/${{ github.event.pull_request.number }}'
claude_args: '--model claude-sonnet-4-6'
\\\`
Real example from a private repo (PR #449, comment id 4402885550). Initial body retrieved via \gh api\:
\\\`
Code review\n\n1件の問題が見つかりました。\n\n### CLAUDE.md 違反: 依存ライブラリ管理ワークフローの迂回\n\n対象ファイル: \services/ctfd/...\ (line 1)\n\n...
\\\`
\\\n\ is stored as 2 literal characters (backslash + n), not as the newline control character.
Frequency: ~1 in 8 PRs in the same repo (12%). The other 7 reviews had proper newlines.
Self-recovery: A subsequent push triggered re-execution and the comment was updated to proper newlines (about 11 minutes later).
Root Cause Analysis
Tracing the comment-posting code paths:
| Path | Mechanism | Affected? |
|---|---|---|
| Inline comments (\mcp__github_inline_comment__create_inline_comment\) | Buffered to \/tmp/inline-comments-buffer.jsonl\ and posted via Octokit (JSON-encoded) — see \post-buffered-inline-comments.ts\ | ✅ safe |
| Action orchestration | \run.ts\ does not construct comment bodies | ✅ safe |
| Skill's \gh pr comment\ invocation (§7) | LLM-generated bash string fed to \gh pr comment <PR> -b "..."\ | ❌ vulnerable |
The vulnerable path: the skill prompt §7 instructs:
If \--comment\argument IS provided and NO issues were found, post a summary comment using \gh pr comment\and stop.
When the LLM generates something like:
\\\bash\
gh pr comment 449 -b "## Code review\\n\\n1件..."
\\
bash does not interpret \\\n\ inside double quotes as a newline — it passes the 2 literal characters to \gh\, which forwards them to the GitHub API, which stores them as-is.
Proposed Fix
Update the \code-review\ skill prompt §7 to mandate \--body-file\ with a temp file (or heredoc):
If \--comment\argument IS provided and NO issues were found, post a summary comment using \gh pr comment\and stop. Always pass the body via a temporary file with \--body-file\to ensure newlines are preserved: \\\bash cat > /tmp/review.md <<'EOF' ## Code review No issues found. Checked for bugs and CLAUDE.md compliance. EOF gh pr comment <PR> --body-file /tmp/review.md \\\Do not use \-b "..."\with escape sequences (\\\n\, \\\t\, etc.) as bash will not interpret them inside double quotes.
The same change should apply anywhere else in the skill (or sibling skills) where \gh pr comment\ / \gh issue comment\ is suggested.
Why this is the right place to fix
- The action's TypeScript entrypoints already use Octokit (which handles JSON encoding correctly)
- The vulnerable path is only the skill's instruction → fixing the prompt fixes all consumers
- Downstream consumers cannot easily work around this without forking the skill
- A post-process workaround (e.g. \
PATCH /comments\after detecting literal \\\n\) is fragile and adds maintenance burden
Acceptance Criteria
- [ ] \
code-review\skill prompt updated to mandate \--body-file\for any \gh pr comment\/ \gh issue comment\invocation - [ ] Manual test: trigger the skill on a PR and verify the resulting comment renders newlines correctly
Environment
- Action: \
anthropics/claude-code-action@v1\ - Skill: \
code-review@claude-code-plugins\(from \anthropics/claude-code\) - Model: \
claude-sonnet-4-6\
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗