CodeDelta code·delta User Guide & Technical Reference
codedelta.app
code_delta — see the risk, prevent the disaster

Automated Source Code Churn Analysis & AI Agent Detection

Version2.0.2 (Build 47)
Released8 September 2026
Guidev2.0.2 · 8 September 2026
PlatformsmacOS · Linux · Windows
What's New in v2.0.2
Previously in v2.0.1
Previously in v1.9.7
Previously in v1.9.6
Previously in v1.9.5
Previously in v1.9.4
Previously in v1.9.3
Previously in v1.9.2
Previously in v1.9.1
Previously in v1.9.0
Previously in v1.8.8–v1.8.9
Previously in v1.8.5–v1.8.6
Contents
01What CodeDelta Measures 02Metrics Reference 03GUI Guide 04The Code Browser 05Command Line Reference 06AI Audit (Code Scan + Agent Scan) 07Agent Scan (AIS) 08CI/CD Integration 09Accuracy & Methodology 10Licensing
01

What CodeDelta Measures and How

CodeDelta is a command-line source code metrics tool with a browser-based GUI. It compares two snapshots of a source project — an old version and a new version — and measures exactly what changed, how much, and how complex. It is a professional-grade source code analysis tool for macOS, Linux, and Windows.

Core Principle

If your source files are constantly being changed, the source base is not stable and is not ready for release. CodeDelta makes this visible. Every build, every sprint, every release — run CodeDelta and watch the churn numbers. A healthy codebase shows decreasing churn as a release approaches. A codebase that remains "hot and active" near release is a risk.

What churn measures — and what it does not

Software metrics should never be used to measure productivity. Our metrics are an indicator of where, and how much, coding activity is being conducted — and this can point to areas of code weakness, bugs, upgrades, rogue development, or something else entirely. They let managers see where the code is changing, and by how much.

This can be particularly important in mission-critical software, where code changes could be dangerous and must be strictly controlled and documented.

Key Features

The Difference Between SLOC and LLOC

SLOC (Source Lines of Code) is a physical count — the number of non-empty, non-comment lines in the file. Two statements on one line = 1 SLOC.

LLOC (Logical Lines of Code) is a count of logical statements, excluding anything inside comments or string literals. Statements are delimited by semicolons in C-family languages, and by statement-ending newlines — with bracket, string and line-continuation awareness — in newline-terminated languages such as Python, JavaScript/TypeScript, Go, Ruby and Shell. One statement spread over three lines = 1 LLOC. This is invariant to formatting and is the preferred metric for measuring real code change.

int i=0; float j=0;  // This is 2 LLOC, 1 SLOC

cout << "Testing"
     << " Hello"
     << " there.";   // This is 1 LLOC, 3 SLOC

What Gets Measured

CodeDelta counts all source files recursively under the base directory, maps each file to a language by extension, and counts metrics per file. A file with no extension is classified by its first line when that is a #! interpreter line: #!/bin/sh or #!/usr/bin/env python3 make it Shell or Python, and Perl, Ruby and node scripts are recognised the same way. Symbolic links are never followed: each one is skipped and listed with the files not measured (the Coverage block in the report, Status X rows in the CSV). For comparisons, files are matched by relative path. A file present in the new project but not the old is Added (N). A file in the old but not the new is Deleted (D). A file present in both is either Changed (C) or Unchanged (U).

Supported Languages

CodeDelta detects 55 languages by file extension. For 27 of them it computes real, formatting-invariant logical lines (LLOC); the remaining 19 are measured by physical lines, where LLOC equals SLOC. The table below is the complete, current list.

LanguageExtensionsLogical lines
Ada.ada .adb .adsReal LLOC
ASP.asp .aspxSLOC only
Assembler.asm .sSLOC only
C / C++.c .h .cpp .hpp .cc .cxx .hh .hxx .inl .ipp .tppReal LLOC
C#.csReal LLOC
COBOL.cbl .cob .cobol .cpyReal LLOC (sentences)
CSS.cssSLOC only
Dart.dartReal LLOC
DeviceTree.dts .dtsiReal LLOC
DockerfileDockerfileSLOC only
Erlang.erl .hrl .app .app.src .appup .rel .escript .xrl .yrlSLOC only
ASN.1.asn1 .asn .mibSLOC only
Make / CMake.mk .gmk .mak .kbuild .cmake, Makefile, CMakeLists.txtSLOC only
Protobuf.protoReal LLOC
JSON / YAML / TOML / INI.json .yaml .yml .toml .ini .cfg .propertiesSLOC only
Eiffel.eSLOC only
Fortran.f .f90 .f95 .forSLOC only
Go.goReal LLOC
Groovy.groovy .gvy .gradleReal LLOC
HTML.html .htm .htpSLOC only
IDL.idlSLOC only
Java.javaReal LLOC
JavaScript.js .jsxReal LLOC
JCL.jclSLOC only
JSP.jspSLOC only
Kotlin.kt .ktsReal LLOC
Lisp.lisp .lsp .cl .scm .elSLOC only
MMP.mmpSLOC only
Objective-C.m .mmReal LLOC
Oracle (PL/SQL).pls .pks .pkbReal LLOC
Perl.pl .pmReal LLOC
PHP.phpReal LLOC
PL/I.pli .pl1Real LLOC
PowerBuilder.srd .srf .srs .sru .srwSLOC only
PowerShell.ps1 .psm1 .psd1SLOC only
Python.py .pywReal LLOC
R.rReal LLOC
Ruby.rbReal LLOC
Rust.rsReal LLOC
Scala.scala .scReal LLOC
Shell.sh .bash .zsh .csh .ash .bsh .tcsh .tshReal LLOC
Smalltalk.stSLOC only
SQL.sqlReal LLOC
Swift.swiftReal LLOC
TypeScript.ts .tsx .mts .ctsReal LLOC
UCode.ucSLOC only
VBScript.vbsSLOC only
Visual Basic.vb .bas .cls .frmSLOC only
VHDL.vhdl .vhdReal LLOC
Windows Batch.bat .cmdSLOC only
XML.xml .xsd .xsl .xslt .wsmlSLOC only

Need a language we don't cover yet — or full two-pass LLOC for one currently counted SLOC-only? Additional language support can be added on request as part of a support arrangement — contact us at codedelta.app to discuss your stack.

See the complete extension-to-language reference in section 03 (GUI Guide → Extension Overrides) for which file extensions auto-detect to which language. Custom mappings can be added without recompiling via the Extension Overrides field.

02

Metrics Reference

CodeDelta computes the source code metrics most commonly used in software-engineering analysis: SLOC, LLOC, comment counts, file counts, and per-language breakdowns. See the Metrics Reference table above for the full set.

Size Metrics

CodeNameDescription
LOCLines of CodeTotal lines including whitespace and comments. A count of newlines.
SLOCSource Lines of CodeNon-empty, non-comment lines. Physical line count of actual source.
LLOCLogical Lines of CodeSemicolon count excluding those in comments or string literals. Statement count.
PLOCPreprocessor Directive LOCLines beginning with # (#include, #define, #ifdef etc.). C/C++ and C# only.
U_LOCUnclassified LOCNon-blank lines in files of no recognised language. These are usually not plain-text documents but source code files (e.g. .lua, .vim) — counted as text lines into Total LOC and U_LOC and given their own UNCLS row, but kept out of the SLOC, LLOC and CRN totals (their churn appears on the file row only), because there is no language-specific parser, so comment stripping and true LLOC are not possible and they are measured as text lines. Comments count as content (no parser exists to strip them — which is why it is not U_SLOC); blank lines excluded. U_LOC and its churn (CHG_U_LOC / DEL_U_LOC / ADD_U_LOC / CRN_U_LOC, the CSV UNCLS row) are reported separately and never enter the SLOC/LLOC totals, churn totals or REWORK/REP_CHURN. Use --ext to map an extension to a supported language.
COM_LOCComment Lines of CodeTotal comment lines = J_COM + C_COM + EOL_COM.
J_COMJava-style comment linesLines inside /** ... */ docblock comments: a docblock spanning three lines contributes 3. The same split applies in JavaScript and TypeScript: a docblock is J_COM, a plain /* ... */ block is C_COM.
C_COMC-style comment linesLines inside /* ... */ block comments, one per line spanned (also Ruby =begin/=end and Perl POD blocks). These are line counts, not counts of comments: one three-line comment is three comment lines.
EOL_COMEnd-of-line comment linesLines carrying a // (or #, --, ;) comment to end of line.
BYTESFile SizeFile size in bytes from the filesystem.
NFILENumber of FilesTotal number of source files in the project.

Change Metrics (per file and project)

CodeNameDescription
CHG_SLOCChanged SLOCSource lines that exist in both files but differ.
DEL_SLOCDeleted SLOCSource lines in the old file not present in the new.
ADD_SLOCAdded SLOCSource lines in the new file not present in the old.
CRN_SLOCChurn SLOCCHG_SLOC + DEL_SLOC + ADD_SLOC. Total change volume.
MOV_SLOCMoved SLOCPhysical lines occupied by moved statements (see MOV_LLOC). A move is not churn: these lines are taken out of DEL_SLOC and ADD_SLOC, so CRN_SLOC = CHG_SLOC + DEL_SLOC + ADD_SLOC excludes them and MOV_SLOC is reported alongside it.
CHG_LLOCChanged LLOCLogical lines that exist in both but differ. The primary metric.
DEL_LLOCDeleted LLOCLogical lines in old not in new.
ADD_LLOCAdded LLOCLogical lines in new not in old.
CRN_LLOCChurn LLOCCHG_LLOC + DEL_LLOC + ADD_LLOC.
MOV_LLOCMoved statementsA statement deleted at one position whose identical text was added at another position in the same file — recorded once as a move, not as a delete plus an add. A move is not churn: CRN_LLOC = CHG_LLOC + DEL_LLOC + ADD_LLOC, and MOV_LLOC is reported alongside it, never inside it (ruled 2 Sep 2026). Moving code is reorganisation — human maintenance behaviour.
CHM_LLOCChanged and movedStatements edited inside a block that moved. Edits trump moves: such a statement is counted in CHG_LLOC (it is churn), never in MOV_LLOC, and reported here so both facts stay visible. The Code Browser paints it red with the navy move edge. Recognised only inside a moved block (at least two moved neighbours); a lone statement that moved and was edited leaves the same trace as a delete plus an unrelated add and is not recognised.
REP_CHURNReplacement Churn(ADD_LLOC + DEL_LLOC) / CRN_LLOC, bounded 0–1. The share of churn that was insertion and removal rather than in-place editing.
REWORKRework shareCHG_LLOC / CRN_LLOC — the complement of REP_CHURN and the readable form for comparisons: the share of all change activity spent editing statements that already existed. Hand-maintained established projects measure around 17% (1 statement in 6); intensively agent-assisted code around 0.2% (1 in 500). A low value alone is not evidence of AI — rapid greenfield growth is also low. Strongest read is against a project’s own history.
REWRITE_LLOCRewritten in placeCo-located DEL+ADD statement pairs inside one replace region that were rewritten beyond recognition — a block torn out and rewritten where it stood. Each pair consumes one DEL_LLOC and one ADD_LLOC.
PDEL_LLOCPure deletionsDEL_LLOC − REWRITE_LLOC: statements removed with nothing put in their place.
PADD_LLOCPure additionsADD_LLOC − REWRITE_LLOC: new statements that replaced nothing (growth).

How the shape metrics are classified — full disclosure

REWORK vs REWRITE, in one breath: REWORK measures editing — statements modified in place that recognisably survive; REWRITE counts replacement-in-place — statements torn out with something different written where they stood. Editing a novel: REWORK is touching up sentences, REWRITE is redoing the paragraph. REWORK is a ratio of total churn; REWRITE is a count of pairs.

REP_CHURN, REWORK, PURE_DEL and PURE_ADD are pure arithmetic over the churn counters. REWRITE is the one metric that rests on a judgement, so here is exactly how it is made. The differ aligns the two versions’ logical statements (Myers shortest edit script) and finds replace regions — gaps where old statements were removed AND new statements inserted at the same location. Inside each region, deleted and inserted statements are paired positionally (1st with 1st, up to the smaller count); each pair takes a character-overlap similarity test (integer Jaccard, threshold 30%). At or above threshold the pair is CHG (edited in place); below it, REWRITE (torn out, different content written in its place). Unpaired leftovers are pure deletions or pure additions.

Verify it yourself on any scan: REWRITE + PURE_DEL must equal DEL_LLOC, and REWRITE + PURE_ADD must equal ADD_LLOC — these identities hold on every run or the implementation is broken. The four composition figures sum to CRN_LLOC only when REWRITE is counted twice (CHG + 2×REWRITE + pure deletions + pure additions = CRN_LLOC) — each pair is one tile but two statements of churn. And REWORK + REP_CHURN = 1 exactly: they are complements (tiles round for display). Known limits, stated before you find them: the 30% threshold is a calibrated dial (statements near the boundary can flip); positional pairing can mis-pair inside a heavily rearranged block (aggregates barely move); moved-and-tweaked code counts as pure del + pure add, not REWRITE; and mechanical reformat sweeps inflate CHG. These metrics characterise a development process over a period — never a verdict on an individual change or author.

Disk space for large scans

Measured figures from a 1,400-scan campaign across the largest public codebases (2010–2026), so you can plan before scanning a big estate. The rule of thumb for git mode (codedelta --git a..b): peak disk ≈ repository clone + two extracted snapshot trees + output files — the engine extracts both versions to a temporary folder for the scan and deletes them afterwards. For two-directory mode the trees are already on disk, so the cost is outputs only.

Verified examples: curl (six-month scan) — clone 0.3 GB, peak under 1 GB, seconds to run. Linux kernel (one-year window, ~2 million logical statements of churn) — clone ~3 GB, peak ~7 GB. WebKit (half-year window, ~4 million statements of churn) — clone ~12 GB, peak ~17–20 GB. A full half-year WebKit scan completes on a consumer laptop.

Two further sizes to know: the results database grows with each recorded run (a few MB per large scan — tens of KB for typical projects), and the Code Browser embeds the full source of every changed file (and, within a 25 MB budget, of unchanged files too). Measured guidance: roughly 26 KB of report per changed file — about 80 MB / 5 seconds to open at 3,000 changed files, 210 MB / 19 seconds at 8,000. Past ~1.5 million display lines the generator automatically switches to embedding changed regions with context instead of whole files (each report states this in its story lines), which keeps very large scans openable; use the main report (much smaller) for a first look either way. Machines with 256 GB disks comfortably run any normal project scan; the multi-gigabyte figures above apply only to whole-history scans of the world’s largest repositories.

File Churn Metrics (project level only)

CodeNameDescription
CHG_FILEChanged FilesNumber of files present in both snapshots that changed.
DEL_FILEDeleted FilesNumber of files in the old snapshot not in the new.
ADD_FILEAdded FilesNumber of files in the new snapshot not in the old.
CRN_FILEChurn FilesCHG_FILE + DEL_FILE + ADD_FILE.

Data Metrics — code churn vs data churn (v1.8.8)

Large codebases carry data wearing code’s syntax: generated instruction tables, firmware images and lookup tables committed as single initializer statements (NVIDIA’s open GPU modules embed firmware as C arrays up to 3MB per statement — 28% of that tree’s source lines are data). Data metrics separate this from engineering change. A data statement is one whose initializer body holds 16 or more top-level elements (comma-separated values; a nested {…} or a call’s argument list counts as one element). Churned statements partition exactly: CRN_LLOC = code + data.

CodeNameDescription
DATA_CHG / DATA_DEL / DATA_ADDData-statement churnHow many of the churned statements (already counted in CHG/DEL/ADD_LLOC) are data initializers. Subtract from the headline numbers for working-code churn and working-code REWORK — the engineering signal with table refreshes removed.
ELEM_CHG / ELEM_DEL / ELEM_ADDElement churnChanged / deleted / added elements inside the data statements — “37 of 1,647 table rows updated”. Whitespace-invariant: reformatting a table produces zero element churn.
DATA_LLOCData statementsWhole-tree composition: how many of the codebase’s statements are data initializers.
DATA_SLOCData linesContent lines inside those initializer bodies — the share of your SLOC that is data, shown as a percentage in the terminal summary.
DATA_ELEMSData elementsTotal elements the data statements hold.

Coverage: C, C++, C#, Java, Objective-C, JavaScript and TypeScript (brace initializers), plus Erlang collection literals ([ ], { }, #{ }, << >>). The code/data churn partition (DATA_CHG…) applies to the semicolon languages only — Erlang reports composition and element churn. These metrics never alter CHG/DEL/ADD_LLOC, CRN or REWORK; they appear as additional CSV columns, terminal lines and an HTML report row, and are not yet stored in the trend database.

File Status Codes

StatusMeaning
CChanged — file exists in both snapshots and content differs
NNew — file exists only in the new snapshot (added)
DDeleted — file exists only in the old snapshot (removed)
UUnchanged — file exists in both with no code, statement or comment churn: byte-identical, or a whitespace-only edit (indentation, blank lines, trailing spaces)
OOld — CSV only: old metrics row for a changed file
XDiff — CSV only: arithmetic difference row for a changed file

Two-Pass LLOC Algorithm

LLOC is computed in two passes. Pass 1 strips all comments and string literals and identifies statement boundaries — semicolons in C-family languages, or statement-ending newlines (respecting brackets, strings and line continuations) in newline-terminated languages such as Python, JavaScript/TypeScript, Go, Ruby and Shell. Braces never count: a line holding only { or } is not a logical line in any language, and a closing brace neither ends nor starts a statement (ruled 2 Sep 2026). Pass 2 identifies function boundaries using brace counting and signature detection, allowing CodeDelta to attribute LLOC to specific functions. The two-pass approach resolves the common ambiguity where a single logical statement spans multiple physical lines.

When LLOC diverges significantly from SLOC (ratio > 3.0 or < 0.3), CodeDelta flags the file with an LLOC warning in the report. This usually indicates unusual formatting — very long chained expressions, or highly condensed single-line code.

Per-Language Parsing — Why the LLOC Is Accurate

Most churn tools apply a single generic rule to every language — count physical lines, or count semicolons. That is quick to build but wrong for any language whose statements do not end in a semicolon. Python, Go, Ruby, Shell and modern (semicolon-free) JavaScript all break a naïve counter: it either inflates the count (treating one statement spread over several lines as many) or collapses it (merging a whole function body into a single logical line). Both corrupt the churn figure.

CodeDelta instead ships a dedicated logical-line parser for each language family, encoding that language's real rules for where a statement begins and ends. The payoff is directly observable: the same logical change lands at a near-identical Replacement Churn in every language — the bundled multi-language demo (the same Account class in seven languages) demonstrates this side by side.

LanguageHow a logical line is determinedNotable cases handled
C, C++, C#, Java, Objective-C, PL/I, PHP, SQL, Perl, Rust Semicolon-terminated statements Comments and string literals stripped first; PHP # comments; SQL/Perl --; PL/I /* */
Python A newline ends a logical line at bracket depth 0; () [] {} and a trailing \ continue it; ; splits Triple-quoted strings, # comments, multiple statements per physical line
Dart Statements are strictly ;-terminated (no ASI) — the C-family semicolon rule, with scope braces discarded and map/set literals kept NESTED /* */ comments, /// doc comments, triple-quoted multiline strings, raw r'...' strings, ${} interpolation
JavaScript / TypeScript Automatic Semicolon Insertion — a newline ends a statement unless the line is incomplete (trailing or leading operator, open bracket); both ; and ASI are honoured, inside function bodies too Template literals, regex literals, method chains, and block {} vs object-literal {} disambiguation
Go, Kotlin, Swift, Scala, Groovy ASI rule — a newline ends a statement when the last token is value-ending (identifier, literal, ) ] }, ++/--) and not inside ( or [. Kotlin, Swift, Scala and Groovy are semicolon-optional and reuse this counter Composite literals vs blocks; back-tick raw strings spanning lines; statements inside function bodies
Ruby A newline ends a statement unless continued by a trailing operator, a leading . (method chain), a \, or an open bracket; ; splits Here-documents, #{} interpolation, block parameters
Shell A newline, ; or & ends a command unless continued by \, |, && or ||; pipelines and &&/|| lists are one logical line Here-documents, $( ) and ${ } expansions, word-boundary # comments, function and group bodies
R Newline-terminated (Go-ASI shape) with # comments; { } code blocks count statements inside; not inside ( or [ <- assignment and %>% pipe continuation, identifiers containing .
COBOL Sentence counting — a logical line is a COBOL sentence, ended by a separator period: a . followed by a space or end of line, outside string literals (the ISO/IEC 1989 rule). Note what this means: an IF … END-IF. sentence spanning several physical lines is one logical line, and several statements before a single period also count once — LLOC counts sentences, not verbs. Decimal literals (3.14) and picture clauses (PIC 999.99) never split, because their period is not followed by a space Fixed format (column-7 *// comments) and free format (*>) both recognised; sequence-number columns 1–6 and columns 73+ are ignored, so wholesale renumbering registers zero churn; reformatting a sentence across different line layouts registers zero LLOC churn
JCL, PowerShell Counted at SLOC granularity — LLOC = SLOC JCL //* comment lines; PowerShell # line and <# … #> block comments, # inside strings ignored
Ada, VHDL, Assembly, Fortran, VB, CSS, HTML, … Counted at SLOC granularity — LLOC = SLOC (no separate logical-line lexer) Per-language comment styles still recognised (--, ;, ', //)

This is why CHG_LLOC is the headline metric: it measures real statement-level change, invariant to formatting, and it is comparable across a polyglot codebase. Where a language has no dedicated lexer, CodeDelta falls back to LLOC = SLOC rather than guessing — and any of those can be promoted to full logical-line parsing on request (see Supported Languages above).

03

GUI Guide

Start the GUI server from the Terminal:

python3 /Applications/CodeDelta/codedelta_server.py

Then open http://localhost:7654 in your browser. The GUI runs entirely locally — no internet connection required, no data leaves your machine.

Analysis Mode Selector

The Run Analysis tab is split into two columns. Pick whichever fits the work you're doing:

Compare Projects (left column)

ModeWhat it does
Code ChurnStandard SLOC/LLOC churn metrics between two snapshots (Old and New). The classic CodeDelta function.
Code Churn + AI AuditChurn metrics (Old vs New) PLUS AI Audit on the new snapshot. Single pass, three reports.
Project MetricsSingle project, no comparison and no AI — SLOC/LLOC/comment/file counts on one folder. The fastest mode; use it to confirm all code parsed cleanly. Columns are filterable with Metric Sets.

Single Project (right column) — requires only one directory

ModeWhat it does
AI AuditRuns BOTH AI Code Scan and Agent Scan, producing TWO reports side by side. Use this when you want a complete AI assessment.
AI Code ScanJust the GSS + MLS → AIC analysis. Produces codedelta_ai_code_scan.html with an inline source viewer that highlights flagged lines.
AI Agent ScanJust the AIS (Agent Initiation Signature) analysis. Produces codedelta_agent_scan.html for security review.

Every single-project mode (AI Audit, AI Code Scan, AI Agent Scan) also runs the engine as a snapshot, so each one shows the same project-metrics tiles — you can always confirm how much code was parsed, whichever scan you ran. The Code Browser has a light/dark toggle in its top-right corner, defaulting to light.

Run Analysis Fields

FieldDescription
Old ProjectPath to the previous version of the source code.
New ProjectPath to the current version of the source code.
Exclude DirectoriesComma-separated directory names to skip (e.g. vendor,tests,node_modules). New in v1.4.0.
Extension OverridesMap non-standard extensions to existing language parsers. Comma-separated ext=lang pairs (e.g. h2=cpp,inc=php,ksh=sh). New in v1.4.2.
HTML ReportOutput path for the HTML report.
DatabasePath to the SQLite database file. Accumulates all runs for trend analysis. Defaults: ~/Library/Application Support/CodeDelta/codedelta.db on macOS, ~/.local/share/CodeDelta/codedelta.db on Linux, %APPDATA%\CodeDelta\codedelta.db on Windows. Survives reinstalls.
Project NameA label for this project, shown in reports and the History tab.
Old LabelA label for the old snapshot (e.g. v1.0, sprint-13).
New LabelA label for the new snapshot (e.g. v1.1, sprint-14).
Snapshot DateThe date the source was extracted (YYYY-MM-DD). Stored in the DB and shown in reports. New in v1.4.0.
Metric SetOptional: select a named metric set to filter which columns appear in the report and CSV. New in v1.4.0.

Metric Sets

A Metric Set is a named subset of metric columns. When active, only the selected metrics appear in the HTML report table and CSV output. This is useful for management reports that only need CHG_LLOC and ADD_LLOC, without the full detail of every metric.

To create a Metric Set:

  1. Click Manage Sets next to the Metric Set dropdown.
  2. Enter a name for the set (no spaces — underscores are fine).
  3. Tick the metric codes you want to include.
  4. Click Save Set.

The set is saved in the database and appears in the dropdown for future runs. To edit an existing set, click Edit beside it — it loads into the editor. To delete, click Delete.

To run without a metric set filter, leave the dropdown on — All metrics (no filter) —.

Available metric codes for sets: LOC, SLOC, LLOC, PLOC, COM_LOC, J_COM, C_COM, EOL_COM, Bytes, CHG_SLOC, DEL_SLOC, ADD_SLOC, CRN_SLOC, CHG_LLOC, DEL_LLOC, ADD_LLOC, CRN_LLOC, REP_CHURN, REWORK, REWRITE_LLOC, PDEL_LLOC, PADD_LLOC, CHG_COM, DEL_COM, ADD_COM, CRN_COM, CHG_FILE, DEL_FILE, ADD_FILE, CRN_FILE

Excluded Directories

Enter a comma-separated list of directory names to exclude from both the old and new scans. For example: vendor,tests,third_party,generated. The names are matched against each path component — you do not need to provide full paths.

Built-in excluded directories (always skipped): .git, .svn, .hg, node_modules, __pycache__, vendor, dist, build, Debug, Release

Symbolic links are never followed, whether they point at a file or a directory: each is skipped and counted among the files not measured. The build-file change alert in Threat Detection looks inside build/ even though the churn scan skips it.

Excluded directories are stored in the database run record and shown in the report header, so you always know what was and wasn't included in a historical run.

Extension Overrides

Some organizations use non-standard file extensions — for example .h2 for C++ headers, .inc for PHP include files, or .ksh for shell scripts. By default CodeDelta ignores files with unrecognized extensions. Extension overrides let you map any extension to an existing language parser without recompiling.

Enter a comma-separated list of ext=lang pairs in the Extension Overrides field:

h2=cpp,inc=php,ksh=sh

The target language can be any known extension (cpp, py, java, sh etc.) or a language name. Unknown target languages are silently ignored. The override takes effect before directory scanning, so all file matching uses the updated map.

Complete extension reference

LanguageAuto-detected extensions
C / C++c h cpp hpp cc cxx
C#cs
Javajava
JavaScript / TypeScriptjs jsx ts tsx
Pythonpy pyw
PHPphp
Rubyrb
Perlpl pm
Shellsh ash bash bsh csh tcsh tsh zsh
SQLsql
SQL (Oracle/PL-SQL)pls pks pkb
Visual Basicvb bas cls frm
VBScriptvbs
Windows Batchbat cmd
Adaada adb ads
COBOLcbl cob cobol cpy
JCLjcl
PL/Ipli pl1
Objective-Cm mm
Scalascala sc
Groovygroovy gvy gradle
PowerShellps1 psm1 psd1
Fortranf f90 f95 for
Assemblyasm s
VHDLvhd vhdl
HTMLhtml htm htp
ASPasp aspx
JSPjsp
CSScss
XMLxml xsd xsl xslt wsml
IDLidl
Symbian MMPmmp
PowerBuildersrd srf srs sru srw
Dartdart
Erlangerl hrl app appup rel escript xrl yrl
DeviceTreedts dtsi
ASN.1 / MIBasn1 asn mib
Make / CMake / Dockerfilemk gmk mak kbuild cmake + well-known filenames
Protobufproto
Data formatsjson yaml yml toml ini cfg properties
Smalltalkst
Eiffele
Lisplisp lsp cl scm el
μCodeuc
Texttxt tsv cvs install readme

When mapping a custom extension via the override field, the target side of the ext=lang pair can be any of the codes above (e.g. cpp, py, java, sh, f90). Both the alias and the destination must already be known to CodeDelta — unknown destinations are silently ignored.

Results Tiles

After a run, results appear as coloured tiles in four groups:

History Tab

Shows all previous runs stored in the selected database. Columns include run date, snapshot date, project, old/new labels, file counts, SLOC/LLOC totals, and churn metrics. Click any row to open its HTML report.

Trend Tab

Charts CRN_SLOC and CRN_LLOC over time for a selected project. A declining trend indicates the codebase stabilising toward release. An increasing trend near a release deadline is a quality risk.

04

The Code Browser

Every scan generates a Code Browser (*_diff.html, beside the report) — a self-contained page that reads the scanned code. Five tabs stay at the top of every screen: Changes (comparisons only), Overview, Files, Classes and Visualiser; the browser’s Back button retraces your steps and every screen carries a breadcrumb. For a churn comparison the Changes tab is the side-by-side diff — the place to read the change and the evidence behind every number the scan reported. Its organising rule: every counter is a claim you can click, walk, and cite. A single-project scan has no Changes tab: the same page is the project’s code browser — structure, classes, files and their relationships.

The Overview

The page opens on the Overview. For a comparison it begins with the scan overview: one plain-language sentence of totals, then the changed files ranked by how much happened in them, each with a one-line story (“Mostly new content — 564 lines added … 15 statements moved within the file”); click any file to open it in the diff. Below that (and first, for a single-project scan) comes the project’s structure: languages, top-level directories with their include links, every class (language, files, methods, who it talks to), every file (filter, sort, churn chips for changed files) and the strongest relationships — directory include links and class “talks-to” pairs.

Files, Classes, Visualiser

Files is the directory tree (changed files wear C/D/A chips and open in the diff; directories show how many of their files changed) with a reader for any file: its classes, its functions in line order, what it includes and who includes it, and its source with line numbers. Classes lists every class or namespace container found (C++, C# and Java) — files, methods with file and line, the classes its code mentions (a textual name match, a pointer for review, not a resolved call graph, each mention cited by file and line) and the classes that mention it. Visualiser draws the include map (directories) and the class ego view in 3D. Source is embedded for unchanged files up to a 25 MB budget; past it, files show structure only and the page says how many.

Code Browser — class ego view
Class ego view. One class at the centre (here folly, across 51 files), its methods round it — red where this scan churned them — and the classes its code mentions as satellites; every link cites the file and line of the mention. A pointer for review, not a resolved call graph.

The Changes tab

Comparisons only: the changed-file list on the left (sort by path, churn or moves; MOV filter; per-function counts), the file’s diff on the right.

Reading a file

Under the toolbar, a story line describes the file in words before any code. Colours follow the CodeDelta convention: red changed, blue deleted, green added, yellow comment-only churn, violet moved. On changed rows the exact tokens that differ are shaded; when a pair of lines is mostly different the whole line is shaded instead — that pair is effectively a removal and an addition that met at the same diff position, not an edit. Alignment gaps (a line that exists on only one side) show as hatched space.

Walking the numbers

Click any counter in the toolbar — CHG, DEL, ADD, MOV, XMOV, AI% — and the stepper (◀ ▶) walks exactly the rows that counter counts, e.g. “changed 3/106”. The Ledger button decomposes every counter into its rows — each entry jumps to its line, and “Copy as text” exports the lot with citable links. Where the displayed rows and the engine’s counted total differ (comment-adjacent alignment), the ledger shows both numbers side by side.

Moves — within and between files

A moved statement (identical text deleted at one position, added at another, at least 12 characters and unique on both sides) paints violet at both ends, each end carrying a chip naming its counterpart (“→ L163”); click the chip to jump. The stepper walks moves as pairs (“move 4/9”), and the ☰ button lists every move in the file. Cross-file moves (dashed chips, XMOV counter) are statements that left for, or arrived from, another file — clicking follows across files. XMOV is a reporting overlay: the churn counters still count the deletion and the addition, so per-file numbers never depend on unrelated files.

Git-derived overlays

When the scan can see git history — always in --git mode, or when a scanned directory lies inside a git work tree — three further overlays appear. AI provenance: lines authored in commits signed by an AI tool (Claude Code, Copilot, Cursor, Aider and others) carry a teal mark on the line number and the code edge; the AI% counter walks them, and hovering names the tool. Age of destroyed code: the story line reports what share of the churned code was under 30 days old — rework of recent work. People: the overview lists, per author, how many lines of their code were churned away and how many of the new lines they wrote. All three are reporting overlays; none of them changes a churn counter, and none appears when scanning plain directories with no git history.

Getting around

The minimap strip on the right shows every change in the file as a coloured mark — click it to jump. Search in file marks its matches in the landed row (Enter / Shift+Enter cycle). Double-click any line number to copy a link that reopens the report at exactly that line — the address bar always reflects where you are, so a finding can be pasted into a ticket. Keyboard: j/k step the selected counter, m moves, a AI-signed lines, f the file filter, / search; the ? button holds the full legend. Large, sparse files (changelogs) open in Changes Only automatically, with the collapse stated in the story line; the … separators expand in place. The file list sorts by path, churn, or moves, filters by name, and the bar between the list and the code drags to resize (double-click resets).

05

Command Line Reference

Basic Usage

codedelta <old-dir> <new-dir> [options]
codedelta --git <oldref>..<newref> [options]   # run inside your git repo

Git Mode

With --git there is no need to check out two copies of the project — CodeDelta extracts both committed snapshots itself (via git archive, so the state of your working tree never affects the result), compares them, and removes the temporary trees afterwards. Refs can be tags, branches, or hashes: --git v1.7..v1.8, --git HEAD~10..HEAD, or a bare --git v1.7 meaning v1.7 against HEAD. Labels, the project name, and the snapshot date default to the refs and the new ref's commit date — useful for backfilling a longitudinal database from historical releases. Requires git and tar on the PATH (both standard on macOS, Linux, and Windows 10+). New in v1.8.2.

Full Options

FlagDescription
--git <a>..<b>Compare two committed git refs instead of two directories (see Git Mode above). New in v1.8.2.
-o, --output <file>HTML report output path (default: codedelta_report.html)
--csv <file>Also write a CSV report
--xml <file>Also write a structured XML report. Contains all metrics including PLOC.
-d, --db <file>SQLite database path (default: codedelta.db)
--project <name>Project name for the database and report
--old-label <label>Label for the old snapshot
--new-label <label>Label for the new snapshot
--note <text>Freeform note stored in the database run record
--exclude <dirs>Comma-separated directory names to skip (e.g. vendor,tests). New in v1.4.0.
--snapshot-date <date>Date source was extracted, YYYY-MM-DD. New in v1.4.0.
--metric-set <codes>Comma-separated metric codes to include in report/CSV. New in v1.4.0.
--ext <pairs>Map non-standard extensions to language parsers. Comma-separated ext=lang pairs, e.g. h2=cpp,inc=php. New in v1.4.2.
--threshold-churn <n>Exit with code 2 if CRN_LLOC exceeds n (for CI gates)
-v, --verboseVerbose output
-q, --quietSuppress all stdout output
-V, --versionPrint version and release notes
-h, --helpPrint usage

Exit Codes

CodeMeaning
0Success
1Generic failure (I/O error, missing directory, report write failed)
2Invalid arguments
3Churn threshold exceeded (--threshold-churn) — deliberate build-fail signal
4No valid license found

CSV Output Format

The CSV has one header row and one or more data rows per file. For changed files, three rows are output:

The CSV output format is compatible with standard spreadsheet tools. Unchanged and deleted files have one row only. The file ends with a TOTAL row and a NFILE summary row.

If a Metric Set is active via --metric-set, only the specified columns appear in the CSV header and data rows.

Example: Nightly Build Integration

#!/bin/bash
codedelta /builds/project-v1.1 /builds/project-v1.2 \
  --project "MyApp" \
  --old-label "v1.1" \
  --new-label "v1.2" \
  --snapshot-date "$(date +%Y-%m-%d)" \
  --exclude "vendor,node_modules,generated" \
  --db /var/lib/codedelta/myapp.db \
  -o /var/www/reports/myapp-latest.html \
  --csv /var/www/reports/myapp-latest.csv \
  --threshold-churn 5000 \
  -q

if [ $? -eq 2 ]; then
  echo "ALERT: churn exceeds threshold — build is hot"
  exit 1
fi

Threat Detection — the security view

For the security reader — the auditor, the AppSec engineer — CodeDelta’s scans are five threat-detection instruments in one pass. Everything dangerous that hides in a repository — an implant, a rogue agent, a leaked key — leaves hard, checkable evidence; each instrument looks for one kind of it and reports file-and-line facts, never verdicts of malice.

  1. Build-file change alert — every two-version scan lists the build, CI and packaging files that changed (the xz-utils entry route). Install hooks (code that runs on install) ride first; below them, build files that fetch remote content at build time — and for a changed fetcher the alert prints the URL delta itself (+ new-source / − old-source), because one edited download URL redirects the build’s supply chain.
  2. Build & deployment surface inventory — the standing map of what build machinery exists in the tree, changed or not, in every agent report.
  3. Agent Scan — the AI inside the software: SDK imports and model calls by name, raw endpoints, and the rogue pattern (model output flowing into exec or a shell — how prompt injection becomes code execution), plus the artifacts agents leave behind, down to tier-3 residue. The same layer detects committed credentials with a fixed table of documented key formats (AWS, GitHub, OpenAI, Anthropic, Google, Hugging Face, Slack, Stripe live keys, PEM private keys) — no entropy scoring: a string matches a vendor’s published format or it is not flagged. Findings are redacted everywhere, including the report’s embedded source viewer, because reports travel. Rotate the key first, then remove it: removal alone leaves it valid in git history.
  4. AI Bill of Materials--bom emits the record (native JSON or CycloneDX): every provider, jurisdiction, sovereignty risk, with files named.
  5. The merge gate--fail-on-new blocks pull requests that add findings against your baseline; --gate fails builds on policy. The rogue pattern and denied jurisdictions gate by default; three further switches ship off so a test fixture can never break a build uninvited — enable them in your --gate-policy file:
{
  "fail_on_committed_credentials": true,
  "fail_on_new_install_hook": true,
  "fail_on_new_fetcher": true
}

“New” is computed against the old side of the diff: a project that has always fetched does not fail — only the diff where fetching started does. All of it runs in one scan (GUI: Churn + Agent Scan; headless: --mode churn_agent --bom --gate --fail-on-new) and inside your own infrastructure.

At the command line

One line runs all five layers:

./codedelta-gui scan new/ old/ --mode churn_agent --bom --gate --gate-policy policy.json --fail-on-new

What comes back on the terminal: [build] ALERT: with per-file status lines, ** install hook ** / ** fetches remote content at build time ** markers and the +/ URL delta lines beneath a changed fetcher; [agent] tier counts, artifact and ALERT: N committed credential(s) lines (values redacted), followed by the gate-off notice naming the exact policy key to flip; [bom] summary; and [gate] pass or an itemised violation list. Exit code 0 clean, 3 on a --fail-on-new regression or a gate failure — the exit code is what makes CI block the merge. The reports — the agent HTML with the red boxes, the AI-BOM JSON — are written alongside for the humans.

The standalone threat-detection mini guide covers each layer in depth, with the report screenshots and the full policy reference.

Headless Batch CLI (scan / trend)

Everything above drives the C++ engine directly. The batch CLI runs that same engine and adds the rest of the product headlessly — the AI scans, the pass/fail gates, SARIF, the AI-BOM and the longitudinal database. Two subcommands: scan and trend. Note the argument order: the engine takes old new; the batch CLI takes new old.

codedelta-gui scan <new_dir> [old_dir] [options]   # from the installed bundle
codedelta-gui trend <db> [--out FILE] [--project NAME] [--limit N]

The full scan --help, verbatim:

CodeDelta batch scan (headless — no GUI)

Usage:
  codedelta-gui scan <new_dir> [old_dir] [options]

  <new_dir>   directory to scan (required)
  [old_dir]   previous version, for churn/diff (optional; omit for snapshot)

Modes (--mode M — the same choices the GUI offers):
  churn         churn only                 (default when two dirs are given)
  churn_agent   churn + Agent Scan, no ML  (the GitHub Action's default)
  agent         Agent Scan only
  ai            AI code audit only
  ai_audit      AI audit + Agent Scan on one dir (default when old_dir omitted)
  both          everything: churn + AI audit + Agent Scan

Output (default: all formats):
  --out-dir DIR     where to write outputs        (default: current dir)
  --bom FILE        write an AI Bill of Materials (providers, jurisdictions,
                    risk/cost/sovereignty flags) for the Agent Scan
  --bom-format F    native (default) or cyclonedx (CycloneDX 1.6)
  --gate            fail (exit 3) on the default policy: egress to a non-allied
                    jurisdiction (CN/RU/KP/IR) or the rogue exec-on-model pattern
  --gate-policy F   fail using a custom JSON policy (deny_jurisdictions,
                    allow_providers, deny_flags, max_risk,
                    fail_on_agent_artifacts — off by default; true fails on
                    tier-3 agent artifacts: rogue residue / agent credentials)
  --html            HTML reports (churn + audit + agent)
  --csv             raw CSV (engine metrics + audit + agent per-file)
  --json            raw JSON (audit + agent)
  --xml             engine EPM-compatible XML
  --db PATH         longitudinal SQLite DB
  (if none of --html/--csv/--json/--xml given, ALL are produced)

Labels / trending:
  --project NAME    --note TEXT   --old-label TEXT   --new-label TEXT
  --threshold N     AI sensitivity 0-100            (default 50)

Baselining (suppress known findings; alert only on new ones):
  --write-baseline FILE accept the current flagged files; snapshot to FILE
  --baseline FILE       compare this scan to FILE; report only what got worse
  --fail-on-new         exit 3 if any new finding vs --baseline (CI merge gate)

CI integration (with --mode ai/agent/both):
  --sarif               write SARIF 2.1.0 for GitHub code-scanning
  --pr-comment          write a markdown summary for a pull-request comment

Performance:
  --jobs N              parallelise the AI audit across N processes (or 'auto'
                        for all CPUs). Big speed-up on large scans; default 1.

Cron / alerting:
  --quiet               errors only
  --fail-on-critical    exit 3 if any agent-scan CRITICAL file
  --fail-on-ai N        exit 3 if AI%% >= N
  -h, --help

Stopping a run:
  Press Ctrl-C (or send SIGTERM) to terminate cleanly. The scan stops within a
  second, prints a notice, and discards partial results — nothing is written
  (the engine's run rolls back; reports/DB are written only on completion).

Exit codes: 0 ok · 2 usage/error · 3 threshold/new-finding tripped · 130 terminated by user

Example: Metric Set for Management Report

codedelta /src/old /src/new \
  --metric-set "SLOC,LLOC,CHG_LLOC,ADD_LLOC,CRN_LLOC,CHG_FILE,CRN_FILE" \
  -o management_report.html \
  --csv management_report.csv
06

AI Code Scan & AI Audit

About CodeDelta's AI Detection Features — Please Read

CodeDelta is built on 20 years of expertise in code-churn measurement across huge legacy codebases deployed globally. Its core purpose is to measure changed, added, and deleted SLOC and LLOC across massive, multi-language projects — and that is where its proven value lies.

It seemed natural to extend this into the emerging area of AI-generated-code and AI-agent detection. We researched this seriously, using both a heuristic approach — GSS (Generation Signature Scoring) — and a more sophisticated machine-learning approach — MLS (Machine Learning Scoring) — the latter trained on datasets of known AI- and human-written code.

Our honest finding: AI-generated code can be detected only unreliably. It is possible to identify signals and properties that suggest code was AI-generated, but no technique we assessed does so dependably. In particular, if a developer instructs an AI to write code in the style of a human, every detection method we tried or uncovered proved ultimately unreliable. The differences that remain detectable are largely cosmetic — commenting and formatting habits — which are easily changed and are not proof of authorship.

For that reason, the AI Scan is a pointer toward code that may warrant a closer look — nothing more. It is not a determination of authorship, and it carries a meaningful false-positive rate on code unlike its reference data. Treat every flag as a prompt to review, never as evidence.

We also added a churn metric, Replacement Churn, on the observation that AI tools often delete and replace whole blocks rather than editing in place. This too is only a pointer: it reflects a workflow pattern, not authorship, and as AI tooling shifts toward in-line editing the signal is likely to weaken. It is a useful hint, not a measure of AI code.

The one component that detects something concrete is the Agent Scan, which identifies calls to known AI-agent frameworks and SDKs — because those are real, named artifacts in the code rather than statistical guesses.

In short: the AI element is provided free of charge, as an experimental extra, offered honestly for what it is — a set of pointers, not verdicts. Because it is included at no additional cost and makes no claim to reliable or definitive AI detection, it should not be regarded as a paid feature or relied upon as one. We genuinely welcome feedback on whether the AI features are useful to you and how they might be improved.

By contrast, CodeDelta's churn engine — the measurement of SLOC and LLOC change across versions — is the product's mature, dependable core, refined over two decades and trusted on large-scale legacy systems worldwide. The churn engine is the product you are purchasing; the AI features are a complimentary (no-cost) addition to it.

CodeDelta detects AI-generated code via two complementary scans:

The AI Audit mode in the GUI runs BOTH scans in a single pass, producing two separate HTML reports (codedelta_ai_code_scan.html and codedelta_agent_scan.html).

How GSS Works

Each file receives a Generation Signature Score (GSS) from 0 to 100. The score is the weighted sum of several signals. A high score indicates the file exhibits many of the structural patterns associated with AI-generated code. A low score does not prove the code is human-written — it means no unusual patterns were detected.

SignalWeightWhat it detects
Structural uniformity40Many repeated function bodies in one file. Strong signal — humans parameterise repeated logic, AI/generators produce N copies. New in v1.5.0.
Docblock coverage40Unusually uniform documentation — every function has a structured docblock
Guard clause density35High ratio of defensive checks (null checks, boundary guards) to total code
Formulaic exceptions30Exception messages that follow predictable patterns ("Invalid X: must be Y")
Audit/notify coupling25Logging calls systematically paired with operations
Annotation saturation20High density of decorators, attributes, or annotations
Zero inline comments10No // inline comments despite high docblock coverage
High add velocity15Large newly-added files with no history of incremental change
LLOC warning15SLOC/LLOC ratio anomaly suggesting unusual formatting

Risk Ratings

The score used for classification is AIC where an ML model exists for the file's language, and GSS alone otherwise. Languages without an ML model are capped at ELEVATED — the heuristics can never declare HIGH without ML confirmation. (The single exception: a user-defined custom pattern with the override flag forces HIGH.)

RatingRuleMeaning
HIGHscore ≥ threshold + 20 (ML-supported languages only)Strong AI-generation characteristics — review first
ELEVATEDscore ≥ thresholdEnough signals to warrant review
NORMALscore < thresholdBelow the review line at this sensitivity

Sensitivity Setting

Sensitivity excludes and includes nothing. Every file is always scanned, every signal always computed, and the ML model always runs — a file's scores are identical at every setting. The slider only moves the two classification lines drawn over those fixed scores:

RatingRuleStrict (30)Balanced (50)Conservative (70)
HIGHscore ≥ threshold + 20≥ 50≥ 70≥ 90
ELEVATEDscore ≥ threshold≥ 30≥ 50≥ 70
NORMALbelow threshold< 30< 50< 70

Two useful corollaries. First, the flagged sets nest: everything flagged at Conservative is also flagged at Strict — lowering the threshold only adds files further down the ranking; it never changes any file's score. Second, because the report embeds source evidence for every flagged file, stricter settings produce larger reports and longer report-generation times.

Validation Results

GSS was validated against two corpora. A set of 26 human-written C++ files produced a mean score of 0.0 with no HIGH ratings. A set of 12 AI-generated files across multiple languages produced a mean score of 48.9 with 2 HIGH and 3 ELEVATED ratings. Zero false positives were observed on the human corpus.

Important Caveats

GSS measures patterns, not intent. A highly disciplined human developer who writes uniform docblocks and systematic null checks will score higher than average. The score is a signal for review, not a determination of authorship. It is most useful when scores are unexpectedly high for files in a codebase where the baseline is known.

ML Score (MLS) and AI Confidence (AIC)

When the ML plug-in is installed, the AI Code Scan report shows two additional columns alongside GSS:

Language coverage

LanguageGSSMLSNotes
Python✓ (83%)Original ML model
C / C++✓ (99%)
Java✓ (99%)
C#✓ (97.5%)New in v1.7.0
JavaScript / TypeScriptML model planned for v1.8
GoML model planned for v1.8
Other languagesGSS-only scoring

When MLS is unavailable for a language, the AIC column shows and risk classification uses GSS alone. All other functionality is unaffected.

Risk Bands

Files are placed into risk bands based on the AIC score (or GSS where MLS is not available):

BandAICMeaning
HIGH50+Strong evidence of AI generation. Review the file.
ELEVATED30–49Several signals present. May warrant review depending on context.
NORMAL<30No unusual patterns detected.

The AI% metric — what it means

AI% is the headline project-level number on the AI report and GUI. It is the proportion of code, measured in lines, that sits in files flagged HIGH or ELEVATED:

So “AI% = 29” means 29% of the codebase, by lines, lives in files the scan flagged HIGH or ELEVATED — in a snapshot, 29% of total source lines are in HIGH/ELEVATED files.

What AI% is NOT

It is not a claim that 29% of the code was written by AI, and it is not a probability or confidence score. It is a coverage measure — how much of the codebase, by volume, sits in files worth a closer look. Flagging means a file “shows characteristics associated with AI generation,” which CodeDelta treats as a pointer for review, not a verdict on authorship. Whole files are flagged or not; AI% is the line-share of the flagged ones.

AI Detection Config

The AI Detection Settings card on the Run Analysis page (visible in any AI Audit or AI Code Scan mode) opens a configuration dialog where you can fine-tune detection per language. The card's status line shows "X/Y signals active · N custom patterns" — a quick view of how much of the default scoring is in effect.

Language tabs

The dialog has six tabs: C/C++, Java, Python, C#, JavaScript, Go. The tab bar is sticky — it stays visible as you scroll through long signal lists.

Built-in signal toggles

Each language has a set of built-in signals. You can toggle individual signals on or off. This matters because some signals are context-dependent:

Signal configuration is saved to ml_config.json in the CodeDelta directory and takes effect on the next analysis run.

Custom patterns

Add patterns specific to your codebase. Four pattern types:

Each custom pattern can be set to Override — when the pattern fires, the file is always rated HIGH regardless of the ML score. Use this for definitive markers in your codebase.

Custom patterns apply across all AI Code Scan and AI Audit runs until removed. Saved to ml_config.json.

07

Agent Scan — Agent Initiation Signature (AIS)

In plain terms: Agent Scan finds the files that actually use AI — code that calls or runs an AI model while your program runs (for example, importing an AI library or sending it a prompt). It answers one question — "does this code talk to AI?" — not "was this code written by AI?" (that's the AI Code Scan). It flags where AI is wired into your software and highlights the riskier uses.

Try it — demos. CodeDelta ships with no demo code. Each demo card on the app's home screen downloads its own small sample project from the public code-delta-app/demo repository into a private folder (~/.codedelta/demo-code) when you press its Download button, scans it locally, and keeps it until you press Delete. The Churn Demo compares one small Account class across seven languages over two versions. The Agent Scan Demo scans a small project full of embedded AI usage (SDK imports, agent orchestration, exec on model output, raw API endpoints, non-Western SDKs) plus one clean control file — the files are synthetic and never executed, antivirus tooling may flag them, which is expected, and that download asks for your confirmation first. View demo code opens the sample's source so you can check every figure and flag against it. From a terminal the same scans are:
python3 codedelta_server.py scan <folder>/churn-demo/new <folder>/churn-demo/old --mode churn --html
python3 codedelta_server.py scan <folder>/agent-scan-demo --mode agent --html
Each sample's expected results are listed in its README.md.

The Agent Scan analyzes source files for code that initiates AI agents at runtime — code that imports AI SDKs, orchestrates agents, executes dynamic code, or constructs prompts from user input. This is entirely distinct from the AI Audit: Agent Scan detects code that runs AI agents, not code that was written by AI.

What Agent Scan is: A pattern-matching detector that looks for specific import statements, function calls, and code proximity patterns associated with AI agent invocation. It operates entirely on source text — no execution, no runtime analysis.

What Agent Scan is not: A security scanner, a vulnerability detector, or a complete AI usage audit. It cannot detect obfuscated AI calls or indirect agent invocation. Raw HTTP calls to recognized model endpoints are detected (v1.8.2), but calls to unlisted or private endpoints are missed unless you add them — see Recognized providers & extending the list.

How It Works

Agent Scan reads each source file and looks for four categories of pattern using regular expression matching. Each pattern category carries a weight. Files whose total weight exceeds the configured threshold are flagged.

The scan is entirely static — it reads source text only and never executes any code. It works on files even when dependencies are not installed.

AIS Signal Categories — the exact points table

Every file starts at an Agent Initiation Score (AIS) of 0. Signals add points, capped at 100. The table below is the complete, current scoring model — there are no other inputs, and no randomness: the same file always produces the same score.

SignalPointsWhat it detects
AI SDK import+40An import of a recognised AI SDK or framework — the full, current list is in “Recognized providers & extending the list” below (plus anything you add via codedelta_agents.json).
Known model endpoint+40A raw HTTP call to a recognised model endpoint (api.openai.com, bedrock-runtime, api.deepseek.com…) with no SDK import — language-agnostic, comments stripped first.
Agent orchestration+40Invoking agent behaviour, not just importing it: Agent(, AgentExecutor(, chain.invoke( and similar.
Hand-rolled agent loop+40An AI API call inside a loop — a self-driving agent pattern without a framework (also raises the separate cost-risk flag).
Rogue pattern+70eval/exec near an AI API call — model output executed as code. Forces HIGH regardless of everything else.
Dynamic execution (plain)+50eval(/exec( in Python (in Java/C++/JS these are ordinary identifiers and are deliberately not flagged).
Indirect execution+50Aliased or obscured exec access — getattr, globals() dictionary tricks. If an AI call is anywhere in the file this also counts as the rogue pattern.
Shell execution with variables+40subprocess/shell invocations built from variables — a command-injection vector.
Dynamic import+20Runtime module loading (__import__ and kin).
Prompt-injection vectors+18 / +35Unsanitised user input interpolated into prompts: one or two occurrences +18, three or more +35.

How the score becomes a rating

Three fixed cut-offs, applied to the capped score:

RatingRuleWhat it means in practice
NORMALAIS < 40No AI-agent initiation signatures.
ELEVATEDAIS ≥ 40“This file uses AI.” Any single AI signal lands exactly on 40 by design — ELEVATED carries no judgement beyond that fact.
HIGHAIS ≥ 70, or eval/exec combined with an AI SDK, or the rogue pattern (unconditional)“This file uses AI in a way that can execute or be steered” — either the one genuinely dangerous construct, or two signals compounding.

CRITICAL is the reserved top tier; the current deterministic scan rates files HIGH at most, so a CRITICAL count of 0 is expected. Data-sovereignty, cost-risk and agent-artifact findings are reported alongside but deliberately do not move the AIS — they are compliance information, not initiation evidence.

The Rogue Agent Pattern

The most serious finding is the Rogue Agent pattern: a dynamic code execution call (eval, exec, or subprocess) that appears within 10 lines of an AI API call. This pattern indicates code where an AI model's output may directly influence what gets executed on the host machine — a significant and specific security risk.

A file flagged for the Rogue Agent pattern has its AIS rating escalated to HIGH regardless of its total score.

Example of Rogue Agent pattern:

response = client.chat.completions.create(...)   # AI API call
code_to_run = response.choices[0].message.content
exec(code_to_run)                                 # within 10 lines — ROGUE AGENT

CRITICAL Risk Rating

A file that scores HIGH on both GSS (appears AI-generated) and AIS (initiates AI agents) receives a CRITICAL rating. This is the highest-risk scenario: code that nobody may have fully reviewed or understood, which autonomously initiates AI agents at runtime.

Source Viewer

The Agent Scan report includes an inline source viewer. Click View Source on any flagged file to see it with dangerous lines highlighted:

SDK Inventory

When AI SDK imports are found, the Agent Scan report includes an SDK Inventory — a list of each recognized AI framework detected and the number of files importing it. This gives a quick overview of which AI dependencies are present across the codebase.

Governance & compliance flags — data sovereignty and cost

Beyond which AI a file uses, Agent Scan flags two things that matter to compliance and budget owners, rolled up in a Governance & Compliance panel at the top of the report:

Both are informational compliance/cost flags — they do not change a file’s AIS risk score. Endpoint matching ignores comments and docstrings, so a hostname that appears only in a comment is not flagged.

AI Bill of Materials & CI policy gate

From the command line, Agent Scan can export an AI Bill of Materials — a machine-readable inventory of every AI provider the code touches, with jurisdiction, file usage, and the risk / cost / sovereignty flags:

python3 codedelta_server.py scan ./src --mode agent --bom ai-bom.json
python3 codedelta_server.py scan ./src --mode agent --bom ai-bom.json --bom-format cyclonedx

Two formats: native (CodeDelta-AI-BOM, the richest) or cyclonedx (CycloneDX 1.6 — SDK libraries become components, model endpoints become services with an outbound “prompt” data flow, for existing SBOM tooling).

The same data drives a CI policy gate. --gate fails the build (exit code 3) on the default policy: any egress to a non-allied jurisdiction (CN/RU/KP/IR) or the rogue exec-on-model pattern. --gate-policy policy.json uses your own rules and implies the gate:

{
  "deny_jurisdictions": ["CN", "RU"],
  "allow_providers": ["openai", "anthropic"],
  "deny_flags": ["rogue_pattern", "cost_risk"],
  "max_risk": "ELEVATED",
  "fail_on_agent_artifacts": true
}

Each violation is listed and the process exits non-zero, so it drops straight into a CI step (the gate needs an Agent Scan: --mode agent, both, or ai_audit).

Recognized providers & extending the list

Agent Scan ships with a broad built-in list of AI SDKs and frameworks — OpenAI, Anthropic, Google, Cohere, Mistral, LangChain, CrewAI, AutoGen, and many more, including enterprise cloud routes (AWS Bedrock, Azure OpenAI), Model Context Protocol SDKs (mcp, fastmcp), and non-Western providers such as DeepSeek, Alibaba Qwen (dashscope), Zhipu GLM (zhipuai), Baidu ERNIE (qianfan), Moonshot Kimi, Sber GigaChat and YandexGPT. It also detects raw HTTP calls to known model endpoints (e.g. api.openai.com, bedrock-runtime, gigachat.devices.sberbank.ru) even when no SDK is imported.

You can extend detection without waiting for a release. Drop a codedelta_agents.json file in your application-support folder (or next to the engine, or your project root) to add your own AI SDK import names and API endpoints — useful for internal AI wrappers or private gateways. It is additive on top of the built-ins:

{
  "providers": [
    { "name": "Internal LLM", "lang": "python",
      "imports": ["acme_llm"], "endpoints": ["llm.acme.internal"] }
  ],
  "artifacts": [
    { "name": "AcmeAgent", "tier": 3,
      "paths": ["acme-agent/", "acme.agent.key"] }
  ]
}

The artifacts array adds your own entries to the Agent Infrastructure scan (next section): a trailing slash means a directory name, otherwise a file name.

Agent Infrastructure — artifacts in the tree

Alongside detecting code that calls AI, Agent Scan inventories agent infrastructure committed to the tree — the files AI agents leave behind, evidence that an agent operates on this repository. The scan walks the full tree (including dot-directories the source scan skips), is deterministic, and reports every hit as a named path. Findings appear in the Agent Infrastructure section of the agent report and as agent_artifacts entries in the AI-BOM. They never change any file’s risk rating.

TierMeaningExamples
1 — informationalSanctioned agent-assisted development; shown as a count only.CLAUDE.md, AGENTS.md, .cursorrules, Copilot instructions
2 — notableAgent runtime or configuration — an agent runs against this repo..claude/ workspace, MCP configs (.mcp.json), aider config/history
3 — reviewRogue-agent residue or committed agent credentials; listed with full paths. Credential files carry a note saying whether they hold a token-shaped value or are an empty placeholder.openclaw/, clawdbot/, moltbot/ directories; gateway.auth.token

Tier 3 findings are reported, never build-failing, by default — many teams run agents such as OpenClaw deliberately. To make the CI gate fail on them, set "fail_on_agent_artifacts": true in your --gate-policy JSON. Artifacts flow through every headless output too: the console prints a per-run artifact line, --csv appends ARTIFACT rows after the per-file rows, --json carries an agent_artifacts block, and the AI-BOM and SARIF outputs include them. As everywhere in Agent Scan: pointers for review, not verdicts.

Git History Evidence

When the scanned folder is a git repository, the Agent Scan report adds a Git History Evidence section — commits carrying verifiable agent signatures: Co-Authored-By trailers (Claude Code, GitHub Copilot, Cursor, Aider, and others), generation footers, and agent bot accounts. Unlike the pattern-based scans, this is documentary: a match proves an agent participated in that commit. The reverse does not hold — signatures can be stripped or never written, so the absence of evidence proves nothing. The section shows the share of agent-signed commits, a breakdown by agent, the most recent signed commits, and the files most often touched by them. In batch mode the raw data also exports as *_git_evidence.json. New in v1.8.2.

Build & Deployment Surface — the build-file alerts

Every agent report also watches the files that control how the project builds and ships. A change to build machinery can alter the shipped artifact without touching application source — the mechanism behind supply-chain backdoors such as xz-utils, where the payload entered through an autoconf .m4 file rather than readable source. Two tables cover it:

Build Files Changed In This Diff — the change alert, shown whenever the scan compared two versions. Of the files that control how the project builds and ships, these differ between old and new. It is computed with no ML and no scoring — pure determinism: both directory trees are walked and every filename is checked against a rule table (exact names like Makefile, Dockerfile, package.json; tell-tale suffixes like .m4, .spec; locations like .github/workflows/ where a yml file is executable CI). Each recognised file gets a category — build definition, CI/CD, packaging, dependency manifest. Then the two lists are compared: in new only = ADDED, in old only = DELETED, in both = the bytes are compared and if they differ = MODIFIED. The count in the title is the red-alarm entries; dependency manifests sit in a quieter line below because they change constantly and red-flagging them would desensitise the alert.

Build & Deployment Surface — the presence inventory: what build machinery exists in the scanned tree, changed or not, in the same categories. It renders in every agent report, snapshot or pair.

Install / build hooks head both tables regardless of category. package.json and setup.py are read and checked for install-time execution (a postinstall script, a cmdclass override) — code that runs the moment someone installs the package, the classic supply-chain vector.

Where each appears, by scan mode — the change alert follows churn (it needs two versions); the presence inventory follows the agent scan (it describes one tree):

ModeChange alert (“changed in this diff”)Presence inventory (“what exists”)
Churn✓ GUI box + CLI [build] lines
Churn + Agent Scan✓ + agent report + PR comment
Both (churn + AI + agent)✓ + agent report + PR comment
Agent Scan only— (no pair)
AI Audit— (no pair)
Metrics + Agent Scan— (no pair)
AI Code Scan
Metrics

Every scan that compares two versions carries the change alert; no snapshot scan does (the single-project modes deliberately run the engine with old = new, so there is nothing to diff). A churn-only scan shows the alert in the GUI and CLI output but not in an HTML report — the section lives in the agent report, and churn-only does not produce one. A pair where no build file changed shows an explicit grey “no build-file changes” line, so an empty result never looks like a missing feature. As everywhere in CodeDelta, this is a pointer for review, not a verdict — it flags that the build machinery changed, not whether the change was malicious.

Honest Limitations

What Agent Scan cannot detect:

  • HTTP-based AI calls without SDK imports — if code calls an AI API directly via requests.post("https://api.openai.com/...") without importing the openai SDK, Agent Scan will not flag it.
  • Aliased or renamed importsimport openai as ai_lib may not match all detection patterns depending on subsequent usage.
  • Obfuscated or dynamically constructed calls — if the AI SDK name is assembled at runtime from strings, Agent Scan cannot see it.
  • Indirect AI invocation through helper libraries — a custom internal library that wraps AI calls will not be recognized unless its imports match the known SDK list.
  • New or obscure AI SDKs — the SDK list covers the 20 most common frameworks as of May 2026. Newer or less common SDKs will not be detected unless added to the list.
  • Intent — Agent Scan cannot distinguish between a security researcher intentionally studying prompt injection and a developer accidentally introducing one. It flags patterns, not intent.
  • Safety of the AI usage — a file importing an AI SDK and using it responsibly will score the same as one using it dangerously. AIS score indicates AI agent presence, not AI agent risk quality.

False Positives

Agent Scan will produce false positives in some situations:

The source viewer is the most effective tool for investigating potential false positives — it shows exactly which lines triggered each flag.

Languages Supported

Agent Scan analyzes all source files regardless of language but SDK import detection patterns are primarily calibrated for Python, JavaScript, and TypeScript — where AI agent frameworks are most commonly used. C++, Java, C# and Go projects that call AI APIs via HTTP without a recognized SDK will have lower AIS scores, but may still be flagged when they hit a known model endpoint or use dynamic execution patterns.

08

CI/CD & CMVC Integration

CodeDelta integrates with any CI/CD system or version control system that can export source files to a local directory. It does not interface directly with any CMVC system — it requires plain directory copies of your source.

Churn Threshold Gate

Use --threshold-churn <n> to fail the build if CRN_LLOC exceeds a threshold. Exit code 2 means the threshold was exceeded.

Jenkins Example

stage('Code Metrics') {
  steps {
    sh """
      codedelta ${WORKSPACE}/old ${WORKSPACE}/new \
        --project "${JOB_NAME}" \
        --old-label "${OLD_TAG}" \
        --new-label "${NEW_TAG}" \
        --snapshot-date "${BUILD_DATE}" \
        --exclude "vendor,tests" \
        -d ${WORKSPACE}/codedelta.db \
        -o ${WORKSPACE}/report.html \
        --threshold-churn 10000 -q
    """
  }
}

GitHub Actions Example

- name: Run CodeDelta
  run: |
    codedelta ./old ./new \
      --project "${{ github.repository }}" \
      --old-label "${{ github.event.before }}" \
      --new-label "${{ github.sha }}" \
      --snapshot-date "$(date +%Y-%m-%d)" \
      --exclude "vendor,node_modules" \
      -o report.html --csv report.csv -q

Jenkins, Docker and Kubernetes

The engine also ships as a public container imageghcr.io/code-delta-app/codedelta, republished with every release — which is the easiest route in CI systems other than GitHub Actions: nothing is installed on the runner. The licence rides in as an environment variable (CODEDELTA_LICENSE_B64, the base64 of your codedelta.lic) or a mounted file; all arguments pass straight to the batch CLI described above.

docker run --rm -v "$PWD:/work" -e CODEDELTA_LICENSE_B64 \
    ghcr.io/code-delta-app/codedelta \
    scan /work/new /work/old --mode churn_agent --html --csv

In a Jenkins pipeline that command is a single sh step: store the base64 licence as a secret-text credential, git worktree add the base branch, scan workspace against base, and let exit code 3 (from --gate or --fail-on-new) fail the stage. On Kubernetes, run the identical image inside your CI agent pods, or as a scheduled CronJob snapshot scan with the licence in a Secret and reports written to a volume. Copy-paste recipes for all three: the CLI page and Jenkins, Docker and Kubernetes — where measurement fits.

Baselining — alert only on new findings

The first scan of an established codebase flags many files at once, and most of them are pre-existing — not something the current change introduced. A baseline records the accepted current state so later scans surface only what got worse: files newly flagged, or flagged at a higher severity than before. This is what makes CodeDelta usable as a merge gate rather than a one-time audit. New in v1.8.2.

Accept the current state once and commit the baseline file to your repository:

python3 codedelta_server.py scan ./src --mode both \
      --write-baseline codedelta-baseline.json -q

Then, on every run (or every pull request), compare against it. Only files that regressed are reported; --fail-on-new sets exit code 3 so a build can block the merge:

python3 codedelta_server.py scan ./src --mode both \
      --baseline codedelta-baseline.json --fail-on-new -q

A finding counts as new when its risk exceeds its baselined level (absent from the baseline counts as lowest, so genuinely new flags and severity regressions both surface). Files that dropped below their baselined level are reported as resolved — positive feedback, never a failure. With --json, the comparison is also written to *_baseline_diff.json. Re-run --write-baseline whenever you want to accept the current state as the new normal.

Executive Summary & Trends

The longitudinal database accumulates every run, which makes it the source for a one-page executive summary — the artifact you forward to whoever approves the purchase, rather than the detailed engineer's report. It shows headline numbers for the latest run, trend arrows versus the previous run, and inline charts of churn and AI% across recent runs. New in v1.8.2.

python3 codedelta_server.py trend codedelta.db \
      --out summary.html --project MyApp --limit 20

--project selects which project in the database to chart (defaults to the one with the most runs); --limit caps how many recent runs are shown. The page is self-contained HTML — no external libraries — so it emails and embeds cleanly. Backfill historical points with --git snapshots (the commit date becomes the run's date), then run trend to chart the whole release history at once.

Database Access

The SQLite database (codedelta.db) accumulates every run. You can query it directly:

sqlite3 codedelta.db "
  SELECT r.run_at, rt.crn_lloc, rt.total_sloc
  FROM run r JOIN run_totals rt ON r.id = rt.run_id
  WHERE r.project_id = (SELECT id FROM project WHERE name = 'MyApp')
  ORDER BY r.run_at DESC LIMIT 10;"

Key DB Tables

TableContents
projectProject names and creation dates
runEach run: old/new dirs, labels, snapshot_date, exclude_dirs, note
run_totalsProject-level totals for every metric per run
file_metricsPer-file metrics for every file in every run
metric_setNamed metric sets
metric_set_itemMetric codes belonging to each set

Database location, size & backups

Where it lives. The GUI uses a permanent per-user location that survives reinstalls (~/Library/Application Support/CodeDelta/codedelta.db on macOS, ~/.local/share/CodeDelta/codedelta.db on Linux, %APPDATA%\CodeDelta\codedelta.db on Windows). The command-line engine defaults to codedelta.db in the current directory — for cron jobs always pass an explicit -d /path/to/project.db. In WAL mode you will also see codedelta.db-wal and codedelta.db-shm alongside it; these are normal.

One database per project. Point each project at its own .db. This keeps history clean and avoids write contention — two scans writing the same database serialise (brief overlaps wait safely), but two long scans against one shared database can time out the second writer.

Keep the database on local disk

Do not place a CodeDelta database on a network share (NFS, SMB/Windows file shares, some cloud-sync folders). SQLite's file locking is unreliable over network filesystems and can corrupt the file — this is a general SQLite limitation. Keep it on a local disk; if you need history on a server, run locally and copy the backup up.

How big it gets. Size grows with files × runs at roughly 0.4 KB per file per run (the per-file detail rows). A 4,000-file project is about 1.5 MB per run; a year of nightly runs is a few hundred MB. The project-level totals that trend reports read are tiny (one row per run), so trend and history queries stay fast no matter how long you keep the database. For very large projects kept for many years, you can prune old per-file detail while keeping the totals.

Backups. The database is a single local file with no built-in replication, so back it up like any data you would not want to lose. Because of WAL mode, do not just copy the live .db file — use SQLite's safe online backup, which captures a consistent snapshot even while a scan is running:

# either of these produces a clean, single-file backup
sqlite3 /path/to/project.db ".backup '/backups/project-$(date +%F).db'"
sqlite3 /path/to/project.db "VACUUM INTO '/backups/project.db'"

Schedule that (e.g. a nightly cron right after the scan) and copy the backup to a second location or offsite for redundancy. Integrity is protected at runtime by write-ahead logging and atomic, all-or-nothing runs (an interrupted scan rolls back cleanly and never leaves a half-written run); you can confirm a database is healthy any time with sqlite3 project.db "PRAGMA integrity_check;".

AI Agents (MCP)

CodeDelta ships an MCP server (codedelta_mcp.py, in the install folder) so AI coding assistants — Claude Code, Claude Desktop, Cursor, and any other Model Context Protocol client — can call the real engine instead of improvising their own analysis scripts. The agent provides the conversation; CodeDelta provides the deterministic, reproducible numbers. New in v1.8.2.

Register it with your agent. Claude Code example (claude mcp add or in your MCP config):

{
  "mcpServers": {
    "codedelta": {
      "command": "python3",
      "args": ["/Applications/CodeDelta/codedelta_mcp.py"]
    }
  }
}

The server exposes three tools:

ToolWhat it does
churn_scanEngine churn measurement between two directories or two git refs (v1.7..v1.8); returns totals plus paths to the HTML reports
agent_scanAI-usage inventory: SDK imports, risk ratings, and git-history agent evidence
ai_auditAI-written-code audit (heuristics + ML); per-file ratings and AI%

Once registered, asking your agent "how much churn between release 1.7 and 1.8?" or "does this codebase use AI agents?" invokes CodeDelta and cites its numbers. Licensing is unchanged — the engine verifies codedelta.lic locally no matter who calls it. Requires Python 3.8+ to run the server script.

09

Accuracy & Methodology

The Myers Algorithm

CodeDelta uses the Myers diff algorithm for file comparison, which finds the shortest edit script between two files. This is more accurate than simple line-by-line comparison for files that have been significantly restructured.

Jaccard Similarity

Before running the full Myers diff, CodeDelta uses Jaccard similarity to detect file renames and large-scale moves. A file that appears deleted in the old snapshot and created in the new, but with high token similarity, is treated as a rename rather than a delete+add. This prevents inflated churn numbers from routine refactoring.

LLOC vs GNU diff

LLOC comparison works by tokenising each file's semicolon-terminated statements and running Myers on the resulting token stream rather than the line stream. This means a purely cosmetic reformatting — changing indentation, line breaks, or spacing within a statement — does not register as a change. Only actual logical changes increment CHG_LLOC.

PLOC Definition

PLOC counts lines beginning with # (after optional whitespace) in C/C++ and C# files. This includes all preprocessor directives: #include, #define, #ifdef, #ifndef, #endif, #pragma, #undef, #if, #else, #elif, #error, #warning. PLOC is included within SLOC and LOC — it is not subtracted, it is identified separately for clarity.

Comment Counting

J_COM counts /** ... */ Java-style docblock comments. C_COM counts /* ... */ C-style block comments. EOL_COM counts // to-end-of-line comments. Every line a block comment spans counts as a comment line (a three-line /* */ comment is 3 in C_COM); the tool reports comment lines, not comments. COM_LOC = J_COM + C_COM + EOL_COM.

Character Literal Handling

Single-quoted character literals are correctly excluded from LLOC counting. A semicolon inside a character literal — such as char c = ';' — is not counted as a logical statement. This applies to C/C++, C#, Java, and JavaScript. Escape sequences ('\\', '\n', '\0') are also handled correctly. This was a known limitation corrected in v1.4.1.

10

Licensing

CodeDelta requires a valid license to run. Your license is a signed file named codedelta.lic, verified entirely offline — no license server, no internet connection needed. License types:

TypeDurationUse
EvaluationTime-limited (typically 30 days)Free trial
CorporatePer agreementOrganization-wide, unlimited seats
Single-userPer agreementLocked to one named machine

Installing a License

GUI: on first launch, the activation screen asks for your license — select the codedelta.lic file you were sent. It is saved to your application support folder and verified locally.

Command line: install the license file with:

./codedelta --activate /path/to/codedelta.lic

Or place codedelta.lic in any location the engine searches (first valid match wins):

  1. The file named by the CODEDELTA_LICENSE environment variable
  2. The folder containing the codedelta binary
  3. ~/.codedelta/
  4. Your platform's configuration directory

Contact

For licensing, volume pricing, or academic licenses: codedelta.app