Count your code, line by line

A ledger-room counter for refactors, KPI reports and honest scale claims. Total, Code, Comment, Blank — per file, per language, one click to CSV.

Drop files or a whole folder

Everything is counted locally in your browser — nothing is uploaded. Drag anywhere in this zone, or browse:

01 · The Calibers

Three calibers, one ledger

Physical line counts flatter generated code; comment-only counts hide documentation debt. LinesTool keeps all four numbers side by side, aligned with the conventions of cloc, so a scale claim survives an audit.

Code lines

const rate = 0.5;
let total = base * rate;  // price

Lines with at least one effective code character. A statement with a trailing comment still counts as code — only pure-comment lines move to the comment column.

Comment lines

// load defaults
/* legacy shim */

Single-line remarks (//, #, --) and every line inside a block comment — tracked across lines with a state machine, not a regex.

Blank lines

const a = 1;
                ← blank
const b = 2;

Empty or whitespace-only lines. They cost nothing to read but say a lot about formatting style — so they get their own column, never silently merged.

Total (physical)

2 code + 2 comment
+ 2 blank = 6 total

The plain newline count — the number wc -l would give you. Total always equals Code + Comment + Blank; if it doesn't, the scanner is wrong.

02 · Detection

The language fingerprint

An extension alone lies — deploy scripts hide in .sh files with Python inside. Every file passes through four checks, most-authoritative first:

i.

Well-known filenames

Extensionless staples map directly: Dockerfile, Makefile, CMakeLists.txt, .gitignore, .bashrc, .vimrc.

ii.

Shebang override

The #! first line wins over any extension — #!/usr/bin/env python3 inside run.sh is counted as Python, as the kernel would run it.

iii.

Extension index

40+ language tables cover mainstream extensions (.ts, .kt, .rs, .vue, .sql, .yaml…) including less common ones like .plt-style MATLAB blocks and PowerShell <# #>.

iv.

Content sniff

No extension, no shebang? Structure gives it away: <?php headers, def/class indented blocks, package main + func, {"key": JSON shapes, --- YAML front matter.

 1  #!/usr/bin/env python3
 2  import json
 3  
 4  def load(path):
 5      """Load a JSON config."""
 6      with open(path) as fh:
 7          return json.load(fh)

A run.sh file — the Shebang line says Python, so the scanner counts it as Python. The """...""" docstring is recognized as a block comment, not code.

03 · FAQ

Frequently asked

The questions auditors, leads and résumé reviewers actually ask.

How do I count lines of code in a project?

Drag your files or an entire folder onto the drop zone — or use the Choose Files / Choose Folder buttons. LinesTool walks the directory tree, detects each file's language and totals everything into a ledger: physical, code, comment and blank lines, with per-language subtotals and a file-by-file manifest you can export to CSV.

What is the difference between Total, Code, Comment and Blank lines?

Total counts every physical line separated by a newline. Code lines contain at least one effective code character — including mixed lines like a statement with a trailing comment. Comment lines contain only comments: single-line // or # remarks and every line inside a /* ... */ block. Blank lines are empty or whitespace-only. The calibers match cloc: Total = Code + Comment + Blank.

How does it know which programming language a file is?

A four-step fingerprint, most authoritative first: well-known extensionless filenames, the Shebang line (which overrides the extension), the file extension across 40+ language tables, then a content sniff of structural features like def ...: blocks, <?php headers or JSON object shapes.

Can it count a whole folder at once?

Yes. Drag a folder onto the drop zone and it is traversed recursively with each file's relative path preserved in the report. Heavy directories — node_modules, .git, dist, build, .next, target, vendor, __pycache__, venv — are skipped by default, and you can switch that off with the toggle under the drop zone.

How is this different from wc -l?

wc -l only counts physical newlines, so a generated bundle and a hand-written module look identical. LinesTool separates code from comments and blanks with a string-aware scanner — it knows a // inside a string literal is not a comment — and reports per-language subtotals, the same three-caliber reporting used to size refactors and audits.

Can I export the line count report to CSV or Excel?

Yes. Export CSV produces an RFC 4180 compliant file with a UTF-8 BOM, so Excel opens it with correct encoding. It contains one row per file (path, language, four line counts, code ratio, bytes), a subtotal block per language, and a grand TOTAL row — ready for KPI reports and budget spreadsheets.

Which languages are supported?

40+ language families: JavaScript/TypeScript, Python, Java, C#, C/C++, Go, Rust, Ruby, PHP, Swift, Kotlin, Scala, Dart, HTML, Vue/Svelte, CSS/SCSS, JSON/JSON5, YAML, TOML, INI, XML, Markdown, SQL, Shell, PowerShell, Lua, Perl, R, MATLAB, Makefile, Dockerfile, Haskell, Elixir, Erlang, Clojure, Vim script, Batch and Objective-C — plus plain text.

Is my source code uploaded to a server?

No. All parsing and counting runs entirely in your browser with client-side JavaScript. Files never leave your machine — nothing is transmitted, logged or stored, which makes it safe for proprietary code, unreleased projects and work covered by NDAs. Close the tab and every trace is gone.

Latest Articles