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.
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:
devtoolz strip-comments src --dry-run --diff # see exactly what would change
devtoolz strip-comments src --keep-jsdoc -y # apply, keeping JSDoc above exportsconsole-strip
Removes console.log/console.debug/debugger statements left in by mistake.
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:
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:
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