external-review 1.0.0
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 +21 -0
- package/README.md +311 -0
- package/bin/external-review.mjs +582 -0
- package/docs/PLAYBOOK.md +234 -0
- package/docs/PRIVACY.md +182 -0
- package/examples/prompts/data-integrity.txt +49 -0
- package/examples/prompts/second-opinion.txt +41 -0
- package/examples/prompts/user-journey.txt +47 -0
- package/package.json +44 -0
- package/skills/external-review/SKILL.md +198 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Yev Gavrikov
|
|
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,311 @@
|
|
|
1
|
+
# external-review
|
|
2
|
+
|
|
3
|
+
**Review your code with a second, independent model — and know what it costs,
|
|
4
|
+
where your source goes, and which findings to believe.**
|
|
5
|
+
|
|
6
|
+
A Claude Code skill plus a small CLI. No dependencies.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Why bother
|
|
11
|
+
|
|
12
|
+
Your assistant reviews its own work with the assumptions that produced it. A
|
|
13
|
+
model from a different lineage does not share them, so it sees defects yours
|
|
14
|
+
walks past — not because it is smarter.
|
|
15
|
+
|
|
16
|
+
In one day of use on a production mobile app, a second model found around forty
|
|
17
|
+
real defects that four in-house review passes had missed. Two were severe data
|
|
18
|
+
loss, and both are shapes you will recognise:
|
|
19
|
+
|
|
20
|
+
- **Reconnecting a device re-ran a one-time calibration**, silently erasing
|
|
21
|
+
every unit of usage recorded while it was disconnected. The sync path had
|
|
22
|
+
guarded against exactly this for months. The link path never did.
|
|
23
|
+
- **A single mistyped value in stored JSON deleted an entire record** — `1`
|
|
24
|
+
where a boolean was expected — taking its children, its history and its
|
|
25
|
+
attachments with it. The next autosave made it permanent. Seventeen fields
|
|
26
|
+
had the same shape.
|
|
27
|
+
|
|
28
|
+
Both had one signature, and it is the thing this skill teaches you to hunt:
|
|
29
|
+
|
|
30
|
+
> **The codebase already argued the correct rule somewhere else, and had not
|
|
31
|
+
> applied it here.**
|
|
32
|
+
|
|
33
|
+
That reframing is most of the value. It turns "look for bugs" — a search over
|
|
34
|
+
infinite possibilities — into a search over the codebase's own documented
|
|
35
|
+
intentions, which is finite and enumerable.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Install
|
|
40
|
+
|
|
41
|
+
### The CLI
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npm install -g external-review
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Or run it without installing:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npx external-review doctor
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### The skill
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
external-review install-skill # this project
|
|
57
|
+
external-review install-skill --global # every project
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Then ask your assistant to *"review this with a second model"* and it will pick
|
|
61
|
+
the skill up.
|
|
62
|
+
|
|
63
|
+
(It is a command rather than a `cp` because the source path differs between a
|
|
64
|
+
global install, a local one and a git clone. It refuses to overwrite an existing
|
|
65
|
+
skill unless you pass `--force`.)
|
|
66
|
+
|
|
67
|
+
### A model provider
|
|
68
|
+
|
|
69
|
+
The CLI talks to [OpenRouter](https://openrouter.ai), which fronts most models
|
|
70
|
+
behind one key and one API.
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
export OPENROUTER_API_KEY=sk-or-v1-...
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
It also reads the key from [opencode](https://opencode.ai)'s auth store if you
|
|
77
|
+
already use that, so `opencode auth login` is enough.
|
|
78
|
+
|
|
79
|
+
You need a **runner** — something that can drive a model against a directory of
|
|
80
|
+
code. `opencode` is what this was built against:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
npm install -g opencode-ai
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Use it
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
external-review doctor
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
external-review doctor
|
|
96
|
+
|
|
97
|
+
ok API key found sk-or-v1…a037
|
|
98
|
+
ok a runner is installed /Users/you/.opencode/bin/opencode
|
|
99
|
+
ok rsync available
|
|
100
|
+
ok ssh available
|
|
101
|
+
ok key reachable (free tier) spent today: $0.0000
|
|
102
|
+
|
|
103
|
+
Ready.
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 1. Know your budget before you scope the work
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
external-review quota
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
Account
|
|
114
|
+
|
|
115
|
+
tier free
|
|
116
|
+
spent today $0.0000
|
|
117
|
+
spent this month $0.0000
|
|
118
|
+
credit limit none set
|
|
119
|
+
|
|
120
|
+
Free-model request cap
|
|
121
|
+
OpenRouter limits :free models to 50 requests/day, raised to 1000/day
|
|
122
|
+
once the account has purchased 10 credits at any point. That cap is not
|
|
123
|
+
exposed by the API, so it is not shown above — but it is what usually
|
|
124
|
+
stops a long review.
|
|
125
|
+
|
|
126
|
+
A whole-subsystem review is 40-150 requests. On the free tier that is
|
|
127
|
+
ONE pass, maybe two. Add credits, or use stealth models, or expect to
|
|
128
|
+
plan a day at a time.
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
This matters more than it sounds. Runs die **partway**, having read your code
|
|
132
|
+
and reported nothing, and the reason appears only in stderr.
|
|
133
|
+
|
|
134
|
+
There are **two separate pools**, which is why a day can run far past 50
|
|
135
|
+
requests and then stop abruptly:
|
|
136
|
+
|
|
137
|
+
| | pool | cap |
|
|
138
|
+
|---|---|---|
|
|
139
|
+
| `:free` models | `free-models-per-day` | 50/day, or 1000/day once you have ever bought 10 credits. 20/min either way. |
|
|
140
|
+
| stealth / cloaked | `free-models-per-day-stealth` | separate, much larger |
|
|
141
|
+
|
|
142
|
+
Both reset on the UTC day. The `:free` counter is account-wide, so switching
|
|
143
|
+
free models buys nothing — switching to a *stealth* model does.
|
|
144
|
+
|
|
145
|
+
### 2. Pick a model
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
external-review models --free
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
20 model(s) with ≥60k context, free only
|
|
153
|
+
|
|
154
|
+
context price / 1M tokens id
|
|
155
|
+
1049k free in / free out minimax/minimax-m3:free
|
|
156
|
+
1000k free in / free out nvidia/nemotron-3-ultra-550b-a55b:free
|
|
157
|
+
512k free in / free out dots-studio/dots-3-note-preview:free
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Ranked by **context window**, deliberately. A model that cannot hold the
|
|
161
|
+
subsystem cannot review it. Then reasoning quality; price last, because review
|
|
162
|
+
reads a lot and writes a little.
|
|
163
|
+
|
|
164
|
+
### 3. Decide where your code is allowed to go
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
external-review providers nvidia/nemotron-3-ultra-550b-a55b
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
```
|
|
171
|
+
NVIDIA: Nemotron 3 Ultra
|
|
172
|
+
|
|
173
|
+
Your prompt is sent to ONE of these, chosen per request.
|
|
174
|
+
|
|
175
|
+
DeepInfra
|
|
176
|
+
headquarters US
|
|
177
|
+
datacenters not published
|
|
178
|
+
privacy https://deepinfra.com/privacy
|
|
179
|
+
terms https://deepinfra.com/terms
|
|
180
|
+
|
|
181
|
+
Together
|
|
182
|
+
headquarters US
|
|
183
|
+
...
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
**This is the honest answer to "is it safe to send my code to a model I have
|
|
187
|
+
never heard of".** Not reassurance — facts. Who operates the machine, where
|
|
188
|
+
they are based, where they publish their datacenters, and a link to the policy
|
|
189
|
+
you would actually be agreeing to.
|
|
190
|
+
|
|
191
|
+
Note what the question actually turns on. **Who trained a model and who serves
|
|
192
|
+
it are different companies.** A model may be trained by one organisation and
|
|
193
|
+
run by four unrelated providers, any of which may take your request — and it is
|
|
194
|
+
the *operator* who sees your prompt. So "is this model from a country I trust"
|
|
195
|
+
is the wrong question; "what is this endpoint permitted to do with my code" is
|
|
196
|
+
the right one, and it is the one this command answers.
|
|
197
|
+
|
|
198
|
+
For a **free** model it adds the part people miss. OpenRouter will not route to
|
|
199
|
+
free endpoints at all unless your account has enabled *"free endpoints that may
|
|
200
|
+
train on inputs"* and *"free endpoints that may publish prompts"* — so if free
|
|
201
|
+
models work for you, those are on, and **the code you send may be trained on and
|
|
202
|
+
published.** That is the trade, and it is a reasonable one for open source. It
|
|
203
|
+
is not reasonable for code under an NDA.
|
|
204
|
+
|
|
205
|
+
For a **stealth** model — an unreleased model shipped anonymously to gather
|
|
206
|
+
usage — it tells you that no provider is published at all:
|
|
207
|
+
|
|
208
|
+
```
|
|
209
|
+
Ox Alpha
|
|
210
|
+
|
|
211
|
+
This model does not disclose its providers.
|
|
212
|
+
|
|
213
|
+
So the questions this command exists to answer — who operates it, from
|
|
214
|
+
where, under which policy — have no available answer. What IS known is
|
|
215
|
+
the arrangement: these models are offered free because prompts and
|
|
216
|
+
completions are logged and used to improve them. That is their purpose,
|
|
217
|
+
not a side effect.
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
The remedy, when you need one, is **Zero Data Retention**: an account toggle, a
|
|
221
|
+
per-key guardrail, or `"zdr": true` per request. It blocks storage and training
|
|
222
|
+
— and removes most free endpoints, which is the same trade seen from the other
|
|
223
|
+
side. [`docs/PRIVACY.md`](docs/PRIVACY.md) has the decision table.
|
|
224
|
+
|
|
225
|
+
### 4. Run a pass
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
external-review run --prompt ./examples/prompts/data-integrity.txt \
|
|
229
|
+
--model nvidia/nemotron-3-ultra-550b-a55b:free \
|
|
230
|
+
--out findings.md
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Reviewing on a VM or VPS? Recommended — but for narrower reasons than usual.
|
|
234
|
+
It does **not** change what the model sees; the prompt is identical either way.
|
|
235
|
+
What it does is contain the *runner*: a third-party binary running an agentic
|
|
236
|
+
loop with filesystem access, which on your laptop sits next to `~/.ssh`, your
|
|
237
|
+
cloud credentials and every other client's repo. On a throwaway box it sits next
|
|
238
|
+
to one dated copy of one project. [`docs/PRIVACY.md`](docs/PRIVACY.md) has the
|
|
239
|
+
full argument and a setup checklist.
|
|
240
|
+
|
|
241
|
+
Sync first — scanned, secrets excluded, then **verified absent**:
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
external-review sync --to you@review-box:~/review-2026-08-26 \
|
|
245
|
+
--exclude 'config/production.json'
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
```
|
|
249
|
+
verified: no excluded path is present in the copy
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
The verification is the point. An exclusion pattern that silently failed to
|
|
253
|
+
match is the entire risk, so the command checks the copy over SSH rather than
|
|
254
|
+
trusting rsync's exit code.
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## The part people skip, and shouldn't
|
|
259
|
+
|
|
260
|
+
**A finding is a claim, not a fact.** Reproduce before fixing.
|
|
261
|
+
|
|
262
|
+
Then, having fixed it and written a regression test, **revert the fix and
|
|
263
|
+
confirm the test fails.** There are four ways that check silently lies — all
|
|
264
|
+
observed in practice, all documented in
|
|
265
|
+
[`docs/PLAYBOOK.md`](docs/PLAYBOOK.md):
|
|
266
|
+
|
|
267
|
+
1. the revert did not apply (scripted replace, no assertion, silent no-op);
|
|
268
|
+
2. it applied in the wrong place;
|
|
269
|
+
3. the run failed on a compile error, not your assertion;
|
|
270
|
+
4. the test never reached the defect at all.
|
|
271
|
+
|
|
272
|
+
And check your *existing* fixtures do not pin the bug as correct. A "corrupt
|
|
273
|
+
record" fixture that is really a recoverable record with one mistyped field
|
|
274
|
+
asserts that recoverable data gets deleted — green for months, in two separate
|
|
275
|
+
codebases.
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## Commands
|
|
280
|
+
|
|
281
|
+
| | |
|
|
282
|
+
|---|---|
|
|
283
|
+
| `install-skill [--global]` | put the skill where your assistant will find it |
|
|
284
|
+
| `doctor` | check the setup, say what is missing |
|
|
285
|
+
| `quota` | spend so far, credit limit, free-tier cap |
|
|
286
|
+
| `models [--free] [--all] [--min-context N] [--limit N]` | candidates by context window |
|
|
287
|
+
| `providers <model-id>` | who serves it, HQ, datacenters, policy links |
|
|
288
|
+
| `scan [--in DIR]` | find credentials **inside** source files, which no filename exclusion catches |
|
|
289
|
+
| `sync --to HOST:DIR [--from DIR] [--exclude PATH]` | scan, refuse if anything is found, copy excluding secrets, then verify |
|
|
290
|
+
| `run --prompt FILE --model ID [--in DIR] [--out FILE]` | run a pass |
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## Docs
|
|
295
|
+
|
|
296
|
+
- **[`docs/PLAYBOOK.md`](docs/PLAYBOOK.md)** — the bug signature, prompt shapes
|
|
297
|
+
that worked, and every way a verification step can lie to you.
|
|
298
|
+
- **[`docs/PRIVACY.md`](docs/PRIVACY.md)** — what leaves your machine, what does
|
|
299
|
+
not, and how to decide.
|
|
300
|
+
- **[`examples/prompts/`](examples/prompts/)** — the actual prompts that found
|
|
301
|
+
the bugs above, ready to adapt.
|
|
302
|
+
|
|
303
|
+
## Contributing
|
|
304
|
+
|
|
305
|
+
Findings about the *process* are the most valuable contributions — a new way a
|
|
306
|
+
vacuity check can lie, a prompt shape that outperformed, a failure mode worth
|
|
307
|
+
warning about. Open an issue.
|
|
308
|
+
|
|
309
|
+
## License
|
|
310
|
+
|
|
311
|
+
MIT
|