ClaudeでF8変換が二重入力になる問題の解決法3つ

Claudeで日本語で入力中にF8変換を使うと、文字が二重入力になることがあります。たとえば、日本語IMEがONのまま「claude」と入力してしまったとき、入力途中で次のような文字列になります。

cぁうで

F9で全角英字に変換し、続けてF8で半角英字に変換する操作を使う人は少なくありません。隣のキーなので2キーを素早く押すことも出来ます。

F9 → 全角アルファベット化
F8 → 半角アルファベット化

通常の入力欄なら「claude」と入力されますが、Claudeの入力欄では

claudeclaude

のように、全角英字と半角英字が二重に入る場合があります。しかも、単に二重入力されるだけではありません。前半の「claude」は確定済みの文字列として入り、後半の「claude」は未確定文字列のような状態で残ります。これは非常に書きにくい。

なので、なんとか解決できる方法がないか探ってみました。

この問題への対処法は、現時点で3つあります。

  • Ctrl+Oを使う:F8と同じ半角変換のショートカットキー「Ctrl+o」ならば、Claudeで正常に動くので、入力方法を変える方法です。
  • AutoHotkeyでF8をCtrl+Oに置き換える:OS側でF8の入力をCtrl+Oとして置換する方法です。今まで慣れたキー操作で済みますが、他のアプリで支障が出る場合もあり。
  • Chrome拡張機能で処理する:F8によって発生した二重入力を検知して、余分な文字を自動で削除する拡張機能をインストールする方法です。多少強引ですが可能です。

原因は、Claude側の入力欄がF8キーイベントをIMEと競合する形で処理していることにあります。ユーザー側からClaude本体の挙動を直接直すことはできません。なので、解決法というよりは対処法になっています。

この記事では、ClaudeでF8変換が二重入力になる原因を整理しながら、実用上のストレスを減らす3つの方法を紹介します。

対処法 向いている人 弱点
Ctrl+Oを使う キー操作を変えられる人 F8の手癖を直す必要がある
AutoHotkeyで置き換える F8の手癖を残したい人 設定範囲を誤ると他アプリに影響する
Chrome拡張機能で後処理する Chromeブラウザだけで問題を解決したい人 根本修正ではなく、発生後の補正になる

F8は半角カタカナだけのキーではない

F8というと、日本語IMEの半角カタカナ変換として説明されることが多いです。ただ、実際の作業では半角カタカナだけに使うわけではありません。

IMEがONのまま英単語を打ってしまったとき、F9で全角英数字に変換し、そのあとF8で半角英数字へ戻す使い方があります。

cぁうで
↓ F9
claude
↓ F8
claude

この操作に慣れると、打ち直すより早いです。英単語やサービス名を頻繁に入力する人ほど、F9→F8の変換が便利です。Claudeでバグるのは、このF8キーだけです。

Ctrl+Oなら正常に動く

最初に気づいたのは、F8とCtrl+Oで挙動が違うことでした。Microsoft IMEでは、F8とCtrl+Oはどちらも半角変換として使えます。Claudeの入力欄でも、Ctrl+Oを使うと期待どおりに変換できました。

claude
↓ Ctrl+O
claude

しかしF8を使うと、次のようになります。

claudeclaude

結果だけ見れば、F8とCtrl+Oは同じ半角変換のはずです。それなのにClaudeでは、F8だけが二重入力になります。

この時点で、問題はIMEそのものではなく、Claudeの入力欄がF8キーイベントを扱うタイミングにあると考えました。

AIと一緒にコンソールログで原因を追った

最初から原因が分かっていたわけではありません。

F8キーがClaudeの入力欄と相性が悪い、という程度の理解から始まりました。

そこでAIとチャットしながら、Chrome DevToolsでイベントログを取って原因を追うことにしました。

確認したのは、IME入力で重要になる次のイベントです。

  • keydown
  • beforeinput
  • input
  • compositionstart
  • compositionupdate
  • compositionend

コンソールにログを出すため、次のようなコードを一時的に仕込みました。

document.addEventListener('keydown', e => {
  console.log('[keydown]', e.key, 'isComposing=', e.isComposing);
}, true);

document.addEventListener('compositionstart', e => {
  console.log('[compositionstart]', e.data);
}, true);

document.addEventListener('compositionupdate', e => {
  console.log('[compositionupdate]', e.data);
}, true);

document.addEventListener('compositionend', e => {
  console.log('[compositionend]', e.data);
}, true);

document.addEventListener('beforeinput', e => {
  console.log('[beforeinput]', e.inputType, e.data, 'isComposing=', e.isComposing);
}, true);

document.addEventListener('input', e => {
  console.log('[input]', e.inputType, e.data, 'isComposing=', e.isComposing);
}, true);

このログで、かなり重要なことが分かりました。

F8を押したとき、拡張機能側でkeydownを拾う時点では、すでにisComposingがfalseになっていました。

コンソールログで確認したところ、compositionendの発火元がvendor-radix-CCCnjTZn.jsであることが分かりました。つまり、Claude側のRadixコンポーネントがcompositionを終了させていることが、ログから確認できました。

問題の本質はcompositionendのタイミングだった

Claudeの入力欄には、ProseMirror系のエディタが使われています。

ProseMirrorのようなリッチテキストエディタは、通常のtextareaとは違い、入力内容をJavaScriptで細かく管理します。

日本語IMEの未確定文字列も、compositionイベントとして扱われます。

本来なら、F9で全角英字にした未確定文字列に対して、F8で半角変換がかかるだけです。

期待する結果:
claude

ところがClaudeでは、F8押下時に次のような流れになっていると考えました。

F8を押す
↓
Claude側のProseMirror系処理がcompositionを終了させる
↓
全角英字が確定済みテキストとして入る
↓
その後にIME側のF8変換結果が別の入力として追記される
↓
claudeclaude になる

この流れだと、keydownイベントでevent.isComposingを見ても間に合いません。

こちらがF8を捕まえた時点では、すでにClaude側の処理によってcompositionは終わった扱いになっているからです。

keydownで止める案はうまくいかなかった

最初に考えたのは、F8のkeydownイベントを捕まえて止める方法です。

document.addEventListener('keydown', (event) => {
  if (event.key === 'F8' && event.isComposing) {
    event.preventDefault();
    event.stopImmediatePropagation();
  }
}, true);

考え方としては自然です。IME変換中にF8が押されたら、Claude側に渡さずに止める。

しかし、これは今回のケースでは効きませんでした。理由は、F8のkeydown処理に来た時点で、event.isComposingがすでにfalseになっているからです。つまり、「IME変換中なら止める」という条件が成立しません。

この時点で、isComposingだけを見て対処する方法は捨てました。

AutoHotkeyでF8をCtrl+Oにする案もあった

次にAIから、AutoHotkeyでF8をCtrl+Oに置き換える方法が提案されました。

Ctrl+OではClaude上でも正常に半角変換できていたため、OS側でF8をCtrl+Oとして送れば、手癖を変えずに済みます。

#Requires AutoHotkey v2.0

#HotIf WinActive("ahk_exe chrome.exe") && InStr(WinGetTitle("A"), "Claude")
F8::Send "^o"
#HotIf

この方法はかなり現実的です。

Claudeのタブだけに限定できれば、F8の手癖を残したまま、Ctrl+Oの正常な変換を使えます。

ただし、問題もあります。

F8は他のアプリでも機能が割り当てられていることがあります。Windows全体でF8を置き換えるのは危険です。Chrome全体に限定しても、Claude以外のページでF8を使う場合に影響します。Claudeのタブタイトルで絞る方法もありますが、タイトルは会話が始まると内容に応じて変わるため、「Claude」という文字列で判定しても確実に絞れないことがあります。実用上はahk_exe chrome.exeのみに絞るか、URLで判定する方が安定します。

この方法は手癖を変えずに済むという点では有効です。ただ、AutoHotkeyのインストールが前提になるため、採用しにくいと判断しました。

Ctrl+P→Ctrl+Oに慣れる方法もある

人によっては、F9→F8をやめて、Ctrl+P→Ctrl+Oに慣れる方法もあります。

日本語IMEでは、Ctrl+Pで全角英数、Ctrl+Oで半角英数に変換できます。

Ctrl+P → 全角英数字
Ctrl+O → 半角英数字

ClaudeではCtrl+Oが正常に動いていたため、この操作に切り替えるのも選択肢です。ただ、私の場合はF9→F8の操作が完全に手癖になっていました。英単語を直すたびに、無意識にF9→F8を押しています。こういう操作は、頭で分かっていても簡単には変わりません。

入力のたびに自分の手癖を意識するくらいなら、ツール側で吸収したほうが早いと判断しました。

Chrome拡張機能で余分な文字を削除する方針にした

最終的には、F8を正しく再現するのではなく、F8によって発生した余分な文字を削除する方針にしました。

Chrome拡張機能だけで、本物のIME変換を呼び直すことはできません。

JavaScriptでKeyboardEventを作ってCtrl+Oを発火させても、それはユーザーが実際に押したキーではありません。

JavaScriptで生成したイベントはisTrusted: falseになるため、ブラウザやIMEのネイティブ処理をトリガーしません。

そこで、発想を変えました。

F8変換そのものを再現するのではなく、Claude上に現れた壊れた結果を見て、後処理で直します。

claudeclaude
↓
claude

この方法なら、F9→F8の手癖を変えずに済みます。

また、OS全体のキー割り当てを変更しないため、Claude以外のアプリにも影響しません。

実装の考え方

今回作ったChrome拡張機能では、Claudeの入力欄であるProseMirror要素を監視します。

Claudeの入力欄は、最初から単純なtextareaとして存在しているわけではありません。

画面の状態に応じて動的に生成されるため、MutationObserverで.ProseMirror要素を探し、見つけた入力欄に処理を適用します。

処理の流れは次のとおりです。

compositionendで確定文字列を取得
↓
その文字列を半角変換した結果を作る
↓
エディタ末尾が「元文字列+半角文字列」になっているか確認
↓
一致した場合だけ二重入力と判断
↓
該当部分を削除
↓
半角文字列だけを再挿入

たとえば、compositionendで得られた文字列が「claude」だったとします。

これを半角変換すると「claude」になります。

Claudeの入力欄の末尾が次のようになっていれば、二重入力と判断できます。

claudeclaude

この場合だけ、末尾の二重部分を削除し、半角の「claude」だけを挿入します。

通常の入力まで巻き込まないように、「元文字列+半角文字列」というパターンに一致したときだけ処理します。

変換処理では全角英数字と日本語を半角化する

今回の主目的は、IME ONのまま打ってしまった英単語を直すことです。

そのため、全角英数字を半角英数字に戻す処理が中心になります。

ただし、F8は半角カタカナ変換にも使われるため、平仮名や全角カタカナも半角カタカナへ変換できるようにしました。

実装では、次のような文字を変換対象にしています。

  • 全角英数字
  • 平仮名
  • 全角カタカナ
  • 全角スペース
  • 一部の全角記号

全角英数字は文字コード差分で半角へ変換できます。

平仮名と全角カタカナは、半角カタカナへの変換マップを用意しました。

これにより、英単語だけでなく、F8由来の二重入力全般にある程度対応できます。

削除と再挿入にはdocument.execCommandを使った

二重入力を検出したあと、該当部分を削除して半角文字列を再挿入します。

ここでは、ProseMirrorの内部状態とDOMのズレをできるだけ避ける必要があります。

単純にinnerTextやtextContentを書き換えると、ProseMirror側の状態管理と衝突する可能性があります。

そのため、今回の実装ではdocument.execCommandを使い、入力操作として削除と挿入を行う方針にしました。

document.execCommand('delete', false, null);
document.execCommand('insertText', false, halfText);

execCommandはWeb標準から非推奨(deprecated)とされており、将来的にブラウザから削除される可能性があります。ただし、contenteditable系の入力欄に対して、ブラウザの入力操作として扱わせたい場面ではまだ実用になります。

ClaudeのProseMirror入力欄に対しては、この方法のほうが素直に反映されました。

この拡張機能は根本解決ではない

今回のChrome拡張機能は、Claude側のProseMirrorやRadixのcomposition処理そのものを直しているわけではありません。本来であれば、Claude側の入力欄がIMEの未確定文字列を正しく扱うべきです。F8を押したときに、全角英字を確定済みとして残し、その後ろに半角変換結果を別入力として追記する挙動は、入力欄側のIME対応としてはかなりつらいです。

ただ、ユーザー側のChrome拡張機能から、Claude内部の入力処理を完全に制御するのは難しいです。そのため今回は、根本修正ではなく、実用上のストレスを消す後処理にしました。

発生した二重入力を検出し、余分な全角文字列を削除するという多少強引な方法ですが、対処法としては有効なツールが出来上がりました。

AIとのデバッグで分かったこと

今回の修正で面白かったのは、AIとのチャットがそのままデバッグの相手になったことです。最初は「F8とCtrl+Oは同じはずなのに、なぜClaudeでは違うのか」という疑問から始まりました。

そこから、keydownで止める案、isComposingを見る案、AutoHotkeyでF8をCtrl+Oに置き換える案、Ctrl+P→Ctrl+Oに慣れる案など、複数の回避策を検討しました。ただ、実際にChromeのコンソールログを取っていくと、単純なkeydown対策では間に合わないことが分かりました。F8のkeydownが来たときには、すでにcompositionが終わった扱いになっている。この発見が大きかったです。

AIとのやり取りだけでは、原因は確定しません。しかし、仮説を立てて、ログを仕込み、結果を見て、次の案を考える。この流れをAIと進められるのはかなり便利でした。AIは適切なデバッグログ出力のコードを書いてくれます。ログを読み込ませるだけで解析してくれるので、少しの質問と提案をするだけで、デバッグの壁打ち相手としてAIを使う価値を感じました。

まとめ

ClaudeでF9→F8変換を使うと、全角英字と半角英字が二重入力になることがあります。私の場合、IMEがONのまま英単語を入力してしまったとき、F9→F8で直す手癖がありました。通常の入力欄なら問題ありませんが、Claudeでは「claudeclaude」のように、全角英字と半角英字が二重に入ります。Chromeのコンソールログで調べたところ、F8のkeydownを処理する時点では、すでにcompositionが終了しているように見えました。そのため、event.isComposingを見てF8を止める方法では間に合いません。

AutoHotkeyでF8をCtrl+Oにする案や、Ctrl+P→Ctrl+Oに慣れる案もありました。しかし、他のアプリへの影響や手癖の問題を考え、最終的にはChrome拡張機能で余分な文字を後処理で削除する方針にしました。根本解決ではありません。それでも、毎回の入力ストレスは消えました。

日本語IMEとWebアプリのリッチテキストエディタは、まだ相性問題が出ます。特にProseMirror系の入力欄では、keydownだけでなく、compositionend、beforeinput、inputの順序まで見ないと原因が見えません。今回の件は、小さな入力バグに見えて、IMEとWebエディタの難しさがかなり詰まった事例でした。