clines 6.0 — the machine-readable release

15 August 2026 · covers 6.0.0

Until this release clines could only talk to a person. There was no --json, no --csv, nothing but formatted tables, three HTML files and a markdown block written into a README. Exactly one flag could fail a build (ctx --max), and nothing could compare a run against a git ref.

That is a strange shape for a tool whose most distinctive analysis measures what a codebase costs a language model to read. The consumers of that number are pipelines and coding agents, and neither can read a table. 6.0 fixes that.

--json on every command

Every command now takes --json and writes one document to stdout under a shared envelope, so a consumer parses first and dispatches second.

$ clines ctx --json | jq '.result.totalTokens'
3303084

Three decisions are worth naming. The output carries no timestamp, so two runs of the same tree diff cleanly and a CI baseline stays stable. --json implies --no-pager and every progress line already went to stderr, so stdout is only ever JSON. And --top is ignored — a person wants the top 20, a program wants all of it.

One exception, made deliberately: dup --json carries every clone group and every fragment location, but not the snippet text. Including it would make the document scale with the size of the duplication rather than its shape, and the text is reproducible from the files. --html still has the snippets.

Exit 2 means "found something"

Before, everything failed with 1: a bad flag, a missing directory, a breached budget. A pipeline could not tell a finding from a failure. Now a breached threshold exits 2 and errors keep exiting 1.

$ clines dup --max-duplication 5
Duplication exceeded: 5.5% > 5.0% (--max-duplication)
$ echo $?
2

dup, cx, comments and refactor gained threshold flags to go with ctx --max. This is the breaking change behind the major version: ctx --max used to exit 1.

refactor deliberately did not get a gate on verdict counts. Its thresholds are quantiles of the repository computed per run, so every repository always has a top quartile — "fail if more than 50 files say refactor" would measure nothing across runs. --max-reread gates an absolute number instead.

--diff main

A budget on a whole repository is close to unactionable: it is either already breached or it is noise. What a team will actually keep is a check on the change. Any command now takes --diff <ref> and reports only what a branch touched.

$ clines ctx --diff main --max 50k

dup needs different treatment, and gets it. Filtering its input would destroy detection — a clone needs its other copies to exist. So detection still runs over the whole tree, and only then does the result narrow to the groups a changed file takes part in, naming the other copies. The headline percentage is recomputed over the changed files, so the gate measures the branch rather than the repository.

The shallow clone bug

Building --diff surfaced something worse than a missing feature. git blame and git log --since both answer a depth-1 clone without complaint and return truncated history. actions/checkout defaults to fetch-depth: 1. So refactor and comments have been quietly reporting near-zero change counts in CI, confidently, with no way to tell.

Shallow clone: git history is truncated here, so these numbers are too
low. Fetch the full history (actions/checkout with `fetch-depth: 0`) for
a real answer.

The same pass gave git failures distinguishable causes. Every git call used to collapse into undefined, so a 64 MB buffer overflow on a large git log was reported to the user as "no git history is available".

clines mcp

clines mcp runs a Model Context Protocol server on stdio, so an agent can ask what a repository costs to read without shelling out and parsing a table. All six analyses are exposed as tools.

$ claude mcp add clines -- npx clines mcp

It adds no dependency. The JSON-RPC is hand-rolled — about 120 lines, in a codebase that already hand-rolls a glob engine, a config validator and a TTY pager — so commander remains the only runtime dependency.

Its responses are compact and capped at 20 rows by default, which is the opposite of what --json does on purpose. An agent pays for every token it reads back; a 6,915-file dump would defeat the point of asking.

And the obvious embarrassment

clines did not run clines in its own CI. The flagship CI feature was unused by the only repository guaranteed to have it installed. It now gates itself on token budget, duplication and complexity density, and checks out full history to do it.

Also in 6.0

← All posts