robin-review 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Anton Gulin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,321 @@
1
+ # Robin
2
+
3
+ Free AI code reviews for every pull request. You bring an API key; Robin reviews show up like a teammate left comments.
4
+
5
+ [![Self-Test](https://github.com/antongulin/robin/actions/workflows/self-test.yml/badge.svg)](https://github.com/antongulin/robin/actions/workflows/self-test.yml)
6
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
7
+ [![Node 24](https://img.shields.io/badge/runtime-node24-brightgreen.svg)](action.yml)
8
+
9
+ ![A Robin review on a pull request — summary, severity-tiered findings, and a teammate-style note](docs/assets/robin-review.png)
10
+
11
+ ## What you get
12
+
13
+ - A review when you open a pull request (or when someone comments `/robin`)
14
+ - A short summary plus inline comments on changed lines
15
+ - Your choice of AI provider — including **free** options
16
+
17
+ When there's nothing worth flagging, Robin says so instead of inventing nitpicks:
18
+
19
+ ![A clean Robin pass on a pull request — no issues found](docs/assets/robin-review-clean.png)
20
+
21
+ You are **not** signing up for a separate review bot service. The workflow runs in your repo and calls the AI URL you configure.
22
+
23
+ ## For AI coding agents
24
+
25
+ Using Cursor, Copilot, Claude Code, or similar? Copy this prompt after secrets are set:
26
+
27
+ ```text
28
+ Add Robin to this repository.
29
+ - Workflow file: .github/workflows/robin.yml
30
+ - Reusable workflow: antongulin/robin/.github/workflows/review.yml@main
31
+ - Action ref if needed: antongulin/robin@main
32
+ - Secrets: LLM_API_KEY, LLM_BASE_URL, LLM_MODEL
33
+ - Do NOT use @v0 or any v0 tag
34
+ - Do NOT use pull_request_target or synchronize on pull_request
35
+ Read AGENTS.md in the robin repo for full rules.
36
+ ```
37
+
38
+ ## Quick install
39
+
40
+ In a terminal, from your project folder, run either:
41
+
42
+ ```bash
43
+ npx robin-review
44
+ ```
45
+
46
+ or, without Node.js:
47
+
48
+ ```bash
49
+ curl -fsSL https://robinreview.dev/install.sh | bash
50
+ ```
51
+
52
+ Either one creates `.github/workflows/robin.yml` for you (it never overwrites an existing
53
+ file) and installs the [companion chat skill](#robin-in-your-editor) into your coding agents.
54
+ You still need to add the three secrets — do **Steps 1 and 2** below, then commit and push.
55
+ You can **skip Step 3**: the installer already did it.
56
+
57
+ **Auto-updates:** the generated workflow references `antongulin/robin@main`, so every
58
+ review runs the latest Robin automatically — nothing to bump or re-install. Prefer fixed
59
+ versions? Pin a tag with `ROBIN_REF=v2 npx robin-review` (see [Version pins](#version-pins)).
60
+
61
+ Prefer to do it by hand, or read the installer first? It's
62
+ [bin/robin-review.js](bin/robin-review.js) (npm) / [scripts/install.sh](scripts/install.sh)
63
+ (curl) — or follow the manual 3 steps instead.
64
+
65
+ ## Setup in 3 steps
66
+
67
+ ### Step 1 — Get an API key (free option)
68
+
69
+ The easiest free setup uses [OpenRouter](https://openrouter.ai/):
70
+
71
+ 1. Create an account at [openrouter.ai](https://openrouter.ai/).
72
+ 2. Create an API key in the dashboard.
73
+ 3. Use these values for your GitHub secrets:
74
+
75
+ | Secret name | Value |
76
+ | --- | --- |
77
+ | `LLM_API_KEY` | Your OpenRouter key (`sk-or-...`) |
78
+ | `LLM_BASE_URL` | `https://openrouter.ai/api/v1` |
79
+ | `LLM_MODEL` | `openrouter/free` |
80
+
81
+ > [!TIP]
82
+ > `openrouter/free` picks a free model for each review — **$0 from OpenRouter**. OpenRouter rotates which model runs; **leave this secret as `openrouter/free`** — the action retries and uses provider fallbacks when a route is temporarily unavailable. You only spend [GitHub Actions](https://docs.github.com/en/billing/concepts/product-billing/github-actions) minutes while the job runs (often a few minutes per review).
83
+ >
84
+ > GitHub Free includes about **2,000 Actions minutes/month** (public and private repos); [GitHub Pro](https://docs.github.com/en/billing/concepts/product-billing/github-actions) includes about **3,000 minutes/month** (check your plan for current limits). Reviews usually take a few minutes each.
85
+
86
+ Other providers (OpenAI, Groq, Ollama, etc.) work too. See [Supported providers](#supported-providers) or [docs/ADVANCED.md](docs/ADVANCED.md).
87
+
88
+ ### Step 2 — Add secrets on GitHub
89
+
90
+ 1. Open **your** repository on GitHub (not this one).
91
+ 2. Go to **Settings** → **Secrets and variables** → **Actions**.
92
+ 3. Click **New repository secret** and add each name from the table above.
93
+
94
+ > [!WARNING]
95
+ > Never put API keys inside workflow files, pull request comments, or chat with an AI. Only use GitHub Secrets.
96
+
97
+ ### Step 3 — Add the workflow file
98
+
99
+ > [!NOTE]
100
+ > **Ran the Quick install one-liner above?** Skip this step — the script already created
101
+ > this file. Just finish Steps 1 and 2 (the secrets), then commit and push.
102
+
103
+ Create a new file in your repo:
104
+
105
+ **Path:** `.github/workflows/robin.yml`
106
+
107
+ **Contents:** copy this exactly:
108
+
109
+ ```yaml
110
+ name: Robin
111
+
112
+ on:
113
+ pull_request:
114
+ types: [opened, reopened, ready_for_review]
115
+ issue_comment:
116
+ types: [created]
117
+
118
+ permissions:
119
+ contents: read
120
+ pull-requests: write
121
+
122
+ jobs:
123
+ review:
124
+ uses: antongulin/robin/.github/workflows/review.yml@main
125
+ secrets:
126
+ LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
127
+ LLM_BASE_URL: ${{ secrets.LLM_BASE_URL }}
128
+ LLM_MODEL: ${{ secrets.LLM_MODEL }}
129
+ ```
130
+
131
+ Commit and push. Open a pull request — you should see a review within a few minutes.
132
+
133
+ > [!IMPORTANT]
134
+ > Use **`@main`** for the latest fixes, or pin a release tag (for example `@v1` or `@v1.0.0`) after [releases](https://github.com/antongulin/robin/releases) exist. Do **not** use `@v0`. See [Version pins](#version-pins) below.
135
+
136
+ ## Running on a self-hosted runner
137
+
138
+ By default, the reusable workflow runs on GitHub's hosted `ubuntu-latest` runner:
139
+
140
+ ```yaml
141
+ with:
142
+ runner: '"ubuntu-latest"'
143
+ ```
144
+
145
+ To run reviews on your own machine, Mac mini, home server, local Linux box, or Coolify runner, pass `runner` as valid JSON. Use a JSON string for one label or a JSON array for multiple labels.
146
+
147
+ To create a local runner, go to:
148
+
149
+ ```text
150
+ Repository Settings -> Actions -> Runners -> New self-hosted runner
151
+ ```
152
+
153
+ Then add labels such as `local`, `linux`, `mac`, or `coolify`, and reference those labels through the `runner` input.
154
+
155
+ ### Does the runner need to run all the time?
156
+
157
+ A matching self-hosted runner must be online when GitHub starts the review job. It can be a local runner process (`./run.sh`), a service (`./svc.sh start`), a Docker container, or a Coolify-managed service. Docker is optional; it is just one way to run the GitHub Actions runner.
158
+
159
+ If no matching runner is online, GitHub queues the job until one comes online. It will not fall back to `ubuntu-latest` unless you add a separate fallback job. For reliable PR reviews, keep an always-on runner available, such as a Mac mini, home server, VPS, or Coolify service. A laptop runner only works while the laptop is awake and the runner process or service is running.
160
+
161
+ > [!WARNING]
162
+ > Self-hosted runners can execute arbitrary workflow code.
163
+ > Do not use them for untrusted public pull requests.
164
+ > Prefer repo-owned private repos or trusted collaborators only.
165
+ > Consider ephemeral runners for stronger isolation.
166
+
167
+ Local machine runner:
168
+
169
+ ```yaml
170
+ jobs:
171
+ review:
172
+ uses: antongulin/robin/.github/workflows/review.yml@main
173
+ with:
174
+ runner: '["self-hosted", "local"]'
175
+ secrets:
176
+ LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
177
+ LLM_BASE_URL: ${{ secrets.LLM_BASE_URL }}
178
+ LLM_MODEL: ${{ secrets.LLM_MODEL }}
179
+ ```
180
+
181
+ Coolify runner:
182
+
183
+ ```yaml
184
+ jobs:
185
+ review:
186
+ uses: antongulin/robin/.github/workflows/review.yml@main
187
+ with:
188
+ runner: '["self-hosted", "linux", "coolify"]'
189
+ secrets:
190
+ LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
191
+ LLM_BASE_URL: ${{ secrets.LLM_BASE_URL }}
192
+ LLM_MODEL: ${{ secrets.LLM_MODEL }}
193
+ ```
194
+
195
+ ## Using it day to day
196
+
197
+ | When | What happens |
198
+ | --- | --- |
199
+ | You open a PR | Review runs once automatically |
200
+ | You push more commits | No new review (saves time and API usage) |
201
+ | You want another review | Comment `/robin` on the PR (first line of the comment) |
202
+ | You want a short overview only | Comment `/summary` |
203
+ | You need help | Comment `/help` |
204
+
205
+ `/review` still works as an alias for `/robin`. Only people with **write** access (or higher) on the repo can run these commands by default.
206
+
207
+ ## Example
208
+
209
+ The bot posts a status comment, then a review with severity counts:
210
+
211
+ ```md
212
+ ## 🏹 Robin
213
+
214
+ 🚨 **1 High** | ⚠️ **1 Medium** | 💡 **2 Suggestions**
215
+
216
+ ### Summary
217
+ Focused change. Main risk: timeout errors are not handled clearly.
218
+
219
+ ### Findings Not Posted Inline
220
+ **1 (`src/example.ts:24`)** — Retries exist but timeout failures lack context.
221
+ ```
222
+
223
+ ## Robin in your editor
224
+
225
+ The one-line installer also installs a small **companion skill** into every coding agent
226
+ on your machine (Claude Code, Cursor, Copilot, Windsurf, …) via the cross-platform
227
+ [skills CLI](https://skills.sh) — `npx skills add https://github.com/antongulin/robin --all --global`. It
228
+ ships with Robin; there's nothing separate to sign up for. (Skip it with `ROBIN_SKILL=0`,
229
+ or install it by hand with that command.) Once it's there, you can say things like:
230
+
231
+ > "review this PR with Robin" · "robin this PR" · "fix the Robin feedback and merge"
232
+
233
+ …and the agent drives a bounded review → fix → re-review → merge loop: it waits for
234
+ Robin's review, fixes only the findings it can verify (skipping noise from weaker free
235
+ models), replies to each comment, resolves threads, and merges when green — capped at
236
+ five passes. Source: [skills/robin/SKILL.md](skills/robin/SKILL.md).
237
+
238
+ ## Supported providers
239
+
240
+ | Provider | `LLM_BASE_URL` | `LLM_MODEL` example |
241
+ | --- | --- | --- |
242
+ | **OpenRouter (free)** | `https://openrouter.ai/api/v1` | `openrouter/free` |
243
+ | OpenAI | `https://api.openai.com/v1` | `gpt-4o` |
244
+ | Groq | `https://api.groq.com/openai/v1` | `llama-3.3-70b-versatile` |
245
+ | Ollama (your server) | `http://YOUR_SERVER:11434/v1` | `llama3.2` |
246
+
247
+ GitHub’s servers cannot reach `localhost` on your laptop. For Ollama at home, use a public server, a tunnel, or a [self-hosted runner](docs/ADVANCED.md#save-github-actions-minutes).
248
+
249
+ ## Optional: config and custom rules
250
+
251
+ Copy [`.github/robin.yml.example`](.github/robin.yml.example) to `.github/robin.yml` to set `max-diff-size`, skip extra paths, and more. Details: [docs/ADVANCED.md](docs/ADVANCED.md#repository-config-file).
252
+
253
+ Add `.github/code-reviewer.md` in your repo:
254
+
255
+ ```md
256
+ # Reviewer rules
257
+
258
+ - Focus on bugs and security, not formatting.
259
+ - Ask for tests when business logic changes.
260
+ ```
261
+
262
+ ## Something went wrong?
263
+
264
+ | Problem | What to try |
265
+ | --- | --- |
266
+ | Workflow fails immediately | Check all three secrets exist and the workflow uses `@main` |
267
+ | `Input required: model` or `llm-base-url` | Add missing secrets (Step 2) |
268
+ | Review never appears | Open **Actions** tab → open the failed run → read the error |
269
+ | `/robin` does nothing | Put `/robin` on the **first** line; you need write access on the repo. On `@v1`, pin `@v1.4.0`+ or use `/review` if the tag predates v1.4.0 |
270
+ | Review is very short | PR may be huge — see [docs/ADVANCED.md](docs/ADVANCED.md) (`max-diff-size`) |
271
+ | `Empty response from LLM` | Free routers sometimes return no text — the action retries automatically; comment `/robin` again |
272
+ | `OpenRouter stall` / job runs 15 min with no review | Auto-router hung — action now aborts after 45s with no stream and retries | Watch Actions log for `LLM resolved model` (routing OK); pin `@v2` or `@main` for the fix |
273
+ | `404 Provider returned error` | Normal for `openrouter/free` when one provider is down — the action retries up to 5 times; keep `LLM_MODEL=openrouter/free` |
274
+
275
+ More fixes: [docs/ADVANCED.md#troubleshooting](docs/ADVANCED.md#troubleshooting)
276
+
277
+ ## Version pins
278
+
279
+ | Pin | When to use |
280
+ | --- | --- |
281
+ | `@main` | Latest changes on the default branch |
282
+ | `@v1` | Latest `1.x` release (updated on each release) |
283
+ | `@v1.0.0` | Exact version (most predictable) |
284
+ | Full commit SHA | Maximum supply-chain safety |
285
+
286
+ ```yaml
287
+ uses: antongulin/robin/.github/workflows/review.yml@v1
288
+ ```
289
+
290
+ Releases and notes are published automatically from [CHANGELOG.md](CHANGELOG.md) when changes land on `main`. See [CONTRIBUTING.md](CONTRIBUTING.md) for commit message format.
291
+
292
+ ## Learn more
293
+
294
+ - [docs/ADVANCED.md](docs/ADVANCED.md) — all settings, strict mode, manual-only reviews, security notes
295
+ - [CONTRIBUTING.md](CONTRIBUTING.md) — run tests and send pull requests
296
+ - [CHANGELOG.md](CHANGELOG.md) — release history
297
+
298
+ ## Support
299
+
300
+ Robin is free and open source (MIT). If it saves you money on code review, you can help keep it maintained:
301
+
302
+ - ⭐ Star the repo — it's the cheapest way to help others find it.
303
+ - 💛 [Sponsor the project](https://github.com/sponsors/antongulin) to support ongoing work.
304
+ - 🐛 [Open an issue](https://github.com/antongulin/robin/issues) for bugs or ideas.
305
+
306
+ Built by [Anton Gulin](https://github.com/antongulin), AI Architect building AI systems, agent workflows, and software automation. Need a custom AI agent, code-review pipeline, or QA automation? Visit [Anton.QA](https://www.anton.qa).
307
+
308
+ ## Development
309
+
310
+ ```bash
311
+ git clone https://github.com/antongulin/robin.git
312
+ cd robin
313
+ npm ci
314
+ npm run lint
315
+ npm test
316
+ npm run build
317
+ ```
318
+
319
+ Runtime code lives in `dist/index.js`; run `npm run build` before releasing. A full build removes intermediate files under `dist/` after bundling so only `index.js` remains locally (same file CI checks against).
320
+
321
+ If you ran `tsc` alone and see extra files under `dist/`, run `npm run clean`.
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * npx robin-review — adds the Robin code-review workflow to the current repo.
4
+ * Node port of scripts/install.sh, so it works anywhere npx does (incl. Windows).
5
+ *
6
+ * Writes one file (.github/workflows/robin.yml), never overwrites an existing
7
+ * one, then best-effort installs the Robin companion skill for coding agents.
8
+ * Env overrides: ROBIN_REF=v1 (action ref), ROBIN_SKILL=0 (skip skill install).
9
+ */
10
+ const fs = require("fs");
11
+ const path = require("path");
12
+ const cp = require("child_process");
13
+
14
+ const info = (msg) => console.log("\x1b[0;32m🏹 " + msg + "\x1b[0m");
15
+ const warn = (msg) => console.log("\x1b[0;33m🏹 " + msg + "\x1b[0m");
16
+ const die = (msg) => {
17
+ console.error("\x1b[0;31m🏹 " + msg + "\x1b[0m");
18
+ process.exit(1);
19
+ };
20
+
21
+ const ref = process.env.ROBIN_REF || "main";
22
+ if (!/^[A-Za-z0-9._/-]{1,100}$/.test(ref)) die("Invalid ROBIN_REF: " + JSON.stringify(ref));
23
+
24
+ let root;
25
+ try {
26
+ root = cp
27
+ .execSync("git rev-parse --show-toplevel", { stdio: ["ignore", "pipe", "ignore"] })
28
+ .toString()
29
+ .trim();
30
+ } catch {
31
+ die("Not a git repository. cd into your repo and run again.");
32
+ }
33
+
34
+ const workflowPath = path.join(root, ".github", "workflows", "robin.yml");
35
+ const workflow = `name: Robin
36
+
37
+ on:
38
+ pull_request:
39
+ types: [opened, reopened, ready_for_review]
40
+ issue_comment:
41
+ types: [created]
42
+
43
+ permissions:
44
+ contents: read
45
+ pull-requests: write
46
+
47
+ jobs:
48
+ review:
49
+ uses: antongulin/robin/.github/workflows/review.yml@${ref}
50
+ secrets:
51
+ LLM_API_KEY: \${{ secrets.LLM_API_KEY }}
52
+ LLM_BASE_URL: \${{ secrets.LLM_BASE_URL }}
53
+ LLM_MODEL: \${{ secrets.LLM_MODEL }}
54
+ `;
55
+
56
+ if (fs.existsSync(workflowPath)) {
57
+ warn(workflowPath + " already exists — leaving it untouched.");
58
+ } else {
59
+ fs.mkdirSync(path.dirname(workflowPath), { recursive: true });
60
+ fs.writeFileSync(workflowPath, workflow);
61
+ info("Created " + path.relative(root, workflowPath));
62
+ }
63
+
64
+ if (process.env.ROBIN_SKILL !== "0") {
65
+ info("Installing the Robin chat skill for coding agents…");
66
+ try {
67
+ cp.execSync(
68
+ 'npx -y skills add https://github.com/antongulin/robin --skill robin --agent "*" --global --yes',
69
+ { stdio: "ignore", timeout: 180000 }
70
+ );
71
+ info('Robin chat skill installed (all agents). Say "review with Robin".');
72
+ } catch {
73
+ warn(
74
+ "Couldn't auto-install the skill. Run: npx -y skills add https://github.com/antongulin/robin --skill robin --agent \"*\" --global --yes"
75
+ );
76
+ }
77
+ }
78
+
79
+ info("Next steps:");
80
+ console.log(`
81
+ 1. Add three repository secrets (Settings → Secrets and variables → Actions):
82
+ LLM_API_KEY — e.g. your OpenRouter key (sk-or-…)
83
+ LLM_BASE_URL — e.g. https://openrouter.ai/api/v1
84
+ LLM_MODEL — e.g. openrouter/free
85
+ 2. Commit and push .github/workflows/robin.yml
86
+ 3. Open a PR — Robin reviews it automatically. Comment /robin to re-run.
87
+
88
+ Docs: https://github.com/antongulin/robin#readme
89
+ `);
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "robin-review",
3
+ "version": "2.4.1",
4
+ "description": "Free AI code reviews for every PR. BYOK, works with OpenRouter free tier.",
5
+ "bin": {
6
+ "robin-review": "bin/robin-review.js"
7
+ },
8
+ "files": [
9
+ "bin/"
10
+ ],
11
+ "engines": {
12
+ "node": ">=18"
13
+ },
14
+ "publishConfig": {
15
+ "access": "public"
16
+ },
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/antongulin/robin.git"
20
+ },
21
+ "bugs": {
22
+ "url": "https://github.com/antongulin/robin/issues"
23
+ },
24
+ "homepage": "https://github.com/antongulin/robin#readme",
25
+ "scripts": {
26
+ "build": "tsc && ncc build dist/index.js -o dist && npm run clean",
27
+ "clean": "node scripts/clean-dist.js",
28
+ "dev": "ts-node src/main.ts",
29
+ "lint": "eslint src/**/*.ts",
30
+ "test": "jest",
31
+ "package": "ncc build dist/index.js -o dist --license licenses.txt && npm run clean"
32
+ },
33
+ "keywords": [
34
+ "github-action",
35
+ "code-review",
36
+ "llm",
37
+ "ai",
38
+ "openai",
39
+ "ollama",
40
+ "self-hosted"
41
+ ],
42
+ "author": "antongulin",
43
+ "license": "MIT",
44
+ "dependencies": {
45
+ "@actions/core": "^1.10.1",
46
+ "@actions/github": "^6.0.0",
47
+ "@octokit/rest": "^20.0.2",
48
+ "openai": "^4.28.4"
49
+ },
50
+ "overrides": {
51
+ "undici": "^7.25.0"
52
+ },
53
+ "devDependencies": {
54
+ "@types/jest": "^29.5.12",
55
+ "@types/node": "^20.11.19",
56
+ "@typescript-eslint/eslint-plugin": "^7.0.2",
57
+ "@typescript-eslint/parser": "^7.0.2",
58
+ "@vercel/ncc": "^0.38.1",
59
+ "eslint": "^8.56.0",
60
+ "jest": "^29.7.0",
61
+ "ts-jest": "^29.1.2",
62
+ "ts-node": "^10.9.2",
63
+ "typescript": "^5.3.3"
64
+ }
65
+ }