diff --git a/README.md b/README.md
index 201e93b..77b5976 100644
--- a/README.md
+++ b/README.md
@@ -129,6 +129,10 @@ Click on any action name below to view detailed documentation, usage examples, a
render-ios-app-icon-badge |
Adds a badge to an iOS app icon to indicate that the app is meant for testing purposes. |
+
+ | review |
+ Reviews one pull request with the Banzai harness and posts inline + summary comments. |
+
| swiftlint |
Runs SwiftLint on a codebase. |
diff --git a/review/README.md b/review/README.md
new file mode 100644
index 0000000..03a2eb3
--- /dev/null
+++ b/review/README.md
@@ -0,0 +1,57 @@
+# Banzai review
+
+Reviews one pull request. A thin composite over the
+`banzai-harness review` CLI (see
+[framna-dk/banzai-codes-harness](https://github.com/framna-dk/banzai-codes-harness)):
+it boots the review agent on the PR head, reads the diff, and posts a concise
+review — inline comments plus one summary (`COMMENT`/`REQUEST_CHANGES`, never
+`APPROVE`). The review is **static** (no file edits, no commits), so it never
+re-triggers itself.
+
+This is the sibling of the `harness` action and shares the same self-hosted
+runner pool: `banzai-harness`, `gh`, and `git` (plus the runner's configured
+review agent) must be on `PATH`.
+
+## Inputs
+
+| Input | Required | Default | Notes |
+|-------|----------|---------|-------|
+| `pr_number` | yes | — | PR to review, e.g. `42`. |
+| `repo_url` | no | current repo | `owner/repo`. |
+| `base_branch` | no | `main` | Branch the PR targets. |
+| `prompt_path` | no | embedded template | Override review template; validated against the `banzai-review` version marker. |
+| `workspace_root` | no | `$HOME/banzai-workspaces` | Per-PR review workspaces. |
+| `log_level` | no | `info` | `info` \| `warn` \| `error`. |
+
+`GH_TOKEN` is read from the environment, never passed on the command line:
+export it in the calling job. The review agent's own credentials are configured
+on the runner, not supplied through this action.
+
+## Usage
+
+```yaml
+name: PR review
+on:
+ pull_request:
+ types: [opened, synchronize, reopened]
+
+# One review per PR; a new push cancels the in-flight one.
+concurrency:
+ group: banzai-review-${{ github.event.pull_request.number }}
+ cancel-in-progress: true
+
+jobs:
+ review:
+ runs-on: [self-hosted]
+ steps:
+ - uses: framna-dk/actions/review@main
+ with:
+ pr_number: ${{ github.event.pull_request.number }}
+ base_branch: ${{ github.event.pull_request.base.ref }}
+ env:
+ GH_TOKEN: ${{ secrets.GH_TOKEN }}
+```
+
+The agent reacts 👀 on the PR when it starts, then posts the review. It writes a
+`review-outcome.json` to `${{ runner.temp }}` (`outcome`, `reason`, `pr_number`,
+`head_sha`, `turn_count`, `tokens`, `ended_at_ms`).
diff --git a/review/action.yml b/review/action.yml
new file mode 100644
index 0000000..2f80203
--- /dev/null
+++ b/review/action.yml
@@ -0,0 +1,52 @@
+name: "Banzai review"
+description: "Reviews one pull request with the Banzai harness inside a GitHub Actions job."
+
+inputs:
+ pr_number:
+ description: "Pull request number to review (e.g. 42)."
+ required: true
+ repo_url:
+ description: "Repository slug owner/repo the PR belongs to. Defaults to the current repo."
+ required: false
+ default: ${{ github.repository }}
+ base_branch:
+ description: "Branch the PR targets (used to scope the diff)."
+ required: false
+ default: "main"
+ prompt_path:
+ description: "Optional override for the review prompt template (relative to the workspace repo, or absolute). When omitted, the harness uses its embedded canonical review template. An override is validated against the banzai-review version marker and fails fast if stale."
+ required: false
+ default: ""
+ workspace_root:
+ description: "Directory under which per-PR review workspaces are created."
+ required: false
+ default: "$HOME/banzai-workspaces"
+ log_level:
+ description: "info | warn | error"
+ required: false
+ default: "info"
+
+runs:
+ using: composite
+ steps:
+ - name: review-preflight
+ shell: bash
+ run: |
+ banzai-harness preflight \
+ --pr-number "${{ inputs.pr_number }}" \
+ --repo-url "${{ inputs.repo_url }}" \
+ --log-level "${{ inputs.log_level }}"
+ - name: review-run
+ shell: bash
+ env:
+ PROMPT_PATH: ${{ inputs.prompt_path }}
+ run: |
+ args=(review
+ --repo-url "${{ inputs.repo_url }}"
+ --pr-number "${{ inputs.pr_number }}"
+ --base-branch "${{ inputs.base_branch }}"
+ --workspace-root "${{ inputs.workspace_root }}"
+ --log-level "${{ inputs.log_level }}"
+ --runner-temp "${{ runner.temp }}")
+ [ -n "$PROMPT_PATH" ] && args+=(--prompt-path "$PROMPT_PATH")
+ banzai-harness "${args[@]}"