New MacOS App: Syncthing Menu

Hi, folks.

This post is about Syncthing Menu.

The official Syncthing app for MacOS has been excellent in most ways but it isn’t keeping pace with regular Syncthing releases (which is the prerogative of the author/owner). Because the Syncthing engine is embedded in the app, it requires a rebuild each time Syncthing is released and these rebuilds have been sporadic.

I’ve wondered if it’s possible to build a MacOS app that separates the host app from the Syncthing engine, and that’s what I’ve done here.

Introducing Syncthing Menu.

This is a frugal app with no opinion about Syncthing semantics. There are other solutions if you want selective sync or anything else that impacts Syncthing behavior. This app is simply a host that downloads and runs Syncthing and allows Syncthing to keep itself up to date. It provides a menu item with simple status and small (but growing) list of minor, helpful features.

The app is fully open source and is signed and notarized by Apple (meaning Apple scans it for malware).

You can read about and download it here: GitHub - gtunes-dev/syncthing-menu: A frugal, native macOS menu-bar app for Syncthing · GitHub

@calmh - Thank you for your continuing exceptional work on this project. I’ve tried to stay within the bounds of the license and usage guidelines. I use the Syncthing icon in two specific places to refer to Syncthing itself and not the host app. The about box notes Syncthing and Kastelo copyrights. If you have any concerns or suggestions, please share them with me here or privately.

All feedback is more than welcome. Thanks for reading!

4 Likes

Quick note that I changed my forum username from “zendnez” to “gTunes” for consistency with my github profile, from which this app is published.

Great app!

Thanks a lot.

1 Like

Thanks for the kind words!

I just released version 0.2.0. Some minor user-facing changes but the primary changes relate to hardening of the code that verifies the hash and developer signature of the Syncthing binary.

I’ll let this bake for a couple of days and if no issues come up, I’ll promote it to 1.0.

It was nice to see the official MacOS Syncthing recently get an update. For those of us that like the convenience and actionability of a MacOS menu, but also want to stay on current releases, this app is hopefully a nice option for people.

Hi! First of all, thank you for creating this app. I’ve been using it for a few days now and I really like it. The idea of separating the app from the Syncthing daemon is excellent, and the UI feels very native on macOS.

I did notice one issue, though. According to the README, the menu bar icon should change depending on the current state (idle, syncing, paused, etc.). On my Mac, the menu bar icon never changes – it always stays the same, even while files are actively syncing. The transfer window correctly shows the live activity, so syncing itself works perfectly.

I’m running the latest version of Syncthing Menu on macOS Tahoe. Is this a known issue, or is there something I should check?

Apart from that, it’s a fantastic app. Thanks again for your work!

1 Like

Thank you for the very kind words. This started as a proof of concept but it’s actually a fairly robust and complete app now.

You note that you’re running the latest Syncthing Menu. I did fix a couple of issues related to detection of updates. The current Syncthing Menu version is 0.3.0 - can you confirm that this is the version you’re running and, if not, update to the latest from the Settings dialog and try to reproduce the issue?

I think there may be some remaining issues with state detection - if you’re on the latest, I’ll take a look. It should work fine on Tahoe (I have family and friends running it on that). It also runs fine on the betas of Golden Gate.

The latest version of Syncthing Menu introduces an “Activity” window which shows recent sync activity. I haven’t documented this yet but it’s not hard to find or figure out. I’d love to hear feedback, comments, and issues on!

Thanks again!

Thanks for your quick reply!

I did some more testing and I have to correct my original report a little.

I’m running version 0.3.0.

The menu bar icon does actually change state, but the difference is very subtle and easy to miss. Also, the “syncing” icon only appears for a very short moment before switching back, even when files are still being transferred.

Because of that, I initially thought the icon never changed at all.

Apart from that, everything else works perfectly. I especially like the new Activity window—it’s a really nice addition.

Thanks again for your work on this app!

It might be worth making the menu bar state changes a bit more visually distinct, as they’re currently quite difficult to notice at a glance.

1 Like

Hi, @chris87 . Thanks for the follow up and the additional information!

I replicated this. I also found multiple scenarios in which the menu bar state didn’t change at all.

I just released version 0.3.1. It’s a fairly significant overhaul of the activity detection and reporting code including the activity window and the menu bar.

Activity window status is now more accurate and granular. Some status used to depend on folder state, it’s now file-based. So it shows accurate pending, syncing, complete state at the file level rather than in folder-granularity batches. The menu bar icon is now much more accurate and has a minimum display time so it should flash so quickly that the state changes can’t be seen.

I’ll look into this. I’m finding it challenging to get these icons into the shape I’d like them to be in. They need to convey the app’s identity as well as Syncthing status and availability update. That’s a lot of information and not a lot of real estate.

Version 0.3.1 should be available - you can check/update in Settings.

Thanks you again for the feedback, kind words, and for using the app!

@gTunes nice to see alternative implementations. There is a good reason why the macOS wrapper and seperate daemon are bundled and lagging behind some times. The reason is compatibility and rebustness. When something changes in the Syncthing daemon REST API, I can ship a new version or bugfix. So when people report bugs, the versions are symmetrical. And as the owner of syncthing/syncthing-macos I need to catch up on life sometimes. I read all Syncthing changelogs, when it is critical I will update immediate. Currently the syncthing-macos application is sort of in maintaince mode. No big changes or additions will be made as I have already a raw prototype in pure Swift and SwiftUI (with very thin ObjectiveC binding to old APIs/older macOS support). I write software/firmware for my day-to-day job, so in the evening I’m not almost happy to fix all github issues raised. But keep up the good work !

P.s I looked very short at the syncthing-menu repository and looks neat. It’s sort of what I have in mind for the not announced “syncthing-macos-ng” (next-gen) project. To modernize and make it more maintainable. And you have it licensed MIT which I prefer. If you want @gTunes can u send me a DM here for eventual collaboration in the future ?

Hi, @xor-gate. Thanks for your comments and kind words!

I’m very grateful for the work you’ve done on the MacOS Syncthing app. I’ve used it for years and it’s been great. I support a small number of people who use Syncthing on Mac and your app has been a big part of that.

I do, of course, understand that it’s a best effort and I sincerely do appreciate the work you do.

You’re aware that I’ve raised concerns about the MacOS app not keeping pace with Syncthing releases for a while. I hope you and I can continue to respectfully disagree about whether or not this is the right thing for the “official” Syncthing app. In my opinion, it’s not. With only positive intent, I decided to stop complaining and explore an alternative :slight_smile:

My primary goal with Syncthing Menu was to explore making Syncthing updates independent from my app’s updates. I have that working. Sparkle for Syncthing Menu updates, Syncthing itself for its own updates.

A case in point from today:

If Syncthing breaks the APIs I use, then my app can break. I have update guards in place but I understand that it’s an issue. It’s a managed risk, though - there are numerous apps that have taken a dependency on Syncthing’s APIs and the team has an understanding of this.

I’m happy to collaborate further and you’re, of course, welcome to do as you like with Syncthing Menu sources!

1 Like

Hi, @chris87

I re-worked the menu bar status icons in version 0.3.3. I was able to make the outer circle a bit bigger and re-worked the contents. It’s not perfect but it’s much better. I hope the difference will be apparent.

Thanks for the quick update!

I’ve just tried version 0.3.3, and I think the new icons are a clear improvement. They’re much easier to notice now and the different states are easier to distinguish at a glance.

Thanks again for listening to the feedback and for making the change so quickly. I really appreciate it!

I realise I may be an outlier here, but I think it would be neat to be able to run the menu with the existing Syncthing install I already have. (i.e., as opposed to it having a --home under Syncthing-menu etc.)

1 Like

Interesting. Can you explain more about the problem you’re interested in solving?

Currently, it downloads syncthing.exe into /Users/{users}/Library/Application Support/Syncthing Menu/bin

Are you interested in having it run a non-release version of syncthing or something similar? If you want to play with that, you can drop any version of syncthing.exe into that directory and it should work fine.

Or is it more of an aesthetic thing or even migration?

I should also note - Syncthing Menu and the official MacOS Syncthing app can run side by side and don’t share configuration.

It’s more that I’m usually running some random development version, using our launchdaemon setup, but also it seems neat to have the menu thing. Maybe it’s out-of-scope for it to talk to a binary it didn’t launch itself, but it seems like it could be possible to “just” point it at a config dir (simplest) or API address+key (more advanced) and have it talk to that instance.

Got it.

Let me think about it a bit. I’ll be travelling for a few days and won’t look until next week.

A good chunk of what Syncthing Menu does is related to process management including spawning and monitoring the syncthing.exe process. The most straightforward approach would be to add some sort of advanced Syncthing mode where I just connect to the running process with an address and API key. I wouldn’t spawn (or quite) the subprocess or do anything related to Syncthing updates.

It’s a cool idea. You’d get the visibility and control of the menu (and the Activity view which I think is nice) but no process stuff. You could launch as many instances as you like and point it at whichever one you want.

Would that do it?

1 Like

@calmh - The feature you requested was more straightforward than I anticipated. It’s in build v0.3.4.

It works only with localhost instances - you provide the port and the API Key. Here’s a brief description:

  • In “Settings…” you can toggle between “Syncthing is managed by this app” and “Syncthing is managed by me”
  • When set to managed by me the following is true:
    • I don’t spawn the process
    • I don’t poll for Syncthing updates, display their availability, invoke them, or squelch them in the Syncthing Web UX as I do in the default mode
    • I will never download a Syncthing binary in “managed by me” mode. When you initially run the app, it will be in the default mode and Syncthing will be download to Application Support/Syncthing Menu/bin. If you toggle into “…managed by me” and delete the binary I downloaded, it won’t get downloaded again provided you don’t change the mode
    • I connect to the user-specified port. There’s UX that reports various connectivity states. As long as the Syncthing Menu is running, it will always be able to connect to your custom Syncthing instance when it comes up
    • All of the menu functions work in the new mode
    • The Activity window works in the new mode
    • Toggling into “managed by me” causes the child Syncthing process that I spawned to quit. Toggling back into “managed by this app” causes it to be spawned
    • Syncthing Menu app polling and updating continues to work as always based on user prefs. There are no differences in these behaviors based on the Syncthing mode

Screen shots:

It’s an interesting feature. Thanks for the idea!

1 Like

Hi all and @gTunes ,

There is no good or bad choice about the feature if Syncthing daemon should update or not. In the early days of syncthing/syncthing-macos the Syncthing Daemon auto update was enable, but after two years or so I made the decision to ship symmetrical versions (which has its own problems). For the end user it “feels” like one application. And for bug reporting it is also deterministic. For the ideas of “syncthing-macos-ng” both options can be present but by default it should be version locked. It could be hidden “behind” an advanced tab to let it update independently. And as last I ship the daemon and sign the .app bundle so its not good to have different file signatures in the bundle after it has been installed (as this can trigger a malware detection of the macOS system, as the bundle was modified).

I’m not 100% sure why you implemented fetching an update from github. As the daemon itself has an update mechanism built-in. But probably you have a good reason for that.

To make sure the bundle notarized and signed signature will not break I did place an updated daemon in ~/Library/Application Support/Syncthing/syncthing/syncthing or so (which can be the unpacked zipfile from github).

@gTunes you are not complaining at all, different ideas, different people, and specific solutions for specific “problems”.

It’s a very busy summer time with my garden, so not much time for programming in spare-time. Probably I should write up my ideas the direction I want to go with the syncthing/syncthing-macos project and what it does, and what it doesn’t. The idea of a simple and “frugal” application still persists. Which I like also about the Syncthing Menu. Features which are not present don’t break, or people don’t “complain” about.

Have a good one, and keep up the good work.

1 Like

This is not accurate.

On first run, I download the latest release Syncthing build from github. I fetch the Apple-signed universal binary. I verify the SHA-256 hash and I verify that the Developer ID signature is Kastelo AB. If the validations fail, I don’t run it.

The update model is a little more complicated. I wanted to squelch the update notifications in Syncthing so I run it with STNOUPGRADE=1. I directly poll the Syncthing upgrade server at https://upgrades.syncthing.net/meta.json to determine if an update is available. When it’s time to actually do the Syncthing update (an update is available and the user has enabled auto updates or explicitly clicks “Update”), I invoke the Syncthing API and let it do its own update.

So…other than the initial download, I let Syncthing do its own heavy lifting.

Syncthing Menu is signed and notarized as part of the github workflow that builds it. It uses Sparkle for updates.

To be honest, I only partially understand the points you’re making about versions. I very much understand the issues we can all have with work, life, family, hobbies, health, and so on. I don’t agree that an “official” platform build should version drift. I think I figured out a way to separate the concerns that works and while it does ask the user to understand that Syncthing Menu runs Syncthing, I think that’s a reasonable approach for this particular user community. I suspect that anyone that can figure out Syncthing devices, folders, topologies, filters and the rest can wrap their head around the concept of a wrapper Menu app that runs the official Syncthing app. I suppose only time will tell, though :slight_smile:

I do hope I clarified the update mechanism. The details of what I did for process management are also interesting - at least to me. I use posix_spawn but had to experiment with declaiming to get it to work well with Apple’s privacy model. It does seem to work, though!

And one more thing - after 30+ years in various engineering roles at companies big and small, I retired early and now have plenty of time to play with hobby projects. It’s nice :slight_smile:

Hi @gTunes, thanks for clearing this up in a very detailed post. I didn’t had time to look into the code/implementation how it was done. I’m not “attacking” you if the upgrade mechanism is not good, but I understand why you choose to “side-channel” an update mechanism. You can indeed verify the signatures with the tooling if the executable is trusted. I also have an engineering role as DevOps, Software and Embedded systems tasks. So we have some things in common probably. It’s good to read you use the “upgrade portal” JSON file from the project itself and don’t rely “100%” on Github infrastructure. Supply chain attacks are a real thing nowadays. And as Syncthing processes private and confidental data we should be aware of it and keep that in mind. I would dream of having 40h a week busy with hobbies. But 32h at the office and electronics lab is also not to bad.

Could you send me a direct message on the forum or via github mail so we can look into future collaboration so the syncthing/syncthing-macos project will not “bleed to death”?