Before letting an agent run npm install, I decided to look at the project path again. My working folder sits under ~/Library/CloudStorage/Dropbox, and I wanted to know whether the exclusion mark I wrote about earlier could still be trusted in that location.
The honest first point: I have not been able to confirm on a Mac which mark actually takes effect on my setup. What follows is what I could verify, and how to check the rest yourself.
The help page splits macOS into two cases
Dropbox's "ignored files" help page (read in October 2026) lists two macOS variants.
| Setup | Example path | Command |
|---|---|---|
| File Provider | ~/Library/CloudStorage/Dropbox | xattr -w 'com.apple.fileprovider.ignore#P' 1 PATH |
| Not on File Provider | ~/Dropbox | xattr -w com.dropbox.ignored 1 PATH |
My earlier article only used the second row. If your folder lives under CloudStorage, it is worth asking whether the first row is the right one before repeating the old steps. The page also warns that the commands do not work if you moved the Dropbox folder away from its default location.
A few other points from the same page:
- Online-only files, and folders containing them, cannot be ignored.
- Anything moved into an ignored folder becomes ignored too.
- Ignored items are removed from the server and stay only on your disk.
The last one suits regenerable things like node_modules, but I would not plan on syncing them back later.
List first, mark later
You do not need to write anything just to check. I made the script below print a list by default; nothing changes unless you pass --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
doneWhat I verified:
- A listing-only run picks up
node_modules,.nextandPods, and skipssrc. - For a path containing
/Library/CloudStorage/,xattris called withcom.apple.fileprovider.ignore#P(checked with a stand-inxattrthat only records its arguments). - Running with no argument stops with an error.
What I have not verified is whether a real Dropbox on a real Mac stops syncing because of that mark. Try it on a throwaway folder first and watch the Dropbox status icon change; I will do the same before touching a real project.
Read the mark back to confirm it
A successful mark call does not prove the mark is there. Read the same attribute right after setting it.
# Read the attribute; a value of 1 means it is set
xattr -p 'com.apple.fileprovider.ignore#P' node_modules
# List every attribute on the directory
xattr -l node_modulesThe syntax is ordinary xattr usage; I have not yet seen the result for the File Provider attribute name on my own machine. If nothing comes back, suspect the wrong variant and try the other attribute name.
The surprise: npm ci did not wipe the mark
In my earlier article I wrote that a clean build recreates the directory and the mark disappears (see the piece on Xcode builds breaking in a synced folder). I assumed npm ci would behave the same way.
So I tested it: a tiny project with only a local file: dependency, a user extended attribute set on node_modules, then npm ci.
- The directory's inode was identical before and after.
- The attribute was still there.
The conditions were npm 10.9.4, Node 22, and a Linux user xattr. That is not Dropbox's own mark, and it may not hold for the Mac xattr, other npm versions, pnpm or yarn. Still, on my side I did not need to re-mark after npm ci. Deleting the directory yourself with rm -rf node_modules does create a fresh directory, so that case needs the mark again.
A mark survives operations that keep the directory and not the ones that replace it. Check in the logs which one your agent actually uses.
Next step
Before the next time you hand dependency installs to an agent, run mark-volatile.sh without --apply and see whether node_modules appears in the list. Then mark a throwaway folder, confirm Dropbox reacts, and only then move on to the real project. As an indie developer who keeps working folders in Dropbox, that is the order I intend to follow.