エージェントに npm install を任せる前に、プロジェクトのパスを見直すことにしました。私の作業フォルダは ~/Library/CloudStorage/Dropbox の下にあります。この場所で、以前の記事に書いた除外の印をそのまま信じてよいのかを、一度確かめておきたかったのです。
最初にお伝えしたいのは、Mac 上でどちらの印が効くかは、私の手元ではまだ確かめきれていないということです。ここには、確かめられたことと、確かめ方だけを書き残します。
ヘルプの記載が、方式ごとに分かれています
Dropbox の「無視されるファイル」のヘルプ(2026-10 に確認)では、macOS が二通りに分かれています。
| 方式 | パスの例 | 印のコマンド |
|---|---|---|
| File Provider 版 | ~/Library/CloudStorage/Dropbox | xattr -w 'com.apple.fileprovider.ignore#P' 1 パス |
| File Provider を使わない版 | ~/Dropbox | xattr -w com.dropbox.ignored 1 パス |
私が以前の記事で書いたのは、下の行だけでした。作業フォルダが CloudStorage の下に移っているなら、同じ手順を繰り返す前に、まず上の行が自分の環境の正解なのかを疑う価値があります。ヘルプには、Dropbox のフォルダを既定の場所から移している場合はコマンドが使えない、という注意もあります。
あわせて、ヘルプには次の記載がありました。
- オンライン専用のファイル、およびそれを含むフォルダは、無視できません。
- 無視したフォルダの中へ移したものは、同じように無視されます。
- 無視したものはサーバー側から消え、手元のディスクにだけ残ります。
最後の点は、node_modules のように再生成できるものには好都合です。一方で、「あとから同期へ戻す」ことは想定しないほうが安全です。
まず一覧だけ出して、印はあとから付けます
エージェントに任せる前の確認で、いきなり印を書き込む必要はありません。私は次のスクリプトを、一覧表示だけが既定になるように組みました。--apply を付けない限り、何も書き換えません。
#!/usr/bin/env bash
# 使い方: mark-volatile.sh [--apply] <プロジェクトのパス>
set -euo pipefail
APPLY=0
if [ "${1:-}" = "--apply" ]; then APPLY=1; shift; fi
ROOT="${1:?プロジェクトのパスを指定してください}"
ROOT="$(cd "$ROOT" && pwd -P)" # シンボリックリンクを解決した実パスで判定する
# CloudStorage 配下なら File Provider 版とみなす
case "$ROOT" in
*/Library/CloudStorage/*) MODE="fileprovider" ;;
*) if [ "$(uname)" = "Darwin" ]; then MODE="legacy"; else MODE="linux"; fi ;;
esac
mark() {
case "$MODE" in
fileprovider) xattr -w 'com.apple.fileprovider.ignore#P' 1 "$1" ;;
legacy) xattr -w com.dropbox.ignored 1 "$1" ;;
linux) attr -s com.dropbox.ignored -V 1 "$1" >/dev/null ;;
esac
}
# 見つけたディレクトリの中は掘り下げない(-prune)
find "$ROOT" -maxdepth 4 -type d \( -name node_modules -o -name .next -o -name Pods \
-o -name DerivedData -o -name .gradle -o -name .swiftpm \) -prune -print |
while IFS= read -r d; do
if [ "$APPLY" = 1 ]; then mark "$d" && echo "marked [$MODE]: $d"
else echo "would mark [$MODE]: $d"; fi
done動作は、次の範囲で確かめました。
- 一覧表示だけの実行で、
node_modules・.next・Podsの三つが拾われ、srcは拾われないこと。 - パスに
/Library/CloudStorage/を含むとき、xattrがcom.apple.fileprovider.ignore#Pで呼ばれること(xattrを記録用の代役に差し替えた状態での確認です)。 - 引数を省いたときに、エラーで止まること。
確かめていないのは、実際の Mac の Dropbox が、この印を見て同期を止めるかどうかです。ここは Dropbox のアイコンの変化を見ながら、使い捨てのフォルダで一度試してから、本命のプロジェクトに進んでいただければと思います。私もそこから始めます。
印が付いたかは、読み出して確かめます
mark が成功を返しても、付いたことの証明にはなりません。付けた直後に、同じ名前の属性を読み出します。
# 付けたい属性を読み出す。値が 1 なら付いている
xattr -p 'com.apple.fileprovider.ignore#P' node_modules
# どの属性が付いているかを全部見る
xattr -l node_modules読み出しの書式は xattr の通常の使い方に沿ったもので、File Provider 版の属性名に対する結果は、私の手元ではまだ見ていません。値が返らなければ、方式の取り違えを疑って、もう一方の属性名でも試します。
直感に反した点: npm ci では印が消えませんでした
以前、クリーンビルドでディレクトリごと作り直されると印が消える、と書きました(Xcode のビルドが壊れる理由を書いた記事)。そのため npm ci でも同じだろうと思い込んでいました。
確かめるために、ローカルの小さな依存(file: 指定)だけを持つプロジェクトで、node_modules に拡張属性を付け、npm ci を実行しました。結果は次のとおりです。
- ディレクトリの inode は、実行の前後で同じでした。
- 付けた属性も、そのまま残っていました。
条件は、npm 10.9.4・Node 22・Linux 上のユーザー拡張属性です。Dropbox の印そのものではなく、拡張属性が npm ci で消えるかを見た結果ですので、Mac の xattr や別バージョンの npm、pnpm や yarn に当てはまるとは限りません。それでも、「npm ci のたびに印を付け直す」という手間は、少なくとも私の手元では要りませんでした。一方で、rm -rf node_modules で自分から消した場合は、ディレクトリが新しくなるので、印は付け直しになります。
印は、ディレクトリを残す操作には耐え、作り直す操作には耐えません。 エージェントが何で消しているかを、一度ログで見ておくと安心です。
次の一歩
次にエージェントへ依存関係の導入を任せる前に、mark-volatile.sh を --apply なしで一度走らせ、一覧に node_modules が入っているかをご覧ください。そのあとで、使い捨てのフォルダに印を付け、Dropbox 側の表示が変わることを確かめてから、本命に進みます。