DESKTOP - nself-org/nchat GitHub Wiki
nChat Desktop is a native desktop application built with Tauri 2. It wraps the nChat web frontend in a native shell with full OS integration.
nchat/desktop/ β workspace package (@nself-chat/desktop)
src/ β React/Vite renderer (shares @nself-chat/web)
src-tauri/ β Rust shell
src/
commands/ β IPC command handlers (EIE layout)
app.rs β app_get_version, app_get_name, app_get_path,
app_set_badge_count, toggle_autostart
window.rs β window_minimize, maximize, close, is_maximized
shell.rs β shell_open_external, shell_show_item_in_folder
clipboard.rs β clipboard_read/write_text/image, clipboard_has_image
notification.rs β notification_show
update.rs β update_check (with semver downgrade guard)
drag.rs β drag_start_file
menu.rs β Native menu builder + event handler
tray.rs β System tray icon + context menu
state/ β App state (AppState)
lib.rs β Tauri builder + plugin wiring
tauri.conf.json β Identifier: org.nself.chat
Cargo.toml
capabilities/
default.json β Core permissions
desktop.json β Tray permissions (macOS/Windows/Linux)
All channels are registered in src-tauri/src/lib.rs via tauri::generate_handler![].
Run pnpm ipc-parity to verify all channels are present.
| Channel (snake_case) | Frontend invoke() | Status |
|---|---|---|
app_get_version |
invoke("app_get_version") |
Registered |
app_get_name |
invoke("app_get_name") |
Registered |
app_get_path |
invoke("app_get_path", { name }) |
Registered |
app_set_badge_count |
invoke("app_set_badge_count", { count }) |
Registered (macOS dock badge; no-op on other platforms) |
toggle_autostart |
invoke("toggle_autostart", { enabled }) |
Registered |
window_minimize |
invoke("window_minimize") |
Registered |
window_maximize |
invoke("window_maximize") |
Registered |
window_close |
invoke("window_close") |
Registered |
window_is_maximized |
invoke("window_is_maximized") |
Registered |
shell_open_external |
invoke("shell_open_external", { url }) |
Registered |
shell_show_item_in_folder |
invoke("shell_show_item_in_folder", { path }) |
Registered |
clipboard_read_text |
invoke("clipboard_read_text") |
Registered |
clipboard_write_text |
invoke("clipboard_write_text", { text }) |
Registered |
clipboard_read_image |
invoke("clipboard_read_image") |
Registered |
clipboard_write_image |
invoke("clipboard_write_image", { base64Image }) |
Registered |
clipboard_has_image |
invoke("clipboard_has_image") |
Registered |
notification_show |
invoke("notification_show", { title, body }) |
Registered |
update_check |
invoke("update_check") |
Registered (semver downgrade guard active) |
drag_start_file |
N/A β uses Tauri drag-and-drop API directly | Registered |
The native application menu is built in src-tauri/src/menu.rs. Menu events are forwarded to the
renderer as Tauri events:
| Menu Item | Event emitted to renderer |
|---|---|
| File β New Conversation | menu:new-conversation |
| File β Preferencesβ¦ | menu:preferences |
| View β Toggle Sidebar | menu:toggle-sidebar |
| Window β Bring All to Front | (no event β focuses main window) |
The app registers the nchat:// URL scheme. Supported patterns:
| URL | Renderer event |
|---|---|
nchat://chat/<room> |
deep-link:chat with room as payload |
nchat://invite/<token> |
deep-link:invite with token as payload |
- Endpoint:
https://packages.nself.org/chat-desktop/latest-{{target}}-{{arch}}.json - Updater artifacts are published to S3 (
s3://packages.nself.org/chat-desktop/) on every tag push - Semver downgrade guard: updates with remote version β€ current version are silently ignored
Window size, position, maximized state, and fullscreen state are restored across launches via
tauri-plugin-window-state with stateFlags: "SIZE | POSITION | MAXIMIZED | FULLSCREEN".
On macOS and Windows, a tray icon is shown with a context menu:
- Show nChat
- New Conversation
- Preferences
- Quit nChat
On macOS, closing the window hides it to the tray (Command+Q quits). On Windows/Linux, closing the window exits the app.
Set SENTRY_DSN in the environment before launching. If unset, crash reporting is disabled.
See .env.example.
To regenerate all icon variants from the master source:
# Source master icon (1024Γ1024 PNG):
# .claude/docs/brand/icons/nchat-512.png (or commission a dedicated nchat icon)
cp /path/to/nchat-1024.png nchat/desktop/src-tauri/icons/source-1024.png
# Generate all icon variants:
cd nchat/desktop
pnpm tauri icon src-tauri/icons/source-1024.pngThis produces 32x32.png, 128x128.png, [email protected], icon.icns, icon.ico as required
by tauri.conf.json.
Tauri 2 sets the dpiAware manifest entry automatically for all Windows builds. No custom
DPI application manifest is required. The tauri.conf.json windows[].scaleFactor field
(when set) overrides the system scale factor if needed.
Record test results here after running on each platform. Update PASS/FAIL and date.
| Platform | Version | Arch | Build type | Window resize | Tray | Deep-link | Updater | Notification | Clipboard | Result | Date | Notes |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| macOS 15 Sequoia | 0.0.0 | arm64 | debug | - | - | - | - | - | - | PENDING | - | - |
| macOS 13 Ventura | 0.0.0 | x64 | debug | - | - | - | - | - | - | PENDING | - | - |
| Windows 11 | 0.0.0 | x64 | debug | - | - | - | - | - | - | PENDING | - | - |
| Windows 10 | 0.0.0 | x64 | debug | - | - | - | - | - | - | PENDING | - | - |
| Ubuntu 22.04 | 0.0.0 | x64 | debug | - | - | - | - | - | - | PENDING | - | - |
Update this table as physical-device testing completes (T21).
# Install deps
cd nchat && pnpm install
# Run in dev mode
cd desktop && pnpm tauri:dev
# Build release
cd desktop && pnpm tauri:build
# Unit tests
cd desktop && pnpm test
# IPC parity check
cd desktop && pnpm ipc-parity
# E2E (requires a built binary)
cd desktop && pnpm test:e2eThe macOS arm64 DMG must not exceed 90 MB. This is enforced by the
desktop-macos.yml CI workflow (T27). If the budget is exceeded, remove
unused assets or enable compression in tauri.conf.json β bundle.macOS.