株式会社TOEでは、すべての案件フォルダに「成果物/」というフォルダを置き、そこに入れたファイルをGoogle Driveへ自動でミラー同期しています。目的は1つで、外出先のiPhoneから提案書や納品PDFをすぐ開けるようにすることです。仕組みの実体は73行のシェルスクリプトで、この54日間で448回動きました。この記事は、そのスクリプトと実行ログを実際に開いて確認できたことだけを書いています。運用ルールと実装がズレていた箇所も、そのまま書きます。
仕組みは73行のシェルスクリプト
やっていることは単純です。ローカルの案件フォルダ配下にある「成果物/」を、Google Driveのデスクトップアプリがマウントしているフォルダ(Macから普通のフォルダとして見えるDrive領域)へ、rsyncというファイル同期の標準コマンドでコピーします。
| 項目 | 内容 |
|---|---|
| ソース | 案件フォルダ配下の各「成果物/」 |
| 宛先 | Google Driveマイドライブ配下の専用フォルダ(案件名ごと) |
| 方向 | ローカル→Driveの片方向。削除は同期しない |
| 実行タイミング | Claude Codeのセッション終了時(SessionEnd hook) |
| 実装 | bashスクリプト73行+rsync |
案件フォルダは執筆時点で34個あり、そのうち「成果物/」を持つ31案件が同期対象です。直近の実行ログにも「clients: 31」と記録されています。スクリプトは案件を1つずつ回り、「成果物/」が無い案件は黙ってスキップします。
なお、DriveアプリがDriveをマウントできていない状態で走った場合はエラーを記録して即終了する安全弁が入っていますが、このエラーは54日間で0回でした。
何を入れて、何を入れないか
このフォルダに入れるもの・入れないものは、社内の共通ルールファイルに明文化してあります。
入れるものは、要するに「人に見せる完成品」です。
- PDF・pptx・docx・xlsx などの文書類
- ai・psd・indd・sketch・fig などのデザインデータ
- 画像(jpg/png/svg等)・動画・音声
入れないものは3種類です。
- ソースコード(gitで管理するため。Driveに二重で持たない)
- node_modules などのビルド成果物
- 契約書・見積原本などの社外秘
スクリプト側でも、rsyncの除外設定で .DS_Store などのシステムファイル、node_modules/・.git/・.next/・dist/・build/ といった開発系フォルダを弾いています。うっかり成果物フォルダにコードごと置いても、開発ゴミはDriveに流れない作りです。
なぜ「片方向・削除なし」なのか
rsyncには「ソースで消えたファイルを宛先でも消す」オプションがありますが、このスクリプトは意図的に使っていません。スクリプト内のコメントにも「片方向ミラー、ただし削除はしない(誤削除防止)」と書いてあります。
理屈はこうです。ローカルで誤ってファイルを消しても、削除まで同期してしまうとDrive側の控えも一緒に消えます。削除を同期しなければ、Drive側が実質的な「消し忘れ保険」になります。同期は追加と上書きだけ、消すときは人間が両方を意図的に消す。自動化の対象を「増える方向」に限定するわけです。
代償もあります。ローカルでファイル名を変えたり整理したりすると、Drive側には古い名前のファイルが残り続けます。実際、宛先フォルダは少しずつ「歴史地層」化します。私たちはこれを、閲覧用のミラーだから許容する、と割り切っています。マスターはあくまでローカル(とgit)で、Driveは読むための鏡です。
いつ動くか — cronでもlaunchdでもなくセッション終了時
実行タイミングは、Claude CodeのSessionEnd hookです。Claude Code(AIコーディング支援のCLIツール)には、セッションが終わった瞬間に任意のコマンドを実行させる仕組みがあり、そこにこのスクリプトを登録してあります。設定ファイルを実際に開いて、登録行を確認しました。
発想としては「成果物が変わるのは、作業したときだけ」です。毎時のポーリングではなく、作業の区切りに同期する。作業していない深夜や休日に空振りで回り続けることがありません。
当初はmacOS標準のスケジューラであるlaunchdで毎時実行する案でしたが、macOSのTCC(アプリごとのフォルダアクセス権限の仕組み)に阻まれて「Operation not permitted」になり、不採用になりました。この顛末は別の記事で詳しく書く予定なので、ここでは深入りしません。
もう1つ、実装で効いているのが多重起動防止です。Claude Codeのウィンドウを複数開いていると、セッション終了のたびにフックが発火し、同期が同時に走りかねません。スクリプトはロック(実行中の目印となるフォルダ)を先に作り、既にあれば即終了します。ログには「SKIP: already running」が1,658回記録されていました。完走448回に対してスキップ1,658回。つまり発火の大半は「もう走ってるからやめた」で終わっています。無駄に見えますが、これが正常です。同じ処理が重なって走るより、静かに譲る方が安全です。
ロックには「1時間以上残っていたら強制解放する」保険も付いていて、これは54日間で19回発動していました。何かの理由でロックが残骸として残っても、翌回には自力で復旧しています。
54日間のログを読む
実行ログは2026年5月28日から残っており、執筆時点で71,533行ありました。集計するとこうなります。
| 項目 | 値 |
|---|---|
| 期間 | 2026-05-28 〜 2026-07-20(54日間) |
| 同期完走 | 448回(1日平均8回強) |
| 多重起動スキップ | 1,658回 |
| Drive未マウントエラー | 0回 |
| 古いロックの強制解放 | 19回 |
| rsyncのエラー行 | 2,559行 |
最初の完走時は対象5案件、直近は31案件です。案件が6倍に増えても、仕組み側は1行も変えずに追従しています。フォルダ規約(案件フォルダに「成果物/」を置く)さえ守れば対象が自動で増える、という設計が効いています。
一方で、rsyncのエラー行が2,559行あります。転送が途中で切れた形跡がログに繰り返し残っていました。原因はログからは特定できていません。ただし、この仕組みは毎回全案件を舐め直すので、失敗した転送は次の実行で再送されます。ミラー同期は1回の成功に賭けるのではなく、「何度でも走って最終的に一致すればいい」処理として設計するのが正解だと考えられます。
運用ルールにしかない除外設定があった
ここからが正直に書くべき部分です。
社内ルールにはこう書いてあります。「社外秘ファイルは _社外秘/ フォルダに置けば同期対象外(rsyncで除外設定済み)」。
スクリプトを確認したところ、_社外秘 の除外設定は存在しませんでした。 除外リストにあるのはシステムファイルと開発系フォルダだけで、_社外秘/ はどこにもありません。つまり、ルールを信じて社外秘をそのフォルダに置いたら、そのままDriveへ同期されます。
実害が出ていないことも確認しました。案件フォルダを検索した結果、_社外秘/ フォルダを作っている案件は現時点で0件です。誰もまだこの逃し方を使っていなかったため、漏れたものはありません。ですが、これは運が良かっただけです。ドキュメントが実装より先に書かれ、実装が追いつかないまま「済み」と記されていた。この記事の執筆で見つかったので、スクリプトへの除外追加を直近の修正項目にしています。
似たズレはもう1つありました。スクリプト冒頭のコメントには「実行: 手動 or launchd(毎時)」と書いてあります。前述の通りlaunchdは不採用になり、実際はSessionEnd hookで動いています。コメントが方式変更前のまま残っているわけです。
前回の記事(AI秘書)でも「社内で言われている時刻と実際のcron設定が違う」ズレを見つけました。2記事続けて同じ種類の発見です。自動化のドキュメントは、書いた瞬間から実装とズレ始めます。「済み」と書く前に実物をgrepで確認する、記事や監査のタイミングで突き合わせる、という機会を意図的に作らないと、ズレは見つかりません。
毎回同じファイルを送り直している
もう1つ、効率の面で美しくない挙動を見つけました。
直近のログでは、ある案件の同じ7ファイル(合計約2MB)が、実行のたびに毎回転送されていました。rsyncは本来「変わったファイルだけ送る」のが売りですが、このスクリプトはファイルの更新日時を宛先に引き継がない設定(--no-times)で動かしています。Drive側の更新日時がローカルと一致しないため、rsyncが毎回「変わったかもしれない」と判断して送り直しているのだと考えられます。
1回あたり数MBなので実害はほぼありませんが、成果物が数GBに育ったら問題になります。動いているものにも、こういう「静かな無駄」は潜んでいます。ログを読まなければ気づきませんでした。
関連する記録
- なぜ会話履歴を同期しないのか — 複数のPCとiPhoneで「最後の作業」に戻るために自動生成している2つのファイル
- 自動化26本に「見張り役」の画面を付けたら、そもそも全部止まっていた — DB不要・追加コストゼロのダッシュボード
まとめ
- 案件ごとの「成果物/」フォルダをGoogle Driveへ片方向ミラーし、iPhoneから閲覧できるようにしている。実体は73行のシェルスクリプト+rsync
- 削除は同期しない。Drive側を誤削除の保険にするための意図的な設計
- 実行はcronではなくClaude CodeのSessionEnd hook。「作業した区切りにだけ同期する」方式で、54日間で448回完走・多重起動は1,658回を自動スキップ
- 運用ルールに「除外設定済み」とあった
_社外秘/の除外は、スクリプトに実在しなかった。実害0件で発見できたが、ドキュメントと実装のズレは監査の機会を作らないと見つからない - ログには2,559行のrsyncエラーと「毎回同じ7ファイルを再送する」無駄も残っていた。何度でも走る前提の設計だから破綻していないだけで、動いている仕組みにも読みに行くべきログはある
派手なAIは1行も出てこない記事でしたが、AI活用の土台はこういう「ファイルがあるべき場所に自動で届く」配管です。株式会社TOEでは、こうした社内実践を土台に、中小企業向けのAI導入コンサルティングとAI開発を提供しています。自社の業務でどこから自動化すべきか迷っている方は、AIの鬼のお問い合わせフォームからご相談ください。