Claude Codeを使ったlinterを作ったら強力なリファクタツールになった件について
CLI系のAI Agentを使った開発の練習としておもちゃを1つ作りました。
実用ツールというよりはコンセプトの確認目的の方が強いのであんまりメンテする気はないです。もしこのツールいいねと思われた方がいれば誰か完成品を作ってください。
モチベーション
Claude Codeさんを使ってコードを生成していると無意味なコードコメントが量産されます。
これを防ぐためにCLAUDE.md
やプロンプトでコメント書かないように指示することは可能ですが、ロングタスクではコンテキストから外れたり、コンパクションで失われることがよくあります。
また、コンテキストは貴重なリソースであり、こんなしょうもない指示をしたくないという思いもあります。
しかし、何の意味もないコメントを見ていると殺意が湧き上がるため、心の平穏にもよろしくありません。
それならいっそ、タスク完了後にClaude Codeさん自身でコード規約に沿っているか確認できればいいよね!ということで自然言語ベースでチェック可能なlinterを作りました。
仕組み
1. 自然言語からのルールの生成
AI Agentを利用している方ならいろいろガイドラインファイルを作成していると思います。
# Comment Guidelines
This document outlines the commenting standards for our codebase to ensure consistency, maintainability, and clarity across all projects.
## Acceptable Inline Comments
While we minimize inline comments, certain situations require them for clarity and maintainability:
### 1. Clarifying Non-Obvious Values
**Use comments to explain the meaning of numeric values, color codes, or other constants** that aren't immediately clear.
\```typescript
// ✅ Good - Time calculations
const SESSION_TIMEOUT = 60 * 60 * 24; // 1 day in seconds
const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes in milliseconds
// ✅ Good - Color values
const THEME_COLORS = {
primary: '#3B82F6', // Blue
secondary: '#6B7280', // Gray
danger: '#EF4444', // Red
success: '#10B981' // Green
};
// ✅ Good - Configuration values
const MAX_RETRY_ATTEMPTS = 3; // Based on network timeout studies
const BATCH_SIZE = 100; // Optimal for database performance
\```
...
というように、どういったコメントを残すのかというガイドラインを作成し、そこから下記のようなルールを生成します。
rules:
- id: no-obvious-comments
description: Avoid comments that state the obvious or merely repeat what the
code already clearly expresses through naming and structure
severity: warning
correct: |-
function processUserData(userData: UserData): ProcessedData {
if (!userData) {
return null;
}
return {
id: userData.id,
name: userData.name.trim(),
email: userData.email.toLowerCase()
};
}
incorrect: |-
function processUserData(userData: UserData): ProcessedData {
// Check if user data exists
if (!userData) {
// Return null if no data
return null;
}
// Process the data
return {
id: userData.id,
name: userData.name.trim(), // Trim whitespace
email: userData.email.toLowerCase() // Convert to lowercase
};
}
fix: Remove comments that describe what the code is doing when it's already
clear from variable names, function names, and code structure. Keep only
comments that explain why something is done
- id: explain-numeric-values
description: Numeric constants, time values, and configuration numbers should
have comments explaining their meaning and units
severity: info
correct: |-
const SESSION_TIMEOUT = 60 * 60 * 24; // 1 day in seconds
const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes in milliseconds
const MAX_RETRY_ATTEMPTS = 3; // Based on network timeout studies
incorrect: |-
const SESSION_TIMEOUT = 86400;
const CACHE_DURATION = 300000;
const MAX_RETRY_ATTEMPTS = 3;
fix: Add comments to numeric constants explaining their units and purpose. For
time values, specify the unit (seconds, milliseconds). For other values,
explain why that specific number was chosen
...
こういった形式変換はLLMが得意なところであり、元のガイドラインの品質によるところもありますが、結構良い精度で生成することができます。
2. コードがルールに違反しているかチェックする
次にファイルとルールを渡してClaude Codeに違反しているかのチェックをさせます。
Reviewing 1 files with 4 rules...
/Projects/cconv/src/services/claude-provider.ts:31:3: warning [no-obvious-comments] Comment 'Static variables for execution throttling' is redundant - the variable names and context already make this clear
/Projects/cconv/src/services/claude-provider.ts:50:48: info [explain-numeric-values] Numeric constant '10' should have a comment explaining it represents the default execution interval in milliseconds
...
そうすることでこのようにエラーを出すことができました。
内部的な動作としてはclaude -p
で呼び出しを行い、違反の有無、行と列、メッセージなどを生成する形になります。簡単ですね!
3. 違反内容を修復する
違反内容を特定できたら同様にclaude -p
で違反内容と修正指示を出すことでClaude Codeさんが修正を行なってくれます。
修正自体はAI Agent側でルール違反チェックすれば修復できるのでなくても良いとは思いつつ、何となくあると便利かなレベルで作った機能になります。
この何となくがめちゃくちゃ重要でした・・・!!!
これによって出来るようになったこと
必要な意味あるコメントのみを残すみたいなチェックは機械的な方式では実現することができません。
一定、人の目を通さないとチェックのしようがなかったのですが、作成したcconvではそういったチェックをClaude Codeを使うことでできるようになりました。
単純なLLMでも同様のことはできますが、例えば複数ファイルにまたぐものや、インターネットや外部SaaSの情報を参照した上で判断するなど、Claude Codeを使う上でより複雑なチェックを行えるようになっています。
というだけのつもりだったのですが、違反の修復機能を作ったことでちょっと別の様相を見せ始めました。
Claude Codeは大量のファイルに対して読み書きするのはすごい下手です。
指示の出し方などである程度緩和しますが、タスクを早く終わらせたい圧力があるのか、全てのファイルを一定処理できないことが多いです。
対してcconvではファイル単位でClaude Codeの実行を行っているため、確実に指定したファイルの処理が行えます。
これが先の複雑なチェックと組み合わせると、例えばTypeScriptでのany
の一括潰しなどのリファクタリングを行えるようになります。
関数の返り値の型をany
にしている場合、これは呼び出し元の修正も必要になりますが、Claude Codeを使って場所の特定・修正を行えるためそこまで一括で行えてしまいます。何ならHooksで型チェックを入れておけばそのエラーを潰すような動きもできますし。
というので自然言語ベースのlinterを作ったつもりが、ワークフローベースのAI一括コード修正ツールができてしまったということですね!!!!!!!!!!!!
現在抱えている問題
というのでとりあえずClaude Codeでcconvを作ってみましたがいくつか課題を抱えています
- Claude Codeの出力で決まったJSON構造を返しているので安定しない
- Claude Code的には一時ファイルを作成した方が安定しやすい
- というか回答に一言入れたがるので純粋にファイル作って、自身にJSON Schemaでのチェックするように指示した方が安定する
- 同一ディレクトリでのClaude Codeの並列実行が動作しない
-
~/.claude.json
の競合エラーが起きる - たぶんシンボリックリンクを貼ってClaude Codeから見たパスを変えた方が良い
-
- 実行が遅い
- ただでさえ遅いClaude Codeが何度も呼び出しするのでめちゃくちゃ遅い
- ファイル数 x ルール数の数だけ呼び出すので本当に遅い
- 品質的には1ファイル・1ルールでチェックさせるのが安定だと思うけど、速度のトレードオフが・・・
- Claude CodeのRate Limitに入る
- ガチると呼び出しすぎてRate Limitにさくっと入ります。Max 20xなのに・・・
- 大量に修正が入るともう差分読めない
- 本当に一括修正するなら都度ブランチを切り替えるなどしないと人間にはチェックしきれない
- でもブランチを切ったらコンフリクト地獄に入る自信もあります。辛い
- Claude Codeで雑に作ったのでコードが汚すぎてメンテ辛い
特に最後のが致命傷しすぎて、Claude Codeさんに指示しても機能追加に失敗しやすくなっていますが、これ僕が読んで直すの・・・?まじで???という状態のため正直詰みました。そこまでのやる気が出ないです。
いや、ちょっとやろうとしてブランチ切ってガチャガチャしてたのですが、僕は何でこんなことをしているんだ・・・?と心が折れてしまいました。
時間とやる気を誰かください。
おわりに
というわけでcconvの供養をするためにこの記事を書きました。R.I.P.。
今回これを作ったことで血肉になったので気が向いたらリベンジとしてcconv2が生まれるかもしれません。
自然言語linterも面白いけど、もうちょっと負債返却文脈に特化した汎用ツール作りたいかも。
Discussion