Skip to content

Releases: superuser-miguel/foresight

Foresight 1.0.1

Choose a tag to compare

@superuser-miguel superuser-miguel released this 19 Sep 02:25
v1.0.1

Two fixes from a month of daily use on 1.0, and a newer rsync.

New Job after a remote transfer left a dead window

After syncing to or from another machine, New Job left both remote buttons greyed out and the destination row still reading "Remote folder" — there was no way to start another job without restarting Foresight. The lock that protects the endpoints during a transfer was never lifted after it. Fixed, and the headless checks now hold a real transfer open to prove it stays fixed.

Exclude rules that silently match nothing

This one looked like data loss, and wasn't — but it deserves a plain explanation.

In an rsync filter rule, a leading / means the top of the transfer, not the top of your disk. So with a source folder Photos:

You type What happens
private, private/, /Photos/private excluded — stays put
/home/me/Pictures/Photos/private matches nothing
/private matches nothing

rsync accepts the last two without a word: no warning, exit 0. The folder you meant to keep back transfers like any other — and with Move on, it is then removed from the source. Every file arrives safely at the destination; it just isn't where you believed it was. (Turning on Copy contents swaps which of /Photos/private and /private works, with no change to the rule.)

Foresight now catches this two ways:

  • Before anything runs. A rule that cannot match gets a warning on its row saying why, and — when it can tell what you meant — a Fix button with the corrected rule. The collapsed Filter rules row says so too.
  • From the dry run. Dry Run now reports what each rule matched — matched 12 paths, or matched nothing — and names any that matched nothing. This also catches a perfectly valid rule that simply matches nothing in this folder.

And with Move on, Start checks first: if an exclude isn't holding anything back, Foresight stops and asks, the same way it already does before mirror deletions.

One limit: when the source is a remote machine, the far end does the filtering and reports nothing back, so only the first check applies there.

rsync 3.5.0

The bundled rsync moves from 3.4.4 to 3.5.0, which fixes 33 security issues — including one in the code path behind Move. Its output formats are unchanged, and because 3.5.0 reworked how rsync walks paths, it was tested inside the sandbox against real document-portal folders before shipping.

Also

  • The preset format is untouched — the 1.0 promise holds.
  • For contributors: build-aux/run-dev.sh runs a dev build without installing it, so it can't take over a published install.

Upgrading

If you installed from the repository:

flatpak update

On a bundle install, switch over once and updates come automatically from then on:

flatpak uninstall --user io.github.superuser_miguel.Foresight
flatpak install --user https://superuser-miguel.github.io/foresight-repo/foresight.flatpakref

Foresight 1.0.0 — remote sync over SSH

Choose a tag to compare

@superuser-miguel superuser-miguel released this 11 Aug 02:08
v1.0.0

Remote sync over SSH, and filter rules you can order.

This is 1.0 — not because a feature count was reached, but because the advertised surface is now complete and the formats Foresight saves have stopped moving.

Sync to another machine

Either the source or the destination can now be a user@host:/path endpoint. (Not both — rsync doesn't allow it, so the two controls lock each other out and tell you why.)

Authentication uses the keys already in your desktop's SSH agent. The agent stays outside the sandbox and only signs on request, so no private key ever enters Foresight and your ~/.ssh is never read. That's why the permission added for this is --socket=ssh-auth and not access to your key directory.

Host-key trust is Foresight's own, kept beside your presets. The first time you connect to a machine you're shown its fingerprint and asked — never a silent trust-on-first-use. After that, strict checking means a key that doesn't match stops the transfer, and a key that has changed says so rather than just failing.

IPv6 link-local endpoints work, scope id and all, which is what syncing to a phone over a hotspot needs.

Filter rules are ordered

Advanced → Exclude patterns is now Filter rules: one list where each rule is an Include or an Exclude, with arrows to move it.

Order is the whole meaning. rsync obeys the first rule that matches, so putting *.jpg above * copies only JPEGs — while putting build/ above *.jpg keeps everything in build/ out, even from the include. A UI with a separate includes list and excludes list can express the first of those and never the second, which is why this is one ordered list instead.

Also

  • When a remote transfer fails, the reason SSH gave is now shown with the failure. Previously only rsync's unexplained error (code 255) made it out, and the actual cause — "Permission denied", "REMOTE HOST IDENTIFICATION HAS CHANGED" — sat in the log.
  • The in-app capability list no longer claims SSH is unimplemented.

The 1.0 promise

The preset format is frozen. It changed three times on the way here; from now on its on-disk shape is a compatibility promise, and every reader for every older encoding stays permanently. Presets written by any earlier version — including 0.1.0 — still load, and always will.

Upgrading

If you installed from the repository:

flatpak update

On a bundle install, switch over once and updates come automatically from then on:

flatpak uninstall --user io.github.superuser_miguel.Foresight
flatpak install --user https://superuser-miguel.github.io/foresight-repo/foresight.flatpakref

Foresight v0.1.2 — exclude-rule editor and a preset save fix

Choose a tag to compare

@superuser-miguel superuser-miguel released this 29 Jul 17:50
v0.1.2

An exclude-rule editor, and a fix for presets that quietly failed to save.

Exclude rules are a list now

Advanced → Exclude patterns was a single space-separated field, which made a whole class of rule impossible to write: My Documents/ split into two rules, My and Documents/, and neither matched anything. Since Foresight hands rsync an argv vector with no shell in between, that splitting was self-inflicted — nothing downstream ever needed it.

It's now a list: one row per rule, each with its own remove button, added by typing a rule and pressing Enter. The row header shows how many rules are active without opening it. Rules are trimmed of surrounding whitespace but otherwise passed whole, so My Documents/, Photos [2024], and weird;name all work. Duplicates are refused rather than silently doubled.

Fixed: presets that looked saved but weren't

A preset whose name contained [, ], a tab, or a line break was silently discarded on save. The name was used as a config-file section header, and those characters aren't legal there — so nothing was written.

The failure was invisible: the preset appeared in the dropdown, applied correctly, and kept working for the rest of the session. It was simply gone at the next launch, with no error anywhere. A preset called Photos [raw] was enough to trigger it.

Preset names are now stored as ordinary values, so no name can be unstorable.

Upgrading

If you installed from the repository, this arrives with:

flatpak update

If you're on a bundle install, switch over once and updates come automatically from then on:

flatpak uninstall --user io.github.superuser_miguel.Foresight
flatpak install --user https://superuser-miguel.github.io/foresight/foresight.flatpakref

Existing presets load unchanged and are migrated to the new layout the next time you save one. Nothing to do by hand.

Two rsync behaviours worth knowing

Both are correct rsync, and both surprise people:

  • Excluded files already in the destination are protected from Mirror deletions. If you exclude *.tmp, old .tmp files sitting in the destination are kept, not removed. Add --delete-excluded under Extra arguments if you want them gone.
  • A rule can't end in a space, since surrounding whitespace is trimmed. A file literally named "report " can't be excluded by name.

How it ships

Sandboxed, reaching your files only through XDG portals — no --filesystem=home, no blanket host access. rsync 3.4.4 is bundled and version-pinned. No telemetry.

Built offline from the GPG-signed v0.1.2 tag against a vendored crate graph. Verify with git verify-tag v0.1.2 (key D67DB8E03D50A8C0).

Still to come

  • Include rules — --include alongside excludes, so a rule can carve an exception out of a broader one.
  • Remote sync over SSH. Network access and an ssh client are already in place; still needed are agent forwarding so keys never enter the sandbox, a host-key trust story, and the endpoint UI.

Full changelog: v0.1.1...v0.1.2

Foresight v0.1.1 — predictable folder placement

Choose a tag to compare

@superuser-miguel superuser-miguel released this 29 Jul 14:37
v0.1.1

A bug-fix release, and it's one worth updating for: a folder you add now lands in the destination as that folder.

The fix

Previously, if a job's source was a single folder, Foresight handed rsync the trailing-slash form (rsync -a /photos/ /backup) — which copies the folder's contents into the destination rather than the folder itself. So dropping Photos onto a backup drive scattered its children loose across the drive's top level, mixed in with whatever was already there. The only way to get the folder you expected was to create it in the destination first.

Now every source is passed to rsync verbatim. Photos arrives as Photos. A file arrives as that file. This applies identically whether you drag items in, use Add Folders, or use Add Files — all three go through the same code path, and one function is still the only place a path becomes an rsync argument.

rsync's contents-mode is a legitimate workflow, so it isn't gone — it's just something you now ask for, under Advanced → Sync folder contents. It's only available when the job has exactly one folder as its source, since a trailing slash is meaningless otherwise.

Worth noting: nesting is also the safer default for Mirror deletions. With the folder passed verbatim, --delete can only prune inside the subfolder this transfer actually writes, never the wider destination.

Also in this release

  • What Foresight Can Do now opens with a plain-language note on where your files land, so the placement rule is stated in the app rather than learned by surprise.
  • The change is covered by unit tests on the argument builder plus an end-to-end test driving real rsync, which asserts the contents don't spill.

Installing / upgrading

Foresight now has its own signed repository, so this is the last release you
have to install by hand — from here on, new versions arrive with flatpak update:

flatpak install --user https://superuser-miguel.github.io/foresight/foresight.flatpakref

That adds the remote and installs the app in one step. If you already have 0.1.0
from a bundle, uninstall it first (flatpak uninstall --user io.github.superuser_miguel.Foresight) —
a bundle install has no origin, so it can't be upgraded in place.

The Foresight.flatpak bundle below is still published for offline or air-gapped
installs, but it stays un-updatable by nature.

Saved presets carry over. Presets saved under 0.1.0 load with Sync folder contents off — matching the new, predictable behaviour rather than silently reproducing the old spill.

How it ships

Sandboxed, reaching your files only through XDG portals — no --filesystem=home, no blanket host access. rsync 3.4.4 is bundled and version-pinned. No telemetry.

The bundle is built offline from the GPG-signed v0.1.1 tag against a vendored crate graph. Verify the tag with git verify-tag v0.1.1 (key D67DB8E03D50A8C0).

Still to come

  • Remote sync over SSH has no UI yet — the engine and sandbox already carry it, only the user@host:/path endpoint is missing.
  • Excludes are a single space-separated field, not a managed list.

Full changelog: v0.1.0...v0.1.1

Foresight v0.1.0

Choose a tag to compare

@superuser-miguel superuser-miguel released this 21 Jul 18:43
v0.1.0

The first release.

Foresight is a GNOME-native front-end for rsync built around one idea: every sync can be previewed as a grouped change list — created, updated, deleted, attributes-only — before a single byte moves.

It never reimplements rsync. It composes an argv vector, spawns the bundled rsync as a subprocess, and parses its output into structured events. No shell strings are ever built, and the engine version is pinned — the pin is the behaviour contract.

What's in it

  • Dry-run preview as a grouped change list, from a real rsync -a -n -i run
  • Multi-source jobs — files and folders from different locations, with per-item remove and drag and drop
  • Live transfer — progress bar, current-file label, a structured streaming log (one typed row per file and message), and cancel at any time
  • Mirror deletions asks you to confirm the exact list of files it will remove
  • Advanced options — move (--remove-source-files), unit-aware bandwidth limit, excludes, and a free-form extra-arguments field — saveable as presets
  • What Foresight Can Do — an in-app inventory of every rsync flag this build exposes, kept in lockstep with the code by a test, plus the bundled rsync --help

How it ships

Sandboxed, reaching your files only through XDG portals — no --filesystem=home, no blanket host access. rsync 3.4.4 is bundled and version-pinned. No telemetry.

Known limitations

  • Remote sync over SSH has no UI yet. The engine and sandbox are already verified to carry it — only the user@host:/path endpoint is missing.
  • Excludes are a single space-separated field, not a managed list.
  • Updates mean downloading a new bundle; a self-hosted repo for flatpak update is next.

Install

Download Foresight.flatpak and run:

flatpak install --user Foresight.flatpak
flatpak run io.github.superuser_miguel.Foresight

If you don't have the runtime yet: flatpak install flathub org.gnome.Platform//49

The tag v0.1.0 is GPG-signed (key D67DB8E03D50A8C0). The bundle is built offline from that tag against a vendored crate graph.