{"id":76154,"date":"2026-05-20T06:21:58","date_gmt":"2026-05-20T06:21:58","guid":{"rendered":"https:\/\/www.devopsschool.com\/blog\/?p=76154"},"modified":"2026-05-20T06:22:00","modified_gmt":"2026-05-20T06:22:00","slug":"how-to-review-github-pull-requests-from-the-terminal-using-gh-and-claude-code","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/how-to-review-github-pull-requests-from-the-terminal-using-gh-and-claude-code\/","title":{"rendered":"How to Review GitHub Pull Requests from the Terminal Using gh and Claude Code"},"content":{"rendered":"\n<p><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>AI-Powered Pull Request Reviews with GitHub CLI and Claude Code<\/strong><\/li>\n\n\n\n<li><strong>Build a Simple PR Review Bot Using <code>gh<\/code>, Git, and Claude<\/strong><\/li>\n\n\n\n<li><strong>Speed Up Code Reviews with Claude Code and GitHub CLI<\/strong><\/li>\n\n\n\n<li><strong>Review GitHub PRs Locally with Claude: A Practical Bash Script<\/strong><\/li>\n\n\n\n<li><strong>From PR to AI Review: Automating Developer Feedback with <code>gh<\/code> and Claude<\/strong><\/li>\n\n\n\n<li><strong>Using Claude Code as Your Terminal-Based PR Reviewer<\/strong><\/li>\n\n\n\n<li><strong>A Practical Guide to AI-Assisted GitHub PR Reviews<\/strong><\/li>\n\n\n\n<li><strong>Automated PR Review Workflow with Bash, GitHub CLI, and Claude<\/strong><\/li>\n\n\n\n<li><strong>How I Use Claude to Review Pull Requests from the Command Line<\/strong><\/li>\n\n\n\n<li><strong>Claude + GitHub CLI: A Fast Workflow for Pull Request Reviews<\/strong><\/li>\n\n\n\n<li><\/li>\n<\/ol>\n\n\n\n<h1 class=\"wp-block-heading\">How to Review GitHub Pull Requests from the Terminal Using <code>gh<\/code> and Claude Code<\/h1>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p>Code review is one of the most important parts of software development, but it can also be time-consuming. Every pull request needs to be checked for correctness, security issues, missing tests, edge cases, and maintainability concerns.<\/p>\n\n\n\n<p>With tools like <strong>GitHub CLI<\/strong>, <strong>Git<\/strong>, and <strong>Claude Code<\/strong>, we can create a simple terminal workflow that helps review pull requests faster.<\/p>\n\n\n\n<p>In this blog, we will build a Bash script that:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>accepts a GitHub PR number<\/li>\n\n\n\n<li>checks out the pull request locally<\/li>\n\n\n\n<li>collects PR metadata and diff<\/li>\n\n\n\n<li>asks Claude to review the PR<\/li>\n\n\n\n<li>writes the review to a Markdown file<\/li>\n\n\n\n<li>optionally posts the review back to the GitHub PR<\/li>\n<\/ul>\n\n\n\n<p>This is not meant to replace human review. Instead, it acts like an extra reviewer that can quickly spot bugs, risks, missing tests, and suspicious changes.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<p>Before using the script, your system should have the following tools installed and configured:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">git --version\ngh --version\nclaude --version\n<\/code><\/span><\/pre>\n\n\n<p>You also need to authenticate GitHub CLI:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">gh auth login\n<\/code><\/span><\/pre>\n\n\n<p>It is also useful to configure GitHub CLI with Git credentials:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">gh auth setup-git\n<\/code><\/span><\/pre>\n\n\n<p>This helps avoid authentication prompts when the script fetches PR branches.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Why use <code>gh<\/code>?<\/h2>\n\n\n\n<p><code>gh<\/code> is the official GitHub command-line tool. It allows us to work with GitHub directly from the terminal.<\/p>\n\n\n\n<p>For pull request reviews, <code>gh<\/code> gives us useful commands like:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">gh pr view 56\ngh pr checkout 56\ngh pr diff 56\ngh pr comment 56\n<\/code><\/span><\/pre>\n\n\n<p>Instead of manually opening GitHub in the browser, copying the diff, and pasting it into Claude, we can automate the whole flow.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Basic workflow<\/h2>\n\n\n\n<p>The workflow looks like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">PR number\n   \u2193\ngh pr checkout\n   \u2193\ncollect PR metadata\n   \u2193\ncollect changed files\n   \u2193\ncollect patch\/diff\n   \u2193\nsend context to Claude\n   \u2193\nsave review <span class=\"hljs-keyword\">as<\/span> Markdown\n   \u2193\noptionally post review to GitHub\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This is simple, transparent, and easy to customize.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">The review script<\/h2>\n\n\n\n<p>Save the following as:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">review<\/span><span class=\"hljs-selector-class\">.sh<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">#!\/usr\/bin\/env bash<\/span>\nset -euo pipefail\n\nPR=<span class=\"hljs-string\">\"${1:?Usage: .\/review.sh &lt;pr-number&gt; &#91;--post]}\"<\/span>\nPOST=<span class=\"hljs-string\">\"${2:-}\"<\/span>\n\nOUT=<span class=\"hljs-string\">\"claude-pr-${PR}-review.md\"<\/span>\nCTX=<span class=\"hljs-string\">\"\/tmp\/pr-${PR}-context.md\"<\/span>\nBRANCH=<span class=\"hljs-string\">\"pr-${PR}\"<\/span>\nREMOTE=<span class=\"hljs-string\">\"${GH_REMOTE:-origin}\"<\/span>\n\nrequire_cmd() {\n  command -v <span class=\"hljs-string\">\"$1\"<\/span> &gt;\/dev\/<span class=\"hljs-keyword\">null<\/span> <span class=\"hljs-number\">2<\/span>&gt;&amp;<span class=\"hljs-number\">1<\/span> || {\n    <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Error: required command not found: $1\"<\/span>\n    <span class=\"hljs-keyword\">exit<\/span> <span class=\"hljs-number\">1<\/span>\n  }\n}\n\nrequire_cmd git\nrequire_cmd gh\nrequire_cmd claude\n\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Checking GitHub authentication...\"<\/span>\ngh auth status &gt;\/dev\/<span class=\"hljs-keyword\">null<\/span>\n\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Checking Git remote...\"<\/span>\n<span class=\"hljs-keyword\">if<\/span> ! git remote get-url <span class=\"hljs-string\">\"$REMOTE\"<\/span> &gt;\/dev\/<span class=\"hljs-keyword\">null<\/span> <span class=\"hljs-number\">2<\/span>&gt;&amp;<span class=\"hljs-number\">1<\/span>; then\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Error: Git remote '$REMOTE' not found.\"<\/span>\n  <span class=\"hljs-keyword\">echo<\/span>\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Available remotes:\"<\/span>\n  git remote -v\n  <span class=\"hljs-keyword\">echo<\/span>\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"You can run with a different remote like this:\"<\/span>\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"  GH_REMOTE=upstream .\/review.sh $PR\"<\/span>\n  <span class=\"hljs-keyword\">exit<\/span> <span class=\"hljs-number\">1<\/span>\nfi\n\nREMOTE_URL=<span class=\"hljs-string\">\"$(git remote get-url \"<\/span>$REMOTE<span class=\"hljs-string\">\")\"<\/span>\n\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Reading PR metadata...\"<\/span>\nPR_STATE=<span class=\"hljs-string\">\"$(gh pr view \"<\/span>$PR<span class=\"hljs-string\">\" --json state --jq '.state')\"<\/span>\nBASE_REF=<span class=\"hljs-string\">\"$(gh pr view \"<\/span>$PR<span class=\"hljs-string\">\" --json baseRefName --jq '.baseRefName')\"<\/span>\nHEAD_REF=<span class=\"hljs-string\">\"$(gh pr view \"<\/span>$PR<span class=\"hljs-string\">\" --json headRefName --jq '.headRefName')\"<\/span>\nREPO_FULL=<span class=\"hljs-string\">\"$(gh repo view --json nameWithOwner --jq '.nameWithOwner')\"<\/span>\n\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Repository: $REPO_FULL\"<\/span>\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Remote: $REMOTE\"<\/span>\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Remote URL: $REMOTE_URL\"<\/span>\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"PR: #$PR\"<\/span>\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"State: $PR_STATE\"<\/span>\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Base: $BASE_REF\"<\/span>\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Head: $HEAD_REF\"<\/span>\n<span class=\"hljs-keyword\">echo<\/span>\n\nCHECKOUT_OK=<span class=\"hljs-string\">\"false\"<\/span>\n\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Checking out PR #$PR...\"<\/span>\n\n<span class=\"hljs-keyword\">if<\/span> gh pr checkout <span class=\"hljs-string\">\"$PR\"<\/span> --force; then\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Checked out PR using gh pr checkout.\"<\/span>\n  CHECKOUT_OK=<span class=\"hljs-string\">\"true\"<\/span>\n<span class=\"hljs-keyword\">else<\/span>\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"gh pr checkout failed.\"<\/span>\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Trying GitHub pull-request ref via local remote '$REMOTE'...\"<\/span>\n\n  gh auth setup-git &gt;\/dev\/<span class=\"hljs-keyword\">null<\/span> <span class=\"hljs-number\">2<\/span>&gt;&amp;<span class=\"hljs-number\">1<\/span> || <span class=\"hljs-keyword\">true<\/span>\n\n  <span class=\"hljs-keyword\">if<\/span> git fetch <span class=\"hljs-string\">\"$REMOTE\"<\/span> <span class=\"hljs-string\">\"+refs\/pull\/${PR}\/head:refs\/remotes\/${REMOTE}\/${BRANCH}\"<\/span>; then\n    git <span class=\"hljs-keyword\">switch<\/span> -C <span class=\"hljs-string\">\"$BRANCH\"<\/span> <span class=\"hljs-string\">\"refs\/remotes\/${REMOTE}\/${BRANCH}\"<\/span>\n    <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Checked out PR using refs\/pull\/${PR}\/head.\"<\/span>\n    CHECKOUT_OK=<span class=\"hljs-string\">\"true\"<\/span>\n  <span class=\"hljs-keyword\">else<\/span>\n    <span class=\"hljs-keyword\">echo<\/span>\n    <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Could not checkout PR branch.\"<\/span>\n    <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"This can happen when:\"<\/span>\n    <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"- the PR is merged or closed\"<\/span>\n    <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"- the source branch was deleted\"<\/span>\n    <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"- your Git remote auth is not configured\"<\/span>\n    <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"- origin points somewhere unexpected\"<\/span>\n    <span class=\"hljs-keyword\">echo<\/span>\n    <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Continuing with diff-only review using gh pr diff.\"<\/span>\n    CHECKOUT_OK=<span class=\"hljs-string\">\"false\"<\/span>\n  fi\nfi\n\n<span class=\"hljs-keyword\">echo<\/span>\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Collecting PR context...\"<\/span>\n\n{\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"# PR #$PR Review Context\"<\/span>\n  <span class=\"hljs-keyword\">echo<\/span>\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Repository: $REPO_FULL\"<\/span>\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Remote: $REMOTE\"<\/span>\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"PR state: $PR_STATE\"<\/span>\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Base branch: $BASE_REF\"<\/span>\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Head branch: $HEAD_REF\"<\/span>\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Checkout available: $CHECKOUT_OK\"<\/span>\n  <span class=\"hljs-keyword\">echo<\/span>\n\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"## PR metadata\"<\/span>\n  gh pr view <span class=\"hljs-string\">\"$PR\"<\/span> --json title,body,author,state,baseRefName,headRefName,headRepositoryOwner,headRepository,isCrossRepository,files,commits\n  <span class=\"hljs-keyword\">echo<\/span>\n\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"## Changed files\"<\/span>\n  gh pr diff <span class=\"hljs-string\">\"$PR\"<\/span> --name-only\n  <span class=\"hljs-keyword\">echo<\/span>\n\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"## Patch\"<\/span>\n  gh pr diff <span class=\"hljs-string\">\"$PR\"<\/span> --patch\n} &gt; <span class=\"hljs-string\">\"$CTX\"<\/span>\n\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"PR context written to $CTX\"<\/span>\n<span class=\"hljs-keyword\">echo<\/span>\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Asking Claude to review...\"<\/span>\n\ncat <span class=\"hljs-string\">\"$CTX\"<\/span> | claude -p <span class=\"hljs-string\">\"\nYou are a senior software engineer reviewing GitHub PR #$PR.\n\nRepository:\n$REPO_FULL\n\nPR state:\n$PR_STATE\n\nCheckout available:\n$CHECKOUT_OK\n\nReview goals:\n- Find correctness bugs.\n- Find security or data-leak risks.\n- Find missing tests for changed behavior.\n- Find API compatibility issues.\n- Find race conditions, error handling gaps, and edge cases.\n- Avoid nitpicks unless they materially affect maintainability.\n\nInstructions:\n- Do not edit files.\n- Use the PR metadata and patch.\n- If checkout is available, inspect changed files in the repository if needed.\n- If checkout is not available, review from the supplied diff only.\n- If there are no serious issues, say so clearly.\n- Keep the review practical and actionable.\n- Include file paths and reasoning.\n- Clearly separate must-fix issues from suggestions.\n- End with a concise comment suitable for posting on the GitHub PR.\n\nOutput format:\n\n## Claude PR Review\n\n### Summary\n\n### Must fix\n\n### Should consider\n\n### Tests to run or add\n\n### Suggested PR comment\n\"<\/span> &gt; <span class=\"hljs-string\">\"$OUT\"<\/span>\n\n<span class=\"hljs-keyword\">echo<\/span>\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Review written to $OUT\"<\/span>\n\n<span class=\"hljs-keyword\">if<\/span> &#91;&#91; <span class=\"hljs-string\">\"$POST\"<\/span> == <span class=\"hljs-string\">\"--post\"<\/span> ]]; then\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Posting review comment to PR #$PR...\"<\/span>\n  gh pr comment <span class=\"hljs-string\">\"$PR\"<\/span> --body-file <span class=\"hljs-string\">\"$OUT\"<\/span>\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Posted.\"<\/span>\n<span class=\"hljs-keyword\">else<\/span>\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Not posted. Review the file first:\"<\/span>\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"  less $OUT\"<\/span>\n  <span class=\"hljs-keyword\">echo<\/span>\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"To post it:\"<\/span>\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"  gh pr comment $PR --body-file $OUT\"<\/span>\n  <span class=\"hljs-keyword\">echo<\/span>\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Or run:\"<\/span>\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"  .\/review.sh $PR --post\"<\/span>\nfi\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Make the script executable<\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">chmod<\/span> +<span class=\"hljs-selector-tag\">x<\/span> <span class=\"hljs-selector-tag\">review<\/span><span class=\"hljs-selector-class\">.sh<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Usage<\/h2>\n\n\n\n<p>To review a PR:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">.\/review.sh 56\n<\/code><\/span><\/pre>\n\n\n<p>This creates a file like:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">claude-pr-56-review<\/span><span class=\"hljs-selector-class\">.md<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>You can inspect the result:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">less<\/span> <span class=\"hljs-selector-tag\">claude-pr-56-review<\/span><span class=\"hljs-selector-class\">.md<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>After reviewing the generated comment, post it manually:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">gh<\/span> <span class=\"hljs-selector-tag\">pr<\/span> <span class=\"hljs-selector-tag\">comment<\/span> 56 <span class=\"hljs-selector-tag\">--body-file<\/span> <span class=\"hljs-selector-tag\">claude-pr-56-review<\/span><span class=\"hljs-selector-class\">.md<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Or post automatically:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">.\/review.sh 56 --post\n<\/code><\/span><\/pre>\n\n\n<p>For real team usage, I recommend reviewing the generated Markdown before posting. AI review is helpful, but it should not blindly comment on teammates\u2019 PRs without a human pass.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">How the script works<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">1. Strict Bash mode<\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">set<\/span> -euo pipefail\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This makes the script safer:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>-e<\/code> exits when a command fails<\/li>\n\n\n\n<li><code>-u<\/code> fails on undefined variables<\/li>\n\n\n\n<li><code>pipefail<\/code> catches failures inside pipelines<\/li>\n<\/ul>\n\n\n\n<p>This is a good default for automation scripts.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">2. Read the PR number<\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">PR=<span class=\"hljs-string\">\"${1:?Usage: .\/review.sh &lt;pr-number&gt; &#91;--post]}\"<\/span>\nPOST=<span class=\"hljs-string\">\"${2:-}\"<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The first argument is required:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">.\/review.sh 56\n<\/code><\/span><\/pre>\n\n\n<p>The second argument is optional:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">.\/review.sh 56 --post\n<\/code><\/span><\/pre>\n\n\n<p>If the PR number is missing, the script shows usage instructions.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">3. Check required tools<\/h2>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">require_cmd git\nrequire_cmd gh\nrequire_cmd claude\n<\/code><\/span><\/pre>\n\n\n<p>The script confirms that <code>git<\/code>, <code>gh<\/code>, and <code>claude<\/code> are available before doing anything else.<\/p>\n\n\n\n<p>This avoids confusing errors later.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">4. Check GitHub authentication<\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">gh auth status &gt;<span class=\"hljs-regexp\">\/dev\/<\/span><span class=\"hljs-literal\">null<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This confirms that GitHub CLI is authenticated.<\/p>\n\n\n\n<p>If authentication is missing, run:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">gh auth login\n<\/code><\/span><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">5. Read PR metadata<\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">gh pr view <span class=\"hljs-string\">\"$PR\"<\/span> --json state --jq <span class=\"hljs-string\">'.state'<\/span>\ngh pr view <span class=\"hljs-string\">\"$PR\"<\/span> --json baseRefName --jq <span class=\"hljs-string\">'.baseRefName'<\/span>\ngh pr view <span class=\"hljs-string\">\"$PR\"<\/span> --json headRefName --jq <span class=\"hljs-string\">'.headRefName'<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The script reads useful PR details:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>PR state<\/li>\n\n\n\n<li>base branch<\/li>\n\n\n\n<li>head branch<\/li>\n\n\n\n<li>repository name<\/li>\n<\/ul>\n\n\n\n<p>This metadata helps Claude understand the context before reviewing the diff.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">6. Try normal PR checkout<\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">gh pr checkout <span class=\"hljs-string\">\"$PR\"<\/span> --force\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This is the cleanest way to check out a PR.<\/p>\n\n\n\n<p>But sometimes this fails, especially when:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>the PR branch was deleted<\/li>\n\n\n\n<li>the PR is already merged<\/li>\n\n\n\n<li>the PR came from a fork<\/li>\n\n\n\n<li>the local remote is not configured correctly<\/li>\n\n\n\n<li>GitHub CLI tries to fetch a branch that no longer exists<\/li>\n<\/ul>\n\n\n\n<p>That is why the script includes a fallback.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">7. Fallback checkout using GitHub PR refs<\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">git fetch <span class=\"hljs-string\">\"$REMOTE\"<\/span> <span class=\"hljs-string\">\"+refs\/pull\/${PR}\/head:refs\/remotes\/${REMOTE}\/${BRANCH}\"<\/span>\ngit <span class=\"hljs-keyword\">switch<\/span> -C <span class=\"hljs-string\">\"$BRANCH\"<\/span> <span class=\"hljs-string\">\"refs\/remotes\/${REMOTE}\/${BRANCH}\"<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This fetches the PR directly from GitHub\u2019s pull request reference.<\/p>\n\n\n\n<p>For example, for PR <code>56<\/code>, it fetches:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">refs\/pull\/56\/head\n<\/code><\/span><\/pre>\n\n\n<p>This is often more reliable than fetching the original branch name.<\/p>\n\n\n\n<p>This fallback fixed your earlier issue:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"HTTP\" data-shcb-language-slug=\"http\"><span><code class=\"hljs language-http\"><span class=\"hljs-attribute\">fatal<\/span>: couldn't find remote ref refs\/heads\/update_aws\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTTP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">http<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>That happened because the branch <code>update_aws<\/code> was no longer available as a normal branch.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">8. Continue even if checkout fails<\/h2>\n\n\n\n<p>If checkout still fails, the script does not stop immediately.<\/p>\n\n\n\n<p>Instead, it continues with:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">gh pr diff <span class=\"hljs-string\">\"$PR\"<\/span> --patch\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>That means Claude can still review the pull request from the diff, even if the branch cannot be checked out locally.<\/p>\n\n\n\n<p>This is useful for merged or closed PRs.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">9. Collect PR context<\/h2>\n\n\n\n<p>The script writes everything to:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">\/tmp\/pr-56-context.md\n<\/code><\/span><\/pre>\n\n\n<p>It includes:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>repository name<\/li>\n\n\n\n<li>PR state<\/li>\n\n\n\n<li>base branch<\/li>\n\n\n\n<li>head branch<\/li>\n\n\n\n<li>checkout status<\/li>\n\n\n\n<li>PR metadata<\/li>\n\n\n\n<li>changed files<\/li>\n\n\n\n<li>patch\/diff<\/li>\n<\/ul>\n\n\n\n<p>This context is then sent to Claude.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">10. Ask Claude to review<\/h2>\n\n\n\n<p>The script pipes the context into Claude:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">cat <span class=\"hljs-string\">\"$CTX\"<\/span> | claude -p <span class=\"hljs-string\">\"...\"<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The prompt tells Claude to focus on important review areas:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>correctness bugs<\/li>\n\n\n\n<li>security risks<\/li>\n\n\n\n<li>missing tests<\/li>\n\n\n\n<li>API compatibility issues<\/li>\n\n\n\n<li>race conditions<\/li>\n\n\n\n<li>edge cases<\/li>\n\n\n\n<li>maintainability issues that matter<\/li>\n<\/ul>\n\n\n\n<p>It also tells Claude not to edit files.<\/p>\n\n\n\n<p>That matters because for review workflows, we want feedback, not automatic code changes.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">11. Save the review<\/h2>\n\n\n\n<p>Claude\u2019s output is saved to:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">claude-pr-56-review<\/span><span class=\"hljs-selector-class\">.md<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-17\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This lets you review the AI output before posting.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">12. Optionally post to GitHub<\/h2>\n\n\n\n<p>If you run:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">.\/review.sh 56 --post\n<\/code><\/span><\/pre>\n\n\n<p>The script posts the review using:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-18\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">gh pr comment <span class=\"hljs-string\">\"$PR\"<\/span> --body-file <span class=\"hljs-string\">\"$OUT\"<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-18\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>For safer usage, I prefer:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">.\/review.sh 56\nless claude-pr-56-review.md\ngh pr comment 56 --body-file claude-pr-56-review.md\n<\/code><\/span><\/pre>\n\n\n<p>That keeps a human in the loop.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Real-world use cases<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Use case 1: Quick review before approving a PR<\/h2>\n\n\n\n<p>A teammate opens a PR. Before you manually inspect it, run:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">.\/review.sh 123\n<\/code><\/span><\/pre>\n\n\n<p>Claude gives you a first-pass review. You can then focus your human review on the risky areas.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Use case 2: Reviewing infrastructure changes<\/h2>\n\n\n\n<p>For Terraform, Kubernetes, Helm, or AWS modules, this is especially useful.<\/p>\n\n\n\n<p>Claude can help spot:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>overly broad IAM permissions<\/li>\n\n\n\n<li>missing encryption<\/li>\n\n\n\n<li>accidental public exposure<\/li>\n\n\n\n<li>risky security group changes<\/li>\n\n\n\n<li>missing variable validation<\/li>\n\n\n\n<li>breaking module interface changes<\/li>\n\n\n\n<li>missing README or example updates<\/li>\n<\/ul>\n\n\n\n<p>For Terraform repositories, you can customize the prompt with infrastructure-specific review goals.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Use case 3: Reviewing merged PRs<\/h2>\n\n\n\n<p>Sometimes you want to analyze an old PR after it has already been merged.<\/p>\n\n\n\n<p>Normal branch checkout may fail because the source branch was deleted.<\/p>\n\n\n\n<p>This script still tries to review from:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">gh pr diff\n<\/code><\/span><\/pre>\n\n\n<p>That makes it useful for audits, postmortems, and learning.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Use case 4: Preparing better code review comments<\/h2>\n\n\n\n<p>Instead of posting Claude\u2019s full output directly, you can use it as a draft.<\/p>\n\n\n\n<p>You read the generated Markdown, remove anything unnecessary, and post only the useful comments.<\/p>\n\n\n\n<p>This avoids noisy AI-generated reviews.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Suggested improvements<\/h1>\n\n\n\n<p>You can improve the script further by adding:<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Terraform-specific mode<\/h2>\n\n\n\n<p>Example:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">.\/review.sh 56 --terraform\n<\/code><\/span><\/pre>\n\n\n<p>Then use a Terraform-specific Claude prompt.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Security-only mode<\/h2>\n\n\n\n<p>Example:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">.\/review.sh 56 --security\n<\/code><\/span><\/pre>\n\n\n<p>This would focus only on security and data exposure.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Review without posting<\/h2>\n\n\n\n<p>Default behavior should stay safe:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">.\/review.sh 56\n<\/code><\/span><\/pre>\n\n\n<p>Auto-posting should remain explicit:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">.\/review.sh 56 --post\n<\/code><\/span><\/pre>\n\n\n<p>That is the right default.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Best practices<\/h1>\n\n\n\n<p>Do not blindly post AI-generated reviews.<\/p>\n\n\n\n<p>Use Claude as an assistant, not as the final reviewer.<\/p>\n\n\n\n<p>Prefer this flow:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">.\/review.sh 56\nless claude-pr-56-review.md\ngh pr comment 56 --body-file claude-pr-56-review.md\n<\/code><\/span><\/pre>\n\n\n<p>Keep prompts specific to the repository type.<\/p>\n\n\n\n<p>For example, a Terraform module review should focus on AWS security, IAM, networking, variables, outputs, examples, and provider compatibility.<\/p>\n\n\n\n<p>A backend service review should focus on API behavior, database changes, error handling, concurrency, and tests.<\/p>\n\n\n\n<p>A frontend review should focus on UI behavior, state management, accessibility, performance, and browser compatibility.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Final summary<\/h1>\n\n\n\n<p>This script gives you a lightweight AI-assisted PR review workflow using tools many developers already use:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">Git + GitHub CLI + Claude Code + Bash\n<\/code><\/span><\/pre>\n\n\n<p>It is fast, transparent, and easy to customize.<\/p>\n\n\n\n<p>The best part is that it keeps the human reviewer in control. Claude provides a first-pass review, but you decide what gets posted to the PR.<\/p>\n\n\n\n<p>That is exactly how AI code review should work: helpful, practical, and human-supervised.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>How to Review GitHub Pull Requests from the Terminal Using gh and Claude Code Introduction Code review is one of the most important parts of software development,&#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[11138],"tags":[],"class_list":["post-76154","post","type-post","status-publish","format-standard","hentry","category-best-tools"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/76154","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=76154"}],"version-history":[{"count":1,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/76154\/revisions"}],"predecessor-version":[{"id":76155,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/76154\/revisions\/76155"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=76154"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=76154"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=76154"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}