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.
Everything is counted locally in your browser — nothing is uploaded. Drag anywhere in this zone, or browse:
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.
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.
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:
Well-known filenames
Extensionless staples map directly: Dockerfile, Makefile, CMakeLists.txt, .gitignore, .bashrc, .vimrc.
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.
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 <# #>.
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.
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.
Comment lines
Single-line remarks (
//,#,--) and every line inside a block comment — tracked across lines with a state machine, not a regex.