From 2.0.2 to 3.11.1

8 August 2026 · covers versions 3.0.0 through 3.11.1

Version 2.0.2 was a single 258-line index.js. It walked a directory, skipped blank and comment lines, and printed one number: the count of everything left over. It could write that number into a README and attach a size label to it. There were no tests and no build step.

Everything below happened after that. The tool is now a typed, layered codebase with four commands, and the counting itself is verifiably accurate rather than approximately right.

3.0.0 — the rewrite

The whole tool was rewritten in TypeScript and split into layers: cli → config → core → report. The core is pure functions, so the parts that decide what a line is can be tested without touching a filesystem.

Test coverage is enforced at 100% for statements, branches, functions and lines. This is a CI gate, not an aspiration: a pull request that drops coverage to 99.7% fails. Publishing moved to GitHub Actions using npm trusted publishing over OIDC, with no long-lived token in the repository.

3.0.1 – 3.3.3 — counting got precise

2.0.2 discarded comments and blanks. 3.x classifies every line as code, comment or blank and reports all three per language, so the output is a table rather than a single number:

Language      Files      Lines     Code  Comments    Blank  Complexity       %
JavaScript    3,954    673,654  546,899    62,317   64,438      37,405   65.5%
TypeScript      419     81,509   65,140    11,248    5,121       8,399    7.8%

Along the way:

3.3.3 added this site. Counting accuracy was checked against cloc: on the react repository, over an identical 6,915-file set, the two agree to within 0.12% on code lines and 0.02% on blanks.

3.4.0 – 3.8.0 — clines dup

The first new command finds duplicated code. Detection is maximal-block clone matching over code lines, ignoring whitespace differences, so reformatted copies still match. --html writes a self-contained report with each snippet, every location, and a filter box.

The five releases in this range were mostly corrections found by running it on real repositories: syntax highlighting and indentation in the snippets, merging overlapping fragments, --min-copies for blocks duplicated more than twice, and a fix where the headline statistics ignored the --min-lines and --min-copies filters and so disagreed with the table underneath them.

3.9.0 – 3.10.0 — complexity

3.9.0 added a Complexity column to count: a decision-point count, following the approach used by scc, of branch and loop keywords and logical operators, with comments and string contents excluded. 3.10.0 promoted it to its own command, clines complexity (alias cx), which ranks files rather than aggregating by language.

Complexity: 51,082 total   ·   2,303 files with complexity

Most complex files
  File                                                          Complexity   Code
  packages/react-devtools-shared/src/backend/fiber/renderer.js       1,292   6,487
  packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js       1,102   5,929

3.11.0 — clines context

The newest command estimates how many tokens a language model reads for the whole tree, compares the total against a context window, and breaks it down per file and per top-level directory. --max turns it into a CI check: the command exits with status 1 once the total exceeds the budget.

$ clines ctx --window 1m
Context: 8,776,571 tokens   ·   877.7% of a 1,000,000-token window   ·   11% comments

Adding a tokenizer dependency was not an option, so the estimator approximates one: sub-word splitting on camelCase and snake_case boundaries, symbol runs charged by length, and one token per newline. The constants were fitted against GPT-4o's tokenizer rather than guessed.

Corpus Total error Per-file median
Mixed calibration set (2,943 files, 5.1M tokens) +0.3% 10.3%
facebook/react (6,915 files, 8.3M tokens) +5.2%

The estimate runs a few percent high on JavaScript and TypeScript and low on Markdown and JSON. The near-zero figure on the mixed set is those two biases cancelling out, not a general guarantee. Treat totals as accurate to within about ±10%.

Version summary

Version Change
3.0.0 TypeScript rewrite, layered architecture, 100% coverage gate, CI/CD
3.0.1 Exclude generated files; fold unknown extensions into Other
3.1.0 Per-language table with code, comment and blank columns
3.1.1 Split JSX and TSX into their own categories; fix trailing-blank overcount
3.2.0 Recalibrated project-size scale
3.3.0 clines count subcommand, banner, read-only by default
3.3.1 – 3.3.2 Fix clines help; new README marker comments
3.3.3 This site
3.4.0 – 3.5.1 clines dup, with an HTML report and syntax highlighting
3.6.0 – 3.6.1 Merge overlapping fragments; collapsible cards; snippet fixes
3.7.0 – 3.7.2 --min-copies; statistics now respect the filters
3.8.0 --html opens the report in the browser
3.9.0 Complexity column in count
3.10.0 clines complexity (cx) with a ranked HTML report
3.11.0 clines context (ctx) with a --max budget
3.11.1 Banner lists every command

What did not change

clines.json still uses the same add and remove model, .gitignore is still respected, and --readme still writes into the same marker comments. A 2.x configuration file works unchanged.