ファイル同期とコミット連携の設定

アフィリエイト広告を利用しています

このページの内容が役に立ったら X (旧twitter) でフォローして頂けると励みになります
挨拶や報告は無しで大丈夫です

前回の記事で settings.json・CLAUDE.md の配置と Git リポジトリの初期化が完了しました。この記事では、rsync によるファイル同期の仕組みを構築し、コミットメッセージの連携まで設定します。

作業が終わると、Claude Code で作業 → メインPCに自動同期 → VS Code で差分確認 → コミット、という日々の開発サイクルが回せる状態になります。

この記事で行った設定が正しく反映されているか確認するコマンドをまとめておきます。詳細については本文をご覧ください。

# sudoers の確認(管理ユーザーで実行)
sudo cat /etc/sudoers.d/rsync-sync

rsync の Ubuntu 側の設定

rsync でファイルを同期するには、Ubuntu 側の準備が先に必要です。管理ユーザーで rsync を実行する際、専用ユーザーのホームディレクトリ(パーミッション 700)にアクセスするため sudo が必要です。sync-ready の存在確認(test)と削除(rm)にも sudo が必要です。パスワード入力なしで実行できるよう、対象コマンドを NOPASSWD に設定します。

sudo visudo -f /etc/sudoers.d/rsync-sync

エディタは nano が開きます。以下の内容を入力してください。

<管理ユーザー名> ALL=(ALL) NOPASSWD: /usr/bin/rsync, /usr/bin/rm, /usr/bin/test

# 例:
# shinohara ALL=(ALL) NOPASSWD: /usr/bin/rsync, /usr/bin/rm, /usr/bin/test

nano の操作は Ctrl + O → Enter で保存、Ctrl + X で終了です。保存後、確認しておきます。

sudo cat /etc/sudoers.d/rsync-sync

パスワードなしで sudo rsync が実行できることを確認します。

sudo rsync --version | head -1

接続設定ファイル

SSH の接続情報や rsync のパスは、プロジェクトごとに異なります。これらをスクリプトにハードコードすると Git に含められなくなるため、設定ファイルとして分離します。この設定ファイルは、Ubuntu→メインPC の自動同期とメインPC→Ubuntu のファイル送信の両方で共用します。

設定ファイルは .local\ ディレクトリに配置し、.gitignore で Git 管理から除外します。Git には .sample ファイルを含めておき、新しい環境ではそれをコピーして値を書き換える運用です。

.local\
├── _sync_claude_code_config.env          ← 実際の設定(Git 管理外)
└── _sync_claude_code_config.env.sample   ← サンプル(Git に含める)

設定ファイルの形式は KEY=VALUE(env 形式)です。PowerShell と cmd の両方から読み込めます。

SSH_USER=shinohara
SSH_HOST=192.168.xxx.xxx
SSH_KEY=C:\users\sample\ssh\id_ed25519
SSH_REMOTE_SYNC_READY=/home/cc-sample-wp/project/.claude/sync-ready
RSYNC_USER=shinohara
RSYNC_HOST=192.168.xxx.xxx
RSYNC_KEY=C:\users\sample\ssh\id_ed25519
RSYNC_REMOTE_DIR=/home/cc-sample-wp/project
RSYNC_LOCAL_DIR=/cygdrive/c/projects/sample/cc-sample-wp/cc-sample-wp
RSYNC_DRY_RUN=1
RSYNC_VERBOSE=1
CHECK_INTERVAL=5
設定項目説明
SSH_USER / SSH_HOST / SSH_KEYSSH 接続情報。sync-ready の存在確認と削除に使用
SSH_REMOTE_SYNC_READYsync-ready ファイルのフルパス
RSYNC_USER / RSYNC_HOST / RSYNC_KEYrsync の接続情報。SSH と同じ値になることが多い
RSYNC_REMOTE_DIRUbuntu 側の同期元ディレクトリ
RSYNC_LOCAL_DIRメインPC側の同期先ディレクトリ(Cygwin パス)
RSYNC_DRY_RUN1 でドライラン(実際のコピーなし)、0 で本番
RSYNC_VERBOSE1 で rsync のファイル一覧を表示、0 で非表示
CHECK_INTERVALsync-ready のチェック間隔(秒)

rsync で Ubuntu からメインPCへ

Claude Code が作業を完了すると、.claude/sync-ready に現在日時を書き出します。メインPC(Windows)側の監視スクリプトがこのファイルを検知し、rsync で自動的にファイルを取得します。同期が完了すると sync-ready は削除され、Beep 音で通知されます。

Claude Code が作業完了
    │
    ▼
.claude/sync-ready に日時を書き出す
    │
    ▼
メインPC の監視スクリプトが検知(5秒間隔)
    │
    ▼
rsync で Ubuntu → メインPC にファイルを同期
    │
    ▼
sync-ready を削除
    │
    ▼
Beep 音で通知
    │
    ▼
VS Code / Eclipse で差分を確認

rsync の接続は管理ユーザー経由で行います。プロジェクトごとに専用ユーザーが分かれていても、接続先は管理ユーザーに統一できるため、SSH の鍵管理がシンプルになります。

同期対象のルール

rsync は include 方式で必要なファイルだけを同期対象にしています。メインPC側にある Ubuntu に関係のないファイル(Eclipse の設定ファイルなど)は影響を受けません。

対象ルール説明
/CLAUDE.md同期するプロジェクト固有ルール
/.claude/**settings.json 以外を同期するCLAUDE-global.md、commit-msg.txt、sync-ready 等
/.claude/settings.json同期しないメインPC側で管理し push-to-ubuntu で送る
/.local/*.sample.sample のみ同期する設定サンプルだけ Git に含め、実際の設定は各環境で作成
/_scripts/**すべて同期する同期スクリプト等の運用ツール
.gitignore同期しない承認者がメインPC側で管理する
上記以外同期しない今後ソースコードのディレクトリを追加していく

同期スクリプトの構成

メインPC(Windows)側に3つのスクリプトを配置します。プロジェクトのリポジトリ内に _scripts\_sync_claude_code\ ディレクトリを作成し、その中に置きます。

_scripts\_sync_claude_code\
├── .gitignore                   ← running ファイルを Git 管理外にする
├── sync_claude_code_running     ← 監視中に自動作成される(削除で停止)
├── sync-watch.cmd               ← ダブルクリックで起動するエントリーポイント
├── sync-watch.ps1               ← 監視ループ本体(PowerShell)
└── sync-pull.cmd                ← rsync 実行

sync-watch.cmd

ダブルクリックで起動するエントリーポイントです。PowerShell のスクリプト実行ポリシーを回避するため、-ExecutionPolicy Unrestricted を付けて ps1 を起動します。

@ECHO OFF

echo "sync-watch を実行しています・・・"

powershell -NoProfile -ExecutionPolicy Unrestricted .\sync-watch.ps1

echo "終了しました"

pause > nul

exit

sync-watch.ps1

監視ループの本体です。SSH 経由で sync-ready の存在を確認し、検知したら sync-pull.cmd を呼び出して rsync を実行します。起動時に sync_claude_code_running ファイルが自動作成され、このファイルを削除するとループが停止します。別のプロセスが既に動いている場合は、起動時にエラーを表示して中断します。

# sync-ready を監視し、変更があれば rsync を発動する

# パスの設定
$LOCAL_DIR = Join-Path $PSScriptRoot "..\..\.local"
$CONFIG_PATH = Join-Path $LOCAL_DIR "_sync_claude_code_config.env"
$RUNNING_PATH = Join-Path $PSScriptRoot "sync_claude_code_running"

# 設定ファイルの読み込み
if (-not (Test-Path $CONFIG_PATH)) {
    Write-Host "ERROR: 設定ファイルが見つかりません: $CONFIG_PATH"
    exit 1
}

$config = @{}
Get-Content $CONFIG_PATH | ForEach-Object {
    if ($_ -match '^\s*([^#][^=]+)=(.*)$') {
        $config[$matches[1].Trim()] = $matches[2].Trim()
    }
}

$SSH_USER = $config["SSH_USER"]
$SSH_HOST = $config["SSH_HOST"]
$SSH_KEY = $config["SSH_KEY"]
$SSH_REMOTE_SYNC_READY = $config["SSH_REMOTE_SYNC_READY"]
$CHECK_INTERVAL = [int]$config["CHECK_INTERVAL"]
$RSYNC_DRY_RUN = $config["RSYNC_DRY_RUN"]

# running ファイルが既に存在する場合は中断
if (Test-Path $RUNNING_PATH) {
    Write-Host "ERROR: sync_claude_code_running が既に存在します。"
    Write-Host "別のプロセスが動いている可能性があります。"
    Write-Host "確認の上、手動で削除してから再実行してください。"
    Write-Host "場所: $RUNNING_PATH"
    exit 1
}

# running ファイルを作成
Set-Content -Path $RUNNING_PATH -Value "このファイルを削除すると sync-watch の監視が停止します。`nDelete this file to stop sync-watch."

# 監視開始ミュージック
[Console]::Beep(1479, 200) # F#5
[Console]::Beep(1174, 200) # D5
[Console]::Beep(880,  200) # A4
[Console]::Beep(1174, 200) # D5
[Console]::Beep(1318, 200) # E5
[Console]::Beep(1760, 500) # A5

[Console]::Beep(1318, 200) # E5
[Console]::Beep(1479, 200) # F#5
[Console]::Beep(1318, 200) # E5
[Console]::Beep(880,  200) # A4
[Console]::Beep(1174, 400) # D5

Write-Host ""
Write-Host "sync-ready の監視を開始しました(${CHECK_INTERVAL}秒間隔)"
Write-Host "対象: ${SSH_USER}@${SSH_HOST}:${SSH_REMOTE_SYNC_READY}"
if ($RSYNC_DRY_RUN -eq "1") {
    Write-Host "モード: ドライラン(実際のファイルコピーは行いません)"
}
Write-Host "停止するには sync_claude_code_running を削除してください"
Write-Host ""

while(1){

    # running ファイルのチェック
    if (-not (Test-Path $RUNNING_PATH)) {
        Write-Host "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] running ファイルが削除されました。監視を終了します。"
        break
    }

    # SSH経由でsync-readyの存在を確認
    $exists = ssh -i $SSH_KEY "${SSH_USER}@${SSH_HOST}" "sudo test -f $SSH_REMOTE_SYNC_READY && echo EXISTS"

    if($exists -eq "EXISTS"){

        Write-Host "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] sync-ready 検知"

        # rsync を実行
        $syncPullPath = Join-Path $PSScriptRoot "sync-pull.cmd"
        & cmd /c $syncPullPath

        # sync-ready を削除
        ssh -i $SSH_KEY "${SSH_USER}@${SSH_HOST}" "sudo rm $SSH_REMOTE_SYNC_READY"
        if ($LASTEXITCODE -ne 0) {
            Write-Host "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] sync-ready 削除エラー"
        } else {
            Write-Host "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] sync-ready 削除完了"
        }

        Write-Host "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] 同期完了"

        # 完了 Beep
        [Console]::Beep(523, 100) # ド
        [Console]::Beep(523, 100) # ド
    }

    Start-Sleep -Seconds $CHECK_INTERVAL
}

sync-pull.cmd

Cygwin の rsync を使ってファイルを同期します。include 方式で必要なファイルだけを同期対象にしているため、メインPC側にある Ubuntu に関係のないファイルは影響を受けません。

@ECHO OFF
SETLOCAL
SET PATH=C:\cygwin64\bin;%PATH%

REM 設定ファイルの読み込み
SET CONFIG_PATH=%~dp0..\..\.local\_sync_claude_code_config.env
IF NOT EXIST "%CONFIG_PATH%" (
    echo ERROR: 設定ファイルが見つかりません: %CONFIG_PATH%
    exit /b 1
)
FOR /F "usebackq tokens=1,* delims==" %%A IN ("%CONFIG_PATH%") DO (
    SET "%%A=%%B"
)

REM オプションの組み立て
SET RSYNC_OPTS=-rtD

IF "%RSYNC_VERBOSE%"=="1" (
    SET RSYNC_OPTS=%RSYNC_OPTS% -v
)

IF "%RSYNC_DRY_RUN%"=="1" (
    SET RSYNC_OPTS=%RSYNC_OPTS% --dry-run
    echo "-------- rsync start (DRY RUN) --------"
) ELSE (
    echo "-------- rsync start --------"
)

rsync %RSYNC_OPTS% ^
  -e "ssh -i %RSYNC_KEY%" ^
  --rsync-path="sudo rsync" ^
  --exclude=.gitignore ^
  --exclude=/.claude/settings.json ^
  --include=/CLAUDE.md ^
  --include=/.claude/ ^
  --include=/.claude/** ^
  --include=/.local/ ^
  --include=/.local/*.sample ^
  --include=/_scripts/ ^
  --include=/_scripts/** ^
  --exclude=* ^
  %RSYNC_USER%@%RSYNC_HOST%:%RSYNC_REMOTE_DIR%/ %RSYNC_LOCAL_DIR%/
echo "-------- rsync end --------"

.gitignore と sync_claude_code_running

sync_claude_code_running は監視スクリプトの起動時に自動作成されるファイルです。このファイルを削除すると監視ループが停止します。Git で管理する必要はないので、_scripts\_sync_claude_code\ ディレクトリ内に .gitignore を置いて除外しています。

# _scripts\_sync_claude_code\.gitignore
/sync_claude_code_running

動作確認

まず RSYNC_DRY_RUN=1 の状態で動作確認を行います。Ubuntu 側で手動で sync-ready を作成して、メインPC側の監視スクリプトが検知・同期・削除まで正しく動くことを確認します。

Ubuntu 側(専用ユーザーで実行):

date '+%Y-%m-%d %H:%M:%S' > ~/project/.claude/sync-ready

メインPC側で sync-watch.cmd をダブルクリックして監視を開始します。以下のような出力が表示されれば成功です。

sync-ready の監視を開始しました(5秒間隔)
対象: shinohara@192.168.1.3:/home/cc-sample-wp/project/.claude/sync-ready
モード: ドライラン(実際のファイルコピーは行いません)
停止するには sync_claude_code_running を削除してください

[2026-03-16 12:02:07] sync-ready 検知
"-------- rsync start (DRY RUN) --------"
receiving incremental file list
./
CLAUDE.md
.claude/
.claude/CLAUDE-global.md
.claude/settings.json
.claude/sync-ready

sent 180 bytes  received 206 bytes  772.00 bytes/sec
total size is 836  speedup is 2.17 (DRY RUN)
"-------- rsync end --------"
[2026-03-16 12:02:08] sync-ready 削除完了
[2026-03-16 12:02:08] 同期完了

確認ができたら、設定ファイルの RSYNC_DRY_RUN0 に変更して本番モードに切り替えます。

rsync でメインPCから Ubuntu へ

ここまでの rsync は「Ubuntu → メインPC」方向の自動同期でした。逆方向、つまりメインPCから Ubuntu にファイルを送る仕組みも用意しておきます。

用途は限定的です。最初のセットアップ時や、WordPress の wp-admin・プラグイン・vendor など、Claude Code の編集対象ではないファイルを Ubuntu 側に配置するときに使います。日常的に使うものではないため、誤って実行しないよう安全装置を入れた手動実行スクリプトにしています。

スクリプトの配置

_scripts\ ディレクトリに新しいフォルダを追加します。

_scripts\
├── _push_to_ubuntu\
│   └── push-to-ubuntu.cmd   ← 手動実行(ダブルクリック)
└── _sync_claude_code\
    ├── sync-watch.cmd
    ├── sync-watch.ps1
    └── sync-pull.cmd

フォルダ名を _ 始まりにしているのは、_sync_claude_code と同じ命名規則です。設定ファイルは .local\_sync_claude_code_config.env を共用します。接続先やパスの情報は同じなので、別ファイルを作る必要はありません。

push-to-ubuntu.cmd の全文

スクリプトの全文です。SHIFT_JIS + CRLF で保存してください。

@ECHO OFF
REM ============================================================
REM  push-to-ubuntu.cmd
REM  メインPC → Ubuntu へファイルを送る(手動実行)
REM
REM  ■ 安全装置
REM  下の exit /b を REM にしてから実行してください。
REM  実行後は元に戻すのを忘れずに。
REM ============================================================

exit /b

cd /d %~dp0

REM --- 設定ファイルの読み込み ---
set CONFIG_FILE=..\..\.local\_sync_claude_code_config.env
if not exist "%CONFIG_FILE%" (
    echo [エラー] 設定ファイルが見つかりません: %CONFIG_FILE%
    pause
    exit /b 1
)
for /f "usebackq tokens=1,* delims==" %%A in ("%CONFIG_FILE%") do (
    set "%%A=%%B"
)

REM --- Cygwin rsync のパス ---
set RSYNC_CMD=C:\cygwin64\bin\rsync.exe
if not exist "%RSYNC_CMD%" (
    echo [エラー] rsync が見つかりません: %RSYNC_CMD%
    pause
    exit /b 1
)

REM ============================================================
REM  送りたいディレクトリだけ REM を外してください。
REM  実行後は REM に戻すのを忘れずに。
REM ============================================================
set INCLUDE_RULES=
REM set INCLUDE_RULES=%INCLUDE_RULES% --include="/wp-admin/***"
REM set INCLUDE_RULES=%INCLUDE_RULES% --include="/wp-content/***"
REM set INCLUDE_RULES=%INCLUDE_RULES% --include="/wp-content/plugins/***"
REM set INCLUDE_RULES=%INCLUDE_RULES% --include="/wp-content/themes/***"
REM set INCLUDE_RULES=%INCLUDE_RULES% --include="/vendor/***"
REM set INCLUDE_RULES=%INCLUDE_RULES% --include="/wp-includes/***"
REM set INCLUDE_RULES=%INCLUDE_RULES% --include="/wp-config.php"
REM set INCLUDE_RULES=%INCLUDE_RULES% --include="/composer.json"
REM set INCLUDE_RULES=%INCLUDE_RULES% --include="/composer.lock"

REM --- include が空なら中断 ---
if "%INCLUDE_RULES%"=="" (
    echo [エラー] 送信対象が指定されていません。
    echo          INCLUDE_RULES の REM を外してから実行してください。
    pause
    exit /b 1
)

echo ============================================================
echo  push-to-ubuntu: メインPC → Ubuntu
echo  接続先: %RSYNC_USER%@%RSYNC_HOST%:%RSYNC_REMOTE_DIR%
echo ============================================================
echo.
echo --- 送信対象 ---
echo %INCLUDE_RULES%
echo.

REM --- ドライラン ---
echo ■ ドライランを実行します(実際のコピーは行いません)
echo.

"%RSYNC_CMD%" -rlptv --dry-run ^
    -e "ssh -i '%RSYNC_KEY%' -o StrictHostKeyChecking=no" ^
    --rsync-path="sudo rsync" ^
    %INCLUDE_RULES% ^
    --exclude="*" ^
    "%RSYNC_LOCAL_DIR%/" ^
    "%RSYNC_USER%@%RSYNC_HOST%:%RSYNC_REMOTE_DIR%/"

echo.
echo ■ ドライラン完了。上記の内容でよければ Enter を押してください。
echo    中断する場合はウィンドウを閉じてください。
pause > nul

REM --- 本番実行 ---
echo.
echo ■ 本番実行中...
echo.

"%RSYNC_CMD%" -rlptv ^
    -e "ssh -i '%RSYNC_KEY%' -o StrictHostKeyChecking=no" ^
    --rsync-path="sudo rsync" ^
    %INCLUDE_RULES% ^
    --exclude="*" ^
    "%RSYNC_LOCAL_DIR%/" ^
    "%RSYNC_USER%@%RSYNC_HOST%:%RSYNC_REMOTE_DIR%/"

echo.
echo ■ 送信完了
echo.
echo ============================================================
echo  ★ exit /b と INCLUDE_RULES を元に戻してください ★
echo ============================================================
pause

使い方の流れ

毎回の手順は以下のとおりです。

1. push-to-ubuntu.cmd をエディタで開く

2. 先頭の exit /b を REM にする
   REM exit /b

3. 送りたいディレクトリの REM を外す
   set INCLUDE_RULES=%INCLUDE_RULES% --include="/vendor/***"

4. ダブルクリックで実行
   → ドライランの結果が表示される
   → 問題なければ Enter で本番実行

5. 完了後、exit /b と INCLUDE_RULES を元に戻す

安全装置の仕組み

このスクリプトには3段階の安全装置があります。

exit /b による即時終了
デフォルトではスクリプト先頭で処理が終了します。ダブルクリックしても何も起きません
INCLUDE_RULES の空チェック
送信対象が1つも指定されていない場合はエラーで中断します。exit /b を外しただけでは実行されません
ドライラン → 確認 → 本番実行
まずドライラン(実際のコピーなし)で対象ファイルを表示し、確認してから本番実行に進みます

commit.template の設定

Claude Code にコミットメッセージの作成を依頼すると、.claude/commit-msg.txt にメッセージが書き出されます。rsync で同期された後、このファイルを Git の commit.template に設定しておくと、VS Code や Eclipse のコミット画面にメッセージが自動的にプリフィルされます。

メインPC側の Git リポジトリで以下を実行します。

# commit-msg.txt の空ファイルを作成(テンプレート参照エラーの防止)
type nul > .claude\commit-msg.txt

# commit.template の設定
git config --local commit.template .claude/commit-msg.txt

確認します。

git config --local commit.template
.claude/commit-msg.txt

これで、Claude Code が作成したコミットメッセージがコミット画面に自動表示されるようになります。内容を確認し、必要に応じて修正してからコミットします。

スナップショットの取得

ここまでの設定が完了したら、VMware でスナップショットを取得しておきます。

スナップショット名: 2026-03-16_workflow-setup

この時点の状態は以下のとおりです。

  • settings.json(権限設定)配置済み
  • CLAUDE.md(グローバル + プロジェクト)配置済み
  • CLAUDE-global.md を Git 管理化(シンボリックリンクで ~/.claude/CLAUDE.md に連携)
  • Git リポジトリ初期化・初期コミット済み
  • rsync 同期スクリプト動作確認済み
  • メインPC → Ubuntu のファイル送信スクリプト作成済み
  • commit.template 設定済み
  • 雛形ディレクトリ(~/cc-template/)作成済み

次の記事では、この環境に WordPress 案件のための LAMP 環境を追加構築していきます。