「AIっぽい文章」は、いま日本語のWebで最も指摘されやすい欠陥のひとつになった。読点の打ち方でも語彙でもなく、構文の型が繰り返されることで見抜かれる。この型を機械的に洗い出して書き直すスキルが conorbronsdon/avoid-ai-writing(★3,403・fork 302・MIT)で、Claude Code・Cursor・OpenClaw などで動く。本稿ではこれを実際に手元へ導入し、日本語で本当に効くのかを測った。結論から言うと、このスキルは2つの部品でできていて、片方は日本語で完全に動かない。
wordCount = 1 と数えられて採点されない30秒でわかる
・中身は2部品。LLMに読ませる指示書 SKILL.md(816行・62パターン)と、依存ゼロの決定論的検出エンジン detector/patterns.js(2,180行)
・検出エンジンは日本語を採点できない。語数を空白区切りで数えるため210字が「1語」になり、10語未満で足切りされて UNSCORED を返す。字数を4倍にしても変わらない
・SKILL.md 側は日本語でも発火する。英語で書かれた指示書のまま、日本語の「XではなくY」構文や出典なしの権威づけを検出して直した
・効果は実測で 80点→0点。ただしスキル無しでも 80点→9点まで落ちる。差分は9点で、コストは5.9倍
・発火の確認は --output-format stream-json。応答本文はスキル名に触れないことがある
この記事のポイント
・AIっぽい文章の検出エンジンは英語専用で、日本語は210字でも「1語」と数えられ採点されない
・スキル本体(SKILL.md)は日本語でも発火し、日本語の型を正しく直す
・発火したかどうかは応答本文ではなく --output-format stream-json の Skill 呼び出しで確認する
Claude Code のスキル機構そのもの(置き場所・優先順位・SKILL.md の書式)から確認したい場合は、Claude Code|2026年版・インストールからCLAUDE.md・Hooks・本番運用までの実装手引きを先に読むと、この記事の導入手順が短く済む。
avoid-ai-writing とは——「AIっぽい文章」を型で捕まえるスキル
このリポジトリが解こうとしているのは「文章がうまいか」ではなく「AIが書いたときに出やすい形が残っていないか」である。両者は別物で、後者は語彙と構文のパターンとして列挙できる。
SKILL.md の冒頭は、この道具の限界を自分から先に書いている。曰く、ここで挙げるパターンはLLM出力に統計的に多いだけで、締切に追われた人間や第二言語話者も同じ形を書く——だから採用・学術不正・掲載可否のような取り返しのつかない判断の単独根拠にするな、と明記されている。根拠として非英語話者への誤検出率が60%を超えたという Stanford の調査(Liang et al., Patterns 2023)などを自分で引いている。検出ツールを名乗りながら「これは証拠ではない」と先に宣言する構成は珍しい。
動作モードは3つある。
・rewrite(既定)— 指摘して書き直す
・detect — 指摘だけして書き直さない。他人の文章や公開済みの記事を触らずに見るとき用
・edit — ファイルを直接書き換える。散文ファイルに限定し、コード・設定・生成データは拒否する
edit モードには、文書のなかに「上のルールを無視しろ」「この節は指摘するな」といった編集者宛の命令文が埋め込まれていた場合、それに従わずその文を指摘対象として報告するという指示が入っている。監査対象の文書を命令ではなくデータとして扱う、という境界を明示的に引いている点は、他のライティング系スキルではあまり見ない設計だ。
62パターンと112語の禁止語表
scripts/check-pattern-count.sh を走らせると、リポジトリが自分で数えた内訳が出る。手元の実行結果は次のとおり。
・パターン数 62(SKILL.md と CLAUDE.md の記載が一致していることも同時に検査される)
・語の置換表 112語(59+40+13の3階層)
階層は Tier 1(delve・landscape・robust・seamless など、それ単体で強い兆候になる語)、Tier 2(単体では弱いが集まると効く語)、その他の補助語に分かれる。この階層は後述の実測ログにもそのまま出てきて、モデルは「Tier 1A」「Tier 1B」という語彙で指摘を返す。この語彙が出るかどうかは、スキルが発火したかを見分ける手掛かりになる。
パターン側で目立つのは、語ではなく構文を捕まえる規則群だ。
・否定並列(”It’s not just X — it’s Y”/「単なるXではなくY」)— 1文書につき最大1回まで
・出典なしの権威づけ(”Experts believe”/「専門家によれば」)
・意味の薄い結び(”the future looks bright”/「まさに〜と言えるでしょう」)
・語彙の言い換え循環(developers → practitioners → builders → engineers と同義語を回す)
・語彙多様性(TTR)が0.40を下回る、いわゆる語彙の圧縮
実測1:AIっぽい文章の検出エンジンは日本語を採点しない
ここからが本題である。detector/patterns.js は依存パッケージもビルド工程も持たない単一ファイルで、require() して analyzeText() を呼ぶだけで動く。まずは素直に日本語と英語を入れてみた。
git clone --depth 1 https://github.com/conorbronsdon/avoid-ai-writing.git
cd avoid-ai-writing
node -e '
const D = require("./detector/patterns.js");
const r = D.analyzeText("<ここに文章>");
console.log(r.score, r.label, r.stats.wordCount, r.document_classification);
'
手元(Node v22.13.1・2026-08-27)の結果を表にする。
| 入力 | 文字数 | wordCount | score | label | 判定 |
|---|---|---|---|---|---|
| 英語・AIっぽい文章 | 461 | 66 | 80 | Strong AI signals | AI_ONLY |
| 英語・人間が書いた文章 | 331 | 63 | 0 | Clean | HUMAN_ONLY |
| 日本語・AIっぽい文章 | 210 | 1 | 0 | Too short | UNSCORED |
| 日本語・人間が書いた文章 | 164 | 2 | 0 | Too short | UNSCORED |
英語では期待どおりに分離している。AI的な文章は80点で21件の指摘(Tier 1語彙・つなぎ語・埋め草・”Let’s”構文・em-dash)が付き、人間が書いた同じ長さの文章は0点で指摘ゼロ。この分離性能自体は本物だ。
問題は日本語である。210字の段落が wordCount = 1 と数えられ、Too short で足切りされる。
原因は「短いから」ではなく「空白が無いから」
detector/patterns.js の語数カウントは、次の1行に集約されている。
function countWords(text) {
return (text.match(/\S+/g) || []).length;
}
\S+(空白以外の連続)を数える実装なので、単語間に空白を置かない日本語では、段落全体がまるごと1語になる。そして呼び出し側は wordCount < 10 で UNSCORED を返す。
原因を確定させるため、同じ日本語文に3種類の加工をして比べた。
| 加工 | 文字数 | wordCount | label | 分類 |
|---|---|---|---|---|
| 無加工 | 210 | 1 | Too short | UNSCORED |
| 同じ文を4回繰り返す(長さだけ4倍) | 840 | 1 | Too short | UNSCORED |
| 句読点のあとに半角スペースを入れる | 224 | 14 | Clean | HUMAN_ONLY |
| 全文字の間に半角スペースを入れる | 419 | 210 | Clean | HUMAN_ONLY |
長さを4倍にしても足切りは変わらない(840字でも wordCount は1のまま)。一方、半角スペースを入れた途端に語数の壁は越える。原因が文章量ではなく分かち書きの有無であることは、この2行で確定する。
そして壁を越えた先にもう1つの壁がある。空白を入れて採点対象になった日本語のAIっぽい文章は、0点・Clean・HUMAN_ONLY と判定される。 62パターンと112語の置換表はすべて英語のために書かれているので、日本語の「まさに〜と言えるでしょう」も「革新的なソリューション」も1件も引っかからない。つまり日本語に対しては、足切りされるか、通過して偽陰性になるかの二択になる。
countWords() の1行が入り口を塞いでいる採点されない"] C -->|"No(空白を入れた場合)"| E["62パターンの正規表現に照合"] E --> F["すべて英語向け
日本語は1件もヒットしない"] F --> G["score = 0 / HUMAN_ONLY
偽陰性"] style D fill:#ffe6e6 style G fill:#ffe6e6
なお、この挙動を「バグ」と呼ぶのは正確ではない。リポジトリは日本語対応を一度も主張していない。README の Community 節にはコミュニティ製の多言語版 jurigis/avoid-ai-writing-multilingual が紹介されているが、収録はドイツ語・フランス語・イタリア語・ルーマニア語・スウェーデン語の5言語で、日本語は含まれない(★13・最終更新 2026-08-05)。上流リポジトリ本体を 日本 および Japanese で全文検索しても該当は0件だった。日本語は「壊れている」のではなく、最初から範囲外である。
AIっぽい文章の特徴は「語」より「構文」に出る
日本語で「AI 文章 特徴」「AI 文章 バレる」と検索したとき出てくる指摘の多くは語彙の話(「シームレス」「革新的」など)に寄っている。だが SKILL.md の62パターンを読むと、単語の置換表(112語)よりも構文規則のほうが判定力を持たされていることが分かる。実際、前掲の英語実測で80点を積み上げた21件の指摘のうち、単語1語で決まったものは半数以下で、残りは「否定並列」「出典なしの権威づけ」「意味の薄い結び」「同義語の循環」といった文の形に対する指摘だった。
これは日本語でAIっぽい文章を直すときにもそのまま使える。語を言い換えるだけでは型が残るので、読む側の違和感は消えない。実測2でスキルが日本語に対して出した指摘も、削ったのは語ではなく型のほうだった——「単なるXではなくY」を2回から1回に減らし、「専門家によれば」という主語のない権威づけを丸ごと落とし、文末の「まさに〜と言えるでしょう」の反復を解いている。AIっぽい文章を直す作業の本体は、語の置換ではなく構文の重複除去である、というのがこのリポジトリの主張であり、手元の実測もそれを支持した。
なお、この構文重視の設計には副作用がある。締切に追われた人間や第二言語話者も同じ型を書くため、誤検出が構造的に発生する。SKILL.md が冒頭で「これは証拠ではない」と断り、非英語話者への誤検出率60%超という研究を自分で引いているのは、この副作用を自覚しているからだ。Claude Code スキルとして便利であることと、判定装置として信頼できることは別として扱う必要がある。
実測2:スキル本体(SKILL.md)は日本語でも発火する
検出エンジンが動かないことと、スキルが役に立たないことは別である。SKILL.md はLLMが読んで実行する指示書で、正規表現ではない。日本語で依頼したらどうなるかを確かめた。
同じ日本語のAIっぽい段落を、スキルを置いたディレクトリと置いていないディレクトリの2か所で書き直させた(Claude Code 2.1.241・2026-08-27)。
| 観測項目 | スキル有り | スキル無し |
|---|---|---|
| ターン数 | 3 | 1 |
| 実測コスト | $0.2558 | $0.0766 |
| 応答の長さ | 917字 | 456字 |
| 応答の構造 | 検出リスト → 書き直し → 変更点 → 二次チェック | 書き直し+変更点の箇条書き |
| 応答がスキル名に触れたか | 触れない | — |
スキル有り側の応答は、SKILL.md が定める4部構成(指摘・書き直し・変更理由・収束のための再監査)をそのまま踏襲していた。指摘の中身も日本語の型を正しく捉えている。
・「単なるツールではなく〜」「単に導入することではなく〜」が否定並列の2回目にあたるとして、1回に減らした
・「専門家によれば」を出典なしの権威づけとして削除
・「まさに〜と言えるでしょう」が文中2回出ることを同一ヘッジの反復として指摘
・7文→4文に圧縮し、言い換えによる水増しを削除
英語で書かれたパターン集が、日本語の対応する型へ一般化されて適用されたことになる。ここは正規表現には真似できない部分で、スキルの価値はこちら側にある。
「入れたつもりで効いていない」を機械的に見分ける
ここが実務上いちばん重要な点である。上の表のとおり、日本語で依頼したとき、応答本文はスキル名にひとことも触れなかった。英語で依頼したときは応答が「Using avoid-ai-writing to strip the AI tells…」と自己申告したので、本文を読めば分かった。つまり本文を根拠に「効いている」と判断すると、言語によって判定がぶれる。
確実なのは実行ログを見る方法である。
claude -p "この文章のAIっぽさを消して書き直して: <本文>" \
--output-format stream-json --verbose \
--allowedTools "Skill,Read,Glob" < /dev/null | grep -o '"skill":"[^"]*"'
発火していれば、ツール呼び出しとして次の2行が観測できる。
"name":"Skill","input":{"skill":"avoid-ai-writing", ...}
"content":"Launching skill: avoid-ai-writing"
何も出なければ発火していない。この確認は、スキルが読み込まれているかの確認とは別物である点に注意したい。読み込みだけを見たいなら claude -p "利用可能なスキルを列挙して" で一覧に名前が出るかを見る。一覧に出ていても、依頼の言い回しによっては呼ばれないことがある(別記事で扱う refactoring-ui スキルでは、まさにこの「一覧には出るが呼ばれない」状態を再現できた)。
実測3:出力はどれだけ変わるのか——スキルの取り分を数字にする
「効いている」を主観で語らないために、同梱の検出器で書き直し後の文章を採点した。英語で行ったのは、前述のとおり検出器が日本語を採点できないためである。
手順は単純で、AI的な英語段落を用意し、(1) 素の状態、(2) スキル無しで書き直させた結果、(3) スキル有りで書き直させた結果、の3つを analyzeText() にかけた。
| 対象 | score | label | 指摘件数 | 分類 |
|---|---|---|---|---|
| 元の文章 | 80 | Strong AI signals | 21 | AI_ONLY |
| スキル無しで書き直し | 9 | Minimal AI signals | 2(em-dash・単調さ) | HUMAN_ONLY |
| スキル有りで書き直し | 0 | Clean | 0 | HUMAN_ONLY |
スキルを入れると0点まで落ちる。ただし素のモデルだけでも80→9まで落ちていることを見落としてはいけない。スキルの取り分は残りの9点ぶんで、しかも残った2件は em-dash の使用と文長の単調さという、指摘さえ知っていれば手で直せる種類のものだ。
この採点には構造上の偏りがあることは明記しておく。書き直しを評価しているのは、書き直しを指示したのと同じリポジトリが持つ検出器である。スキルが「この62パターンを消せ」と指示し、同じ62パターンで採点しているのだから、0点が出やすいのは当然だ。第三者の検出器で測ればスコアは変わりうる。それでもスキル無しの9点という対照が同じ物差しで取れているので、両者の差を比べる用途では成立している。
判断材料としては次のように読むのが妥当だろう。
・一度きりの書き直しなら、素のモデルに「AIっぽい言い回しを消して」と頼むだけで大半は片づく
・基準を固定して何十本も通すなら、62パターンという明文化された規準と4部構成の出力が効いてくる。人によって指摘が変わらない
・コストは5.9倍なので、原稿1本ごとに常時かけるかはボリューム次第
導入手順と、検出器だけを使う方法
導入は SKILL.md を1つ置くだけで終わる。
# Claude Code(プロジェクト単位)
mkdir -p .claude/skills/avoid-ai-writing
curl -sL https://raw.githubusercontent.com/conorbronsdon/avoid-ai-writing/main/SKILL.md \
-o .claude/skills/avoid-ai-writing/SKILL.md
# 発火するか確認(何も出なければ発火していない)
claude -p "この原稿のAIっぽさを消して: <本文>" \
--output-format stream-json --verbose --allowedTools "Skill" < /dev/null \
| grep -o 'Launching skill: [a-z-]*'
Cursor 用の cursor-rules/avoid-ai-writing.mdc、Claude Code プラグイン用の .claude-plugin/marketplace.json も同梱されている。compatibility 欄には agentskills.io の SKILL.md 形式に対応する任意のエージェント(Claude Code・Cursor・VS Code Copilot・Hermes Agent・OpenHands)と OpenClaw が挙げられている。
英語原稿を扱うなら、検出器だけをCIに組み込む使い方もできる。package.json の files は detector/patterns.js と detector/validate.js の2つだけで、依存パッケージはゼロ、ブラウザでもそのまま動く(AIDetector としてグローバル登録される)。
手元でリポジトリの検査系を一通り走らせた結果も記録しておく。
・npm test — 検出器のフィクスチャ、カテゴリ契約、書き換え保全、コーパス、文体検査の5系統がすべて通過(文体検査だけで39件)
・node scripts/self-scan.js --check — PASS。リポジトリ自身のドキュメント(README・CHANGELOG・PROOF.md 等)を自分のルールで採点し、全ファイルが予算内に収まっている
自分のルールを自分の文書に適用して落ちないことをCIで縛っている点は、この種のスキルとしては誠実な部類に入る。
同種スキルとの使い分け
当サイトでは同じ問題領域のスキルを個別に検証している。役割が重ならないので、併用が前提になる。
| 対象 | 何を直すか | 決定論的な検査 | 本記事との関係 |
|---|---|---|---|
| avoid-ai-writing | 文章のAIっぽさ | あり(英語のみ) | 本記事 |
| アンチスロップ・スキル10本の実測比較 | 文章(横並び比較) | 比較対象による | 10本の俯瞰。avoid-ai-writing は未収録 |
| Hallmark デザインスキル | UIのAIっぽさ | なし(57ゲートは指示文) | 対象が文章ではなく画面 |
| Claude Skillsとは | — | — | スキル機構そのものの解説 |
「文章のAIっぽさ」を扱うスキルを横並びで比べたい場合は アンチスロップ・スキル10本を全部cloneして実測比較 が俯瞰にあたる。本記事はそこで扱われなかった最大手1本を、日本語で動くかどうかという軸だけに絞って深掘りした位置づけになる。
まとめ——どこまで信じてよいか
・検出器(detector/patterns.js)は日本語で使えない。 210字が1語と数えられ足切りされ、空白を入れて通しても62パターンが英語専用なので0点になる。日本語原稿の判定に使ってはいけない
・スキル本体(SKILL.md)は日本語でも発火し、日本語の型を正しく直す。 英語のパターン集がLLMによって一般化されている
・発火の確認は本文ではなく --output-format stream-json で行う。日本語依頼では応答がスキル名に触れなかった
・効果は英語で80点→0点。ただしスキル無しでも9点まで落ちる。 差分9点にコスト5.9倍を払うかは運用ボリュームで決まる
・リポジトリ自身が「これは証拠ではない」と明記している。 誤検出率の研究を自分で引いており、人事・学術の判断根拠には使えない
日本語で厳密な採点まで欲しいなら、現状は自分でパターンを足すしかない。上流には日本語版が無く、コミュニティ多言語版にも日本語は入っていない。裏を返せば、日本語の型(「まさに〜と言えるでしょう」「〜と言っても過言ではありません」「本記事では〜を包括的に解説します」)を SKILL.md に追記した派生版は、まだ誰も公開していない空白である。
日本語で「AIっぽい 文章 直す」ことだけが目的なら、実は導入しない選択も合理的である。実測3が示したとおり、素のモデルに頼むだけで80点が9点まで落ちる。スキルが必要になるのは、複数人・複数本の原稿に同じ基準を当てたいとき——つまり指摘が人や日によってぶれると困る場面だ。62パターンという明文の規準と、検出→書き直し→変更点→二次監査という固定の出力形式は、そのぶれを潰すために存在する。逆に言えば、原稿が月に数本なら、コスト5.9倍を払って得るものは薄い。
導入するかどうかの判断は、次の3点で切り分けられる。扱う言語が英語なら検出器まで含めて全部使える。日本語ならスキル部分だけを使い、採点は諦める。 そして本数が少ないならスキル自体が不要——この3つだ。日本語で採点まで欲しい場合に残る道は、SKILL.md に日本語の型を自分で追記した派生版を作ることだが、前述のとおり公開されている実装は現時点で見当たらない。
参照ソース
・conorbronsdon/avoid-ai-writing — 公式リポジトリ。SKILL.md v3.26.0・★3,403・fork 302・MIT(2026-08-27 時点)
・detector/README.md — analyzeText() / validate() の返り値仕様
・jurigis/avoid-ai-writing-multilingual — コミュニティ多言語版(DE/FR/IT/RO/SV・日本語なし)
・本記事の数値は 2026-08-27 に macOS・Node v22.13.1・Claude Code 2.1.241 で実行した結果です。コスト表示は CLI が返す total_cost_usd の実測値で、モデルや時期により変動します