Desktop control surface for mvmt — a local file authority that exposes folders on your machine to AI agents over MCP.
The CLI does everything; this app just makes it easier to see what's running, what's mounted, who has access, and how to expose it to the outside world.
- Start / stop the local engine — wraps
mvmt serveso you can seepid, port, and status without a terminal. - Manage mounts — add and remove folders the engine exposes, set read-only vs read+write.
- Manage tokens — scoped credentials for clients (Claude, Gemini, etc.). Inline edit permissions, rotate, revoke.
- Public endpoint via cloudflared — start, stop, and refresh a tunnel so an MCP client outside your laptop can reach the engine.
- Activity log — live tail of what each client is doing against your files.
- macOS (the build is currently
darwin-arm64only; Windows/Linux targets exist inelectron-builderconfig but aren't tested). - The mvmt engine vendored locally. The build script grabs it from
../mvmt(orMVMT_SOURCE_DIR) and bundles it into the app. cloudflaredif you want a public endpoint. Quick Tunnel works out of the box; named tunnel needs your own setup (below).
git clone git@github.com:philipnee/mvmt-desktop.git
cd mvmt-desktop
npm install
# Vendor the engine + cloudflared into ./vendor (one-time, or whenever the engine changes)
npm run vendor
# Dev
npm run dev
# Build a packaged .app / .dmg
npm run dist:macThe vendor step expects the mvmt repo at ../mvmt. Override with MVMT_SOURCE_DIR=/path/to/mvmt npm run vendor.
The desktop app starts and stops a tunnel; it does not configure one. Run mvmt tunnel config once in a terminal to pick a provider, then drive it from the UI.
If you don't bring your own setup, you get a Cloudflare Quick Tunnel — a temporary *.trycloudflare.com URL that changes every time the tunnel restarts. Fine for testing; bad if you want a stable address an agent can keep using.
brew install cloudflared
mvmt tunnel config
# choose: Cloudflare Quick TunnelThat's it. Hit Start in the desktop app's tunnel card and a public URL appears.
If you have a domain on Cloudflare and want a stable URL (e.g. https://mvmt.yourdomain.com/mcp), set up a named tunnel first, then point mvmt at it.
- Authenticate cloudflared with your account:
cloudflared tunnel login
- Create a tunnel and route a hostname to it:
cloudflared tunnel create mvmt cloudflared tunnel route dns mvmt mvmt.yourdomain.com
- Write a
~/.cloudflared/config.ymlthat maps the hostname to your local mvmt port (default4141):tunnel: mvmt credentials-file: /Users/you/.cloudflared/<tunnel-uuid>.json ingress: - hostname: mvmt.yourdomain.com service: http://localhost:4141 - service: http_status:404
- Tell mvmt to use the named tunnel:
mvmt tunnel config # choose: Cloudflare Named Tunnel # cloudflared config file: ~/.cloudflared/config.yml # public base URL: https://mvmt.yourdomain.com
Now the desktop's Start button runs your named tunnel and the public endpoint stays the same across restarts.
mvmt tunnel config also offers localhost.run and a custom option (any command that exposes {port}). The desktop app drives any of them with the same Start / Stop / Refresh controls.
Electron main process spawns the vendored mvmt CLI as a child for serve, and shells out for everything else (mounts, tokens, tunnel). The renderer is a single React tree that polls the main process over IPC every few seconds for status. There is no separate API layer — the engine's CLI is the API. If a feature exists in the desktop app, it exists in mvmt --help.
MIT.
