Download Latest Version v1.7.0 source code.zip (10.1 MB)
Home / v1.7.0
Name Modified Size InfoDownloads / Week
Parent folder
macSCP-1.7.0.dmg 2026-11-09 51.8 MB
README.md 2026-11-09 46.4 kB
v1.7.0 source code.tar.gz 2026-11-09 8.6 MB
v1.7.0 source code.zip 2026-11-09 10.1 MB
Totals: 4 Items   70.5 MB 0

1.7.0 (2026-11-09)

Features

  • actions: ask for a declared variable's value before planning the action (f1a8a14)
  • actions: bind PATH, DIR and NAME from a selected item (0a0e226)
  • actions: export and import actions, and never snippets (57dc32c)
  • actions: FileAction, a user-authored command template for the file menu (4198fda)
  • actions: hand the user's actions to the menus, and draw an action's name safely (43a6dac)
  • actions: offer a user's actions in the file context menu (0dbce8f)
  • actions: persist file actions in their own file (5c6b6be)
  • actions: refuse quoting in a local-capable action at the gate (81dd617)
  • actions: review an import before it is stored, and trim a pasted command (715a722)
  • actions: run an action, owned by an activity rather than by a Task (9c108a4)
  • actions: the gate that decides whether an action can run, and where (a87d9c4)
  • actions: the menu reaches a sheet that shows what will run (ddadb76)
  • actions: turn a selection into the commands that will run (18d12e3)
  • actions: write, store, import and export your own file actions (59724de)
  • app: "Connect and Create Bucket…" on a stored S3 connection, through a real tab (6e28474)
  • app: a connection's own actions, as one list per backend (d6b0874)
  • app: a read-only access-list section in the metadata sheet (14421bb)
  • app: bucket-versioning cache and per-row file-action availability (71e0a0b)
  • app: create a bucket, with the two switches that are final (040fd7c)
  • app: deleted files in the remote pane, and the row that brings one back (8d373f5)
  • app: draw the empty state an account with no buckets lands on (081e7c6)
  • app: edit a bucket's CORS rules as fields or as text (7f4a1e2)
  • app: say what resuming versioning starts again (70032ea)
  • app: set a retention or a legal hold, and make compliance deliberate (27db9a6), closes #expect
  • app: the five bucket-settings writes leave a line in the audit trail (ee0df3d)
  • app: the five row actions of the version history, with the conditions each is refused under (12d57a7)
  • app: the FTP port follows the security mode until the user types one (219492d)
  • app: the metadata sheet, with the COMPLIANCE acknowledgement (f17bd44)
  • app: the permission editor is offered per connection, so a server without SITE CHMOD shows none (4857e79)
  • app: turn a bucket's versioning on, and say what suspending keeps (9225a34)
  • app: version history sheet, file-action route table, versioning cache that takes a write (74e9f3f)
  • archive: a channel that takes a line and bytes, nothing else (d7c6cdf)
  • archive: one operation per pane, cancellable, outside the transfer queue (09dbcd6)
  • archive: the context-menu entries, absent where a backend cannot run them (16fe803)
  • archive: the extract dialog, and a collision count no tool would report (47a942e)
  • archive: the formats, the refusals, and the name an archive is offered (255c73f)
  • archive: the local and the remote runner, and one failure vocabulary (53c33cd)
  • archive: the plan, with a word that carries whose it is (7dfef1b)
  • archive: the remote line, quoted by the one file that can phrase it (f4ac452)
  • cli: --kind ftp, with its own fields and completions (da707b6)
  • compare: a comparison window as a third scene (4a43ba3)
  • compare: a line diff over two local files (26a7b84)
  • compare: an undetermined row offers to compare its contents (64a264b)
  • compare: classify a pair by size, then by checksum only on a tie (655d2dd)
  • compare: fetch both sides, diff a file pair, settle one undetermined row (afb3819)
  • compare: offer a comparison from both panes and the menu bar (f9f92f2)
  • compare: own a comparison from the tab that owns the connection (77ca711)
  • compare: pair two listings by relative name (0f344be)
  • compare: refuse a binary or oversized pair, with a reason (f7ffe4c)
  • compare: render hunks, or the reason there are none (226e7f5)
  • compare: report an unreadable subtree as a row instead of aborting (ab91047)
  • compare: tell a non-UTF-8 file apart from a binary one (e9b6fca)
  • compare: the folder overview, with a per-state count (7467164)
  • compare: walk two trees, pairing and classifying each level (88b959e)
  • connect: point a key or certificate mismatch at the menu that forgets it (aa772cf)
  • core: an FTP diagnosis dials the login and reports the server's features (3ac4d15)
  • core: an FTP failure reaches the dial mapper as its own sentence, with its kind kept (229e7d1)
  • core: an optional capability for an object's metadata and ACL (4bb4461)
  • core: an optional capability for one object's versions (c0113d1)
  • core: four audit kinds for the S3 bucket settings, and the recorder that writes them (3f93e21)
  • core: FTP data connections and a pool whose leases always come back (08da6cc)
  • core: FTP is a connection kind, with its capability row (f76ee49)
  • core: FTP listings parse from MLSD facts and from LIST dialects (cb1cc65)
  • core: FTP server replies parse, including the multiline form (6753355)
  • core: FTP sessions are stored, and the connection type is a menu (e02fc56)
  • core: FTP sessions export and import, and an unknown kind no longer voids a document (febd3c0)
  • core: FTPFileSystem conforms to RemoteFileSystem (991b99b)
  • core: listedItems, the directory's contents whatever the search hides (21168a9)
  • core: one choke point between an FTP path and a command line (51541ca)
  • core: parse ListVersionsResult, markers included (20be3a6)
  • core: S3 reads and replaces an object's metadata and reads its ACL (8ac6930)
  • core: S3FileSystem lists one key's versions and the deleted keys under a prefix (31c1a9d)
  • core: S3FileSystem restores, deletes and lifts versions, reads each back, and audits them (b7e516b)
  • core: the audit recorder for an object's metadata change (dc46423)
  • core: the FTP control connection, with one validated command path (da72dca)
  • core: the permission editor is probed per connection, not per protocol (6318325)
  • core: the system trust store's verdict on an FTPS chain is logged, and decides nothing (02491d4)
  • core: version-aware read, download and read-only open (418dce0)
  • s3: create a bucket, with versioning and object lock (e2782ab)
  • s3: name five refusals the store used to flatten into one (0296fb3)
  • s3: read and write a bucket's CORS rules, validated here (5ec0199)
  • s3: read and write a bucket's versioning state (96aaa44)
  • s3: read and write object lock, per bucket and per object (d8702fc)
  • settings: a stored switch for Option as the Meta key (bd062dd)
  • settings: the Terminal tab offers Option as the Meta key (438939b)
  • terminal: the Option-as-Meta setting reaches the terminal view (e4257e8)
  • views: add controls that cannot be compressed below their ideal width (0290afb)
  • views: declare a view's size bound as a value (01463f8)
  • views: give CheckboxRow a wrapping form for sentence labels (3c95141)
  • views: let a measurement suspend the frame a bound applies (494fed4)

Bug Fixes

  • actions: close three holes in the one-simple-command and placeholder checks (7c6039b)
  • actions: default a FileAction to the per-file form (4715d8c)
  • actions: derive the refused names, and stop calling the C1 carve-out safe (2f5da8c)
  • actions: encode runsOn in declaration order, not by sorting a Set (12797c1)
  • actions: let an emoji joiner through the sheet's markers, and curl the French apostrophes (a6e9420)
  • actions: refuse a control character in a server value on the remote path (1f90fd6)
  • actions: refuse a control character in the command itself, and correct the reason the codec falsified (3739860)
  • actions: refuse a NUL in a local value, and hold the planner to the Character ban (2493f1c)
  • actions: refuse an empty command at the gate, and aim the menu-item guard forwards (ef31284)
  • actions: say where the previewed plan goes, from the plan and not the action (fe73fac)
  • actions: skip a repeated declaration instead of trapping on it (b90b5ab)
  • app: a BrowserSession reaches a tab only through the call that asks (0465d67)
  • app: a bucket the store says we own is taken, and say only what was read (8eb2146)
  • app: a bucket under Object Lock is not offered a suspension it cannot have (5c6efe6)
  • app: a create sheet built in a failed state came up without the failure (f7f7b57)
  • app: a lock read that cannot find out must not fail a create that asked for no lock (8dd7a58)
  • app: a lock that cannot be read costs only the bucket that needs it; the sheet draws why (0d5c04a)
  • app: a metadata write the storage took is not reported as a failure (04fb515)
  • app: a save's outcome cannot be dropped silently, and the rigid-scan header names its two figures (a1ddd59)
  • app: a version read cancelled between its two requests sends no second one (aa28965)
  • app: a write the storage accepted is not announced in the failure slot (0eb24c7)
  • app: access-list section review round 1, the re-read is pinned and hedged, the form scrolls (7e4a9a4)
  • app: access-list section review round 2, every exit of save() is held, the failed-read figure follows the catalogue (263a98a)
  • app: clip the method name, register the form-off states, say why a mixed document cannot be saved (fd69601)
  • app: hold the compliance warning in place and stop promising a governance undo (6547209)
  • app: keep the user's pane across a save, and name what the form cannot show (e573162), closes #13
  • app: metadata sheet review round 1, a save says whether it wrote, and the audit guard sees the sheet (bab9b80)
  • app: new-bucket review round 1, the source scans express the properties they are named for (f52df76)
  • app: new-bucket review round 2, the runner's initialiser is fileprivate and every mention of the sheet state is counted (c597181)
  • app: new-bucket review round 2, the sheet item cannot be built elsewhere and the runner's mount is pinned as a region (c00e108)
  • app: new-bucket review round 3, the access-level comments say what they do and the type names are counted (182523d)
  • app: pin the disabled rows of the connection menu, correct two comments (aab3783)
  • app: read a created bucket's default retention, and say when it was not set here (fbc984a)
  • app: read a created bucket's lock state even where no lock was asked for (6701a78)
  • app: read back a plain create too, and say when a bucket carries protection nobody chose (5d40b14)
  • app: read back what a create wrote before calling it done (b4b1700)
  • app: say when a chosen date has passed, and pin the guards that pinned less than they looked (54ba09d)
  • app: say why Save is off for a value beside a method, and derive the battery from the causes (32d89fe)
  • app: stop a mode change over compliance, and say when a tick went stale (96f668a)
  • app: the audit log's segment filter is exhaustive, and File Ops lists the four bucket-settings kinds (review Minor 1, Ruling 19) (74e4cfd)
  • app: the CORS pane fills its sheet, and the add-rule button stays put (e0baf89)
  • app: the deleted-files guards fail by name, the wiring has a guard, a failing read is not retried (722bf2c), closes #expect
  • app: the history row tells a retention and a hold, speaks one language, and is declined without a bucket (f3cf602)
  • app: the new-bucket spans end at a brace, and check 4 reads the onChange's own block (72bdda2)
  • app: the Object Lock arm's span ends at its own brace, not at the next func (52871ff)
  • app: the permission offer is composed by Core and the session is installed through the call that asks (9bc883a)
  • app: the question bridge no longer claims a hang its own plant disproved (bee8c25)
  • app: the session slot itself is private, not only the property inside it (4462aac)
  • app: the session-closed mapping keeps its closure on the main actor (2a0ff72)
  • app: the sheet item is declared at the top of ContentView+MenuActions.swift (c0392fd)
  • app: the spans two guards read end at a brace, not at the end of the file (4e120bd)
  • app: the stale-rows line no longer displaces a restore outcome, and four guards say what they hold (dc7eb5b)
  • app: the version row actions say what they know, in the reader's language, and keep their trace (e85dd68)
  • archive: a .gz whose output file exists is refused, as compressing one is (7d2f8c0)
  • archive: a local run over a cut-short stdin is not a finished one (5bb3eed)
  • archive: a remote tar extraction over an existing name is not a failure (03ae1ad)
  • archive: a ZIP name unzip would read as a pattern is refused (c4939ea)
  • archive: both tar skip-existing flags are probed, and a tar with neither is refused (0c8739e)
  • archive: compare names the way the file system does, and cover what stayed green (194f9b0)
  • archive: core.-prefix the catalogue key, and make its test able to fail (a8bea0e)
  • archive: do not run after a cancel that lands during prepare (4b6a281)
  • archive: exit 0 over an unwritten stdin is not a success (0a5c2db)
  • archive: local cancel and timeout become typed results, and the status paths are pinned (e976859)
  • archive: make the plan and the listing inside the activity, so a teardown reaches them (e23dc0b), closes #2 #4
  • archive: prefix the archive name ./ and pin the untested plan paths (2b4fbdb)
  • archive: the extract sheet does not offer a .gz extraction the plan refuses (8ab1365)
  • backlog: an exit code that was never the committed line's, and a quote that stopped early (ef7a8cc)
  • backlog: the bold/no-bold pair states its delta, because the collision is an identity (bcf1ac1)
  • backlog: two commit-census commands that could not run as committed (a70eb13)
  • cli: the --user help says to pass anonymous for anonymous FTP, because an empty USER is refused (e03f268)
  • cli: the FTP flag guard reads a blanked view, and --security moves the port like the form (9fe3a7b)
  • compare: a closed comparison window makes its tab forget the comparison (65e3f87)
  • compare: a row's identity is its position, not its path (325e285)
  • compare: a settle in flight is cancelled when the comparison is (8121566)
  • compare: a torn-down comparison keeps its result and loses its connections (9da0d2f)
  • compare: an unreported type is not a special entry (2362fe1)
  • compare: cancelling the awaiting task cancels the fetch (ddcee7c)
  • compare: correct the plan and spec from the pre-flight scan (c863d9e)
  • compare: diff lines by their bytes, not by String equality (eb3e456)
  • compare: give a folder pair its own state instead of same (b328df7)
  • compare: give a row each side's own path instead of one joined twice (50058a2)
  • compare: guard the released connection by reference, refuse starts during teardown (8d33bb1)
  • compare: keep a diff alive through a walk cancel, pin the right-side ceiling (fbee913)
  • compare: pair normalized names only among unmatched leftovers (d937854)
  • compare: pin the two side gates' polarity, count case names not keywords (92547fa)
  • compare: read the far side's kind from the other pane's listing (729d805)
  • compare: refuse a side that is not a file, gate the menu-bar door, make the routing a value (479dc1b)
  • compare: route both panes through one menu handler, name what the far match measures (8ca6d63)
  • compare: say what the listing could not, withdraw an unmeasured claim (6f8d089)
  • compare: the diff refuses what is known unsuitable, not what is unreported (4ea83d7)
  • compare: the overview claims only what the listing measured (08a8cbe)
  • compare: the refusal no longer names a special entry (a5734c1)
  • core,app: a permission probe that outlives its tab dials nothing (9f7e885)
  • core: a data channel's close is idempotent, and the vault prefers an (55a7765)
  • core: a dropped FTP transfer is a connection failure, so the queue can resume it (4d4b01c)
  • core: a kind change clears every backend block, and an FTP host carries no user-info (ba97568)
  • core: a passive reply's host is ignored, not compared (Ruling T6.2) (4ac4373)
  • core: a plain-FTP diagnosis is skipped before the secret is read, and the blank-port case changes the mode (e83184f)
  • core: a preliminary reply is not an answer, and TYPE I is checked (9a8f49f)
  • core: a protected transfer sends its command before awaiting the data handshake (2be4618)
  • core: a raw FTP failure is classified and rendered on the queue and the browser, and a refused login keeps its identity (43e26f7)
  • core: a read stream is pulled, so abandoning one really stops the download (2bb78b9)
  • core: a refusal that is not about the certificate stays the refusal the server wrote (714779e)
  • core: a refused data connection that presented another certificate is reported as such (8af90c0)
  • core: a returned lease refuses to run a transfer, and a second release frees nothing (28a02e3)
  • core: a thrown drain reads the reply it owes, and the turn's span is pinned (4ec7b64)
  • core: a TLS session comes round again once its holder has closed (246625f)
  • core: a transfer owns both its replies, and a read is bounded by (0b433b2)
  • core: a version download warns before it restarts, and the review's counted and withdrawn figures are accounted for (ebc1b16)
  • core: a wait for a transfer slot answers cancellation (f4a5211)
  • core: correct a false coverage claim, a misattributed recount and the version-id doc (2948415)
  • core: deleted rows the silent refresh could not refresh are said to be out of date (103c8ac)
  • core: deletedEntries drops a key equal to the prefix, as the plain listing does (fe6e9ae)
  • core: deletedEntries enforces the one-level reading itself instead of asking the store (305519c)
  • core: deletedEntries is documented one level deep, and the review's smaller findings (f2fd2ea)
  • core: deleteVersion refuses a marker id, version writes name the bucket they were asked about (a04688a)
  • core: drop markerQueryValue, refuse a truncated page with no continuation (9ceb756)
  • core: FEAT's MLST is read as MLSD, so a real daemon is listed with MLSD (ee679b8)
  • core: FTP name guard pinned on all three branches; blank lines skipped by MLSD too (da45d12)
  • core: FTP reply errors carry no server text and the types go internal (df69fac)
  • core: metadata review round 1, a prefixed custom key is refused and the inferred shapes say so (b206f0a)
  • core: only a 2xx is a completed command, and a fired reply bound closes (0fc64a3)
  • core: only an empty FTP listing line is skipped; a line of spaces is refused (c0b3eb4)
  • core: openConnection carries the transfer-slot count, so the FTP pool is the user's number (e3e1642)
  • core: pin the kind tolerance, report what an import skipped, and correct four stale comments (7d88251)
  • core: publish the version types' inits, withdraw the order claim (352e9fc)
  • core: restore the FTP host colon rule and record the stored-host exposure (437724b)
  • core: the 412 sentence drops the ordering it cannot know (00ae83a)
  • core: the ACL guard's declaration scan is a substring, and its scope claims are true (cb5d51d)
  • core: the ACL write guard is an exact set over all of Sources (15eb697)
  • core: the command turn's wait answers cancellation, and the last unbounded Task.value gets its bound (cb39ab8)
  • core: the dial mapper logs an FTP failure in fixed English, not in the user's language (981e56e)
  • core: the FTP error conversion moved to every operation's edge, so a lost connection keeps its job (20105d4)
  • core: the FTP host comment stops claiming a safety it has not got (8e24418)
  • core: the FTP host comments stop outliving what the tree supports (8a123fb)
  • core: the FTP pool closes its connections concurrently, and three comments name the stage's real bound (3d03c4b)
  • core: the pin store is named out loud, the failure set is the (92cc90b)
  • core: the read-back's own failure is an unconfirmed write, not a failed one (25b0451)
  • core: the signer collapses sequential spaces in a canonical header value (bc68af0)
  • core: the trust-store log line's host and port are private, not public (b5bea61)
  • file-actions: stop clipping the editor sheet in Polish and guard its width per language (5b9c120)
  • notices: record all three forks, and close the guard that hid the third (f4cae77)
  • probe: ignore warning-severity issues, keep the log it points to (7269a9f)
  • probe: read every verdict against a control run on the unplanted tree (7b735ab)
  • s3: ask whether a bucket has object lock, restate why it is never enabled (b418eb8)
  • s3: clear CORS with an empty list, keep the raw document, name the refusal (03b1589)
  • s3: hold the bucket-mode refusal to its wire, and say what the tree does (e583319)
  • s3: let an account with no buckets connect, so one can be made (cdec5a2)
  • s3: name a per-key refusal inside a 200 DeleteResult too (eebe832)
  • s3: one protection parameter for createBucket, and named refusals for a taken name (37ba7ed)
  • s3: sign a Content-MD5 on the versioning PUT (57a8364)
  • s3: the connection's session keeps no response cache, so a write never carries a read's validators (eb84da0)
  • settings: the Option-as-Meta footer promises only what the gate keeps (dbb98a3)
  • tabs: clip the tab strip, to answer where the colour above it comes from (e51b2ae)
  • test: the catalogue-coverage test reads a main-actor property (90d4cda)
  • test: the FTP flag-derivation guard was reading a comment, not the code (9ed7e7d)
  • test: the FTP save tests no longer print the password from their #require (f157dbd), closes #expects
  • the backend dial in slotsThroughTheBackend takes the loopback deadline, and the 2026-11-09 record is corrected (adb5c2f)
  • views: attribute the resizable-container ties and name the search mode (2e7d0b9)
  • views: make checkbox and radio rigid at the ideal, pin the floor's value (2c5bcc3)
  • views: state that a view's bound is main-actor isolated, and stop reading it from a nonisolated context (1b79c27)
  • views: stop the resizable containers squeezing their localized controls (be7ab21)
  • views: widen the key generator's bound from 380 to 420 (72a1009)
  • webdav: a Depth-0 PROPFIND no longer blames the folder listing (1b3c3a6)
  • webdav: a read's 412 no longer reports a move it never made (6782e2d)
  • webdav: the 412 sentence stops naming causes it cannot know (28a3989)
  • window: keep the size of a window that has connected when its connection closes (3be2883)

Performance Improvements

  • app: building the version table's rows works each state out once and searches for no row (5539440)
  • compare: flatten the LCS table, and fix what the record said about it (acbb370)
  • compare: measure the line diff's cost and bound it in lines, not bytes (18cbe9f)
  • core: ask a bucket's Object Lock state once per deleteTree, not per refused key (452191a)
  • core: bound deleteTree's probing on a bucket that really is locked (0d67aed)
  • core: bound deleteTree's probing when a bucket's lock state cannot be read (9e8755d)
Source: README.md, updated 2026-11-09