Skip to content

Command-line options

codeanalyzer-java is a Picocli command. Invoke it as a fat JAR (java -jar codeanalyzer-2.3.7.jar ...) or, if you built a native image, as codeanalyzer ....

By default the analyzer writes one analysis.json per project. Pass --emit neo4j to project that same model into a Neo4j property graph instead — either a self-contained graph.cypher snapshot or a live, incremental push over Bolt. The Neo4j-specific flags below all hang off that mode.

Usage: codeanalyzer [-hvV] [--no-build] [--no-clean-dependencies]
[--include-test-classes] [-a=<analysisLevel>] [-b=<build>]
[-f=<projectRootPom>] [-i=<input>] [-o=<output>]
[-s=<sourceAnalysis>] [-t=<targetFiles>]...
[--emit=<emit>] [--app-name=<appName>]
[--neo4j-uri=<uri>] [--neo4j-user=<user>]
[--neo4j-password=<password>] [--neo4j-database=<db>]
Analyze java application.
FlagArgumentDescriptionDefault
-i, --inputpathPath to the project root directory to analyze.
-s, --source-analysisstringAnalyze a single string of Java source instead of a project. No build required.
-o, --outputpathDestination directory. Holds analysis.json for the default emit, graph.cypher for --emit neo4j without a URI, or schema.neo4j.json for --emit schema. If omitted, output goes to stdout.stdout / cwd
-a, --analysis-level1 | 21 = symbol table only; 2 = symbol table + call graph.1
-b, --build-cmdstringCustom build command. When omitted at level 2, an auto build is used.auto
--no-buildflagDo not build the application; use already-compiled output.off
--no-clean-dependenciesflagDo not delete the downloaded _library_dependencies directory after analysis.off
-f, --project-root-pathpathPath to the root pom.xml / build.gradle (for multi-module projects).value of -i
-t, --target-filespathA file to (re)analyze incrementally; repeatable. Forces level 1.
--include-test-classesflagAlso compile/analyze test sources. (Hidden option.)off
--emitjson | neo4j | schemaOutput target. json writes analysis.json; neo4j projects the model into a Neo4j property graph; schema prints the graph schema contract. Matched case-insensitively.json
--app-namestringLogical application name used as the :JApplication anchor that scopes the graph. (Neo4j emit only.)input dir base name
--neo4j-uriuriBolt URI of a live Neo4j, e.g. bolt://localhost:7687. Its presence is what switches --emit neo4j from a snapshot to a live push. Falls back to NEO4J_URI.
--neo4j-userstringNeo4j username for the Bolt push. Falls back to NEO4J_USERNAME.neo4j
--neo4j-passwordstringNeo4j password for the Bolt push. Falls back to NEO4J_PASSWORD. Prefer the env var.neo4j
--neo4j-databasestringTarget Neo4j database. Falls back to NEO4J_DATABASE; when unset, the server default database is used.server default
-v, --verboseflagPrint logs to the console.off
-h, --helpflagShow help and exit.
-V, --versionflagPrint version information and exit.
  • -i points at a project directory on disk. This is the normal mode; dependencies are downloaded and (at level 2) the project is built.
  • -s passes Java source as a string. The symbol table is built directly from that snippet with JDK-only type resolution — no project, no build, no dependency download.

Exactly one of these is the analysis subject. -s takes precedence when both are present.

What lands in -o depends on --emit:

  • json (default) — writes <output>/analysis.json, creating the directory if needed. Without -o, the consolidated JSON goes to stdout — convenient for piping, and how the Python SDK can capture output without a temp file.
  • neo4j without a URI — writes <output>/graph.cypher (defaults to the current working directory if -o is omitted).
  • schema — writes <output>/schema.neo4j.json, or prints it to stdout when -o is omitted.

See Analysis levels. Level 2 implies a build unless you pass --no-build or a custom -b. In the Neo4j projection, level 2 is also what adds J_CALLS edges (the WALA call graph) to the graph; level 1 emits the lossless symbol-table subgraph with no J_CALLS.

See Incremental analysis. Repeat the flag for multiple files. Forces level 1; merges into an existing analysis.json when one is present in the output directory.

On a live Bolt push (--emit neo4j with a URI), -t marks the run as targeted: only the changed compilation units’ subgraphs are replaced, and orphan pruning of vanished units is skipped. A full run (no -t) prunes units whose source file has disappeared. See Neo4j output below.

The four --emit neo4j modifiers (--app-name, --neo4j-uri, --neo4j-user, --neo4j-password, --neo4j-database) follow the same resolution order:

flag > environment variable > default

A flag wins when set; otherwise the matching env var is used; otherwise the built-in default.

FlagEnvironment variableDefault
--neo4j-uriNEO4J_URI— (no URI → graph.cypher snapshot)
--neo4j-userNEO4J_USERNAMEneo4j
--neo4j-passwordNEO4J_PASSWORDneo4j
--neo4j-databaseNEO4J_DATABASEserver default

Keep credentials off the command line — prefer the NEO4J_PASSWORD environment variable to --neo4j-password, which would otherwise show up in shell history and process listings.

Whether --emit neo4j writes a file or talks to a server is decided purely by whether a Bolt URI resolved (from --neo4j-uri or NEO4J_URI):

  • No URI → graph.cypher snapshot. A self-contained, re-runnable Cypher script: constraints and indexes, a scoped wipe of this application’s prior subgraph, then batched UNWIND ... MERGE for nodes and edges. It expresses the full truth (it is not incremental). Load it with cypher-shell < graph.cypher.
  • URI present → live incremental Bolt push. The Bolt writer ensures constraints and indexes, diffs each compilation unit’s content_hash against the live database, and replaces only changed units’ subgraphs via idempotent MERGE upserts. Shared :JPackage / :JAnnotation nodes are upserted once. On a full run it prunes units whose source file has vanished; a -t targeted run skips that pruning.

--app-name is the tenancy key in both modes: it sets the name of the single :JApplication anchor, the wipe deletes only that application’s subgraph, and many applications can share one Neo4j database side by side, each rooted at its own :JApplication. When omitted, it defaults to the base name of the -i input directory. The :JApplication node also carries schema_version (1.0.0), the versioned schema contract the graph conforms to.

--emit schema prints the machine-readable schema contract — every node label, relationship type, and property the projection can emit — and requires no project: it short-circuits before any analysis, so -i / -s are unnecessary. Writes schema.neo4j.json to -o if given, otherwise stdout.

Terminal window
java -jar codeanalyzer-2.3.7.jar --emit schema -o ./out # ./out/schema.neo4j.json
java -jar codeanalyzer-2.3.7.jar --emit schema # prints to stdout

Write a re-runnable snapshot for one application:

Terminal window
java -jar codeanalyzer-2.3.7.jar \
-i /path/to/daytrader8 -a 2 \
--emit neo4j --app-name daytrader8 \
-o ./out
cypher-shell -u neo4j -p "$NEO4J_PASSWORD" < ./out/graph.cypher

Push live and incrementally over Bolt (credentials from the environment):

Terminal window
export NEO4J_PASSWORD=secret
java -jar codeanalyzer-2.3.7.jar \
-i /path/to/daytrader8 -a 2 \
--emit neo4j --app-name daytrader8 \
--neo4j-uri bolt://localhost:7687 \
--neo4j-user neo4j \
--neo4j-database neo4j

Re-push only the files that changed (targeted — no orphan pruning):

Terminal window
java -jar codeanalyzer-2.3.7.jar \
-i /path/to/daytrader8 -a 2 \
--emit neo4j --app-name daytrader8 \
--neo4j-uri bolt://localhost:7687 \
-t src/main/java/com/example/AccountService.java

The --app-name you load with is the same value a reader scopes to. In the Python SDK, Neo4jConnectionConfig(application_name="daytrader8") reads back exactly the graph produced by --app-name daytrader8 — no JDK, no JAR, no project sources, just the Bolt URI and read-only credentials. See the Neo4j guide for the producer/consumer split and the full schema.

The command exits non-zero on failure. Run with -v to see the underlying logs (build invocation, dependency download, parse problems, WALA progress, and — for a live push — the Bolt connection and per-unit upserts) when diagnosing a failed run.

See worked invocations in Examples.