Skip to content

Code Cleanup ​

Two commands for the same pre-commit ritual — removing what's left over from debugging and shouldn't ship: commented-out code and notes (strip-comments), forgotten console.log/debugger calls (console-strip). Both read the real syntax tree via the TypeScript Compiler API instead of searching text with a regex — a string or template literal that merely looks like a comment or a console.log call is never touched. Both share the same safety model: no flags means preview-only in the terminal, -y/--yes actually writes to disk, --diff shows a unified diff instead of a plain file list.

strip-comments ​

Removes //, /* */, /** */, and <!-- --> from source files in place.

bash
devtoolz strip-comments [paths...] [options]

Handles .vue files specially: the <script> block is parsed by the same TypeScript parser as a regular .ts file, and <!-- --> inside <template> goes through a line-aware scan that correctly tells a whole-line comment apart from one trailing real markup on the same line (only the latter is removed, without deleting the line itself).

Real output — a file with a fresh TODO, an old commented-out block, and a JSDoc comment above an export:

🧰 devtoolz, reporting for duty

Scanned 1 file.

Would strip comments in 1 file(s):
  src/formatPrice.ts  7 comments

(nothing written — pass -y to apply, or --dry-run to keep previewing)

── src/formatPrice.ts (7 comments) ─────────────────────────────────
@@ -1,13 +1,5 @@
-// TODO: revisit rounding once finance signs off
-const CURRENCY_SYMBOL = '$' // hardcoded for now, see #482
+const CURRENCY_SYMBOL = '$'

-/**
- * Formats a price in cents as a display string, e.g. 1999 -> "$19.99".
- */
 export function formatPrice(cents: number): string {
-  // old implementation, kept around just in case:
-  // const dollars = Math.floor(cents / 100)
-  // const rest = cents % 100
-  // return `${CURRENCY_SYMBOL}${dollars}.${rest.toString().padStart(2, '0')}`
   const value = (cents / 100).toFixed(2)
   return `${CURRENCY_SYMBOL}${value}`

The line const NOTE = 'a URL can contain // without being a comment' in the same file never shows up in the diff at all — real syntax parsing doesn't mistake a // inside a string literal for a real comment.

With --keep-jsdoc, the same file loses one comment fewer — the /** */ directly above export function formatPrice stays put, while the TODO line and the commented-out block still go:

── src/formatPrice.ts (6 comments) ─────────────────────────────────
@@ -1,4 +1,3 @@
-// TODO: revisit rounding once finance signs off
-const CURRENCY_SYMBOL = '$' // hardcoded for now, see #482
+const CURRENCY_SYMBOL = '$'

 /**
@@ -6,8 +5,4 @@
  */
 export function formatPrice(cents: number): string {
-  // old implementation, kept around just in case:
-  // const dollars = Math.floor(cents / 100)
-  // const rest = cents % 100
-  // return `${CURRENCY_SYMBOL}${dollars}.${rest.toString().padStart(2, '0')}`
   const value = (cents / 100).toFixed(2)
   return `${CURRENCY_SYMBOL}${value}`

Options ​

--keep-jsdoc ​

Don't remove a /** */ comment that sits directly above an exported declaration, so exported types/props keep their IDE tooltips. Every other comment, including a /** */ not above an export, still goes.

--dry-run ​

Preview without writing anything (same as running with neither --dry-run nor -y).

-y, --yes ​

Actually apply the changes. Without this flag the command only previews.

--diff ​

Add a unified diff per changed file instead of a plain list of file names.

--cwd <path> ​

Root paths are resolved against (defaults to the current directory).

--ext <list> ​

Comma-separated extensions to include. Default: .ts,.tsx,.js,.jsx,.cjs,.mjs,.vue.

--ignore <glob> ​

Extra ignore pattern (repeatable) on top of the built-in defaults (node_modules, dist, .git, etc.).

--no-respect-gitignore ​

Don't also honor the project's .gitignore while walking files.

Example:

bash
devtoolz strip-comments src --dry-run --diff   # see exactly what would change
devtoolz strip-comments src --keep-jsdoc -y     # apply, keeping JSDoc above exports

console-strip ​

Removes console.log/console.debug/debugger statements left in by mistake.

bash
devtoolz console-strip [paths...] [options]

console.warn/console.error are deliberately not touched by default — often legitimate production logging, not debug leftovers (the list is configurable via --methods). Only a call that's a whole statement on its own gets deleted — one that sits inside an if/while/for body without braces, or is part of a larger expression (const r = console.log(x) || y), isn't touched automatically: those are listed separately so a human decides, instead of a guessing heuristic.

Real output — a function with four different cases at once:

🧰 devtoolz, reporting for duty

Scanned 1 file.

Would strip console/debugger statements in 1 file(s):
  src/checkout.ts  2 statements

(nothing written — pass -y to apply, or --dry-run to keep previewing)

── src/checkout.ts (2 statements) ───────────────────────────────────
@@ -1,4 +1,3 @@
 export function submitOrder(cartTotal: number, userId: string) {
-  console.log('submitOrder called', { cartTotal, userId })

   if (cartTotal <= 0) console.log('empty cart, skipping')
@@ -10,6 +9,4 @@
   }

-  debugger
-
   return receiptId
 }


2 left in place, needs a manual look:
  - src/checkout.ts:4:23 — inside a single-statement body without braces — console.log('empty cart, skipping')
  - src/checkout.ts:6:37 — part of a larger expression, not its own statement — console.log('charging card')

The standalone call and the bare debugger are removed, console.warn is left alone (not in the default list), and the two ambiguous cases — inside a brace-less if, and part of an assignment — are just listed, with no attempt to guess what to do with them.

Options ​

--methods <list> ​

Comma-separated console methods to remove. Default: log,debug. warn/error can be added explicitly:

bash
devtoolz console-strip src --methods log,debug,warn --dry-run --diff

--no-debugger ​

Don't remove bare debugger statements.

--dry-run ​

Preview without writing anything.

-y, --yes ​

Actually apply the changes.

--diff ​

A unified diff per changed file.

--cwd <path> ​

Root paths are resolved against.

--ext <list> ​

Comma-separated extensions to include. Default: .ts,.tsx,.js,.jsx,.cjs,.mjs,.vue.

--ignore <glob> ​

Extra ignore pattern (repeatable) on top of the built-in defaults.

--no-respect-gitignore ​

Don't also honor the project's .gitignore.

Example:

bash
devtoolz console-strip src --dry-run --diff        # what would go, what would stay
devtoolz console-strip src --no-debugger -y          # apply, leaving debugger alone
devtoolz console-strip src --methods log,debug,warn  # remove console.warn too