- 移除 GovAI, nomifun-tauri, 算力盒子 的 submodule 引用 - 添加所有子项目的完整源代码 - 保留原始 .git 为 .git.bak 备份
9.6 KiB
Running NomiFun as a Desktop App
The desktop app (nomifun-desktop) is a Tauri shell that links the Rust backend (nomifun-app) into the same process. There is no spawned backend binary, no Electron, no bundled nomicore. The shell starts the backend as an async task on a free 127.0.0.1 port, then loads the bundled SPA (ui/dist) into a WebView and points it at http://127.0.0.1:<port>/api.
The desktop WebView does not show a login screen. Instead, the embedded backend
runs under AuthPolicy::TrustLocalToken: the shell injects a per-boot local
trust secret into its own WebView, and only requests carrying that secret are
treated as the desktop user. If you want login + remote browser/phone access,
see WebUI Remote Access for the in-app feature, or
Self-Host the Web Server for the standalone
server.
Quick start
Prerequisites
The desktop app requires:
- A platform Tauri supports (Windows 10+, macOS 11+, mainstream Linux distros).
- A WebView runtime: WebView2 on Windows (preinstalled on Win 11; on Win 10 install the Evergreen Bootstrapper), WKWebView on macOS (built-in), WebKitGTK on Linux (
libwebkit2gtk-4.1-0). - For development: Rust toolchain, Bun ≥ 1.3.13, and the platform Tauri build deps (see the Tauri prerequisites).
Run from source (development)
From the repo root:
bun install
bun run dev
This runs tauri dev --config apps/desktop/tauri.conf.json. It starts the Vite dev server (http://localhost:5173) for the SPA, builds and launches nomifun-desktop, and the embedded backend is started on a fresh free localhost port at every boot.
Build a release bundle
bun run build
Output bundles land under target/release/bundle/ per platform (NSIS installer + MSI on Windows, .app + .dmg on macOS, .deb + .AppImage on Linux). To produce signed updater artifacts (extra .sig files), use bun run build:updater after configuring signing keys (see Updater status below).
A successful build prints the bundle locations, for example on macOS:
$ bun run build
Compiling nomifun-app v0.1.0
Finished `release` profile [optimized] target(s)
Bundling NomiFun.app (macos)
Bundling NomiFun_0.1.0_aarch64.dmg (macos)
Finished 2 bundles at:
target/release/bundle/macos/NomiFun.app
target/release/bundle/dmg/NomiFun_0.1.0_aarch64.dmg
Window and titlebar
The main window is frameless on Windows and Linux: the React titlebar component draws min/maximize/close on the same row as the in-app navigation. On macOS the native traffic-light buttons are kept via Tauri's Overlay title-bar style, with content extending under the bar.
- Default size:
1280 × 832, minimum880 × 600. - Resizable everywhere (edge-resize and Snap still work on Windows even without OS-drawn decorations).
- Title bar:
NomiFun.
The exact chrome differs per OS: a frameless titlebar with in-app controls on Windows and Linux, and the native traffic-light buttons (content under an
Overlaybar) on macOS.
Single instance
tauri-plugin-single-instance enforces a single running copy of the app on Windows and Linux. Trying to launch a second nomifun-desktop will silently focus the existing window instead of starting another backend on a different port.
Deep links
The app registers the nomifun:// URL scheme (configured in apps/desktop/tauri.conf.json under plugins.deep-link.desktop.schemes). When the OS launches Nomi via a nomifun://... URL, the shell forwards the URLs to the renderer over the Tauri event deep-link://received. The renderer can subscribe with listen('deep-link://received', ...) from @tauri-apps/api/event to handle the payload.
register_all() is called at startup to install the scheme; on platforms that need an out-of-band registration step (some Linux desktops, dev contexts) the call is best-effort and a failure is ignored.
Autostart
The shell ships tauri-plugin-autostart so the renderer can opt the app into "launch at login" via the plugin's invoke API. On macOS this uses a LaunchAgent; on Windows the registry's Run key; on Linux a .desktop file in the autostart folder. The user-facing toggle lives in app settings.
Notifications
tauri-plugin-notification is enabled. The renderer can show OS-level notifications (e.g. when an agent finishes a long task or AutoWork has results). On macOS the user is asked for permission the first time; on Windows, notifications use the modern Action Center; on Linux they go through libnotify.
Where data is stored
The desktop app persists the SQLite database, agent state, logs, and the Bun runtime cache under the per-user application-data directory — %LOCALAPPDATA%\NomiFun\Nomi on Windows, ~/Library/Application Support/NomiFun/Nomi on macOS, $XDG_DATA_HOME/NomiFun/Nomi on Linux (resolved by the shared nomifun_app::cli::default_data_dir()). This is the same default the nomifun-web host and the dev scripts use, so a provider or companion configured in one host is visible in the others.
Set NOMIFUN_DATA_DIR=<absolute path> before launching the app and the data dir becomes $NOMIFUN_DATA_DIR/Nomi. The backend takes an exclusive server.lock on the data dir at startup; if it fails to start — for example because another instance already holds the directory — the desktop shell shows a native error dialog and exits.
Older builds defaulted to
<system temp>/nomifun-data/Nomi. An install found there is relocated to the per-user location automatically on launch (one-shot): data is copied, absolute paths stored in the database are rewritten, and the legacy directory is kept as a backup. Regenerable caches (the extracted Bun runtime, logs, browser profile, …) are not carried over — they rebuild on first use.
To start fresh, quit the app and delete that directory. To migrate, copy the directory to a new machine.
~/Library/Application Support/NomiFun/Nomi/ # macOS (see paths above for Windows/Linux)
├── nomifun-backend.db # SQLite state (conversations, settings, sessions, …)
├── logs/ # nomicore.log
├── companion/ # companions + the shared memory hub
├── knowledge/ # managed knowledge bases
├── runtime/ # extracted Bun runtime cache (regenerable)
└── server.lock # exclusive lock held while a backend is running
Authentication and local trust
The desktop shell does not expose the old blanket no-auth backend to every
localhost caller. It starts the embedded backend with TrustLocalToken, injects
window.__nomiLocalTrust into the WebView, and the renderer presents that secret
on HTTP and WebSocket calls. A process that only knows
127.0.0.1:<port>/api is not automatically trusted.
The desktop app is still a single-user tool: the OS account that starts it owns everything the agent can do, including shell and file access.
If you want to access the same install from another device, do not expose the embedded port. Use one of:
- WebUI remote access (a per-instance feature, see WebUI Remote Access) — turns on a separate authenticated server and gives you a QR-code login.
- Self-hosted web server (Web Server Deployment) — runs the same backend headlessly under
nomifun-webwith auth required.
Updater status
The Tauri updater plugin (tauri-plugin-updater) is wired in and the renderer exposes invoke('check_for_updates') (returns the new version string or null if up to date). However:
- The endpoint configured in
apps/desktop/tauri.conf.json(plugins.updater.endpoints) is a placeholder (https://REPLACE-WITH-YOUR-HOST/...). Until you replace it with a real HTTPS URL serving a signedlatest.json, the updater check will fail. - The included
pubkeyis a development key generated for local testing. Replace it before any public release and store your private key in a CI secret. bun run build:updaterproduces signed update artifacts (extra.sigfiles next to each installer).
The full updater flow (signing env vars, latest.json schema, supported platform
keys) is documented in apps/desktop/updater/README.md. OS-level code signing /
notarization is separate. macOS Developer ID signing and notarization are wired
through bun run build:signed and documented in
apps/desktop/signing/README.md; Windows signing still requires an external
code-signing certificate.
Troubleshooting
The window opens to a blank white area.
Make sure the WebView runtime is installed (WebView2 on Windows 10 needs the Evergreen Bootstrapper). On Linux, libwebkit2gtk-4.1-0 is required.
"Failed to bind backend port".
Another process is holding 127.0.0.1 ephemeral ports. The backend tries pick_free_port() and falls back to 8799 if that fails — quit any other NomiFun instance and try again.
Agent commands fail with bun: command not found.
The agent engine spawns Bun as a child process for tool execution. Install Bun (curl -fsSL https://bun.sh/install | bash) and make sure it is on the system PATH, or build the desktop bundle with NOMIFUN_EMBED_BUN=1 to embed it.
See also
- Web Server Deployment — run the same backend headlessly under
nomifun-web. - WebUI Remote Access — expose your desktop instance for remote browser/phone use.
