git clone https://github.com/sito8943/sito-file-browser.gitThis project targets Node 22 (pinned in .nvmrc). Download: https://nodejs.org/en/download
On Windows, just download the binary and install it. On Linux or macOS, use NVM:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bashWith NVM installed, run nvm use in the project root to switch to the version in .nvmrc (run nvm install 22 first if you don't have it yet).
You can also use NVM for Windows if you wish.
Install: https://www.rust-lang.org/tools/install
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | shOn Windows, use the Rust Windows installer.
Download: https://curl.se/windows/
Install all dependencies (only once per clone):
npm installRun the frontend and the desktop app:
npm run tauri devThis installs the Rust packages if they are not on disk yet; this happens only once.
The app ships an AI-friendly CLI, sfb, that drives the same file operations the GUI does
(list, search, copy, move, trash, tags, …). It prints a JSON envelope on stdout and uses exit codes,
so agents and scripts can call it directly. Run sfb schema for a machine-readable list of every
command and its arguments, or sfb help for human-readable help.
sfb list --path ~/Documents
sfb search --path ~ --query invoice
sfb tags-set --path report.pdf --tags '[{"name":"Work","color":4}]'
sfb delete --path old.log --force # destructive ops require --forcesfb is embedded inside the app bundle at Sito File Browser.app/Contents/MacOS/sfb. How it lands
on your PATH depends on how you installed the app:
-
Homebrew (Cask).
brew install --cask <tap>/sito-file-browserinstalls the app to/Applicationsand symlinkssfbonto yourPATHautomatically (seehomebrew/sito-file-browser.rb). Nothing else to do. -
Dragged the
.dmginto Applications. Add the symlink once yourself:sudo ln -sf "/Applications/Sito File Browser.app/Contents/MacOS/sfb" /usr/local/bin/sfb(
/usr/local/binis on the defaultPATH. Use~/.local/binor another PATH dir if you prefer not to usesudo.)
Building it yourself:
sfbis bundled as a Tauri sidecar. Run./scripts/build-sfb-sidecar.sh(stagessrc-tauri/binaries/sfb-<triple>) beforenpm run tauri build. CI does this automatically. For a cross-compile, pass the triple, e.g../scripts/build-sfb-sidecar.sh x86_64-apple-darwin.
The app opens a headless control channel — a Unix-domain socket at
<app config dir>/sfb-control.sock — so sfb ui-* (and, through it, an MCP server) can drive the
running GUI. The socket is created with 0600 permissions, so only the current user can reach it;
it is never exposed on the network.
To keep sfb useful for automation without exposing the app's internals in production, the
channel is split into two tiers:
| Tier | Actions | Available |
|---|---|---|
| Automation (AI-friendly) | all sfb filesystem commands (list, copy, move, trash, tags, …), plus ui-state, ui-navigate, ui-open-window |
Always |
| Introspection (debug-only) | ui-probe — dumps live DOM/drag internals for debugging |
Debug mode only |
Debug mode is on automatically in dev builds (tauri dev). In a release build it is off by
default and must be opted into at launch:
SFB_DEBUG=1 open -a "Sito File Browser" # env var
open -a "Sito File Browser" --args --debug # or launch flagsfb ui-state reports "debug": true|false so a caller can discover whether introspection is
available. When it isn't, ui-probe returns
probe is disabled: launch the app with --debug or SFB_DEBUG=1.
Implementation: is_debug_mode() and the per-action gate live in
src-tauri/src/functions/control.rs.
If the app ever needs stronger protection of the control channel, escalate in this order (each is stricter and costs more automation convenience):
- Gate UI driving behind debug too. Move
ui-navigate/ui-open-windowinto the debug tier so production only allows read-onlyui-state(and the disk-onlysfbfs commands). Loses some GUI automation in production. - Require a shared token. On startup the app writes a random token to a
0600file in the app config dir;sfbreads it and includes it in every control request, and the app rejects requests without a matching token. Blocks other local processes that don't own the file from driving the app, whilesfb(run by the same user) still works transparently. - Disable the socket entirely outside debug mode. Only bind
sfb-control.sockwhenis_debug_mode()is true. Maximum protection — no local process can drive or inspect the GUI in production — butsfb'sui-*commands stop working in release builds (the disk-only fs commands still work, since they never touch the socket).
macOS protects some folders (like the Trash, ~/.Trash) behind a privacy permission. Without it the app shows a "Can't read this folder" notice when you open the Trash, with a button to open the right settings pane.
To enable it:
- Open System Settings → Privacy & Security → Full Disk Access.
- Turn on the toggle for Sito File Browser (use the
+to add it if it's not listed). - Fully quit the app and relaunch it. The app hides to the menu-bar tray on close, so reopening the window is not enough — quit it from the tray (or
Cmd + Q) so macOS re-evaluates the permission on the next launch.
Notes:
- The permission applies per-executable, so the production build (installed
.app) and atauri devrun are treated separately. To test in dev, grant Full Disk Access to the terminal app that launchesnpm run tauri devinstead, then restart the terminal. - Deleting files always moves them to the Trash (via macOS
NSFileManager); this permission only affects listing the Trash contents inside the app.