Ferry

Status and the menu bar

Full status

ferry status shows the state of the snapshot and of each box. It changes nothing. It checks these for each box:

ferry status does not fail for an offline box. The report shows the box as offline.

Skipped MCP servers

The shared part of the report, before the boxes, has the block Skipped MCP servers when Ferry does not carry a stdio MCP server of this machine. Each line has the harness and the name of the server, the reason, and what to change:

Skipped MCP servers:
  codex/node_repl (app-bundle): runs from a macOS app bundle, which the box does not have. There is nothing to change.
  claude/local (home-path): refers to a path in your home. Use a command on the PATH or a path outside the home.
Reason Meaning What to change
home-path The command or an argument refers to a path in your home. Use a command on the PATH or a path outside the home.
inline-script A shell or an interpreter runs an inline script, which Ferry cannot check. Put the script in a file that Ferry carries, or run the server through a tool on the PATH.
unknown-options A shell or an interpreter has options that Ferry cannot classify. Remove the options that come before the script file, or run the server through a tool on the PATH.
app-bundle The server runs from a macOS app bundle, which the box does not have. Nothing. A box cannot run a macOS app.

The block shows only the name and the reason, never a command or an argument of a server. The list is the same for each box. Ferry prints no block when it skips no server. A server with a credential in its arguments is not in the block: it stops the sync, and the deny list has its rule.

Tool states

State Meaning Fix
ok The box has the target version.  
drift The box has another version. ferry update
missing The box does not have the tool. ferry install
hidden A login shell on the box does not find the tool. ferry sync
skipped The tool has no target.  
off The tool has the policy "off". This is not a problem.  
unknown Ferry cannot read the box version.  

Brief status

ferry status --brief prints one line for each item that needs action, with the Ferry command that fixes it:

Disk and memory limits

--brief shows an item when the free disk of the box home file system is below both 10% and 5 GiB, or the available memory is below 10%. Set other limits in [status] of ~/.ferry/config.toml:

[status]
disk_free_percent = 10
disk_free_gib = 5
memory_available_percent = 10

A limit of 0 turns its part of the check off. When one disk limit is 0, the other decides. The load average is only in the JSON report, and it has no limit.

The watch service

ferry watch syncs all boxes one second after a change is stable. ferry watch install runs it as a user service:

System Service file Log
macOS ~/Library/LaunchAgents/dev.ferry.watch.plist ~/Library/Logs/ferry-watch.log
Linux ~/.config/systemd/user/ferry-watch.service journalctl --user -u ferry-watch.service -f

The status file

At the start, every 5 minutes, and after each sync, the watch writes the report of ferry status --brief --json to ~/.ferry/status.json. The menu bar app and the Linux status bar read this file. The report also has the free disk, the memory, and the load of each box. Linux status bar shows the format.

The macOS menu bar app

ferry menubar install installs a menu bar app that shows the report of ferry status --brief for each box. The app reads ~/.ferry/status.json, so ferry watch must run.

Ferry downloads the app of the release of this Ferry, verifies it against SHA256SUMS of the release, and unpacks it to ~/Applications/Ferry Menu Bar.app. When the release does not have these files yet, Ferry stops and the installed app stays. The app starts at login. Run the command again after you move Ferry or update it. ferry menubar uninstall removes the app.

Linux

The menu bar app runs only on macOS. On Linux, a waybar custom module can show the same state from ~/.ferry/status.json. See Linux status bar.

Scripts and agents

ferry status --json prints the status report with schemaVersion: 2. Its skippedMcp field has the skipped stdio MCP servers as { harness, name, reason }. ferry status --brief --json prints { schemaVersion: 1, checkedAt, boxes }. Each item has a summary of at most 60 characters and the full message. The Ferry agent skill describes each field.