Files
miniSCP/docs/platform-notes.md
T
jgamboaandClaude 0eb5608873 Migrate to Electrobun 2.0.2 (Hutch)
Electrobun 2.x replaces the vendored CLI with Hutch: the npm package is now a
bootstrap whose exports are a throwing stub, and the SDK is projected into
.hutch/devkit. The app stays on the Bun main process — `mainProcess: "bun"` is
load-bearing, since the 2.x default (Cottontail) ignores build.bun and with it
the ssh2 externals — and the bundle now ships the pinned Bun 1.4.0.

- electrobun 2.0.2 as an exact devDependency. `electrobun prepare` takes the
  old CLI re-sign step's slot in postinstall and every dev/build/start/release
  script: tsc (root tsconfig extends the devkit's) and the Angular build
  (electrobun/view mapped into the devkit) resolve the SDK there.
- Imports move to electrobun/main. The CLI re-sign script and the v1 "three"
  type shim are gone (Hutch's binaries are validly signed).
- UI: Electroview's bunSocket is hostSocket; noImplicitReturns is off because
  the devkit's raw-TS browser SDK compiles inside the UI program.
- Updater.applyUpdate() now consults before-quit, so the transfers/unsaved
  guard's "Quit Anyway" re-runs the apply instead of quitting without it.
- 2.x applies trafficLightOffset from macOS's default button position (1.18.1
  clamped it inside the titlebar); {12, 4} centres the lights in the header.
- Releases: mac-x64 dropped (2.x publishes no macOS x64 core, so no Rosetta
  path). artifacts/ is emptied before each build and published verbatim.
  Installers lost the stable- prefix (the update feed kept it), so release.ts,
  deploy.sh and the site links follow. Linux ships Electrobun's Setup
  installer instead of the portable tarball and its miniSCP.sh wrapper.
- Docs cover all of the above, plus re-checks against 2.0.2: still no native
  modal windows; window close is now cancellable through will-close.

Verified: tsc, build:ui, a stable mac-arm64 release (dmg + the v1-compatible
stable-macos-arm64 feed) and dev launches (RPC, Settings window, traffic
lights). Windows/Linux builds and the v1 -> 2.x Windows update bridge still
need their first run on native machines.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-05 11:08:03 +02:00

11 KiB
Raw Blame History

Platform notes — macOS / Windows / Linux behavior matrix

macOS (Apple Silicon) is the primary target; Windows 11+ x64 and Linux x64 are beta targets (win-arm64 and linux-arm64 deferred). Intel Macs were dropped with the move to Electrobun 2.x, which publishes no macOS x64 core. Every platform seam carries a PORTABILITY: comment at the branch site.

Seam inventory (where platform branches live)

Concern File mac win linux
Window chrome src/bun/windows.ts chromeOptions hiddenInset + traffic-light offset, UI drag header native titlebar, compact header same as win
Scrollbars ui/src/styles.css (::-webkit-scrollbar) custom square, always visible (styling them turns off overlay scrollbars) custom square custom square
External editor launch src/bun/edits.ts launchEditor open [-a app] cmd /c start "" [app] file app directly / xdg-open
Editor app picker rpc-handlers.ts pickEditorApp /Applications, .app %ProgramFiles%, .exe home, any
Owner/group names fs/local.ts resolveId id -nu + dscacheutil undefined → "—" id -nu + getent
Drive roots fs/local.ts listLocalDrives empty fsutil fsinfo drives empty
chmod/Permissions context-menu.service.ts, file-panel, file-actions full hidden for LOCAL panels (only flips read-only); SFTP unaffected full
Shell wording ui context-menu.service.ts Reveal in Finder / Move to Trash Show in Explorer / Move to Recycle Bin Show in File Manager
Shortcut labels ui platform.ts MOD_LABEL/ALT_LABEL ⌘ / ⌥ Ctrl+ / Alt+ Ctrl+ / Alt+
Tray src/bun/tray.ts 22 pt template PNG 16 px colored PNG colored (needs AppIndicator, see below)
App menu src/bun/menu.ts full menu incl. About none (early return) — Settings opens from the tab-bar gear (Ctrl+,), About from its About section none (unsupported upstream)
connections.json protection store/connections.ts chmod 0600 icacls current-user ACL (0600 is meaningless) 0600
App data dir store/paths.ts ~/Library/Application Support %APPDATA% $XDG_CONFIG_HOME/.config
ssh-agent fs/sftp.ts $SSH_AUTH_SOCK \\.\pipe\openssh-ssh-agent fallback $SSH_AUTH_SOCK
Paths in UI ui format.ts joinPath/isRootPath "/" separator detected from the dir string; drive-root regex "/"

The context menu is HTML on every platform (ui/src/app/skins/shadlike/context-menu.ts + context-menu.service.ts), not a native electrobun menu — see the Linux section below for why. Only the three shell actions it can't do itself (reveal, open with the default app, copy path) cross to bun, via the shellItemAction RPC.

Remote (SFTP) paths are ALWAYS POSIX regardless of host or server OS (path.posix throughout fs/sftp.ts).

Memory footprint (expected, not a bug)

Investigated 2026-07 — packaged build. Roughly ~200 MB macOS / ~300 MB Windows (Linux sits near macOS: WebKitGTK, like WKWebView, is lighter than Chromium), which is normal for a Bun + system-WebView app (30 MB is native / no-web-engine territory; Tauri-class apps run ~80–200 MB, Electron 150–400 MB). Not reducible to tens of MB without dropping the web UI.

  • macOS splits across several "miniSCP" processes: the Bun main (~120 MB: backend + the bundled electrobun runtime + live SSH sessions — the largest and least reducible piece), the views://app WKWebView content process (~60 MB, the Angular UI), and the standard WebKit Networking / Graphics and Media helpers. All are one app; WebKit just names them per-role.
  • Windows is higher because WebView2 is Chromium (multi-process: browser + GPU + renderer + utility + crashpad), vs macOS's lighter WKWebKit.
  • Measure against a packaged build — bun run dev inflates the WebContent heap (ng-serve, unminified, sourcemaps, live-reload) and is not representative.
  • Verified non-issues: transfers stream (no whole-file buffering), icons tree-shaken to ~33 glyphs, zoneless Angular, 364 KB prod bundle.
  • Only real growth levers if this ever matters: the file list is not virtualized (a directory with tens of thousands of entries retains a DOM row each), and each open tab keeps both panels' full entries arrays; terminal transfers are retained until cleared. None affect normal use.

Linux runtime dependencies (REQUIRED — the app will not start without them)

electrobun's libNativeWrapper.so links AppIndicator hard for the tray, so a missing library is a hard boot failure (ERR_DLOPEN_FAILED out of bun:ffi dlopen), not a degraded tray. The transitive deps (libdbusmenu-glib, libdbusmenu-gtk3, libayatana-indicator3, libayatana-ido3) come in as package dependencies:

Distro Install
Arch / CachyOS sudo pacman -S libayatana-appindicator
Debian / Ubuntu sudo apt install libayatana-appindicator3-1
Fedora sudo dnf install libayatana-appindicator-gtk3

GTK/WebKit itself comes from the distro too — electrobun uses the system webview (bundleCEF: false), so webkit2gtk must be present.

Diagnosing a boot failure:

ldd build/dev-linux-x64/*/bin/libNativeWrapper.so | grep 'not found'

libasar.so => not found in that output is expected and harmless — it ships in the same bin/ folder and resolves at load time; only an unresolved libayatana-appindicator3.so.1 is fatal. (Hard link and path verified on 1.18.1 — re-check both on the first 2.x Linux build.)

Tray visibility is a separate matter from linking: GNOME 3.26+ hides the legacy tray, so the icon needs the AppIndicator extension. KDE Plasma, XFCE, MATE and Cinnamon show it out of the box. The app runs fine either way — the tray is a convenience, and every action it offers exists in-app.

Linux known issues (upstream electrobun)

  • No native menus of any kind. Application menus and showContextMenu are both no-ops (electrobun's .hutch/devkit/api/sdks/main/proc/linux.md, still in 2.0.2; the app logs "Application menus are not supported on Linux" at boot). The app menubar was already macOS-only, and the panel context menus are now HTML on every platform, so nothing is missing at the UI level — but do not add a feature that depends on a native menu.
  • NVIDIA renders black without the DMABUF workaround. WebKitGTK can't allocate GBM buffers on the proprietary driver, so the window paints nothing while the log looks perfectly healthy. The dev launches (scripts/linux-gpu.ts) set WEBKIT_DISABLE_DMABUF_RENDERER=1 when /proc/driver/nvidia exists; an installed build (the official Setup installer) does not — launch it with that variable set (e.g. in the desktop entry's Exec). The app can't do it itself (Bun's process.env writes don't reach child processes); see gotchas.md.
  • Benign startup noise: a deprecation warning pointing at libayatana-appindicator-glib. Not fatal.
  • Unsigned; Electrobun's own installer: the release artifact is linux-x64-miniSCP-Setup.tar.gz — a self-extracting installer + README (2.x does the desktop-entry packaging and ships an uninstaller); no AppImage or .deb. Layout unverified until the first 2.x Linux build.

First-Linux-boot smoke test

  1. Install the AppIndicator package for your distro (table above), then bun run start. The window opens and actually renders the UI (a black window on NVIDIA means the DMABUF workaround didn't apply — check for Failed to create GBM buffer in the log), and the tray icon appears (or doesn't, on bare GNOME — that's the extension caveat, not a failure).
  2. Right-click a file row: menu appears at the pointer, Send to Other Panel is first, Permissions is present, Escape / click-outside / arrow keys + Enter all work, and a right-click near the bottom-right flips the menu instead of overflowing.
  3. Right-click empty panel space (New Folder / New File / Refresh / Show in File Manager) and a column header (checkmarks toggle columns live).
  4. Copy Path puts the path on the clipboard; Show in File Manager opens the distro's file manager; Open (local file) launches the default app via xdg-open.
  5. local↔remote transfers both directions; external editor round-trip (temp download → save → auto-upload) with the inotify watcher.
  6. Move to Trash lands the item in the desktop's trash; connections.json is 0600.
  7. bun scripts/release.ts --target linux-x64 produces release/linux-x64/miniSCP-Build<N>-linux-x64-Setup.tar.gz; unpack it elsewhere, run its installer, then launch the installed app (on NVIDIA with WEBKIT_DISABLE_DMABUF_RENDERER=1).

Windows known issues (upstream electrobun, documented not fixed)

  • HiDPI blur — WebView2 renders at 1x on scaled displays (blackboardsh/electrobun#324, seen on 1.18.1). Most user-visible defect; 2.x lists per-monitor DPI setup among its Windows fixes — re-check on the first 2.x Windows build.
  • Notifications are legacy balloon style (Shell_NotifyIcon), not Windows toasts.
  • Unsigned binaries — Setup.exe and the portable exe both trigger SmartScreen / Mark-of-the-Web on first run. No Authenticode support (2.x: "Windows release signing is not currently part of Hutch's packaging pipeline"; a signtool post-hook is an option later). Installer unpacks to %LOCALAPPDATA%, desktop shortcut only; 2.x installer builds add an uninstaller (%LOCALAPPDATA%\<identifier>\<install-root>\uninstall.exe).
  • hiddenInset degrades to hidden on Windows — irrelevant here because non-mac windows use the native titlebar.
  • findInPage is a window.find() shim on WebView2 — irrelevant here, the editor find is custom.

First-Windows-boot smoke test

Code paths written blind (no Windows box was available); verify in order:

  1. Build: bun scripts/release.ts --target win-x64 on the Windows machine — Hutch, the core and the pinned Bun download into ~/.hutch on first run; Setup.zip AND the portable zip appear under release/win-x64/ (the portable step warns instead of failing if the assembled-app folder layout differs — fix the appDir path in release.ts if so). A v1 0.1.78 install must pick up the published 2.x build through its updater (the bridge release).
  2. App boots, tray icon renders colored, window has a native titlebar.
  3. Drives dropdown in each panel lists C:\ (+ others); navigating to a drive root hides the '..' row; the path bar shows consistent \ paths.
  4. local↔remote transfers both directions; self-copy guard still blocks same-path copies.
  5. External editor: default app opens via cmd /c start; the Choose… picker starts in Program Files and accepts an .exe; remote temp-edit → save → auto-upload works (directory watcher on NTFS).
  6. Context menus: Send to Other Panel is the first row item; Show in Explorer, Move to Recycle Bin (item restorable from the bin), Copy Path; Permissions ABSENT on local rows, present on remote.
  7. Ctrl+T/W/F/S and Ctrl+digit tab jumps; tooltips read "Ctrl+…".
  8. connections.json ACL: icacls connections.json shows only the current user after saving a connection.
  9. Editor/manager/Settings windows open, modal bounce works, Ctrl+, opens Settings and About shows from its About section.
  10. Known-issue check: HiDPI blur on a scaled display (seen on 1.18.1 — 2.x's per-monitor DPI setup may have fixed it).