自宅のWindowsを開発機にする その3: Claude Codeの設定とメモリを引っ越す

この記事でわかること
- 移すべきものと移してはいけないものの整理
- プロジェクトのメモリはパスをエンコードしたフォルダ名なので付け替えが要る
- settings.json は jq でマージし、Mac専用のhookは捨てる
- direnvでディレクトリごとにClaudeのアカウントを切り替える
その2の状態(コードは ~/dev に移植済み、desktop の Claude Code はログイン済み)
この記事は「自宅のWindowsを開発機にする」連載のその3です。その2でコードとツールを移したので、今回は Claude Code 側を引っ越します。
なぜ設定まで移すのか
Claude Code 自体はデスクトップにも入っていてログインも済んでいたんですが、それだけだと「まっさらな Claude」なんですよね。Mac で育ててきたグローバルの CLAUDE.md、自作の skill、プラグイン、それと何よりプロジェクトごとのメモリがないと、同じ説明をまた一からすることになります。
あと自分の場合、個人用と仕事用で Claude のアカウントを分けていて、Mac では業務委託先Aのフォルダに入ったときだけ CLAUDE_CONFIG_DIR を切り替えています。これも移さないといけません。
移すもの・移さないもの
~/.claude を丸ごとコピーしたくなるんですが、これはやめたほうがいいです。
移すもの
CLAUDE.md(グローバルの指示)、statusline.sh、scripts/skills/の自作 skill(claude.aiから同期されるsyncedは除く)settings.jsonの中身(マージする。後述)projects/*/memory(プロジェクトごとのメモリ)
移さないもの
- 認証情報や端末の識別子(
.credentials.json、~/.claude.jsonのアカウント情報など)。丸ごと持っていくと端末の区別がおかしくなります - 会話ログや履歴、キャッシュ類。
/resumeも元のディレクトリに紐づくので効きません(ただし Orca から過去の会話を見たい場合は別で、結局あとから移しました。その5で書いています) - プラグインのキャッシュ。プラグインは
claude plugin installで入れ直す - Mac 専用のもの(Chrome 拡張のネイティブホストなど)
メモリはフォルダ名の付け替えが要る
今回いちばん気を使ったのがここです。プロジェクトのメモリは ~/.claude/projects/<エンコードしたパス>/memory/ に入っていて、フォルダ名は作業ディレクトリの絶対パスの / や .、_ を - にしたものなんですよね。
Mac: -Users-<ユーザー>-Desktop-private-my-project
desktop: -home-koki-dev-private-my-projectなので、コピーするときに -Users-<ユーザー>-Desktop- を -home-koki-dev- に置き換えておかないと、移したのに読まれないという状態になります。
で、ここで地味にハマったのが、フォルダ名が - で始まることです。ループの中で ls "$d/memory" と書いたら、ls がオプションと勘違いして全部エラーになり、件数が空になって「1件もコピーされていない」という結果に。ls -- "./$d/memory" のように ./ を付けるか -- を挟めば大丈夫です。
for d in ./-Users-<ユーザー>-Desktop-*; do
d=${d#./}
[ -d "./$d/memory" ] || continue
new="-home-koki-dev-${d#-Users-<ユーザー>-Desktop-}"
rsync -a --mkpath "./$d/memory/" "desktop:.claude/projects/$new/memory/"
done移したあとは、メモリの本文に書かれた Mac のパスも sed で ~/dev/... に置き換えました。ただし「Mac での運用そのもの」を書いたメモリ(osascript の使い方など)は置き換えると嘘になるので、そこは除外しています。
ついでに、アカウントを分ける前に個人アカウント側に溜まっていた仕事のメモリ(90件くらい)も、仕事用アカウント側にまとめました。索引の MEMORY.md だけは両方にあるので、重複しない行だけ追記する形でマージしています。
settings.json は jq でマージする
デスクトップ側の settings.json には、herdr が入れた SessionStart の hook がもう入っていました。Mac のもので上書きするとこれが消えるので、Mac 側から hooks を抜いて深いマージしました。
# Mac 側: hooks を捨てて、autoMode の説明に書いたパスだけ置き換える
jq 'del(.hooks) | .autoMode.environment |= map(gsub("~/Desktop/";"~/dev/"))' ~/.claude/settings.json > p.json
# desktop 側: 既存 * Mac側 でマージ
jq -s '.[0] * .[1]' ~/.claude/settings.json /tmp/p.json > /tmp/m.json && mv /tmp/m.json ~/.claude/settings.jsonMac の hook には afplay で音を鳴らすものがあったんですが、Linux にはないので捨てています。他にも Mac 前提のところがちょこちょこあって、
- tmux 操作用のヘルパーが
md5を使っていた → Linux ではmd5sum - skill の中に
/Users/...の絶対パスが直書きされていた - グローバルの
CLAUDE.mdに「このマシン(macOS)」と書いてあった
といった感じです。CLAUDE.md は冒頭に「これは Mac から移植したもので、Mac の ~/Desktop/X はここでは ~/dev/X」と一文足しておきました。これがあるだけで Claude が読み替えてくれるので。
プラグインは enabledPlugins に入っているものを順に claude plugin install して終わりでした。MCP は ~/.claude.json をコピーせず、claude mcp add で作り直しています。
アカウントの切替は direnv で
Mac では zsh の chpwd フックで切り替えていましたが、WSL 側は bash なので direnv にしました。仕事用フォルダの直下に1枚置くだけで、配下の全リポジトリで効きます。
# ~/dev/Job/<業務委託先A>/.envrc
export CLAUDE_CONFIG_DIR="$HOME/.claude-<仕事用>"注意が必要なのが、スマホ連携用に常駐させている Remote Control のラッパーです。これは「~/dev の直下のフォルダ名」でアカウントを決める作りだったので、フォルダ構成を Mac と同じ ~/dev/Job/<会社> に変えたとたん、Job という存在しないアカウントを探しに行く状態になっていました。systemd から動くので direnv は効かないんですよね。なので判定を case "$rel" in Job/<業務委託先A>|Job/<業務委託先A>/*) に書き換えて、systemd のユニットの PATH には mise の shims も足しました(Node を使う MCP が動かないので)。
まとめ
~/.claudeは丸ごとコピーしない。設定・skill・メモリだけ選んで移す- メモリの置き場はパス依存なので、フォルダ名を付け替える(先頭の
-に注意) settings.jsonは jq でマージして、移植先の hook を残す- アカウント切替はシェルと systemd の両方で効くようにしておく
次回(その4)は、Windows に Orca を入れて WSL のリポジトリを扱ってみた話です。


