← All one-liners·#074·dev-loop·self contained·power

Find leftover console.log calls by AST, not text grep

ast-grep matches syntax trees, not strings — it won't false-positive on a `// console.log(...)` comment or a string that happens to contain the text "console.log(". Point it at any code shape (a banned call, a deprecated API, a debugger statement) and rank hits by file for a pre-deploy cleanup pass.

Setup
  • → npm install -g @ast-grep/cli
Cost per run
free
The one-liner
$ ast-grep run -p 'console.log($$$)' -l ts --json=compact . | jq -r '.[].file' | sort | uniq -c | sort -rn
What each stage does
  1. [01] ast-grepast-grep run -p 'console.log($$$)' -l ts --json=compact .
    Structural search: match any call to console.log with any arguments ($$$ is a multi-node wildcard) across every .ts file under the current directory. --json=compact emits one JSON object per match with file/line/matched text.
  2. [02] jqjq -r '.[].file'
    Pull just the file path out of every match object.
  3. [03] sort/uniqsort | uniq -c | sort -rn
    Count matches per file and rank the worst offenders first — a punch list for cleanup, not just a wall of hits.
Expected output (sample)
36 scripts/forecast-lab.ts
31 scripts/link-audit.ts
27 server/services/scheduler.ts
13 server/services/timelineSourceScraper.ts
 9 server/services/timelineCollector.ts
 9 scripts/add-timeline-urls.ts
 9 scripts/add-timeline-urls-serper.ts
 8 scripts/run-batch-job.ts
 8 scripts/check-timeline.ts
 6 server/services/timeGptForecaster.ts
... (37 files total)
Caveats & tips
  • Verified on @ast-grep/cli 0.45.3 (npm), run for real against this monorepo's trends101/ TypeScript app (37 files, 200+ matches) — swap the pattern and target directory for your own project; the file-ranking shape is what generalizes.
  • -l ts scopes the parser to TypeScript; use -l js, -l python, -l go, etc. for other languages — ast-grep ships grammars for 20+.
  • $$$ matches zero-or-more argument nodes; use $A for exactly one captured argument if you need to inspect what was logged, not just count calls.
  • Unlike ripgrep, this won't match `console.log` inside a comment or a template-literal string — that's the entire point, but it means it's not a drop-in rg replacement for free-text search.