oxide-sloc
oxide-sloc is a Rust-based source line analysis tool — IEEE 1045-1992 compliant, more than a line counter.
Quick Start
Install via Cargo (requires Rust):
Or use a pre-built binary:
| Platform | Install | Launch |
|---|---|---|
| Windows 10/11 | bash scripts/install.sh (Git Bash) |
bash scripts/run.sh (Git Bash) |
| Linux — RHEL 8/9, Ubuntu, Debian | bash scripts/install.sh |
bash scripts/run.sh |
The install script uses a pre-built binary from dist/ if present, or builds from vendored sources when Rust is available. On success, the web UI opens at http://127.0.0.1:4317.
For air-gapped setup, CI, and Docker, see docs/airgap.md.
Features
- CLI —
analyze / report / diff / serve / send / init / git-scan / git-compare / watchwith a full flag set - Localhost web UI — guided 4-step flow with light/dark theme, auto browser-open
- Quick Scan — one-click scan from step 1 using all defaults
- Server mode —
--serverbinds to0.0.0.0, suppresses browser auto-open - IEEE 1045-1992 physical SLOC — configurable counting parameters: mixed-line policy, continuation lines, compiler directives, blank-in-comment classification
- Symbol counting — lexical detection of functions, classes, variables, and imports per file
- Rich HTML reports — per-file breakdown, language charts, warning analysis
- PDF export — background generation via locally installed Chromium
- CSV / Excel export — from CLI flags or the report nav bar (4-sheet workbook)
- Scan history & delta tracking — every run is saved; re-scan to see lines added/removed
- Side-by-side diff view — compare any two scans with 4 chart types at
/compare - Git browser UI — browse branches, tags, and commits of any remote repo; one-click scan or two-ref comparison at
/git-browser - Automated scanning — attach GitHub, GitLab, or Bitbucket webhooks to trigger scans on push; or configure interval-based polling at
/webhook-setup - Point-in-time comparison —
git-scanandgit-compareCLI commands check out any ref via git worktree and produce delta reports (JSON / CSV) - Jenkins Git-Ref stages —
GIT_REF,COMPARE_TO_REF,COMPARE_TO_PREV_TAGparameters with dedicated scan and compare stages - Git submodule support — per-submodule HTML sub-reports
- Metrics API — JSON endpoints for CI/CD dashboards
- SVG badge endpoint — embed live code-line counts in READMEs or Confluence
- Embeddable summary widget —
<iframe>drop-in for internal wikis - Report delivery —
sendcommand: SMTP email or JSON webhook POST - CI/CD ready — Jenkinsfile, GitHub Actions, GitLab CI included; SonarQube integration via
clippy_to_sonar.py - Docker image — auto-published to GHCR on
mainand release tags - Air-gap / offline — all crate dependencies vendored; Chart.js compiled in; no CDN calls
- Confluence integration — push HTML reports via REST API
Installation
Path A — Pre-built binary (no Rust required)
The script tries in order: existing binary → dist/ bundle → offline Rust build.
Transferable bundle: Run
make bundleto produceoxide-sloc-bundle.tar.gz— drop it on a USB drive and runbash scripts/install.shon the target machine.
Path B — Docker
# or build locally
# CLI via Docker
Environment variables for docker compose:
| Variable | Required | Description |
|---|---|---|
SLOC_API_KEY |
Yes | Bearer token for all web endpoints. Generate: openssl rand -hex 32 |
SLOC_ALLOWED_ROOTS |
No | Colon-separated list of paths the web UI may scan. Default: unrestricted |
SLOC_TARGET |
No | Host directory to mount as /repo. Default: ./tmp-sloc |
SLOC_TLS_CERT / SLOC_TLS_KEY |
No | Paths to PEM certificate and key for HTTPS |
See docs/airgap.md for air-gapped setup and docs/server-deployment.md for persistent deployments.
Usage
CLI
# Analyze and print a colored summary
# Machine-readable key=value output
# Full output: JSON + HTML + CSV + Excel
# Per-file breakdown in the terminal
# Open the HTML report immediately after generation
# Quiet mode — only write files, print nothing (ideal for CI)
# Pipeline guards
# Filter by language or glob
# Git submodule breakdown
# Re-render a report from saved JSON
# Compare two saved results
# Generate a starter config
# Start the web UI
# Deliver a saved report
CLI flags reference
analyze
| Flag | Short | Default | Description |
|---|---|---|---|
--json-out |
-j |
(none) | Write JSON result |
--html-out |
-H |
(none) | Write HTML report |
--csv-out |
-c |
(none) | Write CSV summary |
--xlsx-out |
-x |
(none) | Write Excel workbook (4 sheets) |
--pdf-out |
(none) | Write PDF (requires Chrome/Edge/Brave) | |
--open |
off | Open HTML in system browser | |
--quiet |
-q |
off | Suppress all non-error output |
--plain |
off | Machine-readable key=value output | |
--per-file |
off | Per-file breakdown in terminal | |
--fail-on-warnings |
off | Exit 2 if warnings are emitted | |
--fail-below |
(none) | Exit 3 if code lines fall below N | |
--mixed-line-policy |
code-only |
code-only | code-and-comment | comment-only | separate-mixed-category |
|
--python-docstrings-as-code |
off | Treat docstrings as code | |
--continuation-line-policy |
each-physical-line |
each-physical-line | collapse-to-logical — IEEE 1045-1992 §3 |
|
--blank-in-block-comment-policy |
count-as-comment |
count-as-comment | count-as-blank — IEEE 1045-1992 §4 |
|
--no-count-compiler-directives |
off | Exclude #include/#define from code SLOC — IEEE 1045-1992 §4.2 (C/C++/ObjC only) |
|
--include-glob |
(all) | Only scan matching files (repeatable) | |
--exclude-glob |
(none) | Skip matching files (repeatable) | |
--enabled-language |
(all) | Restrict to language (repeatable) | |
--no-ignore-files |
off | Ignore .gitignore / .ignore |
|
--follow-symlinks |
off | Follow symbolic links | |
--report-title |
folder name | Title in HTML/PDF/XLSX reports | |
--submodule-breakdown |
off | Per-submodule stats from .gitmodules |
|
--config |
(none) | Load settings from TOML file |
report / diff / init / serve / send
Run oxide-sloc <command> --help for the full flag list of each subcommand.
Web UI
A guided 4-step flow: select project → counting rules → outputs → review & run. The Quick Scan sidebar button submits from step 1 with all defaults.
Every web UI option maps 1:1 to a CLI flag — see the Web UI → CLI translation table below.
Configuration file
CLI flags always override config file values.
Scan history and delta tracking
Every web UI scan is recorded in out/web/registry.json. Re-running the same project path shows an inline delta — the same data the diff command writes to JSON/CSV/Excel.
Navigate to /history to browse past scans, or /compare?a=<run_id>&b=<run_id> for a side-by-side file-level diff with four chart types.
Comparison metrics
When two scans of the same project are compared (different commits, branches, or dates), oxide-sloc surfaces the following metrics at both the project level and per-language:
| Metric | What it measures |
|---|---|
| SLOC | Effective source lines of code after policy application — the primary size signal |
| Added | Lines present in the new scan that did not exist in the baseline |
| Removed | Lines present in the baseline that are gone in the new scan |
| Modified | Lines that changed in files present in both scans (content diff, not just count) |
| Unmodified | Lines carried over from the baseline with no change |
These five values satisfy the identity: SLOC (new) = Unmodified + Modified + Added.
CLI diff output:
# Print delta to terminal
# Export delta to all formats
Web UI: navigate to /compare?a=<run_id>&b=<run_id> — the comparison view renders all five metrics with bar charts, a per-file breakdown table, and filter controls.
Symbol counting
oxide-sloc performs best-effort lexical detection of structural symbols across 10+ languages. Counts are surfaced in the JSON output (functions, classes, variables, imports fields) and in the HTML report.
Supported languages: C, C++, C#, Go, Java, JavaScript, Rust, Shell, PowerShell, TypeScript.
Counting methodology — IEEE 1045-1992
oxide-sloc implements physical SLOC as defined in IEEE Std 1045-1992 Software Productivity Metrics. Every source line is classified into one of four categories before any policy is applied:
| Category | What it contains |
|---|---|
| Code | Executable statements, declarations, and compiler directives |
| Comment | Lines consisting solely of comment text |
| Mixed | Lines that contain both code and a trailing comment |
| Blank | Empty or whitespace-only lines |
The standard defines several counting parameters as configurable. oxide-sloc exposes all of them via CLI flags and the TOML config file.
Mixed-line policy — mixed_line_policy
Controls how lines that contain both code and a comment are counted toward the totals. Default: code-only.
| Value | Behaviour |
|---|---|
code-only (default) |
Mixed lines count toward code only |
code-and-comment |
Mixed lines are counted in both totals |
comment-only |
Mixed lines count toward comments only |
separate-mixed-category |
Mixed lines are kept in a separate total |
Continuation-line policy — continuation_line_policy (IEEE 1045-1992 §3)
Controls how backslash-continued lines (C/C++ macros, shell, Makefile) are counted. Default: each-physical-line.
| Value | Behaviour |
|---|---|
each-physical-line (default) |
Each physical line is counted separately (physical SLOC mode) |
collapse-to-logical |
A backslash-continued sequence counts as a single logical line |
Blank lines inside block comments — blank_in_block_comment_policy (IEEE 1045-1992 §4)
Controls how blank lines that fall inside /* ... */ (or equivalent) comment blocks are classified. Default: count-as-comment, which is the IEEE-aligned behaviour.
| Value | Behaviour |
|---|---|
count-as-comment (default, IEEE aligned) |
Blank lines inside block comments count as comment lines |
count-as-blank |
Blank lines inside block comments remain blank lines |
Compiler directives — count_compiler_directives (IEEE 1045-1992 §4.2)
Applies to C, C++, and Objective-C only. By default, preprocessor directive lines (#include, #define, #ifdef, #pragma, etc.) are counted as code lines. Set count_compiler_directives = false to exclude them from effective code SLOC — they are still recorded in the raw JSON output as compiler_directive_lines so nothing is lost.
TOML configuration
All parameters are settable in .oxide-sloc.toml under [analysis]:
[]
= "code-only" # code-only | code-and-comment | comment-only | separate-mixed-category
= "each-physical-line" # each-physical-line | collapse-to-logical
= "count-as-comment" # count-as-comment | count-as-blank
= true # false = exclude #include/#define from code SLOC (C/C++/ObjC)
= true # false = treat docstrings as code
Run oxide-sloc init to generate a starter config with all options documented inline.
Supported languages (41)
| Language | Extensions / Filenames | Comment styles |
|---|---|---|
| Assembly | .asm, .s |
; |
| C | .c, .h |
// /* */ |
| C++ | .cc, .cpp, .cxx, .hpp, .hxx |
// /* */ |
| C# | .cs |
// /* */ verbatim strings |
| Clojure | .clj, .cljs, .cljc, .edn |
; |
| CSS | .css |
/* */ |
| Dart | .dart |
// /* */ |
| Dockerfile | Dockerfile, Dockerfile.* |
# |
| Elixir | .ex, .exs |
# |
| Erlang | .erl, .hrl |
% |
| F# | .fs, .fsi, .fsx |
// (* *) |
| Go | .go |
// /* */ |
| Groovy | .groovy, .gradle |
// /* */ |
| Haskell | .hs, .lhs |
-- {- -} |
| HTML | .html, .htm, .xhtml |
<!-- --> |
| Java | .java |
// /* */ |
| JavaScript | .js, .mjs, .cjs |
// /* */ |
| Julia | .jl |
# #= =# |
| Kotlin | .kt, .kts |
// /* */ |
| Lua | .lua |
-- --[[ ]] |
| Makefile | Makefile, GNUmakefile, .mk |
# |
| Nim | .nim, .nims |
# #[ ]# |
| Objective-C | .m, .mm |
// /* */ |
| OCaml | .ml, .mli |
(* *) |
| Perl | .pl, .pm, .t |
# |
| PHP | .php |
// # /* */ |
| PowerShell | .ps1, .psm1, .psd1 |
# <# #> |
| Python | .py |
# docstrings |
| R | .r |
# |
| Ruby | .rb, .rake, Rakefile, Gemfile |
# |
| Rust | .rs |
// /* */ |
| Scala | .scala, .sc |
// /* */ |
| SCSS | .scss, .sass |
// /* */ |
| Shell | .sh, .bash, .zsh, .ksh |
# |
| SQL | .sql |
-- /* */ |
| Svelte | .svelte |
// /* */ |
| Swift | .swift |
// /* */ |
| TypeScript | .ts, .mts, .cts |
// /* */ |
| Vue | .vue |
// /* */ |
| XML / SVG | .xml, .xsd, .xsl, .svg |
<!-- --> |
| Zig | .zig |
// |
Not supported (intentionally): TOML, Markdown, YAML — no meaningful SLOC metric applies. Shebang (
#!) detection works for Python, Shell, Ruby, Perl, PHP, and Node.js scripts.
Adding a new language
crates/sloc-languages/src/lib.rs— add aLanguagevariant, implementdisplay_name/as_slug/from_name, register extensions indetect_language, add aScanConfigentry inanalyze_text.- No change needed in
sloc-config—enabled_languagesfiltering picks up new variants automatically.
PDF export
PDF generation uses a locally installed Chromium-based browser (Chrome, Edge, Brave, Vivaldi, or Opera). Generation runs in the background; the web UI returns results immediately.
# override browser path
In Docker, Chromium is bundled — no extra setup needed.
CSV and Excel export
Every HTML report has Export CSV and Export Excel buttons in the nav bar. The Excel workbook contains four sheets: Summary, By Language, Per File, and Skipped Files — no plugins required, works in Excel, LibreOffice, and Google Sheets.
The same exports are available from the CLI:
Metrics API
| Endpoint | Description |
|---|---|
GET /api/metrics/latest |
Metrics for the most recent scan |
GET /api/metrics/:run_id |
Metrics for a specific run |
GET /api/project-history?path=<dir> |
Scan history for a project root |
GET /badge/:metric |
SVG badge (code-lines, files, comment-lines, blank-lines) |
GET /embed/summary |
Embeddable HTML widget |
GET /healthz |
Health check |

CI/CD
Web UI → CLI translation
| Web UI | CLI equivalent |
|---|---|
| Step 1: select project | oxide-sloc analyze ./my-repo |
| Step 1: include / exclude pattern | --include-glob / --exclude-glob |
| Step 1: submodule breakdown | --submodule-breakdown |
| Quick Scan | oxide-sloc analyze ./my-repo --plain |
| Step 2: mixed-line policy | --mixed-line-policy code-only |
| Step 2: Python docstrings as code | --python-docstrings-as-code |
| (config / CLI only) | --continuation-line-policy collapse-to-logical |
| (config / CLI only) | --blank-in-block-comment-policy count-as-blank |
| (config / CLI only) | --no-count-compiler-directives |
| Step 3: outputs | -j -H --pdf-out -c -x --open |
| Step 3: custom title | --report-title "My Report" |
| Re-render from saved JSON | oxide-sloc report result.json -H report.html |
| Compare two scans | oxide-sloc diff baseline.json current.json |
| Generate starter config | oxide-sloc init |
| Quiet / fail guards | --quiet --fail-on-warnings --fail-below N |
CI config presets
| File | Use case |
|---|---|
ci/sloc-ci-default.toml |
Balanced defaults |
ci/sloc-ci-strict.toml |
Fail-fast on binary files |
ci/sloc-ci-full-scope.toml |
Audit mode — counts vendor/lockfiles too |
GitHub Actions
| Workflow | Trigger | What it does |
|---|---|---|
ci.yml |
push to main, all PRs |
fmt → clippy → build → tests → CLI smoke → web health check |
release.yml |
v* tag |
Cross-compile for 5 platforms → sign Windows binary → GitHub Release |
docker.yml |
push to main, v* tag |
Build and push Docker image to GHCR |
update-dist.yml |
v* tag, manual |
Build platform bundles and commit to dist/ |
All workflows run on Node 24.
To cut a release:
Jenkins / GitLab CI
A Jenkinsfile and .gitlab-ci.yml are included at the repo root. On self-hosted or air-gapped runners, download vendor.tar.xz from the release page, place it in the workspace, and the pipeline will decompress and cache vendor/ between runs.
For detailed setup including Confluence publishing, see docs/ci-integrations.md.
Local development
# Run all CI gates before pushing
# Run the web UI during development
# Fast rebuild (keeps vendored dep cache, ~1 min)
&&
scripts/run.shvscargo run: When Rust is available,scripts/run.shpreferscargo runso changes are always picked up. During active development, either works.
Make targets (Linux/macOS):
Repository layout
crates/
sloc-cli/ # CLI entry point and commands
sloc-config/ # Config schema and TOML parsing
sloc-core/ # File discovery, decoding, aggregation, delta engine
sloc-languages/ # Language detection, lexical analyzers, symbol counting
sloc-report/ # HTML rendering, PDF export, CSV/Excel export
sloc-web/ # Axum web server, scan registry, metrics API, badge endpoint
ci/ # CI shell scripts (lint.sh, build.sh, test.sh, release.sh) + config presets
deploy/ # systemd unit + server config template
dist/ # Release bundles — generated by CI, not tracked in git
docs/
assets/ # Icons, logos (served at /images/* by the web UI)
airgap.md # Offline and air-gapped deployment guide
ci-integrations.md
server-deployment.md
examples/ # Runnable examples + sloc.example.toml config template
scripts/ # install.sh, run.sh, airgap-build.sh, update-vendor.sh
tests/
fixtures/basic/ # Sample source files used by smoke tests
License
oxide-sloc is licensed under AGPL-3.0-or-later. Copyright (C) 2026 Nima Shafie. All intellectual property rights vest solely in the author.
Commercial support, hosted services, and proprietary add-ons are available through separate arrangements. See docs/licensing-commercial.md.
Nima Shafie — github.com/NimaShafie