CLI commands
npx dowsing <command> [options]Common options
Available on most commands.
| Option | Default | Description |
|---|---|---|
--since <date> | 12 months ago | Start of the git window. Anything git can parse. |
--until <date> | — | End of the git window |
--complexity <type> | loc | Complexity proxy: loc | cyclomatic | cognitive |
--json | false | Write JSON to stdout |
--config <path> | auto-detected | Config file (dowsing.config.ts / .mts / .mjs / .js) |
--refresh | false | Ignore the cache and re-analyse |
--no-cache | — | Neither read nor write the cache |
Analysis results are cached in .dowsing/cache, keyed by HEAD, working-tree state, and the options above. A cache hit is announced on stderr.
For a summary of this whole page — plus requirements, output shapes, exit codes, and caching — run dowsing --help.
analyze
Analyses the workspace, writes .dowsing/dowsing.json, and prints a summary.
dowsing analyze [dir]| Option | Default | Description |
|---|---|---|
--top <n> | 10 | Number of hotspots to display |
--out <path> | .dowsing/dowsing.json | Output path |
--verify-churn [n] | off | Verify change frequency of the top N files (default 20) by AST |
--min-degree <n> | 0.3 | Minimum coupling degree (percentages like 30 also accepted) |
--min-shared <n> | 5 | Minimum shared commits for coupling |
With --json the report goes to stdout and no file is written.
hotspots
Prints just the hotspot ranking.
dowsing hotspots [dir] --top 15coupling
Shows change coupling.
dowsing coupling [dir] --hidden| Option | Default | Description |
|---|---|---|
--hidden | false | Only hidden coupling (co-change with no dependency) |
--files | false | Also show file-level coupling |
--top <n> | 20 | Number of rows |
--min-degree <n> | 0.3 | Minimum degree |
--min-shared <n> | 5 | Minimum shared commits |
Lower the threshold to catch what you are missing
Two very active packages have a large denominator, which drags the degree down. --min-degree 15 often surfaces real pairs.
why
Explains why two things change together.
dowsing why <a> <b>Each target can be a package name, a file path, or a directory — resolved in that order (package name → exact path → prefix match).
| Option | Default | Description |
|---|---|---|
--cwd <path> | . | Directory to analyse |
--top <n> | 10 | Number of file pairs to show |
--commits <n> | 10 | Number of representative commits |
dowsing why @acme/admin-web @acme/customer-web
dowsing why packages/ui src/api --since "6 months ago"health
Shows Code Health and the smell breakdown.
dowsing health [dir]
dowsing health --file src/foo.ts # deductions for one file| Option | Default | Description |
|---|---|---|
--file <path> | — | Show the breakdown for one file only |
--top <n> | 10 | Number of rows |
knowledge
Shows ownership and bus factor.
dowsing knowledge [dir] --top 15Reports bus factor per package, the contributor list, and an off-boarding simulation showing what would be left unowned if the main developer left.
report
Generates a self-contained single-file HTML report. It makes no external requests and the data is embedded, so you can share the file as-is.
dowsing report [dir] --out report.htmlinit
Appends a dowsing section to AGENTS.md, so that every agent working in this repository knows the tool exists — whatever host it runs on.
dowsing init
dowsing init --dry-run| Option | Default | Description |
|---|---|---|
--cwd <path> | . | Target directory |
--file <path> | AGENTS.md | File to append to |
--dry-run | false | Print the section instead of writing it |
Running it again updates that section rather than adding a second one.
check
Quality gate. Exits 1 on violation.
dowsing check [dir] --min-file-health 3| Option | Description |
|---|---|
--min-file-health <n> | Floor for file health |
--min-package-health <n> | Floor for package health |
--max-hotspot <n> | Ceiling for hotspot score (0–1) |
--min-bus-factor <n> | Floor for package bus factor |
--max-hidden-coupling <n> | Ceiling on hidden coupling count |
--sarif <path> | Emit SARIF for GitHub Code Scanning |
It checks nothing by default
Only thresholds you name explicitly are enforced. Measure where you are first, then start from a level you can actually pass.
diff
Assesses whether changes since a base touched risky ground, and measures how complexity actually moved between the two revisions.
dowsing diff <base>
dowsing diff origin/main --markdown| Option | Default | Description |
|---|---|---|
--head <ref> | HEAD | Comparison target |
--cwd <path> | . | Directory to analyse |
--markdown | false | Write PR-comment Markdown to stdout |
--out <path> | — | Write the Markdown to a file |
Every changed .ts/.tsx file is read at both revisions and re-parsed, so the delta is independent of who made the change. See Measuring the effect.
Configuration file
Everything above can be fixed in dowsing.config.ts so that it does not have to be passed each time. CLI flags win over the file, which wins over the defaults.
import { defineConfig } from "dowsing";
export default defineConfig({
since: "12 months ago",
complexity: "cognitive",
coupling: { minDegree: 0.3, minShared: 5 },
health: { thresholds: { cognitive: 15 }, weights: { "large-file": 1.5 } },
check: { minFileHealth: 4, maxHiddenCoupling: 0 },
});Lookup order is dowsing.config.ts → .mts → .mjs → .js; --config <path> names one explicitly. TypeScript is read as-is (Node 22.18+ strips the types), so there is no build step.
An unknown key is an error, not a silently ignored line — a threshold you believe you set but which never took effect is worse than a startup failure.