C Claude 導入ガイド

Tips · macOS 向け · 非公式

サイドバーを
日本語化する

Claude Desktop の Recents サイドバーに英語でセッションタイトルが表示される問題を、hook スクリプトで自動翻訳する設定方法です。

2026-05-13 のあおさん主催 Claude Code 勉強会オフ会での質問をもとに Kevin が作成

1. 重要な注意(必読)

このセットアップは非公式な方法です

  • Claude Desktop のローカル保存 JSON をバックアップしたうえで書き換える方法であり、Anthropic 公式が提供する仕組みではありません。
  • Claude Desktop / Claude Code のアップデートで保存場所や JSON フォーマットが変わると動かなくなる可能性があります。
  • 万一セッションタイトルや動作がおかしくなったら ~/.claude/hooks/backup/<日付>/ のバックアップから戻してください。
  • 公式の言語設定対応が来たら、このセットアップは不要になります(ロールバック手順あり)。

2. 他の方への共有文

勉強会などで他の方に紹介するときは、下記をそのままコピペして送れます。末尾に 後述の呪文本体 を続けてから送ってください。

Claude Desktop のサイドバーのスレッド名を日本語にするセットアップを共有します。

※これは Claude Desktop のローカル保存ファイルを書き換える非公式な方法です。
 バックアップは自動で作成されますが、不安な場合は実行しないでください。

【動作環境】
- macOS のみ
- jq コマンドが必要(なければログに `brew install jq` の案内が出ます)

【手順】
1. Claude Desktop を開く
2. 新規セッションで下の呪文を全文コピペ
3. Claude がファイル作成・設定変更を提案するので、内容を確認してから許可ボタンを押す
4. 完了したら Cmd+Q で Claude Desktop を完全終了 → 再起動
5. Recents のタイトルが日本語化されていれば成功

【もし問題が起きたら】
バックアップが ~/.claude/hooks/backup/<日付>/ に残るので復元可能です。
ただし復元はファイル操作を伴うため、不安な場合は詳しい人に相談してください。
手順だけ確認したい場合は Claude に「ロールバック手順を教えて」と聞くと案内されます。

送るときは、この説明文の後ろに 次のセクションの呪文本体 を追記してから送ってください。説明文だけだと受け取った側が何を Claude に渡せばいいか分からないため。

3. 日本語化の呪文

この呪文を全文コピーして Claude Desktop の新規セッション(または Claude Code)に貼り付けると、自動でセットアップしてくれます。Claude がファイル作成・設定変更を提案するので、内容を確認してから許可します。

呪文を唱える場所

Claude Desktop のチャット欄(Code 機能あり)、または ターミナル版 Claude Code どちらでも OK。新規セッションで貼り付けてください。

日本語化の呪文(全文コピー)
Claude Desktop の Recents サイドバーに表示されるセッションタイトルを、自動で日本語化するセットアップをして欲しいです。

## 環境前提
- macOS であること
- jq コマンドが入ってること (なければ案内してください)
- Claude Code がインストール済みであること

## やってほしいこと

### 1. 前提確認
- macOS か確認 (`uname` で Darwin)
- `jq` `python3` `claude` の存在確認
- 不足してたら `brew install jq` 等の案内をして停止

### 2. ファイル `~/.claude/hooks/rename-session-title.sh` を以下の内容で作成
(ディレクトリも無ければ `mkdir -p ~/.claude/hooks` で作成)

```bash
#!/usr/bin/env bash
set -uo pipefail
LOG="$HOME/.claude/hooks/rename-session-title.log"
mkdir -p "$(dirname "$LOG")"
log() { printf '[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" >> "$LOG"; }
if [ "${CLAUDE_RENAME_HOOK_ACTIVE:-}" = "1" ]; then exit 0; fi
export CLAUDE_RENAME_HOOK_ACTIVE=1
log "=== hook fired (pid=$$) ==="
if [ "$(uname)" != "Darwin" ]; then
  log "ERROR this script supports macOS only (got: $(uname))"
  exit 0
fi
MISSING=()
for cmd in jq python3 claude; do
  command -v "$cmd" >/dev/null 2>&1 || MISSING+=("$cmd")
done
if [ ${#MISSING[@]} -gt 0 ]; then
  log "ERROR missing required commands: ${MISSING[*]}"
  log "  Install hint:"
  log "    - jq:      brew install jq"
  log "    - python3: brew install python3  (or use system python)"
  log "    - claude:  visit https://claude.com/claude-code"
  log "  Ensure they are in PATH (e.g. /opt/homebrew/bin or /usr/local/bin)"
  exit 0
fi
CLAUDE_BIN=$(command -v claude)
INPUT=$(cat 2>/dev/null || true)
SID=$(printf '%s' "$INPUT" | jq -r '.session_id // empty' 2>/dev/null || echo "")
EVENT=$(printf '%s' "$INPUT" | jq -r '.hook_event_name // empty' 2>/dev/null || echo "")
log "event=$EVENT session_id=$SID"
SESSIONS_DIR="$HOME/Library/Application Support/Claude/claude-code-sessions"
[ -d "$SESSIONS_DIR" ] || { log "no sessions dir"; exit 0; }
LOCKDIR="$HOME/.claude/hooks/.rename.lock.d"
PID_FILE="$LOCKDIR/pid"
acquire_lock() {
  local retries=3
  while [ $retries -gt 0 ]; do
    if mkdir "$LOCKDIR" 2>/dev/null; then echo "$$" > "$PID_FILE"; return 0; fi
    local old_pid=""
    [ -f "$PID_FILE" ] && old_pid=$(cat "$PID_FILE" 2>/dev/null)
    if [ -n "$old_pid" ] && kill -0 "$old_pid" 2>/dev/null; then
      log "lock held by alive pid=$old_pid, skipping"; return 1
    fi
    log "stale lock (pid=${old_pid:-none} not alive), taking over"
    rm -rf "$LOCKDIR"; retries=$((retries - 1))
  done
  log "could not acquire lock after retries, skipping"
  return 1
}
if [ -d "$LOCKDIR" ]; then
  if [ -n "$(find "$LOCKDIR" -maxdepth 0 -mmin +10 2>/dev/null)" ]; then
    rm -rf "$LOCKDIR"; log "removed stale lock by age (fallback)"
  fi
fi
if ! acquire_lock; then exit 0; fi
trap 'rm -rf "$LOCKDIR"' EXIT
is_non_ascii() {
  printf '%s' "$1" | python3 -c 'import sys; sys.exit(0 if any(b>=0x80 for b in sys.stdin.buffer.read()) else 1)'
}
COUNT=0; SCANNED=0
while IFS= read -r -d '' f; do
  SCANNED=$((SCANNED+1))
  TITLE=$(jq -r '.title // empty' "$f" 2>/dev/null)
  [ -n "$TITLE" ] || continue
  if is_non_ascii "$TITLE"; then continue; fi
  log "translating: $TITLE  ($f)"
  PROMPT="次の英語のセッションタイトルを、自然で簡潔な日本語に翻訳してください。
ルール:
- タイトルだけを1行で返す
- 引用符・前置き・補足説明は不要
- 20文字以内を目安に
- 固有名詞・コマンド名・ファイル名は原文のまま残す

タイトル: $TITLE"
  JP_TITLE=$("$CLAUDE_BIN" -p --model haiku "$PROMPT" </dev/null 2>>"$LOG" \
    | head -1 | sed -E 's/^[[:space:]"'''「『]+//; s/[[:space:]"'''」』]+$//')
  [ -n "$JP_TITLE" ] || { log "  empty result, skip"; continue; }
  [ ${#JP_TITLE} -le 200 ] || { log "  too long, skip"; continue; }
  if ! is_non_ascii "$JP_TITLE"; then log "  ascii result, skip: $JP_TITLE"; continue; fi
  TMP="${f}.tmp.$$"
  if jq --arg t "$JP_TITLE" '.title = $t | .titleSource = "user"' "$f" > "$TMP" 2>>"$LOG"; then
    if jq -e '.sessionId and .cliSessionId and (.title != null)' "$TMP" >/dev/null 2>&1; then
      BACKUP_DIR="$HOME/.claude/hooks/backup/$(date '+%Y-%m-%d')"
      if ! mkdir -p "$BACKUP_DIR" 2>>"$LOG"; then
        rm -f "$TMP"; log "  backup dir creation failed, aborting"; continue
      fi
      BACKUP_FILE="$BACKUP_DIR/$(basename "$f")"
      if [ ! -f "$BACKUP_FILE" ]; then
        if ! cp "$f" "$BACKUP_FILE" 2>>"$LOG"; then
          rm -f "$TMP"; log "  backup failed, aborting"; continue
        fi
      fi
      if mv "$TMP" "$f" 2>>"$LOG"; then
        log "  -> $JP_TITLE  file=$f  backup=$BACKUP_FILE"
        COUNT=$((COUNT+1))
      else
        rm -f "$TMP"; log "  mv failed, original not overwritten"
      fi
    else
      rm -f "$TMP"; log "  health check failed, skipping"
    fi
  else
    rm -f "$TMP"; log "  jq failed"
  fi
done < <(find "$SESSIONS_DIR" -name "local_*.json" -print0 2>/dev/null)
log "done. scanned=$SCANNED translated=$COUNT"
exit 0
```

### 3. 実行権限を付ける
`chmod +x ~/.claude/hooks/rename-session-title.sh`

### 4. `~/.claude/settings.json` を編集 (重要: 重複登録に注意)

以下の要件を必ず満たしてください:

- ファイルが無ければ `{}` で新規作成
- 既存の場合はバックアップ (`cp ~/.claude/settings.json ~/.claude/settings.json.bak.$(date +%s)`)
- `.hooks` / `.hooks.Stop` / `.hooks.SessionStart` キーが存在しなくても壊れないマージ処理
- 同じ command が既に登録されていれば一度削除してから追加 (2 回実行しても重複しない冪等処理)
- `command` には `~` ではなく `$HOME` を展開した絶対パスを使用

参考の jq コマンド (安全版):

```bash
HOOK_CMD="$HOME/.claude/hooks/rename-session-title.sh"

[ -f ~/.claude/settings.json ] && cp ~/.claude/settings.json ~/.claude/settings.json.bak.$(date +%s)
[ -f ~/.claude/settings.json ] || echo '{}' > ~/.claude/settings.json

jq --arg cmd "$HOOK_CMD" '
  .hooks = (.hooks // {}) |
  .hooks.Stop = (
    (.hooks.Stop // [])
    | map(.hooks = ((.hooks // []) | map(select(.command != $cmd))))
    | map(select((.hooks // []) | length > 0))
  ) |
  .hooks.SessionStart = (
    (.hooks.SessionStart // [])
    | map(.hooks = ((.hooks // []) | map(select(.command != $cmd))))
    | map(select((.hooks // []) | length > 0))
  ) |
  .hooks.Stop += [{
    "hooks": [{
      "type": "command",
      "command": $cmd,
      "async": true,
      "timeout": 120
    }]
  }] |
  .hooks.SessionStart += [{
    "hooks": [{
      "type": "command",
      "command": $cmd,
      "async": true,
      "timeout": 120
    }]
  }]
' ~/.claude/settings.json > ~/.claude/settings.json.tmp \
  && mv ~/.claude/settings.json.tmp ~/.claude/settings.json
```

### 5. `~/.claude/CLAUDE.md` の末尾に以下を追記
(ファイルが無ければ新規作成。既に同じセクションがある場合は重複追記しない)

```
## セッションタイトル
新しいセッションのタイトル / 会話のタイトルは必ず日本語で生成してください。
```

### 6. 動作確認
- `~/.claude/hooks/rename-session-title.sh` が +x で存在
- `~/.claude/settings.json` が valid JSON (`jq . ~/.claude/settings.json`)
- 手動 1 回走らせて動作確認:
  `echo '{"session_id":"setup-test","hook_event_name":"Stop"}' | bash ~/.claude/hooks/rename-session-title.sh`
  ログ確認: `tail -20 ~/.claude/hooks/rename-session-title.log`

### 7. 完了報告
完了したら以下をユーザーに伝えてください:
- 「セットアップ完了しました。Cmd+Q で Claude Desktop を完全終了 → 再起動してください。」
- 「再起動後、Recents の英語タイトルが順次日本語化されます (新規セッションも自動で日本語タイトルになるよう設定済み)」
- バックアップ場所: `~/.claude/hooks/backup/<日付>/` に編集前ファイルが残ります

途中で詰まったら、どこで止まったか教えてください。

4. セットアップ後の動作

場面 挙動
再起動前から存在してた英語セッション 再起動後にほぼ全部日本語化される
既に日本語化されたセッション クリックしても英語に戻らない
新規セッション作成直後 数秒だけ英語表示 → hook 発火後に日本語に切り替わる

5. ログ確認方法

方法 A:Terminal アプリで実行

Mac の Terminal(またはiTerm2)を開いて、下のコマンドをコピペして Enter。

方法 B:Claude Code に頼む

Claude Code の新規セッションで「ログを見せて」と伝えるだけで確認してくれます。コマンドが分からなくてもOK。

Terminal を使う場合は、下記コマンドでリアルタイムにログを確認できます。

tail -f ~/.claude/hooks/rename-session-title.log

done. scanned=N translated=M が出れば正常に動作している証拠です。

6. トラブルシューティング

コマンドに慣れていない方へ

このセクションにはコマンド(黒い画面に入力するやつ)が出てきますが、Claude Code の新規セッションに状況をそのまま伝えるだけでも調査・対処してもらえます。

「サイドバーのタイトルが日本語になりません。ログを確認して原因を調べてください」

↑ こんな感じで頼めばOKです。コマンドが分からなくても大丈夫。

セッションタイトルが日本語にならない

1. まずログを確認(Terminal または Claude Code に依頼)

tail -50 ~/.claude/hooks/rename-session-title.log

2. よくあるエラーと対処

  • lock held by alive pid=..., skipping

    別の hook 実行が走り続けている可能性。しばらく待つ。10 分以上続く場合のみ強制クリア:

    rm -rf ~/.claude/hooks/.rename.lock.d
  • ERROR missing required commands

    不足しているコマンドをインストール: brew install jq / which claude で確認

  • done. scanned=0 translated=0

    Claude Desktop のアップデートで保存場所が変わった可能性。スクリプト内 SESSIONS_DIR が指す ~/Library/Application Support/Claude/claude-code-sessions が存在するか確認。

セッションが消えた等の重大トラブル

Qiita で Windows ユーザーが過去スレッド消失した事例あり(macOS では未観測)

バックアップはファイル名のみで保存されるため、元のサブディレクトリ情報はバックアップ側からは分かりません。ただしログにフルパスが残っているので復元は可能です。

  1. ログ (~/.claude/hooks/rename-session-title.log) を見て、file=<フルパス> backup=<バックアップフルパス> の行を探す
  2. その対応関係に従って、バックアップを元のパスへ個別にコピー (cp <backup> <file>)
  3. 不安な場合は手動復元せず、必ず詳しい人に相談する

機械的な一括コピーは推奨しません。複数 workspace に同名ファイルがある可能性、上書き対象を誤る可能性があります。

7. ロールバック手順

~/.claude/hooks/ には他のスクリプトが入っている可能性があるため、ディレクトリごと削除はしないようにしてください。

# 1. settings.json をバックアップから復元 (タイムスタンプは適宜置換)
cp ~/.claude/settings.json.bak.<タイムスタンプ> ~/.claude/settings.json

# 2. このセットアップ関連ファイルだけ削除
rm -f ~/.claude/hooks/rename-session-title.sh
rm -f ~/.claude/hooks/rename-session-title.log
rm -rf ~/.claude/hooks/.rename.lock.d

# 3. ~/.claude/CLAUDE.md に追記した以下のセクションをエディタで削除
#    ## セッションタイトル
#    新しいセッションのタイトル / 会話のタイトルは必ず日本語で生成してください。

# 4. Claude Desktop を Cmd+Q で完全終了して再起動

バックアップ (~/.claude/hooks/backup/) はしばらく残しておくのが安全です。完全に不要になったら手動削除:

rm -rf ~/.claude/hooks/backup/

8. 仕組み・コスト

仕組み概要

要素 役割
Stop hook Claude が応答完了するたびに発火 → 全英語タイトル翻訳
SessionStart hook Desktop 起動 / セッションフォーカス時に発火 → 同上
titleSource: "user" Desktop に「ユーザー設定」と認識させる(これで上書きされにくくなる)
PID ベースロック 同時実行を防ぎつつ、ハングしたら即奪取
バックアップ 編集前ファイルを ~/.claude/hooks/backup/<日付>/ に保存
JSON 健全性チェック 編集後ファイルが壊れていないか確認、壊れていたら書き込みキャンセル

既知の制約

  • 新規セッション直後の数秒: hook 発火までに英語が一瞬見える可能性(実害なし)
  • Anthropic 側の挙動変更: Claude Desktop のアップデートで titleSource: "user" の扱いが変わると壊れる可能性
  • ネットワーク不調時: claude -p haiku の失敗 → その回は英語のまま(次の hook 発火で再挑戦)

コスト目安

Claude Haiku 4.5 の API 単価(2026年5月時点): 入力 $1 / 100万トークン、出力 $5 / 100万トークン

タイトル翻訳は短文(入力 ~150 トークン / 出力 ~20 トークン)なので、1 回あたりのコストは非常に小さい想定です。

ただし claude -p の課金・利用枠の扱いは認証・契約形態(Pro / Max / Team / API キー直接)によって変わる可能性があります。

9. 公式対応について

この問題は GitHub Issue でも複数報告されています。特に今回のセットアップに近いのは:

  • #55951 — Desktop sidebar ignores UserPromptSubmit hook sessionTitle output
  • #54440 — [FEATURE] Localize auto-generated session titles in "Recents" sidebar
  • #58848 — Session titles generated in English despite language setting

開けるものに 👍 しておくと公式対応が早まる可能性があります。公式対応が来たらこの hook は不要になるので、ロールバック手順で剥がしてください。

なお ターミナルで claude コマンドからセッション開始する習慣にすると、hook 経由で公式の backend rename がトリガされてサーバー側のタイトルも日本語になります。Desktop 新規セッションより筋がよい方法です。

10. Windows 向け(実験的・未検証)

このセクションは macOS 環境のみで検証済みです

Windows 版は未テストで、Kevin も動作保証できません。Qiita で報告された事例として、Windows ユーザーが JSON を直接編集して過去スレッドが全消失したケースがあります。

Windows で試す場合は 必ず自己責任 で以下を実施してください:

  • 編集前に %APPDATA%\Claude\ を丸ごと zip でバックアップ
  • 1 ファイルだけテスト → 動作確認 → 次、という段階運用
  • 消えた場合は zip から復元
Windows 向け呪文を表示

Windows ユーザーには このページの URL + 下記の呪文を渡してください。ユーザーが自身の Claude Code に貼ると、Claude がその Windows 環境を探索しながら適応版を作成します。

Windows 向け呪文
あなたは Windows 環境で動いている Claude Code です。
私 (Windows ユーザー) の Claude Desktop サイドバーのスレッド名を、
自動で日本語化するセットアップをして欲しいです。

## 元情報: macOS 用のリファレンス実装

紹介者 (Mac ユーザー) は以下の構成でこれを実現しています。
あなたはこれを参考にしつつ、Windows 環境に適切に翻訳してください。

[ここに https://kevin-claude-guide.pages.dev/sidebar-jp の呪文本体を貼り付け]

## ⚠️ 重大な注意 (Windows 特有のリスク)

- Qiita で報告された事例として、`%APPDATA%\Claude\claude-code-sessions\`
  の JSON を直接編集して過去スレッドが全消失したケースあり。
- このリスクを下げるため、以下を必ず実施してください:
  1. 最初に `%APPDATA%\Claude\` を丸ごと zip でバックアップ
  2. テスト用に 1 セッションだけ翻訳 → Claude Desktop を完全終了 → 再起動して反映確認
  3. 上記で問題なければ全体に展開

## やってほしいこと

### 1. 環境探索
- Claude Desktop の `claude-code-sessions` ディレクトリ実パス(第一候補: `%APPDATA%\Claude\claude-code-sessions\`)
- 使えるシェル(Git Bash / WSL / PowerShell)
- 依存コマンドのパス(jq / claude / python)

### 2. macOS 版スクリプトを Windows に適応
- パスを Windows 形式に置換
- `kill -0 <PID>` の代替を検討
- 改行コード注意(LF で保存)

### 3. 段階テスト(重要)
いきなり全セッションには適用しないでください。
1 セッションだけ翻訳 → Desktop 完全終了 → 再起動 → UI 確認 の順で進めてください。

途中で詰まったり判断に迷ったら、必ず私に確認してください。

macOS との主な違い

観点 macOS Windows
セッション保存先 ~/Library/Application Support/Claude/... %APPDATA%\Claude\...
シェル bash(標準) Git Bash / WSL / PowerShell(要選択)
完全終了 Cmd+Q タスクトレイ右クリック→ Quit + Task Manager 確認

設定後、Cmd+Q で Claude Desktop を完全終了 → 再起動してください

再起動後に Recents の英語タイトルが順次日本語化されます。

トップに戻る