Releases: vdavid/cmdr
Cmdr v0.22.0
Added
- Redesign Search dialog: re-thought UX, better filters, recent-searches history, persistent state across close+reopen,
"Show all in main window", per-row context menu, clickable path pills, source-side copy/move/delete from snapshots
(62aef440,
ac4c6340,
b9ca1e6f,
2c10bba7,
807e456e,
1f03ff49,
f4eea79d,
e52c6dec,
d94187bd,
c79c1112,
4770a93f,
e7afc8b3,
1b1fc5ab,
71c9485b,
f3f45084,
3ea1b45e,
5c35d9ea,
9b8f9dd7) - Select and copy in the file viewer. Works with files until 100 MB. Goes around our virtual scrolling.
Double/triple-click for word/line, right-click menu (6f717829,
1e061820,
8d6f85c0,
46f278bb,
e329bb39,
1445c2d7) - Eject ejectable volumes (USB, SMB, DMG) from the picker and the breadcrumb right-click menu
(2a7e256f) - Replace the human-friendly size units toggle with a 5-way size unit picker (dynamic / bytes / kB / MB / GB)
(78a7f367) - Show climbing bytes and dirs during MTP/SMB scan previews (was "0 / N / 0" until done)
(c2b5a040) - Reuse scan-preview cache for local delete and cross-FS move so the dialog skips straight to the active phase
(9445e61a) - Center child windows on the main window; file viewers cascade
(8cd06bf4) - Tint zebra stripes with the pane bg so per-volume tinting actually shows through
(b84e761e) - Toast confirms zoom changes and points at ⌘0 to reset (37f94410)
- Show a Space hint on "Toggle selection" in the right-click menu
(a24613d9) - Blue info toasts, new colorless
defaultlevel for low-importance feedback, and reclassify routine confirmations and
soft refusals (dabf0e3a,
51e30112)
Fixed
- Fix SMB share mis-loading local paths after a volume switch (stale
onPathChangepoisoned the new volume)
(3e613ca6) - Fix volume copy dialog wedging open after SMB/MTP cancel (0fbafebb)
- Process selected files in pane sort order, not Cmd+click order
(39fc8d2e) - Cursor lands on the new folder, not the row below (38ebdc87)
- Fix Full view ".." row hiding behind the header after PageDown/PageUp
(6ddb4273) - Fix viewer ⌘A in ByteSeek-no-index mode freezing on a 9e15-iter loop
(e29312bd) - Land
range_readcancellation within ~64 KB, not 16 MB (0e758b46) - Fix Escape on viewer context menu closing the whole window
(4464f766) - Honor
prefers-reduced-motionin viewer drag autoscroll (aec327b8) - Surface silent-band viewer copy failures as a warn toast (41398aca)
- Polish viewer copy dialogs: ⌘A routes to the right size tier, Enter triggers the primary action, Tab skips ×
(b6542e7b)
Non-app
- Build git test fixtures via
gixinstead of CLI shell-outs; 91 tests went from tens of seconds to ~1.7 s
(532722c8) - Trim slow tests under the 8 s nextest cap, drop the 30 s
cap_bundle_*exception, make
index_mtime_change_invalidates_cachedeterministic (f4c0b5ad,
9e23ff2a,
44429405) - Re-enable three previously-skipped E2E tests; the culprit was a Node fixture-helper dangling-symlink bug
(915c5f33) - Settings-style chrome and a live SMB diagnostics dashboard in the dev Debug window
(6bd0f15c,
e7660b3a)
Cmdr v0.21.0
Added
- Add Quick Look (⇧Space) (6778494b)
- Add ⌘← / ⌘→ to copy the cursor path between panes (a3e15f45)
- Add red binary-file warning in the file viewer (74e7b0cd)
- Redesign Settings window to look like System Settings (69480931,
76be4f8a,
9668a078,
91c31f35) - Redesign tab bar, flatten panes for a more native-macOS look, fix UI glitches
(dc7d6500,
9668a078,
3771570a,
79ed3b6c)
Fixed
- Fix transfer dialog showing "✓ 0 files" when pre-flight scan beat the FE listeners
(8525835c) - Fix stale path events corrupting the breadcrumb after switching a pane to Network
(a3e15f45) - Fix Quick Look toast/content import cycle (b3d67fe6)
Non-app
Cmdr v0.20.0
Added
- Cmd+click toggles selection (c6adee74)
- Bind
Insertto toggle selection in Total Commander style
(719e4f9b) - Modify Shift+Arrow/Page/Home/End behavior to align more with other file managers
(47932132) - Switch selection to red. Clears WCAG AA across all backgrounds!
(9028722c,
02b295da,
069bc400,
14a36dd8) - Tint each pane's background by volume type (local/SMB/MTP)
(3f5629d3) - Improve MCP: replace fire-and-forgets with wound-trips (48a9701c,
3c1b0dc9,
e12285d1,
df11caef) - New MCP resources:
cmdr://logs+ filters,cmdr://statefilters,recentErrors,upgrade_smb_to_direct, SMB
connection state (e597d24d,
640c3330) - SMB volumes auto-upgrade from OS-mount to direct smb2 sessions
(640c3330) - Propagate MTP cancel all the way to the USB layer; dialog stays at "Cancelling…" until the device settles. No more
30-second wedges! (0de4c6b7,
1696355d,
f894e60e,
b4018891) - Copy/move/delete pre-flight scans reuse watcher-backed listings. Skip a 17s MTP re-list when the folder is already
open in another pane! (9d434638,
ba20ca3e,
49187230,
fdebd329,
b90b9003) - SMB streaming writes no longer hold the client mutex (smb2 0.9). Concurrent writes pipeline over one session
(3d0d5db7,
06bc5da7,
ed4b6886) - Bump SMB watcher to smb2 0.10 to stop losing events between polls
(432d13ff) - Localize macOS pane names in onboarding and error dialogs (points at what System Settings actually shows)
(bad5d926) - Coalesce
directory-diffevents with soft-refresh in the FE. No more empty-pane flicker on bulk ops!
(54674854,
13b486a8) - Honest transfer-complete toasts: report copied vs skipped separately
(5cdf989e) - Friendly message for SMB
STATUS_DELETE_PENDING(was misleading "disk needs attention")
(a560243b) - Polish the license nudge: clearer copy and layout (95007952)
- Add fallback UI colors on macOS Monterey, achieving macOS 12.x compat!
(5792b10e) - Improve accent-fg to match WCAG AA+ against all colors, and add cursor outline
(d00ba5b4) - Properly pluralize all words ("1 file"/"10 files") everywhere
(eb360370)
Fixed
- Fix MTP destination pane staying stale after cross-volume writes
(873f1102) - Fix SMB/MTP listing cache going stale when the watcher misses an event
(1dea24e1,
ab98ee88) - Fix MTP delete not emitting
write-cancelledwhen cancel landed mid-iteration
(e21ca6d3) - Fix transfer dialog wedging at "Cancelling…" when Cancel raced ahead of the
operationIdIPC
(2b2a5ec6) - Fix MCP
open_under_cursoron the Network view (0aec8fbd) - Fix Linux startup hanging on a half-configured D-Bus (probes now bounded by a 500 ms timeout)
(91afacbf,
85580df9) - Fix
refresh_listingshort-circuiting on local volumes during the FSEvents symlink race
(57ef1034) - Fix two SMB shares with the same case-folded name on different servers colliding on the same volume ID
(f2414556) - Fix opening a guest SMB share popping the kernel
smbfscredential dialog
(92119464) - Fix
TransferErrorDialogbeing see-through in the transient branch
(f01af359) - Fix error dialogs rendering OS strings with markdown bleed-through (
STATUS<em>DELETE</em>PENDING)
(dbd7a2ac) - Fix Brief mode cursor stripe briefly spanning the entire pane while column widths load
(d676efa5) - Fix Move dialog hiding the Size progress bar (
bytes_totalwas 0)
(8856e012) - Fix conflict-resolution radios reading "Skip all" / "Ask for each" when only one conflict exists
(4eac76b4) - Fix focused-button Enter firing the dialog's default action instead of the focused button
(079a0ce1) - Fix free-space numbers tier-coloring as red on healthy disks
(8219a06c) - Fix the AI offer prompting Intel Macs for a local-model download they can't run
(52f3cd81) - Fix every tokio task crashing when stderr becomes a broken pipe
(31d97e06) - Fix Linux compile errors in
errno.rsandmcp/resources.rs
(90b0afee) - Fix Linux compile errors in
system_strings.rs(macOS-only loctable items)
(e852f04a) - Fix
clippy::unnecessary_sort_byon Linux volume sorting (1.95 picked it up)
(03faf480)
Non-app
- Cap every Rust test at 8 s (matches the Playwright convention), with documented exceptions
(eb67f389) - Stop gating
desktop-e2e-linuxondesktop-rustin CI (66a2e501) - Harden the checker against supply-chain attacks:
--lockedeverywhere, pinned tool versions, new
workflows-hardening+govulncheckchecks (7d771ca8) - Declare
rustfmtandclippyas requiredrust-toolchain.tomlcomponents
(a23222eb) - Trigger Rust CI on
rust-toolchain.tomlchanges (0f8c9ffb) - Dev override
VITE_CMDR_FORCE_OLD_WEBKIT=1 pnpm devto test the old-WebKit fallback on modern Macs
(17537510) - 14-day release-age gate via Renovate (3-day override for security advisories)
(8bd5af1e) - Shared
pluralizehelper for log/error/UI strings, plus apluralize-nouncheck
(0ae2ee92,
ec277ba8,
e070fc34) - Force file-backed secret store under
CMDR_E2E_MODE=1(no more Keychain prompts in unattended E2E)
(ecb495fc) - New
btn-restylecheck (forbids.btn-*overrides); accent-matrix in the contrast check
(51f31939,
0e885f5d) - Codify 100-char Rust comment width; reflow existing comments
(b76b9277,
610f66f6) - Vendor
smb-consumer-maxreadsizeand pin the SMB streaming-write no-deadlock invariant (200 × 1 MB at concurrency 8)
(1ae6eec7,
e8259eef,
e750920b) - Ticketed acquire/release logs on the
SmbVolumeclient mutex
(2e4aeb9d) - E2E focus hygiene: viewer/settings windows skip OS focus, Escape-binding tests use synthetic dispatch
(be21bebe,
0dfdcb2a) - Defensive disk-poll + refresh in the MTP→local copy E2E (9693b283)
- Stamp the running E2E test name into the main window's OS title
(1181e0c1) - Document the UTM Ubuntu VM loop for iterating Linux-only tests
([...
Cmdr v0.19.0
Added
- Reorganize Settings into Appearance, Behavior, File systems, Updates, AI, Network, Privacy, and Advanced
(c3003a05) - Add "Overwrite all smaller" and "Overwrite all older" conflict actions
(2dfd17b8) - ⌘⇧T reopens closed tabs; double-click the tab bar opens a new tab
(65417fbe,
d7a85a33) - Move AI API keys to the OS keychain, with 300 ms debounced save
(42bc5eaf,
10f8525b) - Command palette recents on empty query (last 10, LRU, grouped, self-heals stale IDs)
(d3406299,
a2971aba) - Type to jump to a file in the explorer (0b9f943f)
- Sort-column shortcuts ⌘3–6 (Brief) and ⌘F3–F6 (Full) (74e827e5)
- Brief mode: backend-computed per-column widths, plus a max-column-width slider
(d84d5c2a,
f7907107,
f9e40fc4,
e18bdbf4) - Volume picker wraps cursor at top and bottom (206ec7d9)
- USB link-speed indicator in the volume switcher (637b152e)
- Stream MTP source-scan progress in the copy dialog (no more 0/0/0 freeze)
(fef1aafd) - Bulk-skip pre-known conflicts under Skip-all for copy and move
(b365076d) - MTP→SMB copy: kill the 2-min stall, faster source scan (1ae5c198)
- Honest copy ETA on long single-file streams: stop decaying files_rate
(4737acbc) - Format sub-1 files/s readouts instead of rounding to 0 (ff7a72f9)
- Strip em-dashes from user copy and docs; rephrase microcopy to sound more human
(971e35c4,
c39ecdc7,
a16afb0c,
adab08fa)
Fixed
- Fix MTP delete freezing instead of showing live scan progress
(4e005f95) - Fix Cancel-copy losing the rollback on the APFS clonefile fast path
(9c2e6244) - SMB upgrade no longer races mDNS in dev (be1350d7)
- "Connect directly" SMB login dialog now shows the actual server name
(0d84e4e7) - Bulk-skip no longer pollutes the throughput estimator, and only fires for top-level file conflicts
(55d3ca46,
c3be95c1) - Per-iter Skip on volume copy credits byte progress (e7f657df)
- Show duration settings in their declared unit (66571349)
- Brief column-width slider enables inside the Settings window
(591e090b) - Brief mode horizontal scrollbar drag no longer vibrates at 60 Hz
(b80789e1) - Restore focus when a ModalDialog closes and when the command palette closes
(35413fa3,
6c45e12d) - File viewer surfaces
SearchStatus::Cancelledto the FE on cancel
(14ba2735) - Separate MCP ports for prod (19224) and dev (19225) so dev no longer collides with the installed app
(f0524658) setSettingis idempotent on unchanged values (c49636d8)- Pane state: clear network host on leaving the network volume; skip FilePane MCP sync on Network
(602fcb94,
a1d19947)
Non-app
- Refactor write ops behind a shared transfer driver: per-source loop for copy/move, sink-based inner functions across
local and volume code paths, drop one unsafe transmute (b6833e26,
1d9f2ca4,
63b6728e,
0218a645,
01c8614e,
101e8385,
118ac6b1,
bc957471,
9d7c69e8,
a056eb58,
5cf1173a,
1280056b,
0a7c257c,
643e7cb2,
afb70901) - Parallel-shard the E2E suite across three Tauri instances (MTP isolated, two non-MTP shards balanced); wall-clock 5m
49s → 2m 48s (7802fca3,
1841e0c5,
6e8971a0) - Cut Playwright wall-clock 10m 12s → 5m 6s via condition polling, MCP-driven cursor moves, beforeEach short-circuits,
and a per-keystroke → menu-dispatch migration (507afb0e,
3b04806e,
f907adc2,
df89b217) - Add proptest-based property tests for
platform_case_compare, search scope parsing,glob_to_regex, and
topological_sort_bottom_up(2e747bf8,
ffd799c8,
1813e3dc,
2cf586d1,
e69e45aa) - Add state-transition tests for
IndexPhase,ActivityPhase,DiscoveryState, andSearchStatus
(c0aed651,
9a9899e9,
9dd32504,
4ae15120) - Add vitest mockIPC harness plus IPC contract tests for SMB connection, file viewer, and write operations
(04c26e4d,
3a538b44,
baa977ed,
967d93be) - Add mutation-testing-driven unit tests across
indexing/store,chunked_copy,watcher,copy_strategy, and
state(ef91cfb8,
a812cd9a,
e9a3a9fd,
b026f43d,
4f04d03c,
41a3a831) - Codify the testing playbook and tools inventory (9515adde)
- Add ESLint rule
cmdr/no-arbitrary-sleep-in-e2e(a9aea301) - File-length check: 10% growth buffer with growth % shown; split long files into focused modules
(1c1bdeb0,
2d7c27a3) - Pre-commit
--fastlane in the check runner (33f77ca5) - E2E windows get a blue title stripe and
E2E -prefix so they can't be mistaken for the installed app
(b1f707b7)
Cmdr v0.18.0
Added
- Suppress the 5–10 native macOS TCC popups that stacked behind the FDA onboarding prompt, deep-link to the Full Disk
Access pane, version-aware copy, Tahoe+-button tip, and a multi-trigger probe that catches kernel short-circuits
(3c708d35,
16918218,
f32dfc55,
791edff0) - Flag TCC-restricted folders live in the sidebar and file list: italic + (i) icon,
<no perms>Size, generic folder
icon for FDA-gated favorites, failed listings stay in nav history
(7baa9317,
6581f5ad,
df6cd794,
762d7b9a) - Defer the AI offer toast until onboarding ends so it stops piling on the FDA prompt
(265c72d9) - Color modified dates by age with per-segment tiers (year, month, day, time each get their own color); App palette is
now the default (c73fcf54,
d98459b6,
be2333c2) - Color sizes at every previously-plain site (tooltips, breadcrumb, transfer/delete dialogs, viewer footer, AI progress,
search results); light-mode palette retuned to clear WCAG AA against every background
(265c5a0e,
31128012) - Show real scan progress in copy/delete dialogs with running tallies, throughput, current directory, and a real
progress bar; hardlinks deduped by inode so totals match the indexer
(03215d25) - Honest ETA when files outnumber bytes: tracks both axes, picks the slower; no more "~0 s remaining" while the
small-file tail drains (16b49a04) - Stream folder-name suggestions in the New folder dialog: first option in under 500 ms instead of after the full reply
(d681c8de) - Add multi-provider AI via the
genaicrate (GPT-5, o-series, Anthropic, Gemini, xAI, Groq, DeepSeek, OpenRouter,
Ollama); fixes GPT-5 400 ontemperatureand*-pro/*-codex404 on chat completions
(0c45a469) - Cap updater hangs at 30 s and surface the real cause (DNS error, TCP deadline) instead of generic "error sending
request" (e5be1467) - Per-row crash email with build mode and short ID, schema migrations, newest-first sort
(e89a63a3) - Stable client-side ID for error reports across dialog, toast, and Discord; env-prefixed R2 keys;
[DEV]/[PROD]
Discord prefix (77260827,
e1810361) - Guard read-only volumes up front for F7/F8/F2 so MTP read-only SD cards warn before you type anything
(d9212b83) - Provider-enriched friendly errors on the write path: MacDroid folders get "Managed by MacDroid…" on move failures;
dialog renders markdown + category icon, retry shown only when meaningful
(e9452032,
51dff4c1,
5bcacfef) - Route every dir-into-dir cross-volume conflict through the resolver so Stop/Skip/Overwrite/Rename works for folders
too; pin Overwrite-means-merge as an architectural guarantee
(7ecf9d37,
2f4e377d) - Bump smb2 to 0.8.0 with typed
STATUS_OBJECT_NAME_COLLISIONandFILE_IS_A_DIRECTORYso merging into an existing SMB
directory works after a partial copy; fast-path WARNs demoted to debug
(7dd9cfc8,
623f8c17) - Move MCP defaults to ports 19224 (prod) and 19225 (dev) so a dev build no longer collides with the installed app
(c9fad17e) - Polish getcmdr.com hero: "Download for macOS" button, viewport-responsive illustration mask, muted link style,
tightened copy (606c724e)
Fixed
- Fix F8 (and other dialogs) dying after a volume switch: Option fields started serializing as JSON
nullinstead of
being omitted after the typed-IPC migration; swept=== undefinedchecks across 11 sites
(f2019aff,
46bd6d0e,
eef042d3) - Fix one or two rows ellipsizing the Modified column under non-100% text size (sub-pixel glyph-advance drift)
(a7a7915e) - Fix light/dark theme briefly flipping at startup when the persisted choice differed from the system preference
(f689da01) - Stop the dev runtime silently overwriting committed
bindings.tson everypnpm devlaunch
(6e39d68d) - Silence the
get_file_atFE/BE drift warning that fired legitimately during async listing refreshes
(0b51a331) - Accept
nullfor optional crash-report fields so reports written by older app versions still upload after upgrade
(3c12ff2f) - Stop re-anchoring focus inside
selectVolumeByIndex/navigateToPath, which dropped keystrokes mid-sequence in fast
multi-select (6074cd21)
Non-app
- Migrate the full IPC surface to typed bindings via tauri-specta; an ESLint rule and a Go check block raw
invoke()
and lockfile drift (f1e58011,
dc5f0b47) - Ban classifying errors by string-matching
message/stderr/titlewith a Go check and ESLint rule; sweep across
SMB, git, friendly errors, and updater (c764962a) - Pin pnpm 11.0.9 in
mise.tomland move overrides topnpm-workspace.yaml; unblocks CI's E2E-Linux
(cee0aa08,
c41d2e0d) - Track recurring upkeep in
docs/maintenance.mdwith a log going back to 2025-12-25
(49a119bd)
Cmdr v0.17.0
Added
- Add dynamic text size slider in Settings (75–150%, ⌘+/⌘-/⌘0 shortcuts)
(a326bca6,
ca78382d,
e207effb) - Add "Open with" and system Services to menus (71e6061b)
- Add iCloud Drive cloud actions to context menu (01bc0dae)
- Split Brief/Full menu items to per-pane View > Left/Right submenus
(7f4d123d) - Add networking toggle, lazy mDNS, no more local-network prompt at launch
(d2ae5170) - Faster external drive detection, fixes USB-C dock invisibility
(6527d850) - Drag & drop matches Finder (same-volume Move, cross-volume Copy, modifier overrides)
(64db140f) - Drag & drop "+" badge tracks the actual op, no flicker (cf8e3818,
dcfe439e) - Drag files into terminals (Warp etc.) (97d10675)
- Add Trash/Delete toggle to delete dialog (778296dd)
- Always show Copy/Move toggle in transfer dialog (450363e6)
- Default to Full mode on fresh installs (57ba47c1)
- File list typography polish: aligned dates, aligned headers, fade selection, clamped Ext
(474f7414,
e9aec7bd,
88f56367,
c5698998) - Add size-color palette setting (Rainbow / Accent / None) (5fe0d77e)
- Restore double-click-to-zoom on macOS title bar (f95441dc)
- Focus search when Settings opens (cb88685d)
- Hand cursor on License dialog support and Buy links (554b3801)
- Show real .git/* files alongside virtual categories in git portal
(33219321) - Per-file Modified dates inside git portal snapshots (3cead878)
- Cache git status per index change, near-instant repeat navs
(19f0e98e) - Error-report preview now lands under 200 ms on big log dirs (was 30+ s)
(f24f255c) - Send error reports in dev too, tagged [DEV] (63ebabf6)
- Persistent "Save bundle to disk" toast with Reveal in Finder
(0debff1c) - getcmdr.com comments follow live theme changes (7333b13c)
Fixed
- Fix Intel DMG download 404 (19f797da)
- Fix crash on virtual git portal toggle; empty git roots no longer render as 1970-01-01
(b266737e) - Fix folder size column losing value after rename (b1d032c1,
d7e08e16)
Non-app
Cmdr v0.16.0
Added
-
SMB live reconnect. When the smb2 session for a network share drops, Cmdr now stays in the folder and runs a
5-attempt backoff cycle (2/4/8/16/30 s, 60 s total) right inside the pane. Both panes on the same share share a single
cycle; success re-runsloadDirectoryautomatically; give-up swaps to the existing unreachable banner with a working
Disconnect button. The session rebuilds in place — sameSmbVolume, samevolumeId, same Full Disk Access
permissions, no re-auth — because connection params now cache for the volume's lifetime. Concurrent operations wait on
a single-flight reconnect lock instead of dog-piling the server. Auth failure re-pulls credentials from the secret
store and retries once before giving up. Unmount mid-cycle short-circuits cleanly so a fresh session never lands in an
orphaned volume. The reconnect view shows an attempt counter and a progress bar driven byrequestAnimationFrame, and
three buttons with disambiguating tooltips: Retry now, Cancel, Disconnect
(d96bc4b4,
0c1d3680). -
Disconnect actually disconnects. Previously the Disconnect button in
SmbReconnectingViewand the gave-up
unreachable banner behaved like a fancy Cancel. Now it runs a real per-volume unmount:diskutil unmounton macOS
(FSEvents picks up the unmount and tears downVolumeManager),smb2-session drop on Linux. Ifdiskutilreturns
"Resource busy" because Finder has the volume open, the user sees an actionable toast instead of silent failure
(c5a410aa). -
Check for updates from inside the app. Two new affordances, both reading the same shared update state:
- Settings > Updates: a "Check for updates" button at the top of the section, disabled while a check is in flight,
with status text below cycling throughChecking…→No updates found. Current version: vX.Y.Z→
Update found, downloading vX.Y.Z (current: vA.B.C)…→Installing vX.Y.Z (current: vA.B.C)…. On error, a "Send
error report" link opens the error reporter pre-populated with the failure context. - Cmdr menu > Check for updates… (right after "Enter license key…"): same status flow, surfaced as a toast that
supersedes itself as the phase changes and dismisses cleanly when the persistent restart toast takes over.
The macOS update path now exposes a separate
installingsubstate — the custom updater runsdownload_updateand
install_updateas two distinct Tauri invokes, so the UI can say "Installing" instead of a misleading "Downloading"
during the sync-into-bundle step (00470b96). - Settings > Updates: a "Check for updates" button at the top of the section, disabled while a check is in flight,
-
Human-friendly size units toggle. New
Settings > Listing > Human-friendly size unitsswitch. Default ON shows
1.02 MB-style values; OFF shows raw bytes with thousands separators for precise comparison. Affects the Full list
size column and the SelectionInfo size readout. Tooltips that already showed both formats are unchanged on purpose,
and so are volume/disk space, dialogs, search results, and the drive-indexing section
(c8cc1008). -
Symlink-aware size hint. Folders containing symlinks anywhere in their tree now show a small info icon next to the
size with the tooltip "This folder contains symlinks. Symlinked content is not counted in the total to avoid double
counting." Cmdr's recursive size aggregation matchesduand Finder by intentionally skipping symlink targets, so a
folder of only symlinks reports 0 bytes — surfacing that fact removes a frequent "huh?" moment. The flag
(recursive_has_symlinks) propagates bottom-up alongside size totals; the index schema bumped to v10 to carry it
(0d83a7b2). -
AI download toast: clear close affordance. The X on the "Downloading AI model…" toast now has the tooltip "Close
this notification — the download will continue in the background", and clicking it actually keeps the toast hidden for
the rest of the download run — previouslyai-toast-syncre-added it within ~200 ms because the next
ai-download-progressevent re-ran its$effect. Cancel still cancels
(97f1cee3). -
Rename: skip warning for equivalent file extensions. Renaming
foo.jpg→foo.jpeg(orhtm/html,
yml/yaml,tif/tiff,mpg/mpeg,mid/midi,aif/aiff,qt/mov,md/markdown/txt) no longer
trips the "you're changing the file type" confirmation. Cross-group changes still warn
(55592ba4).
Fixed
- Brief network blips no longer kick you out of the folder. A few seconds of bad WiFi on a NAS share used to trigger
the directory-eviction poll and "navigate to nearest valid parent" mid-session. ThepathExistsTauri command now
returns a structuredTimedOut<bool>result and is SMB-aware (aDisconnectedSmbVolumereports timed-out
instantly, no syscall timeout fires). The eviction logic inFilePaneonly walks up on a real not-found
(48ac9bf8). - Update toast no longer interrupts onboarding. New
isOnboardedflag (defaultfalse) gates the "restart to
update" toast during first-launch onboarding. Same gate covers the FDA-revoked re-prompt path. Background download
still runs — only the toast surface is deferred — so the update is ready the moment onboarding finishes
(ffeb7d96). - Indexer no longer triggers macOS permission popups during onboarding. Recursive scan from
/was being kicked off
insetup()regardless of FDA state, stacking iCloud/Photos/etc. native dialogs over our in-app explanation modal.
The indexer now waits until the user has either granted FDA (and restarted, where the launch-time OS check passes the
gate) or explicitly clicked Deny (59aca717). - SMB reconnect: runaway subscribe loop after hot reload. Both panes stuck on "Loading…" with thousands of
subscribe/unsubscribe pairs per second from the reconnect manager. Caused bySvelteMap.getreads inside a Svelte
$effectbecoming tracked deps that the manager's own writes invalidated, looping forever. Map-mutating methods now
run insideuntrack()so caller$effects don't pick up internal reads
(91bc2e46). - SMB reconnect:
onSuccesscould fire twice in one cycle. BothrunAttempt's success branch and the
smb-connection-changedlistener could callhandleDirect, double-triggeringloadDirectoryinFilePane. The
handler is now guarded by a baseline-shape check and is safely idempotent
(3f6b1b0d).
Non-app
- Release script now stages
oxfmtauto-fixes alongside the version bumps (viagit add -uafter the bump-stage
plus a secondoxfmt --cipass), so any pre-release.claude/commands/*.mdreformats end up in the release commit
instead of failing CI on the release tag (d523e236). - Three pre-existing eslint warnings the SMB work surfaced when running the full check matrix end-to-end — unused
helper, async-without-await, redundant optional chaining — fixed so CI is green again
(5e4eb307). - Tier-3 a11y test for
UpdateCheckToastContent; new module-level CLAUDE.md section infile-explorer/network/that
ties together the four moving parts of the SMB live-reconnect dance (BE event → volume-store patch → reconnect manager
→ FilePane effect) so the next agent doesn't have to reverse-engineer it
(e8656bb9,
a3638ee7). - Skip the flaky
git-portal toggleE2E (the toggle round-trip was too racy for the 30 s Playwright budget); Rust unit
tests cover the underlying behavior. Retire when we have a "wait for portal state to settle" hook
(129c27ce).
Cmdr v0.15.0
Added
- Git browser. Cmdr now treats every git repo as first-class. Five things you can do that you couldn't before:
- See branch + dirty state at a glance. Open a folder inside a git clone and the breadcrumb shows a pill with the
current branch, ahead/behind counts vs upstream, and a dirty indicator. Detached HEAD shows the short SHA; brand-new
repos show "no commits yet". The pill updates live as you commit, fetch, or branch from a terminal, no polling, no
refresh button. - Browse history as folders. Step into
.gitand seebranches/,tags/,commits/,stash/,worktrees/,
submodules/, plus araw/escape hatch for the real.gitinternals. Drill intobranches/main/(or
commits/<sha>/) and you're browsing the working tree at that point in history. Refs with slashes like
feature/foorender as one entry, not nested folders. Breadcrumb segments inside the portal use a dedicated
git-portal color so it's clear you're in history-land. - Pluck a single file from another branch or commit. Drag a file out of the history pane into the working tree.
Cmdr preserves the bytes and the executable bit. Nogit checkout, no risk of touching anything else. Type or paste
any SHA directly to reach unreachable commits, even in shallow clones. - Open linked worktrees and submodules with one keypress. Each shows as a redirect entry; opening it jumps
straight to its working dir, which is itself a git portal. Turtles all the way down. - Show per-file git status in Full mode. Optional column with single-glyph codes (
M,A,D,?,!) and
long-formaria-labels for screen readers. Off by default; enable in Settings > General > Git
(314e9ae2,
897df2c7,
1ebcfa1c).
- See branch + dirty state at a glance. Open a folder inside a git clone and the breadcrumb shows a pill with the
- Meaningful Modified and Size columns inside the git portal. Every virtual entry carries a real timestamp (branch
tip date, tag date, commit date, stash creation date, snapshot date for files inside a tree). The Size column borrows
loose semantics so each row says something useful:+12 / -3ahead/behind for branches,5 filesfor commits,
on mainfor stashes and worktrees, short SHAs for tags and submodules, item counts for category roots. Tooltips and
aria-labels carry the long-form sentence (31aec35c). - Friendly errors for the git browser. Whatever goes wrong (the repo's damaged, the worktree's orphaned, the commit
is beyond a shallow boundary, the.gitfolder isn't readable, the file's too big to load from history, another git
command holds the index), Cmdr shows a warm, plain-language explanation in the error pane plus a concrete next step,
not a raw stack trace (19d5b075,
af64689f). - Toggle each piece independently. Three switches in Settings > General > Git: show the repo chip, show the
status column, and show the virtual portal. Disabling the portal lets.gitbrowse like any other folder; the toggle
invalidates open listings live so already-visible panes refresh on the spot
(19d5b075,
af64689f).
Fixed
- Virtual
.git/<category>/...paths no longer kick the user back to the parent after a few seconds. The frontend's
externally-deleted-directory poll and the backend'snotifywatcher both used to assume the listed path exists on
disk; both now skip the seven virtual git categories and rely on the per-repo.git/HEADandrefs/watchers for
invalidation (bfcbfa48).
Non-app
- Release process docs now require a runner sanity check 30 s after pushing the tag, watch the standalone CI run in
parallel, and verify the public surface (DMG count,latest.jsonversion) once the release run reports complete.
Lifted from the prvw release flow.
Cmdr v0.14.0
Added
- Error reports. When something goes wrong, you can now ship a redacted diagnostic bundle (manifest + recent
debug-level log tail) to the maintainer with one click. Two flows: Help > Send error report… (or the new button on
error toasts) opens a preview dialog so you see exactly what's about to be sent, and clicking Send is the consent;
no setting required. Optionally, opt in to auto-send via the newupdates.errorReportssetting (default off) — when
enabled, user-visible errors fire a debounced auto-send and a toast lets you view the bundle or change settings. Every
bundle goes through the shared path-shape-preserving redactor (Documents/<file>.pdfstyle). Reports are anonymous —
the shortERR-XXXXXID is the only correlation handle. - Log storage cap setting. New
advanced.maxLogStorageMb(default 200 MB, range 0–5000) controls how much disk
space the rotated log files use. The file target now defaults to debug level so error reports carry useful
context. Set to0to disable log storage entirely (and with it, the ability to send error reports). - Per-output log level filtering. Stdout stays at INFO with optional
RUST_LOG-style per-module overrides while the
on-disk file chain always captures DEBUG, so error reports carry useful context without flooding the terminal. The
developer.verboseLoggingtoggle now flips the stdout threshold at runtime (Info ↔ Debug) without losing records
mid-swap. Replacestauri-plugin-logwith a hand-rolledfernDispatch tree +file-rotatefor native size+count
rotation (319d5d37).
Fixed
- Auto-dispatcher race when an error fired before the Tauri
AppHandlewas wired up — the debounce window opened with
no handle to send the report, so the bundle never shipped. Late-arriving handles now pick up active windows correctly
(f069a712). - Size column icons now align flush with the cell's right edge instead of drifting a pixel inwards
(1d5f661a).
Non-app
- Bumped 24 npm packages (patch + minor; TypeScript held at 5.9).
pnpm dedupecollapsed duplicatepostcssand
@playwright/testversions, fixing stylelint false positives in inlinestyle="..."attributes and a
Page-type mismatch in website-typecheck. SplitresolveValidPathinto a newpath-resolution.tsto break an
app-status-store.ts↔path-navigation.tsimport cycle. Per-test unique paths fix arust-tests-linuxcollision
under higher parallelism (b1a53acb). - New
error-reportendpoint on the api server with R2 presigned-URL handoff, daily eviction sweep, and a dedicated
ERROR_REPORT_METAKV namespace separate fromLICENSE_CODES
(1a2ea1c0,
f78f76af). - Shared PII redactor for both crash files and error-report bundles — single source of truth so log lines redact
identically wherever they're inspected. Adds a per-bundle salted-hash mode (<dir:abc123>/<file:abc123>) for
in-bundle correlation without cross-bundle linkability, plus anmtp_ownerpattern that strips<Owner>'s <Model>
shapes while preserving the model string for diagnostic context
(1d719f36,
b64e2c2c). desktop-rust-log-error-macrocheck fails CI on any rawlog::error!outside the macro definition itself, so every
error site routes through the Flow B auto-dispatcher
(79bc2a28).changelog-commit-linkscheck now also verifies every linked SHA is reachable fromHEAD, catching commits that got
dropped from history (rebase, force-push, etc.) before they ship
(72375de6).releasing.mddocuments thecaffeinate -dimsurequirement during release builds — the self-hosted runner lives on
the dev Mac and any sleep drops the runner connection mid-build
(9f27228d).- Bumped
rustls-webpki0.103.12 → 0.103.13 for routine security maintenance
(9ff7583d).
Cmdr v0.13.0
Added
- SMB copies are ~30× faster on high-latency links. A 100 × 10 KB copy from a NAS over Tailscale (~60 ms RTT)
dropped from ~28 s (~280 ms/file) to 947 ms (9.5 ms/file) over four layered speedups: drop redundantis_directory
stat probes in the copy pipeline (Fix 1, 94090555), send
CREATE+READ+CLOSE / CREATE+WRITE+FLUSH+CLOSE as a single compound frame for small reads/writes (Fix 3,
9d6df0e9), unblock session-level concurrency by cloning
smb2::Connectionper download (Fix 2, 4009b9ba), and pipeline the
pre-copy scan-phase stats over one SMB session (Fix 4, 77ea6e81).
Effective concurrency 16× on the 100-file workload. Full analysis indocs/notes/phase4-rtt-investigation.md. network.smbConcurrencysetting (Phase 4.3) — controls how many concurrent SMB operations run per session for batch
copies. Default 10, range 1–32. Applies immediately without restart
(7fdd85e3,
aa331c4e,
f46d45e4).- Current folder's total on the
..row — shows recursive size, file count, and dir count for the folder you're in (not
the parent), with the same tooltip and size-mismatch indicators as any directory row
(36212ede). - Full mode shrink-wraps Ext / Size / Modified columns to give the name column every spare pixel. Width changes animate
over 300 ms, dir switches snap. The..row's huge recursive size only counts toward column width while actually
on-screen (7325c8f8). - Brief mode shrink-wraps each column to its widest visible filename, capped at
maxFilenameWidthand floored at
MIN_COLUMN_WIDTH. 300 ms width transitions, nav snaps (c336dbba). - Filename tooltip on truncation — hover a clipped filename in Brief or Full mode to see the full name. In Brief mode,
directories combine the full name with the existing dir-size tooltip
(f37d7e51). - Volume tooltip on tabs — every tab now shows
{volume name} — {full path}on hover, so you can tell at a glance
whether a tab is local, external, or on a cloud volume (b6663988).
Fixed
- Security: smb2 bumped to 0.7.2, which fixes an off-by-2 in the DFS referral V2 response parser that let any
DFS-enabled server (malicious or buggy) crash cmdr with a crafted referral. Caught by cargo-fuzz
(7e7eaf76). - Canceling a small SMB upload now actually cancels — the compound write fast-path used to silently drain the source,
send the WRITE, and only then honor the cancel flag (which it ignored entirely). Now checks cancellation per chunk
during drain and aborts before any bytes touch the wire; progress callbacks fire during the drain instead of only once
post-write (f948731c). - Clicking a file already under the cursor no longer eats the drag — the click started the click-to-rename timer and
returned early before drag tracking could arm. Grabbing the cursor item (alone or as part of a selection) now drags
correctly; rename timer cancels once the drag threshold is crossed
(cccf0095). - ⌘C now copies selected text instead of files when there's a non-collapsed text selection. The global shortcut dispatch
was intercepting ⌘C unconditionally, blocking native text copy in panes like the error pane whereuser-select: text
is set (47f03b20). - Drag & drop blocks dropping a folder onto itself or into its own descendants, with "Can't drop here" feedback instead
of letting the drag through and producing a backend error. The..row accepts drops as a normal parent-folder target
(b7c3d960). - Frontend hot reload is reliable again after swapping UnoCSS for unplugin-icons — UnoCSS's dev plugin was regenerating
virtual:uno.csson every Svelte save, triggering SvelteKit's root-layout TDZ crash (sveltejs/kit#15287). Icons now
import as tree-shaken inline SVG components via~icons/lucide/{name}
(00906566).
Changed
- Breaking (internal API): The
Volumetrait no longer exposesexport_to_localandimport_from_local. Every
cross-volume copy now flows throughopen_read_stream+write_from_stream(or the APFS clonefile fast path when
both sides areLocalPosixVolumeon the same volume). Adding a new volume backend takes two streaming methods instead
of four, and concurrency (Phase 4.2) plugs into one dispatch point. Only in-tree consumer wasvolume_copy.rs; no
external crates depended on the removed methods. Seedocs/notes/phase4-volume-copy-unification.md. - Cross-volume batch copies now run up to N streams in parallel instead of one-at-a-time. N is
min(source.max_concurrent_ops(), dest.max_concurrent_ops(), 32)—SmbVolumereturns 10 (tunable via
network.smbConcurrency),LocalPosixVolumereturns physical-core-ish clamped to 4..=16,MtpVolumereturns 1,
InMemoryVolumereturns 32. Batches of 1–2 items stay sequential. New trait method
Volume::max_concurrent_ops() -> usize(default 1) lets each backend advertise its parallelism. Abort-on-first-error
and cancel-under-concurrency preserve existing semantics; partial-file cleanup walks every in-flight task's
destination. Volume::scan_for_copy_batchnow returnsBatchScanResult { aggregate, per_path }, so the copy engine populates its
source_hintsmap from one trait call instead of re-probing each source.SmbVolumeoverrides to pipeline all
per-path stats over one SMB session viaFuturesUnorderedon clonedConnections
(77ea6e81).Volume::open_read_stream_with_hint(path, size_hint)added to the trait (default falls through to
open_read_stream).SmbVolumeuses it to pick the compound read fast-path when the caller knows the file fits in
one READ (9d6df0e9).- smb2 dependency moved from
gitsource to crates.io (96f4bbd3),
then bumped through 0.7.1 (addsTree::downloadfor concurrent streaming reads on a clonedConnection,
0ec95a79) and 0.7.2 (DFS referral parse fix,
7e7eaf76).
Non-app
- Docker SMB integration tests now run on every push. New
desktop-rust-integration-testscheck starts the core SMB
containers, runs the 26smb_integration_*tests, and stops the containers on exit. Closes the gap that let the
compound-write cancel/progress bug sit undetected onmainfor four days
(257269bb). - Byte-level blake3 hash verification on every existing SMB copy test — destination bytes now compared to source, not
just size or return value. Three tests previously only verified metadata; four large-file tests upgraded from
multi-megabyteVec<u8>equality to streaming hash with hex-pair mismatch output
(fd5a2d84). - 100-way concurrent copy cross-contamination guard — 100 files with unique
blake3(b"cmdr-fix8-" || i)content copied
through the realcopy_volumes_with_progresspipeline (same path production uses), per-index verified. Catches buffer
reuse across tasks, wrong-buffer-to-wrong-path routing, and MessageId demux swaps on clonedConnections that
identical-content tests can't see (97062e64). - SMB copy soak harness —
smb_soak_copy_looptest plusscripts/soak-smb.shwrapper andworkflow_dispatch-only CI
job. 30-min Docker-based run completed 41,984 iterations with zero drift in wall-clock, memory, file descriptors, or
SMB credits (3a9b58f2,
6a9e046d). - Settings live-apply is now a documented MUST rule — every setting applies immediately without restart. Rule lives in
both Rust and TS settingsCLAUDE.mdfiles with explicit recipes for adding new settings. Restart-required is now
formally a bug (cd1958ba). - Deflaked two intermittently-failing tests (
test_dir_namecollision under parallel nextest execution,
hidden-file-toggle Playwright E2E race), bumped multi-chunk SMB stream test sizes past the 8 MBmax_read_sizeSamba
negotiates, and addedenv_loggeras a dev-dep so SMB wire-trace logging works in integration and bench tests
(a48a323e,
f7823a0b,
009b851e,
75f856e8). changelog-commit-linkscheck validates everyhttps://github.com/vdavid/cmdr/commit/<sha>URL in CHANGELOG.md
resolves to a real commit, via a singlegit cat-file --batch-checkprocess — catches typos, truncated SHAs, and
prefixes ambiguous with trees before they land. Runs in the desktop-svelte, website, and api-server CI jobs (each does
a full-depth checkout so historical SHAs resolve). Surfaced and fixed 8 bad links in the 0.12.0 and earlier sections
along the way ([d488dfa](https://github.com/vdavid...