iCloud Drive looks like a regular folder in Finder, but it isn't one. It's a synchronized database with multiple layers of state tracking, and most command-line tools ignore all of them. This mismatch is the source of phantom files, sync conflicts, and the slow corruption that happens when you run build scripts in iCloud-managed directories.
I couldn't find a good reference explaining the underlying mechanics, so I wrote one. If you're seeing files reappear after you've deleted them, bird consuming CPU while sync hangs indefinitely, or iCloud silently falling out of sync with your local filesystem, this is probably why.
How iCloud tracks files
iCloud uses a multi-layered approach to track file changes:
-
File System Events (FSEvents): macOS has a kernel-level system called FSEvents that notifies apps when files change. All file operations trigger FSEvents, whether from Finder or the command line. iCloud's
birddaemon subscribes to these events for iCloud folders. -
iCloud Database (client.db): iCloud maintains a SQLite database tracking every file’s state. It contains metadata like sync status, file hashes, server identifiers, and modification dates, mapping local file paths to iCloud document IDs.
-
File Coordination APIs: Apps are supposed to use
NSFileCoordinatorand related APIs. These ensure atomic operations and proper notifications. Finder and well-behaved apps use these; command line tools typically don’t. -
CloudDocs File Provider: Modern iCloud uses a "File Provider" system that acts as an intermediary between apps and actual file storage. It handles on-demand downloading, upload queuing, and conflict resolution.
When "Optimize Mac Storage" is enabled, files you haven't accessed recently get evicted from local storage. In their place, iCloud leaves stub files with a period prefix and an .icloud extension, so notes.md becomes .notes.md.icloud. Open the file through Finder and bird downloads it transparently, restoring the original name. But the command line sees the filesystem as it is: a mix of real files and renamed stubs.
Why command-line tools break things
This system works when apps use the proper APIs. Most Unix tools don't. They operate directly on the filesystem, bypassing every layer iCloud depends on. As Michael Tsai documented, this makes "commands and scripts inordinately complex, and in some cases impossible."
Bypass of Coordination
# This bypasses iCloud's coordination APIs:
rm ~/Desktop/myfile.txt
# bird sees the deletion via FSEvents, but without coordination
# context, it can't distinguish intentional deletion from a sync conflict
-
Missing Coordination Context: Command-line tools generate FSEvents like any other operation, but they don't use NSFileCoordinator. Without that coordination layer, iCloud sees "file deleted" but can't distinguish an intentional deletion from a sync conflict.
-
Database Inconsistency: When you
rma file, the file disappears from disk, but the iCloud database still has an entry. Thenbirdtries to sync a non-existent file, creating the “phantom file” problem.
Race Conditions
# This can create race conditions:
mv large_file.zip ~/Desktop/ # bird starts uploading
rm ~/Desktop/large_file.zip # You delete before upload completes
# iCloud is now confused about the file's state
This is a common pattern. Large files take time to upload, leaving plenty of room for state to be invalidated before the transfer completes.
Workarounds
If you must work in iCloud folders, use trash instead of rm:
# Moves to Trash via NSFileManager, which notifies iCloud properly:
trash ~/Desktop/myfile.txt
# Or use the Finder API:
osascript -e 'tell app "Finder" to delete POSIX file "/path/to/file"'
If you’re writing apps, use file coordination:
NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] init];
[coordinator coordinateWritingItemAtURL:url
options:NSFileCoordinatorWritingForDeleting
error:&error
byAccessor:^(NSURL *writingURL) {
// Perform deletion here
}];
This isn't always practical. A build or deployment script might make hundreds of file operations, and you can't wrap each one.
When things have already gone wrong, killall bird is a common first resort. The daemon respawns automatically and often recovers by reconciling local state with the server. When it doesn't, you may need to sign out of iCloud and sign back in to force a full rebuild of the local sync database, which can take hours depending on drive size.
An iCloud "file" exists in multiple places at once: the local cache, the iCloud database, Apple's servers, and other devices. Command-line operations only affect the local cache, leaving the other layers inconsistent. iCloud can sometimes detect and resolve the discrepancy, but it breaks down under load, especially when you're deleting files while others are still syncing. In the worst case, you end up rebuilding the entire local iCloud state from scratch, or editing the SQLite database by hand.
Debugging any of this is opaque. The Eclectic Light Company notes that "almost all problems are delays in or failure of synchronisation," and that "there are almost no tools to help diagnose or fix problems." The brctl command exists for inspecting iCloud state, but most of its functions are undocumented.
The simplest advice: keep data and code in a local directory and rely on git and dedicated backup tools for sycing (Arq is my personal preference). You get versioning of both this way too. Let iCloud handle documents you work with through Finder and apps, not the terminal.