Static analysis for Java — locally, in 60 seconds.

Scan your Java codebase for cyclomatic-complexity outliers, vulnerable Maven / Gradle dependencies, file-local dead code, empty catches, magic numbers, and more — with the ik CLI. No code leaves your machine except file paths and metrics.

Install the CLI Wire up GitHub Action

Running on a Spring Boot repo

$ ik run inkode · spring-petclinic Running 20 checks... Complexity 3 findings 260ms (chamele, in-process) Dead Code no issues 1.4s (pmd) Dependency Audit 2 findings 11s (osv-scanner: Maven) Magic Numbers 5 findings 3.1s (pmd) Error Handling no issues 610ms (pmd) Test Presence 5 findings 12ms (junit detected) Import Graph no issues 8ms (package-level) Score 77 / 100 grade C Report .ik/brief.html Share https://api.inkode.co/r/17LQVP6sENzp

What we check, and how.

CheckToolWhat it catches in Java
Complexitychamele (in-process)Methods exceeding cyclomatic-complexity threshold (default 10), via the in-process chamele library — no PMD needed for this check, never skipped. Picks up deep if/switch nests AI tends to produce. (PMD still drives the Java checks below.)
Dependency Auditosv-scannerKnown CVEs across pom.xml, build.gradle, build.gradle.kts. Maven ecosystem only — JS deps in polyglot repos still routed through npm audit. CVSS ≥ 7 → Error.
Dead CodepmdUnused private fields, methods, local variables, and formal parameters. File-local view only — protected / public members are intentionally not flagged.
Error HandlingpmdEmpty catch blocks, catch (Exception e) swallow-alls, catch (Throwable t). The exact patterns AI tools love to drop in when the happy path compiles.
Magic NumberspmdInline numeric literals in business logic instead of named constants. Catches PMD's AvoidDecimalLiteralsInBigDecimalConstructor + bestpractices rulesets.
Import Graphbuilt-in parserCycles in the package graph, high fan-in / fan-out, god packages. Reads pom.xml's <groupId> to scope to your own packages (or falls back to longest common dot-prefix).
Test Presencefs walk*Test.java, *Tests.java, *Spec.java classified as test files. JUnit detected via pom.xml scan.
Semantic Duplicationembedded LLMJava methods that do the same thing written differently — regex-extracted, embedded via Qwen2.5-Coder-0.5B, paired by cosine similarity. Lambdas fold into their enclosing method.
AI Stackmanifest scanLangChain4j, Spring AI, Anthropic Java SDK, OpenAI Java SDK detection in pom.xml / build.gradle.
Secrets, Hotspots, Coupling, Duplication, Line Count, Infra, Scripts, TODO Densitylanguage-agnosticSame as every other language — gitleaks for secrets, git-log analysis for hotspots / coupling, jscpd for textual duplication, etc.

The smells nobody refactors out.

Empty / overly-broad catches

catch (Exception e) {} — the shortest path through "make it compile." PMD flags both the empty body and the broad catch separately, so you see exactly which assumption the author made.

Unused private scaffolding

Helper methods that look load-bearing but have no callers; private fields initialised once and never read. AI generates these "just in case" and never circles back.

Vulnerable Maven coordinates

Outdated log4j-core, jackson-databind, spring-core, etc. osv-scanner queries the OSV.dev database directly — no local DB to keep fresh.

Magic constants in BigDecimal math

Inline new BigDecimal("100") hiding business logic constants. PMD's AvoidDecimalLiteralsInBigDecimalConstructor + magic-numbers ruleset surface the exact lines.

Run it on your Java repo.

Install in one line, scan in under a minute. No account required.

$ curl -fsSL https://inkode.co/install.sh | sh $ brew install pmd # one-time, for dead-code / magic-numbers / error-handling (complexity needs no install) $ cd your-java-project && ik init && ik run
Book an Expert Review

Scan another language

C# Go Python Rust TypeScript All scanners

Cross-cutting checks: secret scanning · dependency vulnerability scanning · AI code review