Skip to content

feat: accept smb:// URLs with mount-on-demand — true one-click on macOS - #1

Merged
BrianLeishman merged 1 commit into
masterfrom
smb-mount-on-demand
Jul 8, 2026
Merged

BrianLeishman merged 1 commit into
masterfrom
smb-mount-on-demand

Conversation

@BrianLeishman

Copy link
Copy Markdown
Member

Implements the server-side v0.2 called out in StirlingMarketingGroup/StirlingMarketingGroup#7020 (comment): on macOS, opening a folder on a share that isn't mounted yet previously returned not_found; true one-click needed mount-on-demand.

What changed

POST /open now accepts smb://server/share/... URLs in addition to absolute local paths, so one payload works on every OS:

  • macOS (smb_darwin.go): checks the mount table (getfsstat) for an existing smbfs mount of the host+share (handles percent-encoded mntfromname like //brian@storage/Signature%20Coins); if absent, mounts via the NetFS framework (NetFSMountURLSync through cgo) — the same mechanism Finder uses: mounts under /Volumes, Keychain credentials, and no Finder window at the share root (the explicit reason open smb:// was ruled out).
    • Mounts run silently first (kNAUIOptionNoUI): a failed mount returns a clean JSON error for the caller's ShowError instead of popping the system "There was a problem connecting to the server" alert. Only credential failures (EAUTH/ENEEDAUTH/EACCES/EPERM) retry with UI allowed, so the standard auth dialog still appears for first-time users and saves to the Keychain.
  • Windows (smb_windows.go): translates to the equivalent UNC path (\\server\share\...), which Windows resolves and authenticates natively.
  • Linux (smb_linux.go): mounts through gvfs (gio mount) and opens the path inside the user's gvfs FUSE mount, matching the share directory case-insensitively.

Percent-encoding is optional (literal spaces accepted). Missing folders below the share are still a real 404/not_found; a share that can't be mounted is a 500 with the mount error. No client code changes needed — only a TSDoc note on open().

Live test (real storage share, macOS)

From a fully unmounted state:

  • smb://storage/Signature Coins/<order folder> → silent Keychain mount + exactly one Finder window at the target folder (Unicode/RTL folder names included)
  • missing subfolder → 404 not_found
  • smb://storage/NoSuchShareXYZ → 500 JSON, no system alert, no windows
  • missing share name → 400 bad_request
  • re-open while mounted → mount-table fast path, no remount

Verify

  • go build ./... && go vet ./... && go test ./...
  • GOOS=windows go build / GOOS=linux CGO_ENABLED=0 go build
  • cd packages/client && npm ci && npm run build

New tests cover URL parsing and the mount-table source parser only — per AGENTS.md they never mount a share or open a window.

🤖 Generated with Claude Code

POST /open now takes smb://server/share/... URLs in addition to local
paths, so one payload works on every OS even when the share isn't
mounted yet:

- macOS mounts on demand via the NetFS framework — the same path Finder
  uses (mounts under /Volumes, Keychain credentials) but with no Finder
  window at the share root. Mounts run silently first (kNAUIOptionNoUI)
  so a failed mount returns a clean JSON error instead of the system
  "There was a problem connecting to the server" alert; the standard
  auth dialog is only allowed when the failure is missing credentials.
  Already-mounted shares are matched in the mount table (getfsstat),
  including percent-encoded mntfromname entries.
- Windows translates to the equivalent UNC path, which resolves
  natively.
- Linux mounts through gvfs (gio mount) and opens the path inside the
  user's gvfs FUSE mount.

Live-tested against a real SMB share from a fully unmounted state:
silent mount + exactly one Finder window at the target folder; missing
subfolders still 404, bad share names return JSON 500 with no dialogs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@BrianLeishman
BrianLeishman merged commit 686abee into master Jul 8, 2026
4 checks passed
@BrianLeishman
BrianLeishman deleted the smb-mount-on-demand branch July 8, 2026 16:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant