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 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