Folder sync status

Read whether folders are syncing from the file a running folder watch keeps for other programs on the computer.

While marfa folders watch runs, it writes the state of its folders to a status file, folder-watch.json. A menu-bar app, a status script or any other program on the computer can read it to show whether folders sync and how each one fares. A reader doesn't open a folder's store, call the server or run a command. Keep folders running covers the watch itself.

Where it is

The file sits beside the folder registry, folders.json:

SystemDirectory
macOSLibrary/Application Support/Marfa under the home directory
Elsewhere$XDG_DATA_HOME/marfa, or .local/share/marfa under the home directory
Any, when MARFA_FOLDER_REGISTRY is setThe directory of the file it names

Read the whole file each time. A watch replaces it in one step, so a read never finds half of one. The file holds no credential, no file name inside a folder and no item content: a folder's directory and its ID are the only names in it.

The shape

<notes-directory> stands for the folder's absolute path.

{
  "version": 1,
  "processes": [
    {
      "pid": 4821,
      "build_version": "0.0.56",
      "started_at": "2026-10-15T09:00:00.000Z",
      "heartbeat_at": "2026-10-15T09:20:35.120Z",
      "heartbeat_interval_seconds": 5,
      "ended_at": null,
      "folders": [
        {
          "dir": "<notes-directory>",
          "folder": "01a1232d-949d-758c-b244-70057174b96a",
          "watching": true,
          "reason": null,
          "last_success_at": "2026-10-15T09:20:31.004Z",
          "first_sync_waiting": false,
          "problems": [{ "code": "conflict", "count": 2 }],
          "pending_uploads": 0,
          "pending_downloads": 0,
          "paused_removals": 0
        }
      ]
    }
  ]
}

processes has one entry for each watch process on the computer: one for a watch of every folder, and one for each watch of a single directory. A watch writes only its own entry, and drops the entries of other processes whose last heartbeat is an hour old or lies in the future.

FieldTypeDescription
pidnumberThe watch process.
build_versionstring or absentThe version of the CLI build that runs the watch, as marfa --version prints it. One that differs from the installed CLI's still runs an earlier build. A build too old to write the field drops it from every entry when it writes the file.
started_atstringWhen the process started.
heartbeat_atstringWhen the process last wrote its entry.
heartbeat_interval_secondsnumberHow often a running process writes: at least this often.
ended_atstring or nullWhen the process stopped on Ctrl-C, SIGTERM, the end of --for or a failed watch. null while it runs.
foldersobject[]The folders the process was asked to hold. A watch of every folder lists each folder the registry lists.

Each folder holds:

FieldTypeDescription
dirstringThe folder's directory.
folderstringThe ID of its system.folder.
watchingbooleanWhether the folder is watched. A folder tried again after a failure counts as watched once its watch has lasted about 10 seconds.
reasonstring or nullWhy the folder isn't watched. null for a folder not yet tried.
last_success_atstring or nullWhen a complete sync last finished with nothing pending and no blocking problem. null until one does.
first_sync_waitingboolean or nullWhether the first sync waits for marfa folders confirm.
problemsobject[] or nullThe current problems, each a code from a closed set with its count.
pending_uploadsnumber or nullFiles with changes waiting to be scanned or sent.
pending_downloadsnumber or nullFiles the latest pull could not write out.
paused_removalsnumber or nullRemovals paused for confirmation, from the disk and from the instance.

The last six fields are the values of the folder's latest report to the server, which marfa folders health reads. They stay as last observed while the folder isn't watched.

They are all null until this process has read a report for the folder, so null in problems means unknown and [] means none. While a folder's copy fills, as a new folder's does or one's that a newer CLI fills again, it reports no problem for the fill itself: unavailable then means the latest attempt couldn't reach the server, and goes once a retry is filling. Settings that can't be read still show as settings_invalid (folders/health-hydrating). A folder whose reason is first_sync_waiting shows first_sync_waiting as true.

The reasons

reason is an error code when the watch can't hold the folder, or one of these:

ReasonMeaning
missingThe folder's directory can't be found, as with a deleted directory or a disk that isn't connected. The watch looks again. marfa folders remove takes the folder off the list.
handed_overA command such as marfa folders confirm asked for the folder, and the watch has let it go until the command ends.
first_sync_waitingThe first sync waits for marfa folders confirm.
no_credential, no_keychain, unauthorized, signed_outThe watch has no credential it can use for the folder's server.

Decide whether an entry is current

An entry is current when ended_at is null and heartbeat_at is no later than now and less than three heartbeat_interval_seconds before now.

A watch that is killed, or whose computer loses power, can't say it ended. Its entry stays with watching: true and ended_at: null, and its heartbeat ages until it passes three intervals.

Trust watching only for a current entry. To be sure at once, check that pid names a running process, but a system can reuse a process ID, so the heartbeat decides.

A folder is watched now when a current entry lists it with watching: true. A folder held by a watch of one directory shows as not watched in a watch of every folder, so one folder can appear in two entries.

When the watch can't write the file, such as when another process holds its lock for a long time, the watch says so once and goes on syncing. A reader then finds its entry old and takes it as ended.

The rules behind this page are in the folders chapter of the contract.

On this page