Claude CodeでShift_JIS環境と格闘した話 - 文字化け地獄からの生還
Claude Codeを使って開発していたら、突然ファイルが文字化けして全滅しました。
UTF-8前提のAIツールを、Shift_JIS環境で使う際の落とし穴と解決策を共有します。
事の発端:平和な開発からの突然の悲劇
開発していた環境
- レガシーなWebアプリケーション(15年以上稼働中)
- すべてのファイルが Shift_JIS エンコーディング
- 日本語コメント・日本語変数名が大量に存在
- 理由:Windows環境で日本語を扱うため、当時はShift_JISが標準だった
やりたかったこと
私:「この関数に日本語コメントを追加して」
期待していた結果
// ユーザーデータを取得する関数
function getUserData(userId) {
// データベースから取得
return db.query("SELECT * FROM users WHERE id = ?", userId);
}
実際の結果
// 繝ヲ繝シ繧カ繝シ繝�繝シ繧ソ繧貞叙蠕励☆繧矩未謨ー
function getUserData(userId) {
// 繝�繝シ繧ソ繝吶�繝シ繧ケ縺九i蜿門セ�
return db.query("SELECT * FROM users WHERE id = ?", userId);
}
完全に文字化け。 使えないじゃん悲しい...
原因究明:なぜ文字化けしたのか
調査結果
Claude CodeのEditツールはUTF-8前提で動作する
- ファイルを読み込む → UTF-8として解釈(実際はShift_JIS)
- 日本語文字列を追加 → UTF-8で挿入
- ファイルを保存 → UTF-8とShift_JISが混在
- 結果:文字化け
簡単に言うと
「Shift_JISで書かれた本に、UTF-8の文字をそのまま貼り付けた」状態。
当然読めなくなります。
第一次対策:手動変換(失敗)
やったこと
# ファイルをUTF-8に変換
iconv -f SHIFT_JIS -t UTF-8 file.js > file_utf8.js
# Claude Codeで編集
# Shift_JISに戻す
iconv -f UTF-8 -t SHIFT_JIS file_utf8.js > file.js
問題点
- 毎回手動でやるのが面倒
- 変換忘れが頻発
- チームメンバーにも同じ手順を強いることになる
結論
手動運用は無理。自動化が必須。
第二次対策:Edit禁止・Bashで自動化(成功)
基本方針
Claude CodeのEditツールを使わず、Bashコマンドで編集と変換を一気に実行
新規ファイル作成の場合
# 1コマンドで作成+変換を実行
cat > /path/to/file.js << 'EOF'
// ユーザーデータを取得する関数
function getUserData(userId) {
return db.query("SELECT * FROM users WHERE id = ?", userId);
}
EOF
iconv -f UTF-8 -t SJIS /path/to/file.js > /tmp/temp.js && mv /tmp/temp.js /path/to/file.js
ポイント:
-
catで一旦UTF-8で作成 -
iconvでShift_JISに変換 -
&&で連結して1コマンド化(確認プロンプトを回避)
既存ファイル編集の場合(方法1:Pythonバイナリモード)
# バイナリモードで読み書きすることで、エンコーディング問題を回避
python3 << 'EOF'
# バイナリモードで読み込み(エンコーディング変換なし)
with open('file.js', 'rb') as f:
content = f.read()
# バイト列レベルで置換
content = content.replace(
b"old text",
"新しい日本語テキスト".encode('shift_jis')
)
# バイナリモードで書き込み(構造完全保持)
with open('file.js', 'wb') as f:
f.write(content)
EOF
ポイント:
-
rb(read binary)で読み込むことで、エンコーディングを気にしない - 日本語部分だけ
.encode('shift_jis')でShift_JISバイト列に変換 -
wb(write binary)で書き込み
既存ファイル編集の場合(方法2:sed + iconv)
# ASCIIのみの置換なら安全
sed -i 's/oldText/newText/g' file.js
# 日本語を含む場合は変換が必要
echo "新しい日本語コード" | iconv -f UTF-8 -t SHIFT_JIS >> file.js
第三次対策:CLAUDE.mdで「エンコーディング憲法」を制定
問題
毎回「Shift_JISで保存して!」と指示するのは面倒。
解決策
プロジェクトのルールとして明文化し、Claude Codeに自動で守らせる。
CLAUDE.mdに追加した内容
## エンコーディング(最重要・必須・完全自動化)
**絶対厳守ルール**: ファイルの作成・編集は以下の方法で**完全自動化**すること。
### 🔴 対象ファイル(全てShift_JIS必須):
- `.js` ファイル
- `.html` ファイル
- `.css` ファイル
- その他、日本語を含む全ファイル
### ✅ 新規ファイル作成時
```bash
cat > /path/to/file.js << 'EOF'
[ファイル内容]
EOF
iconv -f UTF-8 -t SJIS /path/to/file.js > /tmp/temp.js && mv /tmp/temp.js /path/to/file.js
✅ 既存ファイル編集時(Pythonバイナリモード推奨)
python3 << 'EOF'
with open('file.js', 'rb') as f:
content = f.read()
content = content.replace(b"old", "新".encode('shift_jis'))
with open('file.js', 'wb') as f:
f.write(content)
EOF
❌ 絶対禁止
- EditツールでShift_JISファイルを編集
- sedで日本語を直接挿入
### 効果
このドキュメントを作成後、Claude Codeは**自動的に正しい方法**でファイルを編集してくれるようになりました。
---
## 検証方法:文字化けしていないか確認
### ファイルのエンコーディング確認
```bash
file file.js
# 正常な場合
# file.js: Non-ISO extended-ASCII text
# 異常な場合(UTF-8混在)
# file.js: UTF-8 Unicode text
文字化けチェック
# Shift_JISとして正しく読めるか確認
iconv -f SHIFT_JIS -t UTF-8 file.js | less
# エラーが出たら文字化けしている
自動修復スクリプト
# 間違ってUTF-8で保存してしまった場合の修復
check_encoding() {
local file=$1
if file "$file" | grep -q "UTF-8"; then
echo "警告: Shift_JISファイルにUTF-8混在検出!"
# バックアップ作成
cp "$file" "${file}.bak"
# 修復
iconv -f UTF-8 -t SHIFT_JIS "$file" > "${file}.tmp"
mv "${file}.tmp" "$file"
echo "自動修復完了"
fi
}
# 使用例
check_encoding file.js
学んだ教訓
1. AIツールのエンコーディング前提を確認せよ
Claude Codeは素晴らしいツールですが、UTF-8前提で動作します。
Shift_JIS環境で使う場合は、追加の工夫が必要。
2. Editツールは万能ではない
状況によっては、BashコマンドやPythonスクリプトを使う方が安全。
3. プロジェクト固有ルールは必ず文書化
CLAUDE.mdに書いておけば、チーム全員+AI全員が守ってくれる。
4. 自動化できることは自動化
「毎回手動で変換」は必ず破綻する。1コマンド化が重要。
5. バックアップは必須
.bakファイルを作る癖をつけておくと、文字化けしても復旧できる。
他のエンコーディング問題と解決策
問題1:CSVファイルのエンコーディング
Excelで開くCSVは**Shift_JIS(BOM付き)**でないと文字化け。
解決策:
# UTF-8 → Shift_JIS (BOM付き)
iconv -f UTF-8 -t SHIFT_JIS < input.csv > output.csv
# BOM追加
printf '\xEF\xBB\xBF' | cat - output.csv > output_with_bom.csv
問題2:データベースからの日本語取得
データベースがUTF-8、アプリがShift_JISの場合。
解決策:
// 取得時にエンコーディング変換
const iconv = require('iconv-lite');
const data = await db.query("SELECT name FROM users");
const shiftJisData = iconv.encode(data.name, 'shift_jis');
問題3:APIレスポンスのエンコーディング
外部APIがUTF-8、内部処理がShift_JISの場合。
解決策:
const response = await fetch(apiUrl);
const utf8Text = await response.text();
const shiftJisText = iconv.encode(
iconv.decode(Buffer.from(utf8Text), 'utf-8'),
'shift_jis'
);
現在の運用
ワークフロー
-
ファイル作成・編集時
- Claude Codeに依頼
- 自動でBashコマンド or Pythonスクリプト実行
- Shift_JIS変換も自動
-
検証
-
fileコマンドでエンコーディング確認 - 異常があれば自動修復スクリプト実行
-
-
コミット前
- git hookでエンコーディングチェック
- UTF-8混在があればコミット拒否
結果
文字化け事故はゼロになりました。
まとめ:UTF-8時代にShift_JISと共存する方法
やるべきこと
- CLAUDE.mdでルール明文化
- Editツール禁止、Bash/Python推奨
- 1コマンド化で完全自動化
- file コマンドで検証
- git hookで防御
やってはいけないこと
- ❌ EditツールでShift_JISファイルを編集
- ❌ 手動変換に頼る
- ❌ エンコーディング検証を怠る
感想
正直、最初の文字化け事件は本当に焦りました。
お友達を失った感覚
でも、この経験のおかげで、
- エンコーディングの重要性
- AIツールの限界と対策
- 自動化の重要性
を深く理解できました。
**「レガシー環境でAIツールを使う」**というのは、
単に「古いコードを書かせる」だけではなく、
環境の特殊性に対応する工夫が必要だと実感しました。
同じようにShift_JIS環境で開発している方、
UTF-8前提のツールを使う際は、ぜひ気をつけてください!
そして、CLAUDE.mdを整備しておくことを強くお勧めします。
一度書いておけば、あとは自動で守ってくれますよ。
参考資料
エンコーディング確認コマンド集
# ファイルのエンコーディング確認
file filename
# 詳細確認
nkf -g filename
# Shift_JIS → UTF-8 変換
iconv -f SHIFT_JIS -t UTF-8 input.txt > output.txt
# UTF-8 → Shift_JIS 変換
iconv -f UTF-8 -t SHIFT_JIS input.txt > output.txt
Python でのエンコーディング処理
# 読み込み時にエンコーディング指定
with open('file.txt', 'r', encoding='shift_jis') as f:
content = f.read()
# 書き込み時にエンコーディング指定
with open('file.txt', 'w', encoding='shift_jis') as f:
f.write(content)
# バイナリモード(エンコーディング問題回避)
with open('file.txt', 'rb') as f:
binary_content = f.read()
# エンコーディング変換
text = binary_content.decode('shift_jis')