[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6DQEQSTSRXBCZ7QP7JCSW3V":3,"skill-same:01M6DQEQSTSRXBCZ7QP7JCSW3V":78},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":30,"publishedAt":50,"linkOnly":51,"markdownContent":52,"markdownBody":53,"frontMatter":54,"refName":57,"commitSha":58,"skillDirectory":59,"forksCount":60,"repositoryHtmlUrl":61,"repositoryHomepageUrl":6,"ownerHtmlUrl":62,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":63,"install":64,"resources":77},"01M6DQEQSTSRXBCZ7QP7JCSW3V","git:attach-review-to-pr",null,"Add line-specific review comments to pull requests using GitHub CLI API","AntifragileTech\u002Fantifragile-claude-code","AntifragileTech","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F174357194?v=4","01M6DQCYMK4CDSQQAN0ZC72NTV","01M6DQCYS9YPW1WKMQ5TJMPQ43",9,"MIT","https:\u002F\u002Fgithub.com\u002FAntifragileTech\u002Fantifragile-claude-code\u002Fblob\u002Fmaster\u002Fassets\u002Fskills\u002Fdev\u002Fattach-review-to-pr\u002FSKILL.md",[17,22,25],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000010","后端与接口","SCENARIO","使用场景",{"categoryNo":23,"categoryName":24,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000023","Skill与智能体开发",{"categoryNo":26,"categoryName":27,"taxonomyType":28,"taxonomyTypeDesc":29},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49],"review","git:attach review to pr","attach","git","pr","auth","pull requests","create","github","pull","api","Bash","gh pr","gh","work","branch","cli","line","MCP","2026-11-10 10:12:30",false,"---\nname: git:attach-review-to-pr\ndescription: Add line-specific review comments to pull requests using GitHub CLI API\nargument-hint: PR number or URL (optional - can work with current branch)\nallowed-tools: Bash(gh api:*), Bash(gh auth:*), Bash(gh pr:*), mcp__github_inline_comment__create_inline_comment\n---\n\n# How to Attach Line-Specific Review Comments to Pull Requests\n\nThis guide explains how to add line-specific review comments to pull requests using the GitHub CLI (`gh`) API or `mcp__github_inline_comment__create_inline_comment` if it not available, similar to how the GitHub UI allows commenting on specific lines of code.\n\n## Preferred Approach: Using MCP GitHub Tools\n\n**If available**, use the `mcp__github_inline_comment__create_inline_comment` MCP tool for posting line-specific inline comments on pull requests. This approach provides better integration with GitHub's UI and is the recommended method.\n\n**Fallback**: If the MCP tool is not available, use the GitHub CLI (`gh`) API methods described below:\n\n- For single comments: Use the `\u002Fcomments` endpoint (see [Adding a Single Line-Specific Comment](#adding-a-single-line-specific-comment))\n- For multiple comments: Use the `\u002Freviews` endpoint (see [Adding Multiple Line-Specific Comments Together](#adding-multiple-line-specific-comments-together))\n\n## Overview\n\nWhile `gh pr review` provides basic review functionality (approve, request changes, general comments), it **does not support line-specific comments directly**. To add comments on specific lines of code, you must use the lower-level `gh api` command to call GitHub's REST API directly.\n\n## Prerequisites\n\n1. GitHub CLI installed and authenticated:\n\n   ```bash\n   gh auth status\n   ```\n\n2. Access to the repository and pull request you want to review\n\n## Understanding GitHub's Review Comment System\n\nGitHub has two types of PR comments:\n\n1. **Issue Comments** - General comments on the PR conversation\n2. **Review Comments** - Line-specific comments on code changes\n\nReview comments can be added in two ways:\n\n- **Single comment** - Using the `\u002Fpulls\u002F{pr}\u002Fcomments` endpoint\n- **Review with multiple comments** - Using the `\u002Fpulls\u002F{pr}\u002Freviews` endpoint\n\n## Adding a Single Line-Specific Comment\n\n### Basic Syntax\n\n```bash\ngh api repos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{pr_number}\u002Fcomments \\\n  -f body='Your comment text here' \\\n  -f commit_id='\u003Ccommit-sha>' \\\n  -f path='path\u002Fto\u002Ffile.js' \\\n  -F line=42 \\\n  -f side='RIGHT'\n```\n\n### Parameters Explained\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `body` | string | Yes | The text of the review comment (supports Markdown) |\n| `commit_id` | string | Yes | The SHA of the commit to comment on |\n| `path` | string | Yes | Relative path to the file being commented on |\n| `line` | integer | Yes | The line number in the diff (use `-F` for integers) |\n| `side` | string | Yes | `RIGHT` for new\u002Fmodified lines, `LEFT` for deleted lines |\n| `start_line` | integer | No | For multi-line comments, the starting line |\n| `start_side` | string | No | For multi-line comments, the starting side |\n\n### Parameter Flags\n\n- `-f` (--field) - For string values\n- `-F` (--field) - For integer values (note the capital F)\n\n### Complete Example\n\n```bash\n# First, get the latest commit SHA for the PR\ngh api repos\u002FNeoLabHQ\u002Flearning-platform-app\u002Fpulls\u002F4 --jq '.head.sha'\n\n# Then add your comment\ngh api repos\u002FNeoLabHQ\u002Flearning-platform-app\u002Fpulls\u002F4\u002Fcomments \\\n  -f body='Consider adding error handling here. Should we confirm the lesson was successfully marked as completed before navigating away?' \\\n  -f commit_id='e152d0dd6cf498467eadbeb638bf05abe11c64d4' \\\n  -f path='src\u002Fcomponents\u002FLessonNavigationButtons.tsx' \\\n  -F line=26 \\\n  -f side='RIGHT'\n```\n\n### Understanding Line Numbers\n\nThe `line` parameter refers to the **position in the diff**, not the absolute line number in the file:\n\n- For **new files**: Line numbers match the file's line numbers\n- For **modified files**: Use the line number as it appears in the \"Files changed\" tab\n- For **multi-line comments**: Use `start_line` and `line` to specify the range\n\n### Response\n\nOn success, returns a JSON object with comment details:\n\n```json\n{\n  \"id\": 2532291222,\n  \"pull_request_review_id\": 3470545909,\n  \"path\": \"src\u002Fcomponents\u002FLessonNavigationButtons.tsx\",\n  \"line\": 26,\n  \"body\": \"Consider adding error handling here...\",\n  \"html_url\": \"https:\u002F\u002Fgithub.com\u002FNeoLabHQ\u002Flearning-platform-app\u002Fpull\u002F4#discussion_r2532291222\",\n  \"created_at\": \"2025-11-16T22:40:46Z\"\n}\n```\n\n## Adding Multiple Line-Specific Comments Together\n\nTo add multiple comments across different files in a single review, use the `\u002Freviews` endpoint with JSON input.\n\n### Why Use Reviews for Multiple Comments?\n\n- **Atomic operation** - All comments are added together\n- **Single notification** - Doesn't spam with multiple notifications\n- **Better UX** - Appears as one cohesive review\n- **Same mechanism as GitHub UI** - \"Start a review\" → \"Finish review\"\n\n### Basic Syntax\n\n```bash\ncat \u003C\u003C'EOF' | gh api repos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{pr_number}\u002Freviews --input -\n{\n  \"event\": \"COMMENT\",\n  \"body\": \"Overall review summary (optional)\",\n  \"comments\": [\n    {\n      \"path\": \"file1.tsx\",\n      \"body\": \"Comment on file 1\",\n      \"side\": \"RIGHT\",\n      \"line\": 15\n    },\n    {\n      \"path\": \"file2.tsx\",\n      \"body\": \"Comment on file 2\",\n      \"side\": \"RIGHT\",\n      \"line\": 30\n    }\n  ]\n}\nEOF\n```\n\n### Review Event Types\n\n| Event | Description | When to Use |\n|-------|-------------|-------------|\n| `COMMENT` | General review comment | Just leaving feedback without approval |\n| `APPROVE` | Approve the PR | Changes look good, ready to merge |\n| `REQUEST_CHANGES` | Request changes | Issues that must be fixed before merge |\n\n### Complete Example\n\n```bash\ncat \u003C\u003C'EOF' | gh api repos\u002FNeoLabHQ\u002Flearning-platform-app\u002Fpulls\u002F4\u002Freviews --input -\n{\n  \"event\": \"COMMENT\",\n  \"body\": \"Testing multiple line-specific comments via gh api\",\n  \"comments\": [\n    {\n      \"path\": \"src\u002Fcomponents\u002FCourseCard.tsx\",\n      \"body\": \"Test comment generated by Claude\",\n      \"side\": \"RIGHT\",\n      \"line\": 15\n    },\n    {\n      \"path\": \"src\u002Fcomponents\u002FCourseProgressWidget.tsx\",\n      \"body\": \"Test comment generated by Claude\",\n      \"side\": \"RIGHT\",\n      \"line\": 30\n    },\n    {\n      \"path\": \"src\u002Fcomponents\u002FLessonProgressTracker.tsx\",\n      \"body\": \"Test comment generated by Claude\",\n      \"side\": \"RIGHT\",\n      \"line\": 20\n    }\n  ]\n}\nEOF\n```\n\n### Response\n\n```json\n{\n  \"id\": 3470546747,\n  \"state\": \"COMMENTED\",\n  \"html_url\": \"https:\u002F\u002Fgithub.com\u002FNeoLabHQ\u002Flearning-platform-app\u002Fpull\u002F4#pullrequestreview-3470546747\",\n  \"submitted_at\": \"2025-11-16T22:42:43Z\",\n  \"commit_id\": \"e152d0dd6cf498467eadbeb638bf05abe11c64d4\"\n}\n```\n\n## Common Issues and Solutions\n\n### Issue 1: \"user_id can only have one pending review per pull request\"\n\n**Error Message:**\n\n```\ngh: Validation Failed (HTTP 422)\n{\"message\":\"Validation Failed\",\"errors\":[{\"resource\":\"PullRequestReview\",\"code\":\"custom\",\"field\":\"user_id\",\"message\":\"user_id can only have one pending review per pull request\"}]}\n```\n\n**Cause:** GitHub only allows one pending (unsubmitted) review per user per PR. If you previously started a review through the UI or API and didn't submit it, it blocks new review creation.\n\n**Solution 1: Submit the pending review**\n\n```bash\n# Check for pending reviews\ngh api repos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{pr_number}\u002Freviews | jq '.[] | select(.state==\"PENDING\")'\n\n# Submit it through the UI or ask the user to submit it\n```\n\n**Solution 2: Use the single comment endpoint instead**\n\n```bash\n# Add individual comments without creating a review\ngh api repos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{pr_number}\u002Fcomments \\\n  -f body='Comment text' \\\n  -f commit_id='\u003Csha>' \\\n  -f path='file.tsx' \\\n  -F line=26 \\\n  -f side='RIGHT'\n```\n\n### Issue 2: Array syntax not working with --raw-field\n\n**Failed Attempt:**\n\n```bash\n# This does NOT work - GitHub API receives an object, not an array\ngh api repos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{pr}\u002Freviews \\\n  --raw-field 'comments[0][path]=file1.tsx' \\\n  --raw-field 'comments[0][line]=15' \\\n  --raw-field 'comments[1][path]=file2.tsx' \\\n  --raw-field 'comments[1][line]=30'\n```\n\n**Error:**\n\n```\nInvalid request. For 'properties\u002Fcomments', {\"0\" => {...}, \"1\" => {...}} is not an array.\n```\n\n**Solution:** Use JSON input via heredoc:\n\n```bash\ncat \u003C\u003C'EOF' | gh api repos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{pr}\u002Freviews --input -\n{\n  \"comments\": [...]\n}\nEOF\n```\n\n### Issue 3: Invalid line number\n\n**Error Message:**\n\n```\nPull request review thread line must be part of the diff\n```\n\n**Cause:** The line number doesn't exist in the diff for this file.\n\n**Solutions:**\n\n- Verify the file was actually changed in this PR\n- Check the \"Files changed\" tab to see actual line numbers in the diff\n- Ensure you're using the correct `commit_id` (the latest commit in the PR)\n\n### Issue 4: Wrong commit_id\n\n**Error Message:**\n\n```\ncommit_sha is not part of the pull request\n```\n\n**Solution:** Get the latest commit SHA:\n\n```bash\ngh api repos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{pr_number} --jq '.head.sha'\n```\n\n## Best Practices\n\n### 1. Get PR Information First\n\nBefore adding comments, gather necessary information:\n\n```bash\n# Get PR details\ngh pr view {pr_number} --json headRefOid,files\n\n# Or use the API\ngh api repos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{pr_number} --jq '{commit: .head.sha, files: [.changed_files]}'\n\n# List files changed\ngh api repos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{pr_number}\u002Ffiles --jq '.[] | {filename: .filename, additions: .additions, deletions: .deletions}'\n```\n\n### 2. Check for Pending Reviews\n\n```bash\n# Check if you have a pending review\ngh api repos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{pr_number}\u002Freviews \\\n  --jq '.[] | select(.state==\"PENDING\" and .user.login==\"YOUR_USERNAME\")'\n```\n\n### 3. Use Meaningful Comment Text\n\n- Be specific and constructive\n- Reference documentation or best practices\n- Suggest alternatives when requesting changes\n- Use code blocks for code suggestions:\n\n```markdown\nConsider using async\u002Fawait:\n\n\\`\\`\\`typescript\nasync function getData() {\n  const result = await fetch(url);\n  return result.json();\n}\n\\`\\`\\`\n```\n\n### 4. Batch Related Comments\n\nUse the review endpoint to group related comments:\n\n- All comments for a single file\u002Farea\n- All comments for a specific concern (security, performance, etc.)\n- Complete review session\n\n### 5. Choose the Right Event Type\n\n```bash\n# For feedback during development\n\"event\": \"COMMENT\"\n\n# When approving\n\"event\": \"APPROVE\"\n\n# When blocking merge\n\"event\": \"REQUEST_CHANGES\"\n```\n\n## Workflow Examples\n\n### Example 1: Quick Single Comment\n\n```bash\n#!\u002Fbin\u002Fbash\nOWNER=\"NeoLabHQ\"\nREPO=\"learning-platform-app\"\nPR=4\n\n# Get latest commit\nCOMMIT=$(gh api repos\u002F$OWNER\u002F$REPO\u002Fpulls\u002F$PR --jq '.head.sha')\n\n# Add comment\ngh api repos\u002F$OWNER\u002F$REPO\u002Fpulls\u002F$PR\u002Fcomments \\\n  -f body='Consider extracting this into a separate function for better testability' \\\n  -f commit_id=\"$COMMIT\" \\\n  -f path='src\u002Futils\u002Fvalidation.ts' \\\n  -F line=45 \\\n  -f side='RIGHT'\n```\n\n### Example 2: Comprehensive Review\n\n```bash\n#!\u002Fbin\u002Fbash\nOWNER=\"NeoLabHQ\"\nREPO=\"learning-platform-app\"\nPR=4\n\n# Create review with multiple comments\ncat \u003C\u003CEOF | gh api repos\u002F$OWNER\u002F$REPO\u002Fpulls\u002F$PR\u002Freviews --input -\n{\n  \"event\": \"COMMENT\",\n  \"body\": \"Thanks for the PR! I've reviewed the changes and have a few suggestions.\",\n  \"comments\": [\n    {\n      \"path\": \"src\u002Fcomponents\u002FCourseCard.tsx\",\n      \"body\": \"Consider memoizing this component to prevent unnecessary re-renders\",\n      \"side\": \"RIGHT\",\n      \"line\": 25\n    },\n    {\n      \"path\": \"src\u002Futils\u002FcourseProgress.ts\",\n      \"body\": \"This function could benefit from error handling for invalid course IDs\",\n      \"side\": \"RIGHT\",\n      \"line\": 12\n    },\n    {\n      \"path\": \"src\u002Fstate\u002FCourseProgressState.ts\",\n      \"body\": \"Consider adding JSDoc comments to document the expected behavior\",\n      \"side\": \"RIGHT\",\n      \"line\": 8\n    }\n  ]\n}\nEOF\n```\n\n### Example 3: Multi-line Comment\n\n```bash\n# Comment on a range of lines (e.g., lines 10-15)\ngh api repos\u002F$OWNER\u002F$REPO\u002Fpulls\u002F$PR\u002Fcomments \\\n  -f body='This entire block could be simplified using array destructuring' \\\n  -f commit_id=\"$COMMIT\" \\\n  -f path='src\u002Futils\u002Fparser.ts' \\\n  -F start_line=10 \\\n  -f start_side='RIGHT' \\\n  -F line=15 \\\n  -f side='RIGHT'\n```\n\n## Helpful Helper Scripts\n\n### Get PR Files and Lines\n\n```bash\n#!\u002Fbin\u002Fbash\n# pr-files.sh - List all files changed in a PR with line counts\n\nOWNER=\"$1\"\nREPO=\"$2\"\nPR=\"$3\"\n\ngh api repos\u002F$OWNER\u002F$REPO\u002Fpulls\u002F$PR\u002Ffiles --jq '.[] | \"\\(.filename): +\\(.additions)\u002F-\\(.deletions)\"'\n```\n\n### Check Review Status\n\n```bash\n#!\u002Fbin\u002Fbash\n# check-reviews.sh - Check review status for a PR\n\nOWNER=\"$1\"\nREPO=\"$2\"\nPR=\"$3\"\n\necho \"=== Reviews ===\"\ngh api repos\u002F$OWNER\u002F$REPO\u002Fpulls\u002F$PR\u002Freviews --jq '.[] | \"\\(.user.login): \\(.state) at \\(.submitted_at)\"'\n\necho -e \"\\n=== Pending Reviews ===\"\ngh api repos\u002F$OWNER\u002F$REPO\u002Fpulls\u002F$PR\u002Freviews --jq '.[] | select(.state==\"PENDING\") | \"\\(.user.login): \\(.state)\"'\n```\n\n## Related Documentation\n\n- [GitHub API: Pull Request Review Comments](https:\u002F\u002Fdocs.github.com\u002Frest\u002Fpulls\u002Fcomments)\n- [GitHub API: Pull Request Reviews](https:\u002F\u002Fdocs.github.com\u002Frest\u002Fpulls\u002Freviews)\n- [GitHub CLI Manual](https:\u002F\u002Fcli.github.com\u002Fmanual\u002F)\n- [Create PR Command](.\u002Fcreate-pr.md)\n- [Commit Command](.\u002Fcommit.md)\n\n## API Reference\n\n### POST \u002Frepos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{pull_number}\u002Fcomments\n\nCreates a review comment on a specific line.\n\n**Endpoint:** `https:\u002F\u002Fapi.github.com\u002Frepos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{pull_number}\u002Fcomments`\n\n**Parameters:**\n\n- `body` (string, required): Comment text\n- `commit_id` (string, required): SHA of commit\n- `path` (string, required): Relative file path\n- `line` (integer, required): Line number in diff\n- `side` (string, required): \"LEFT\" or \"RIGHT\"\n- `start_line` (integer, optional): Start line for multi-line\n- `start_side` (string, optional): Start side for multi-line\n\n### POST \u002Frepos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{pull_number}\u002Freviews\n\nCreates a review with optional line-specific comments.\n\n**Endpoint:** `https:\u002F\u002Fapi.github.com\u002Frepos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{pull_number}\u002Freviews`\n\n**Parameters:**\n\n- `event` (string, required): \"APPROVE\", \"REQUEST_CHANGES\", or \"COMMENT\"\n- `body` (string, optional): Overall review comment\n- `comments` (array, optional): Array of comment objects\n- `commit_id` (string, optional): SHA of commit to review\n\n**Comment Object:**\n\n- `path` (string, required): Relative file path\n- `body` (string, required): Comment text\n- `line` (integer, required): Line number in diff\n- `side` (string, required): \"LEFT\" or \"RIGHT\"\n- `start_line` (integer, optional): Start line for multi-line\n- `start_side` (string, optional): Start side for multi-line\n","# How to Attach Line-Specific Review Comments to Pull Requests\n\nThis guide explains how to add line-specific review comments to pull requests using the GitHub CLI (`gh`) API or `mcp__github_inline_comment__create_inline_comment` if it not available, similar to how the GitHub UI allows commenting on specific lines of code.\n\n## Preferred Approach: Using MCP GitHub Tools\n\n**If available**, use the `mcp__github_inline_comment__create_inline_comment` MCP tool for posting line-specific inline comments on pull requests. This approach provides better integration with GitHub's UI and is the recommended method.\n\n**Fallback**: If the MCP tool is not available, use the GitHub CLI (`gh`) API methods described below:\n\n- For single comments: Use the `\u002Fcomments` endpoint (see [Adding a Single Line-Specific Comment](#adding-a-single-line-specific-comment))\n- For multiple comments: Use the `\u002Freviews` endpoint (see [Adding Multiple Line-Specific Comments Together](#adding-multiple-line-specific-comments-together))\n\n## Overview\n\nWhile `gh pr review` provides basic review functionality (approve, request changes, general comments), it **does not support line-specific comments directly**. To add comments on specific lines of code, you must use the lower-level `gh api` command to call GitHub's REST API directly.\n\n## Prerequisites\n\n1. GitHub CLI installed and authenticated:\n\n   ```bash\n   gh auth status\n   ```\n\n2. Access to the repository and pull request you want to review\n\n## Understanding GitHub's Review Comment System\n\nGitHub has two types of PR comments:\n\n1. **Issue Comments** - General comments on the PR conversation\n2. **Review Comments** - Line-specific comments on code changes\n\nReview comments can be added in two ways:\n\n- **Single comment** - Using the `\u002Fpulls\u002F{pr}\u002Fcomments` endpoint\n- **Review with multiple comments** - Using the `\u002Fpulls\u002F{pr}\u002Freviews` endpoint\n\n## Adding a Single Line-Specific Comment\n\n### Basic Syntax\n\n```bash\ngh api repos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{pr_number}\u002Fcomments \\\n  -f body='Your comment text here' \\\n  -f commit_id='\u003Ccommit-sha>' \\\n  -f path='path\u002Fto\u002Ffile.js' \\\n  -F line=42 \\\n  -f side='RIGHT'\n```\n\n### Parameters Explained\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `body` | string | Yes | The text of the review comment (supports Markdown) |\n| `commit_id` | string | Yes | The SHA of the commit to comment on |\n| `path` | string | Yes | Relative path to the file being commented on |\n| `line` | integer | Yes | The line number in the diff (use `-F` for integers) |\n| `side` | string | Yes | `RIGHT` for new\u002Fmodified lines, `LEFT` for deleted lines |\n| `start_line` | integer | No | For multi-line comments, the starting line |\n| `start_side` | string | No | For multi-line comments, the starting side |\n\n### Parameter Flags\n\n- `-f` (--field) - For string values\n- `-F` (--field) - For integer values (note the capital F)\n\n### Complete Example\n\n```bash\n# First, get the latest commit SHA for the PR\ngh api repos\u002FNeoLabHQ\u002Flearning-platform-app\u002Fpulls\u002F4 --jq '.head.sha'\n\n# Then add your comment\ngh api repos\u002FNeoLabHQ\u002Flearning-platform-app\u002Fpulls\u002F4\u002Fcomments \\\n  -f body='Consider adding error handling here. Should we confirm the lesson was successfully marked as completed before navigating away?' \\\n  -f commit_id='e152d0dd6cf498467eadbeb638bf05abe11c64d4' \\\n  -f path='src\u002Fcomponents\u002FLessonNavigationButtons.tsx' \\\n  -F line=26 \\\n  -f side='RIGHT'\n```\n\n### Understanding Line Numbers\n\nThe `line` parameter refers to the **position in the diff**, not the absolute line number in the file:\n\n- For **new files**: Line numbers match the file's line numbers\n- For **modified files**: Use the line number as it appears in the \"Files changed\" tab\n- For **multi-line comments**: Use `start_line` and `line` to specify the range\n\n### Response\n\nOn success, returns a JSON object with comment details:\n\n```json\n{\n  \"id\": 2532291222,\n  \"pull_request_review_id\": 3470545909,\n  \"path\": \"src\u002Fcomponents\u002FLessonNavigationButtons.tsx\",\n  \"line\": 26,\n  \"body\": \"Consider adding error handling here...\",\n  \"html_url\": \"https:\u002F\u002Fgithub.com\u002FNeoLabHQ\u002Flearning-platform-app\u002Fpull\u002F4#discussion_r2532291222\",\n  \"created_at\": \"2025-11-16T22:40:46Z\"\n}\n```\n\n## Adding Multiple Line-Specific Comments Together\n\nTo add multiple comments across different files in a single review, use the `\u002Freviews` endpoint with JSON input.\n\n### Why Use Reviews for Multiple Comments?\n\n- **Atomic operation** - All comments are added together\n- **Single notification** - Doesn't spam with multiple notifications\n- **Better UX** - Appears as one cohesive review\n- **Same mechanism as GitHub UI** - \"Start a review\" → \"Finish review\"\n\n### Basic Syntax\n\n```bash\ncat \u003C\u003C'EOF' | gh api repos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{pr_number}\u002Freviews --input -\n{\n  \"event\": \"COMMENT\",\n  \"body\": \"Overall review summary (optional)\",\n  \"comments\": [\n    {\n      \"path\": \"file1.tsx\",\n      \"body\": \"Comment on file 1\",\n      \"side\": \"RIGHT\",\n      \"line\": 15\n    },\n    {\n      \"path\": \"file2.tsx\",\n      \"body\": \"Comment on file 2\",\n      \"side\": \"RIGHT\",\n      \"line\": 30\n    }\n  ]\n}\nEOF\n```\n\n### Review Event Types\n\n| Event | Description | When to Use |\n|-------|-------------|-------------|\n| `COMMENT` | General review comment | Just leaving feedback without approval |\n| `APPROVE` | Approve the PR | Changes look good, ready to merge |\n| `REQUEST_CHANGES` | Request changes | Issues that must be fixed before merge |\n\n### Complete Example\n\n```bash\ncat \u003C\u003C'EOF' | gh api repos\u002FNeoLabHQ\u002Flearning-platform-app\u002Fpulls\u002F4\u002Freviews --input -\n{\n  \"event\": \"COMMENT\",\n  \"body\": \"Testing multiple line-specific comments via gh api\",\n  \"comments\": [\n    {\n      \"path\": \"src\u002Fcomponents\u002FCourseCard.tsx\",\n      \"body\": \"Test comment generated by Claude\",\n      \"side\": \"RIGHT\",\n      \"line\": 15\n    },\n    {\n      \"path\": \"src\u002Fcomponents\u002FCourseProgressWidget.tsx\",\n      \"body\": \"Test comment generated by Claude\",\n      \"side\": \"RIGHT\",\n      \"line\": 30\n    },\n    {\n      \"path\": \"src\u002Fcomponents\u002FLessonProgressTracker.tsx\",\n      \"body\": \"Test comment generated by Claude\",\n      \"side\": \"RIGHT\",\n      \"line\": 20\n    }\n  ]\n}\nEOF\n```\n\n### Response\n\n```json\n{\n  \"id\": 3470546747,\n  \"state\": \"COMMENTED\",\n  \"html_url\": \"https:\u002F\u002Fgithub.com\u002FNeoLabHQ\u002Flearning-platform-app\u002Fpull\u002F4#pullrequestreview-3470546747\",\n  \"submitted_at\": \"2025-11-16T22:42:43Z\",\n  \"commit_id\": \"e152d0dd6cf498467eadbeb638bf05abe11c64d4\"\n}\n```\n\n## Common Issues and Solutions\n\n### Issue 1: \"user_id can only have one pending review per pull request\"\n\n**Error Message:**\n\n```\ngh: Validation Failed (HTTP 422)\n{\"message\":\"Validation Failed\",\"errors\":[{\"resource\":\"PullRequestReview\",\"code\":\"custom\",\"field\":\"user_id\",\"message\":\"user_id can only have one pending review per pull request\"}]}\n```\n\n**Cause:** GitHub only allows one pending (unsubmitted) review per user per PR. If you previously started a review through the UI or API and didn't submit it, it blocks new review creation.\n\n**Solution 1: Submit the pending review**\n\n```bash\n# Check for pending reviews\ngh api repos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{pr_number}\u002Freviews | jq '.[] | select(.state==\"PENDING\")'\n\n# Submit it through the UI or ask the user to submit it\n```\n\n**Solution 2: Use the single comment endpoint instead**\n\n```bash\n# Add individual comments without creating a review\ngh api repos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{pr_number}\u002Fcomments \\\n  -f body='Comment text' \\\n  -f commit_id='\u003Csha>' \\\n  -f path='file.tsx' \\\n  -F line=26 \\\n  -f side='RIGHT'\n```\n\n### Issue 2: Array syntax not working with --raw-field\n\n**Failed Attempt:**\n\n```bash\n# This does NOT work - GitHub API receives an object, not an array\ngh api repos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{pr}\u002Freviews \\\n  --raw-field 'comments[0][path]=file1.tsx' \\\n  --raw-field 'comments[0][line]=15' \\\n  --raw-field 'comments[1][path]=file2.tsx' \\\n  --raw-field 'comments[1][line]=30'\n```\n\n**Error:**\n\n```\nInvalid request. For 'properties\u002Fcomments', {\"0\" => {...}, \"1\" => {...}} is not an array.\n```\n\n**Solution:** Use JSON input via heredoc:\n\n```bash\ncat \u003C\u003C'EOF' | gh api repos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{pr}\u002Freviews --input -\n{\n  \"comments\": [...]\n}\nEOF\n```\n\n### Issue 3: Invalid line number\n\n**Error Message:**\n\n```\nPull request review thread line must be part of the diff\n```\n\n**Cause:** The line number doesn't exist in the diff for this file.\n\n**Solutions:**\n\n- Verify the file was actually changed in this PR\n- Check the \"Files changed\" tab to see actual line numbers in the diff\n- Ensure you're using the correct `commit_id` (the latest commit in the PR)\n\n### Issue 4: Wrong commit_id\n\n**Error Message:**\n\n```\ncommit_sha is not part of the pull request\n```\n\n**Solution:** Get the latest commit SHA:\n\n```bash\ngh api repos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{pr_number} --jq '.head.sha'\n```\n\n## Best Practices\n\n### 1. Get PR Information First\n\nBefore adding comments, gather necessary information:\n\n```bash\n# Get PR details\ngh pr view {pr_number} --json headRefOid,files\n\n# Or use the API\ngh api repos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{pr_number} --jq '{commit: .head.sha, files: [.changed_files]}'\n\n# List files changed\ngh api repos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{pr_number}\u002Ffiles --jq '.[] | {filename: .filename, additions: .additions, deletions: .deletions}'\n```\n\n### 2. Check for Pending Reviews\n\n```bash\n# Check if you have a pending review\ngh api repos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{pr_number}\u002Freviews \\\n  --jq '.[] | select(.state==\"PENDING\" and .user.login==\"YOUR_USERNAME\")'\n```\n\n### 3. Use Meaningful Comment Text\n\n- Be specific and constructive\n- Reference documentation or best practices\n- Suggest alternatives when requesting changes\n- Use code blocks for code suggestions:\n\n```markdown\nConsider using async\u002Fawait:\n\n\\`\\`\\`typescript\nasync function getData() {\n  const result = await fetch(url);\n  return result.json();\n}\n\\`\\`\\`\n```\n\n### 4. Batch Related Comments\n\nUse the review endpoint to group related comments:\n\n- All comments for a single file\u002Farea\n- All comments for a specific concern (security, performance, etc.)\n- Complete review session\n\n### 5. Choose the Right Event Type\n\n```bash\n# For feedback during development\n\"event\": \"COMMENT\"\n\n# When approving\n\"event\": \"APPROVE\"\n\n# When blocking merge\n\"event\": \"REQUEST_CHANGES\"\n```\n\n## Workflow Examples\n\n### Example 1: Quick Single Comment\n\n```bash\n#!\u002Fbin\u002Fbash\nOWNER=\"NeoLabHQ\"\nREPO=\"learning-platform-app\"\nPR=4\n\n# Get latest commit\nCOMMIT=$(gh api repos\u002F$OWNER\u002F$REPO\u002Fpulls\u002F$PR --jq '.head.sha')\n\n# Add comment\ngh api repos\u002F$OWNER\u002F$REPO\u002Fpulls\u002F$PR\u002Fcomments \\\n  -f body='Consider extracting this into a separate function for better testability' \\\n  -f commit_id=\"$COMMIT\" \\\n  -f path='src\u002Futils\u002Fvalidation.ts' \\\n  -F line=45 \\\n  -f side='RIGHT'\n```\n\n### Example 2: Comprehensive Review\n\n```bash\n#!\u002Fbin\u002Fbash\nOWNER=\"NeoLabHQ\"\nREPO=\"learning-platform-app\"\nPR=4\n\n# Create review with multiple comments\ncat \u003C\u003CEOF | gh api repos\u002F$OWNER\u002F$REPO\u002Fpulls\u002F$PR\u002Freviews --input -\n{\n  \"event\": \"COMMENT\",\n  \"body\": \"Thanks for the PR! I've reviewed the changes and have a few suggestions.\",\n  \"comments\": [\n    {\n      \"path\": \"src\u002Fcomponents\u002FCourseCard.tsx\",\n      \"body\": \"Consider memoizing this component to prevent unnecessary re-renders\",\n      \"side\": \"RIGHT\",\n      \"line\": 25\n    },\n    {\n      \"path\": \"src\u002Futils\u002FcourseProgress.ts\",\n      \"body\": \"This function could benefit from error handling for invalid course IDs\",\n      \"side\": \"RIGHT\",\n      \"line\": 12\n    },\n    {\n      \"path\": \"src\u002Fstate\u002FCourseProgressState.ts\",\n      \"body\": \"Consider adding JSDoc comments to document the expected behavior\",\n      \"side\": \"RIGHT\",\n      \"line\": 8\n    }\n  ]\n}\nEOF\n```\n\n### Example 3: Multi-line Comment\n\n```bash\n# Comment on a range of lines (e.g., lines 10-15)\ngh api repos\u002F$OWNER\u002F$REPO\u002Fpulls\u002F$PR\u002Fcomments \\\n  -f body='This entire block could be simplified using array destructuring' \\\n  -f commit_id=\"$COMMIT\" \\\n  -f path='src\u002Futils\u002Fparser.ts' \\\n  -F start_line=10 \\\n  -f start_side='RIGHT' \\\n  -F line=15 \\\n  -f side='RIGHT'\n```\n\n## Helpful Helper Scripts\n\n### Get PR Files and Lines\n\n```bash\n#!\u002Fbin\u002Fbash\n# pr-files.sh - List all files changed in a PR with line counts\n\nOWNER=\"$1\"\nREPO=\"$2\"\nPR=\"$3\"\n\ngh api repos\u002F$OWNER\u002F$REPO\u002Fpulls\u002F$PR\u002Ffiles --jq '.[] | \"\\(.filename): +\\(.additions)\u002F-\\(.deletions)\"'\n```\n\n### Check Review Status\n\n```bash\n#!\u002Fbin\u002Fbash\n# check-reviews.sh - Check review status for a PR\n\nOWNER=\"$1\"\nREPO=\"$2\"\nPR=\"$3\"\n\necho \"=== Reviews ===\"\ngh api repos\u002F$OWNER\u002F$REPO\u002Fpulls\u002F$PR\u002Freviews --jq '.[] | \"\\(.user.login): \\(.state) at \\(.submitted_at)\"'\n\necho -e \"\\n=== Pending Reviews ===\"\ngh api repos\u002F$OWNER\u002F$REPO\u002Fpulls\u002F$PR\u002Freviews --jq '.[] | select(.state==\"PENDING\") | \"\\(.user.login): \\(.state)\"'\n```\n\n## Related Documentation\n\n- [GitHub API: Pull Request Review Comments](https:\u002F\u002Fdocs.github.com\u002Frest\u002Fpulls\u002Fcomments)\n- [GitHub API: Pull Request Reviews](https:\u002F\u002Fdocs.github.com\u002Frest\u002Fpulls\u002Freviews)\n- [GitHub CLI Manual](https:\u002F\u002Fcli.github.com\u002Fmanual\u002F)\n- [Create PR Command](.\u002Fcreate-pr.md)\n- [Commit Command](.\u002Fcommit.md)\n\n## API Reference\n\n### POST \u002Frepos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{pull_number}\u002Fcomments\n\nCreates a review comment on a specific line.\n\n**Endpoint:** `https:\u002F\u002Fapi.github.com\u002Frepos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{pull_number}\u002Fcomments`\n\n**Parameters:**\n\n- `body` (string, required): Comment text\n- `commit_id` (string, required): SHA of commit\n- `path` (string, required): Relative file path\n- `line` (integer, required): Line number in diff\n- `side` (string, required): \"LEFT\" or \"RIGHT\"\n- `start_line` (integer, optional): Start line for multi-line\n- `start_side` (string, optional): Start side for multi-line\n\n### POST \u002Frepos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{pull_number}\u002Freviews\n\nCreates a review with optional line-specific comments.\n\n**Endpoint:** `https:\u002F\u002Fapi.github.com\u002Frepos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{pull_number}\u002Freviews`\n\n**Parameters:**\n\n- `event` (string, required): \"APPROVE\", \"REQUEST_CHANGES\", or \"COMMENT\"\n- `body` (string, optional): Overall review comment\n- `comments` (array, optional): Array of comment objects\n- `commit_id` (string, optional): SHA of commit to review\n\n**Comment Object:**\n\n- `path` (string, required): Relative file path\n- `body` (string, required): Comment text\n- `line` (integer, required): Line number in diff\n- `side` (string, required): \"LEFT\" or \"RIGHT\"\n- `start_line` (integer, optional): Start line for multi-line\n- `start_side` (string, optional): Start side for multi-line\n",{"name":5,"description":7,"allowed-tools":55,"argument-hint":56},"Bash(gh api:*), Bash(gh auth:*), Bash(gh pr:*), mcp__github_inline_comment__create_inline_comment","PR number or URL (optional - can work with current branch)","master","c73386b305dec167db7654e0e6feacb462d4f9dc","assets\u002Fskills\u002Fdev\u002Fattach-review-to-pr",1,"https:\u002F\u002Fgithub.com\u002FAntifragileTech\u002Fantifragile-claude-code","https:\u002F\u002Fgithub.com\u002FAntifragileTech","2026-10-02 14:22:14",{"source":8,"skillName":5,"commands":65,"prompt":75,"zipAvailable":76},[66,69,72],{"tool":67,"command":68},"npx","npx skills add AntifragileTech\u002Fantifragile-claude-code --skill \"git:attach-review-to-pr\"",{"tool":70,"command":71},"bunx","bunx skills add AntifragileTech\u002Fantifragile-claude-code --skill \"git:attach-review-to-pr\"",{"tool":73,"command":74},"pnpm","pnpm dlx skills add AntifragileTech\u002Fantifragile-claude-code --skill \"git:attach-review-to-pr\"","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FAntifragileTech\u002Fantifragile-claude-code\u002Fblob\u002Fmaster\u002Fassets\u002Fskills\u002Fdev\u002Fattach-review-to-pr\u002FSKILL.md",true,[],[79,100,115,130,143,156],{"skillNo":80,"name":81,"nameZh":6,"description":82,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":83,"categories":84,"keywords":94,"publishedAt":50},"01M6DT9Q6VYA615SCXR757TZZ7","writing-skills","Use when creating new skills, editing existing skills, or verifying skills work before deployment","https:\u002F\u002Fgithub.com\u002FAntifragileTech\u002Fantifragile-claude-code\u002Fblob\u002Fmaster\u002Fassets\u002Fskills\u002Fthinking\u002Fwriting-skills\u002FSKILL.md",[85,88,91],{"categoryNo":86,"categoryName":87,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":89,"categoryName":90,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000018","写作与文案",{"categoryNo":92,"categoryName":93,"taxonomyType":28,"taxonomyTypeDesc":29},"01JBSEEDCAT000000000000036","内容创作者",[95,96,97,98,45,99],"writing skills","writing","use","editing","deployment",{"skillNo":101,"name":102,"nameZh":6,"description":103,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":104,"categories":105,"keywords":108,"publishedAt":50},"01M6DT9GFHDNY90P41WGAE1TV0","writing-plans","Use when you have a spec or requirements for a multi-step task, before touching code","https:\u002F\u002Fgithub.com\u002FAntifragileTech\u002Fantifragile-claude-code\u002Fblob\u002Fmaster\u002Fassets\u002Fskills\u002Fthinking\u002Fwriting-plans\u002FSKILL.md",[106,107],{"categoryNo":89,"categoryName":90,"taxonomyType":20,"taxonomyTypeDesc":21},{"categoryNo":92,"categoryName":93,"taxonomyType":28,"taxonomyTypeDesc":29},[109,110,96,111,112,97,113,114],"plans","writing plans","requirements","task","code","spec",{"skillNo":116,"name":117,"nameZh":6,"description":118,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":119,"categories":120,"keywords":123,"publishedAt":50},"01M6DT9C6PFGD86WS3HY7YE3XG","docs:write-concisely","Apply writing rules to any documentation that humans will read. Makes your writing clearer, stronger, and more professional.","https:\u002F\u002Fgithub.com\u002FAntifragileTech\u002Fantifragile-claude-code\u002Fblob\u002Fmaster\u002Fassets\u002Fskills\u002Fthinking\u002Fwrite-concisely\u002FSKILL.md",[121,122],{"categoryNo":89,"categoryName":90,"taxonomyType":20,"taxonomyTypeDesc":21},{"categoryNo":92,"categoryName":93,"taxonomyType":28,"taxonomyTypeDesc":29},[124,125,126,127,128,129,96],"docs:write concisely","write","docs","read","Rules","documentation",{"skillNo":131,"name":132,"nameZh":6,"description":133,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":134,"categories":135,"keywords":136,"publishedAt":50},"01M6DT98AWQ27P0N1CG97WAG66","kaizen:why","Iterative Five Whys root cause analysis drilling from symptoms to fundamentals","https:\u002F\u002Fgithub.com\u002FAntifragileTech\u002Fantifragile-claude-code\u002Fblob\u002Fmaster\u002Fassets\u002Fskills\u002Fthinking\u002Fwhy\u002FSKILL.md",[],[132,137,138,139,140,141,142],"why","kaizen","issue","five whys","analysis","root cause analysis",{"skillNo":144,"name":145,"nameZh":6,"description":146,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":147,"categories":148,"keywords":149,"publishedAt":50},"01M6DT93EH25NAX19R3WGE1P53","verification-loop","A comprehensive verification system for Claude Code sessions.","https:\u002F\u002Fgithub.com\u002FAntifragileTech\u002Fantifragile-claude-code\u002Fblob\u002Fmaster\u002Fassets\u002Fskills\u002Fthinking\u002Fverification-loop\u002FSKILL.md",[],[150,151,152,153,113,154,155],"verification loop","verification","loop","sessions","claude code sessions","system",{"skillNo":157,"name":158,"nameZh":6,"description":159,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":160,"categories":161,"keywords":162,"publishedAt":50},"01M6DT90GW7Z7VCN98P9DVYSNC","verification-before-completion","Use when about to claim work is complete, fixed, or passing, before committing or creating PRs - requires running verification commands and confirming output before making any success claims; evidence before assertions always","https:\u002F\u002Fgithub.com\u002FAntifragileTech\u002Fantifragile-claude-code\u002Fblob\u002Fmaster\u002Fassets\u002Fskills\u002Fthinking\u002Fverification-before-completion\u002FSKILL.md",[],[163,151,164,45,97,165,166,167],"verification before completion","commands","evidence","claim","complete"]