Analyze any codebase from the terminal. Get file counts, lines of code by language, and complexity metrics in a clean report. Zero external dependencies.
I needed a quick way to understand unfamiliar codebases without opening a heavy IDE plugin or waiting for a SaaS tool to upload my files. This is what I wrote instead.
# Install
pip install git+https://github.com/mangodxd/code-stats.git
# Analyze the current directory
code-stats .
# Analyze a specific project
code-stats /path/to/projectcode-stats [path] [options]
Positional arguments:
path Directory to analyze (default: .)
Options:
--exclude PATTERN Exclude files matching pattern (repeatable)
--json Output as JSON
--sort by=lines|files Sort languages by lines or files (default: lines)
--min-lines N Only show languages with at least N lines
--version Show version and exit
$ code-stats ~/projects/my-app
Language Files Lines %
Python 47 3,201 52%
TypeScript 23 1,876 31%
Markdown 5 412 7%
HTML 4 310 5%
YAML 3 180 3%
CSS 2 123 2%
-------------------------------------------
Total: 84 files, 6,102 lines
The table shows each language, how many files of that language exist, the total line count, and what percentage of the codebase those lines represent. Languages with zero files are omitted.
code-stats . --jsonReturns structured data for scripting and pipelines:
{
"total_files": 84,
"total_lines": 6102,
"languages": {
"Python": {
"files": 47,
"lines": 3201,
"code_lines": 2850,
"comment_lines": 180,
"empty_lines": 171,
"comment_ratio": 0.0562,
"top_files": [
{"name": "main.py", "lines": 420},
{"name": "utils.py", "lines": 310}
]
}
}
}The JSON output includes per-language comment ratios and the top 5 most complex files by line count. This makes it useful for CI pipelines and automated reporting.
# Skip test fixtures and generated code
code-stats . --exclude test --exclude generated
# Multiple patterns can be specified
code-stats . --exclude migrations --exclude vendor# Sort by file count instead of line count
code-stats . --sort files
# Only show languages with at least 500 lines
code-stats . --min-lines 500Recognizes 90+ programming languages by file extension. Includes commonly used extensions for Python, JavaScript, TypeScript, Go, Rust, Java, C/C++, Ruby, PHP, Swift, Kotlin, and many more. Files with unknown extensions are counted but not attributed to a language.
Detection works by extension only — no file content inspection. This keeps
it fast and avoids false positives from shebang lines or ambiguous files.
Basename-based detection handles files like Dockerfile and Makefile
that have no meaningful extension.
Single-line and block comments are detected for each language. The comment
pattern map covers Python (#), C-style languages (// and /* */),
Ruby (#), Shell (#), SQL (-- and /* */), and many more. Block
comments are tracked across multiple lines so multi-line comment blocks
are not counted as code.
The comment ratio (comment lines divided by total lines) is included in JSON output. This is useful for spotting over- or under-commented code.
The following directories are excluded by default:
node_modules, .git, __pycache__, dist, build, .venv, vendor,
.tox, .eggs, .mypy_cache, .ruff_cache, .pytest_cache.
These cover the most common dependency and build output directories across Python, JavaScript, Rust, Go, and other ecosystems. The list was chosen based on what actual projects commit vs. generate.
The tool follows standard Unix conventions:
- 0: Analysis completed successfully
- 1: An error occurred (invalid path, permission denied, etc.)
Lines are classified into three categories:
- Code lines: Lines that contain executable code. Blank lines and comment-only lines are excluded.
- Comment lines: Lines that contain only comments (single-line or part of a block comment). A line with both code and an inline comment is counted as code, not a comment.
- Empty lines: Lines that contain only whitespace characters.
Block comments spanning multiple lines count each line within the block as a comment line. This includes the opening and closing delimiters.
The classifier reads files as UTF-8 text. Files that cannot be decoded as text (binary files, images, etc.) are skipped without error.
| Tool | Dependencies | Comment detection | JSON output | Language count |
|---|---|---|---|---|
| code-stats | Zero | Yes | Yes | 90+ |
| cloc | Perl required | Yes | Yes | 100+ |
| sloccount | C++ binary | Yes | No | ~30 |
| tokei | Rust binary | Yes | Yes | 100+ |
code-stats fills the gap for Python users who want a zero-dependency CLI that works out of the box. No Perl runtime, no compiled binary, no package manager beyond pip.
- Language: Python 3.10+ (stdlib only for core functionality)
- CLI: argparse (stdlib)
- Testing: pytest
- Linting: ruff
- Dependencies: Zero for core; pytest + ruff for development
src/
code_stats/
__init__.py Package version and metadata
__main__.py Enables `python -m code_stats`
analyzer.py Recursive directory walker and line counter
cli.py Argument parser and main entry point
languages.py Extension-to-language mapping with comment patterns
reporter.py Text table and JSON output formatters
tests/
test_analyzer.py 19 tests for directory analysis and line counting
test_cli.py 8 tests for argument parsing and exit codes
test_languages.py 13 tests for extension-based language detection
test_reporter.py 12 tests for output formatting (text + JSON)
code-stats can analyze itself:
$ code-stats .
Language Files Lines %
------------------------------------------
Python 10 1,168 79%
Markdown 3 218 15%
TOML 1 58 4%
YAML 1 34 2%
------------------------------------------
Total: 15 files, 1,478 lines
git clone https://github.com/mangodxd/code-stats.git
cd code-stats
pip install -e .
pip install pytest ruff
# Run tests (52 tests, all passing)
python -m pytest
# Run linter
ruff check src/ tests/See CONTRIBUTING.md. The project welcomes contributions that keep the codebase minimal, well-tested, and dependency-free.
See CHANGELOG.md for release history.
MIT. See LICENSE.