The tool that made me curious
This week, Alibaba open-sourced open-code-review (CLI name ocr). It climbed to #1 on GitHub Trending with +15,028 stars in a week. Apache-2.0, Go binary, and — here is the part that caught my attention — it ships a built-in provider named dashscope whose base URL is DashScope's OpenAI-compatible endpoint, with Qwen models pre-listed.
No custom provider file to write. No YAML to assemble. Pick a provider, pick a model, and it works.
So I set up a single-variable experiment: one buggy file, seven Qwen tiers, and a real cost table. Not a per-million-token sticker price — the actual bill for one review.
What the tool does
ocr reads your code through tool calling (function calling). The model must natively support it; the project FAQ explicitly names qwen3 as working. Models that merely narrate tool calls in text output cannot drive it, regardless of how clever the prompt is.
It has four modes:
ocr review # review staged/unstaged/untracked changes
ocr review --from main --to feature-branch # review a branch range
ocr review --commit abc123 # review a single commit
ocr scan --path some/dir # full-file scan, no git history needed
The setup
Three things to know before you run it:
DASHSCOPE_API_KEYalone is not enough. The resolver wants the full tuple of (URL, key, model). The env var supplies only the key. You still needocr config set provider dashscopeandocr config set model <name>.The provider is built-in.
internal/llm/providers.goin the repo definesdashscopewith base URLhttps://dashscope.aliyuncs.com/compatible-mode/v1and a model list that starts with five Qwen models. No need to register a custom provider.Region matters. API keys are region-bound. A Beijing key against a Virginia endpoint returns 401. If you migrated to a workspace domain, override the URL with
ocr config set providers.dashscope.url https://<WorkspaceId>.cn-beijing.maas.aliyuncs.com/compatible-mode/v1.
The shortest path to a working setup:
npm install -g @alibaba-group/open-code-review
ocr config set provider dashscope
ocr config set model qwen3.8-max
ocr config set providers.dashscope.api_key sk-your-key
ocr llm test
Create an API key in the Bailian console before the fourth command.
The experiment
One 64-line Python order service with four planted defects:
- A
fetchone()result used without a null check (crashes on missing user) - An f-string interpolated into SQL (textbook injection)
- A counter
+= 1without lock acquisition (concurrency bug) - An
open()withoutwith(handle leak)
Plus two decoys: an @lru_cache on a pure function (correct usage) and a redundant except Exception: raise (harmless, and the bare raise correctly preserves the traceback).
Same prompt, byte-identical input, seven Qwen tiers. Token counts from the API's own usage block. Unit prices from bl model list --model <name> --output json, a command that needs no account and no auth, so every price is checkable.
Prices are in CNY.
The table
| Model | Thinking tokens | Found /4 | Missed | False + | Score | Wall time | In tok | Out tok | Cost per review |
|---|---|---|---|---|---|---|---|---|---|
| qwen-turbo | none | 2 | 2 | 4 | -2.0 | 7.4s | 468 | 1,005 | ¥0.0007 |
| qwen3-coder-plus | none | 3 | 1 | 1 | 2.0 | 10.1s | 464 | 712 | tiered / see console |
| qwen-plus | none | 2 | 1 | 1 | 1.5 | 39.3s | 464 | 1,766 | ¥0.0039 |
| qwen3.7-plus | 1,182 | 4 | 0 | 0 | 4.0 | 23.4s | 502 | 2,052 | not published / see console |
| qwen3.6-flash | 4,258 | 4 | 0 | 1 | 3.0 | 42.6s | 502 | 5,075 | not published / see console |
| qwen3.8-flash | 9,517 | 4 | 0 | 0 | 4.0 | 241.0s | 540 | 12,909 | ¥0.0353 |
| qwen3.8-max | 9,770 | 4 | 0 | 0 | 4.0 | 293.1s | 540 | 11,064 | ¥0.4048 |
One run per configuration. Score is found minus false positives, out of 4. Three cells say "see console": qwen3-coder is officially tiered-priced, and qwen3.7-plus / qwen3.6-flash return no unit price from the lookup command. I do not fill gaps with guesses.
Three things I did not expect
The flagship bought nothing on this file. qwen3.7-plus scored 4.0 in 23.4 seconds. qwen3.8-max also scored 4.0, in 293.1 seconds. The extra 8,588 thinking tokens and 270 seconds bought three genuine findings I had not planted (including that amount <= 0 does not reject float('nan')), but no extra points.
The divider is thinking, not price. Three tiers that did not think all missed at least one bug. Five that thought missed nothing. Past roughly 1,200 thinking tokens the score stops moving.
Line numbers are only trustworthy on thinking tiers. turbo was 0 of 9 correct, plus 0 of 4. qwen3.7-plus and above were accurate to within one line. Treat a non-thinking tier's output as a lead list and find the code yourself.
One observation worth noting: qwen-plus missed the null deref, qwen3-coder-plus missed the race condition. Their blind spots did not overlap. Running both cross-reads the gaps, at the cost of stacked false positives and a human in the loop. Seven configurations measured once each — this is an observation, not a rule.
Unit price versus unit cost
qwen-turbo costs ¥0.3 per million input tokens. qwen3.8-max costs ¥12. That is 40x on the pricing page. Per review, turbo spent ¥0.0007 and max spent ¥0.4048, which is 545x, because the expensive run wrote eleven thousand output tokens and most of them were reasoning.
Budget from the pricing page and your invoice will not agree. Budget from a real review.
What I would pick
| Scenario | Tier | Per review | Reviews per ¥1 |
|---|---|---|---|
| Coarse sieve on every commit, you read the code anyway | qwen-turbo | ¥0.0007 | ≈1,345 |
| Cheap pass with a published price | qwen-plus | ¥0.0039 | ≈256 |
| Default PR gate, line numbers you can jump to | qwen3.7-plus | ≤¥0.0799 (bound) | price unpublished |
| Hard diff, deep reasoning | qwen3.8-flash | ¥0.0353 | ≈28 |
| The gnarliest file in the repo | qwen3.8-max | ¥0.4048 | ≈2 |
The ¥0.0799 is a bound, not an estimate: priced at flagship rates, that run's tokens come to ¥0.0799, one fifth of the flagship's ¥0.4048, and its real price cannot be higher. For tiers with no published price, check the console model pages rather than any reposted number.
Recalculate it yourself
from decimal import Decimal, ROUND_HALF_UP
def cost(in_tok, out_tok, price_in, price_out):
"""prices in CNY per million tokens"""
c = (Decimal(in_tok) * Decimal(price_in) + Decimal(out_tok) * Decimal(price_out)) / Decimal(1000000)
return c.quantize(Decimal("0.0001"), rounding=ROUND_HALF_UP)
print(cost(540, 11064, "12", "36")) # 0.4048: qwen3.8-max, one review
Use Decimal with ROUND_HALF_UP, because Python's round() does banker's rounding and your invoice will not explain the gap.
Boundaries and honest limits
A community member reported 1,400 PRs taking over ten hours. A few-line PR still takes minutes. This is not a pre-commit tool. It does not replace SAST: a rules engine reports deterministic pattern hits, while ocr reports what a model understood about your code. And if your team already pays for a hosted review product that works, this is not a pitch to switch.
Sample size is one file, four bugs, one run per configuration. I ran two of the models twice and their scores moved. Read every number above as "this run", not as a benchmark.
The new-user free quota is per model and independent (typically 1M tokens each), valid for 90 days, Beijing region only, with no reissue after expiry and no automatic failover to another model when it runs out. Create the key here. Install the Bailian CLI to look up prices on your own machine with no account required.


Top comments (0)