ts-comment-scanner

// TypeScript のコメントを検出・集計・安全に削除する CLI // detect, report and safely remove TypeScript comments

「レビューで直しました」は、
コードに書かない
Fixes go in code.
Stories go in git.

コーディングエージェントが焼き込む“開発の経緯”コメントを、TypeScript の AST で検出して安全に削除する CLI。ビルドを支える 78 種類のディレクティブは残したまま、 --diff でエージェントが触ったファイルだけを掃除します。 A CLI that detects and safely removes the narration comments coding agents bake into TypeScript — via the AST. It keeps all 78 directive kinds your build depends on, and --diff scopes the sweep to the files the agent just touched.

$ npx @kongyo2/ts-comment-scanner --remove --dry-run --diff HEAD
✓ removed 3 comments · kept 1 directive

// なぜ要るのか// why this exists

エージェントは“経緯”をコードに焼き込む Agents bake the meeting minutes into the code

エージェントにレビュー往復をさせると、修正のたびに「指摘に従って直した」という報告文が コメントとして積まれていきます。CLAUDE.md やフックで指示しても止まらないことは公式 issue でも報告されている挙動です。コードの制約を書くコメントは資産ですが、開発の出来事を 引用形式で語るコメントは、半年後の読者には何の情報でもありません。経緯なら git blame と PR スレッドが持っています。 Send an agent through a review loop and every round deposits another “per the review feedback, we now …” into your source. Instructions in CLAUDE.md or hooks don't reliably stop it — there are open issues about exactly this. A comment that states a constraint is an asset; a comment that narrates what happened during development tells a reader six months from now nothing. git blame and the PR thread already keep the story.

残るkeeps コードの制約 — 将来の読者に有用 a constraint of the code — useful forever
// Empty string means "--diff with no value":
// fall back to comparing against HEAD.
if (input === "") return "HEAD";
主語がコード。書き直させてでも残す価値がある。 The subject is the code. Worth keeping — or rewriting into this form.
消すgoes 開発の経緯 — コミットメッセージに書くべき a development event — belongs in the commit
// Note: Codex review flagged this case.
// Per that feedback, we now guard it.
if (input === "") return "HEAD";
主語がレビューの議事録。diff レビューをすり抜けやすい。 The subject is the review log — and it slips through diff review easily.

// できること// what it does

検出・集計から、壊さない削除まで From detection to deletion that doesn't break

scan

検出と集計Detect & report

.ts / .tsx / .mts / .cts を再帰的にスキャンし、行・ブロックコメントを位置情報つきで text / json / github の 3 形式で出力。 Recursively scans .ts / .tsx / .mts / .cts and reports line and block comments with positions, as text, JSON or GitHub annotations.

--remove

安全な削除Safe removal

AST のコメント範囲だけを削除。ディレクティブとライセンスヘッダーはデフォルトで保持し、 削除後は再スキャンで検証。 Splices only AST comment ranges. Directives and license headers are kept by default, and the result is re-scanned to verify.

--diff <range>

エージェントの作業範囲だけOnly what the agent touched

git が変更ありと報告するファイルだけに絞り込み。未追跡の新規ファイルも含み、 .gitignore は尊重。 Narrows the sweep to files git reports as changed — untracked files included, .gitignore respected.

78 rules

ディレクティブを知っているKnows the directives

@ts-expect-error から webpackChunkName: まで、消すと挙動が変わるコメントを 78 本のルールで判定。 From @ts-expect-error to webpackChunkName:, 78 rules identify the comments whose removal would change behaviour.

--fail-on-comment

CI ゲートA gate for CI

コメント検出時に終了コード 1。--format github なら PR の該当行にアノテーションが出ます。 Exit code 1 when comments are reported; with --format github the offending lines are annotated right in the PR.

import { … }

ライブラリとしてもAlso a library

scanComments / removeComments / changedFiles などを TypeScript API として利用可能。 scanComments, removeComments, changedFiles and friends are available as a typed API.

// 安全装置// the guard rails

「壊れないコメント削除」を、真面目にやる Comment removal that refuses to break your build

正規表現でコメントを消すと、文字列の中の // やテンプレートリテラル、JSX を平気で壊します。削除を真面目にやると意外と深い — このツールが踏んでいる地雷の一部: Regex-based stripping happily corrupts strings, template literals and JSX. Done properly, removal turns out to be deep — a sample of the mines this tool steps around:

文字列・テンプレート・正規表現・JSX の中の “//” “//” inside strings, templates, regexes, JSX text
AST のコメントトリビアだけを扱うので誤爆しない only AST comment trivia is touched — no false positives
a/* x */b はトークンが結合してしまう a/* x */b would merge two tokens
結合する位置には空白を挿入(→ a b) a space is inserted where they would join (→ a b)
コードに挟まれた複数行ブロックコメントは ECMA-262 上「行終端子」(ASI に効く) a multi-line block comment between code acts as a line terminator (ASI)
消さずに改行へ置換して文の切れ目を保つ replaced with a real line break so statements stay separated
@ts-expect-error 直下の行が消えると適用先がズレる deleting the line under @ts-expect-error shifts its target
次行指示子の直下にあるコメント行は削除しない comment lines shielded by next-line directives are kept
削除処理そのものの想定外 the remover itself misbehaving
削除後のソースを再スキャンして検証。想定外ならファイルを書き換えずエラー output is re-scanned and verified; on mismatch the file is left untouched
書き込み中のクラッシュやディスクフル a crash or full disk mid-write
一時ファイル経由のアトミック置換で元ファイルは壊れない atomic replace through a temp file — the original can't be truncated
UTF-16 や BOM、不正なエンコーディング UTF-16, BOMs, invalid encodings
エンコーディングと BOM を保持。復元不能なファイルは変更せず報告 encoding and BOM preserved; undecodable files are reported, never rewritten

// この挙動は 415 本のテスト100% カバレッジ(statements / branches / functions / lines)で固定しています // pinned by 415 tests at 100% coverage — statements, branches, functions and lines

// 78 のディレクティブ// the 78 directives

消すとビルドが壊れるコメントを、知っている It knows which comments your build depends on

判定は「それっぽい文字列を含むか」ではなく、各ツールの実際のパーサー実装(正規表現・文字列比較)に合わせてあります。 Detection is not “contains a similar-looking string” — each rule mirrors the actual parser implementation of the tool it protects.

// 使い方// how to use it

まず見る、それから消す Look first, then delete

# 何がどこにあるかを見る # see what is where

npx @kongyo2/ts-comment-scanner src

# エージェントが触ったファイルだけ、まず削除対象を確認 # preview the sweep, scoped to files the agent touched

npx @kongyo2/ts-comment-scanner --remove --dry-run --diff HEAD

# 問題なければ削除(ディレクティブとライセンスは保持される) # then delete — directives and license headers survive

npx @kongyo2/ts-comment-scanner --remove --diff main...HEAD

# CI で経緯コメントの混入を止める(PR の該当行に注釈が出る) # gate CI — offending lines get annotated in the PR

npx @kongyo2/ts-comment-scanner --format github --skip-directives --fail-on-comment src
  1. 絞るScope --diff HEAD でエージェントが直近触った範囲だけを対象にする。 --diff HEAD narrows the target to what the agent just touched.
  2. 確かめるPreview --dry-run で削除対象を人間が最終確認する。元からあった資産コメントを守るのはここ。 --dry-run puts a human in the loop — this is where pre-existing comment assets get protected.
  3. 掃除するSweep 削除して、本当に必要な知見は経緯抜きの Why コメントとして書き直させる。 Delete, and have real insights rewritten as Why comments — without the narration.

終了コード: 0 成功 · 1 --fail-on-comment でコメント検出 · 2 引数・実行時エラー / Node.js ≥ 20 / MIT Exit codes: 0 success · 1 comments found with --fail-on-comment · 2 usage or runtime error / Node.js ≥ 20 / MIT