As I mentioned in my Medium post (in Chinese), I’ve been working on a side project called Yomu (and in case you wonder, the name is an Otaku term from the anime 境界の彼方).

Plan 1.0

Yomu was originally designed to be an alternative for Finder, the default file manager on macOS. It was specifically designed for developers, allowing them to run custom shell scripts/AppleScripts from some folders.

For example, users can run Git related commands right in the Yomu window if the current folder contains the .git directory. Similarly for folders containing package.json or Podfile, users will be allowed to run NPM/yarn or CocoaPods related commands from the Yomu window.

This can save us the time wasted in switching from Finder to Hyper/iTerm and cding to a specific directory, and thus optimize we developers’ workflow.

Some other features, like toggling between GUI mode and CLI mode, opening current directory quickly in text editor or terminal with hot keys, as well as FTP/SFTP/S3 support were also planned. But these are not the core feature of Yomu so we won’t be focusing on them in this post.

The Problem with This Plan

I was pretty confident that a file manager like this could be a great product, but after I worked on it for a few days I started to see its problem. I found myself spending huge amount of the development time implementing things like dragging and dropping files between Yomu and Finder, renaming/deleting files, refreshing the file list after the directory’s changing of content, etc.

All of these are necessary and they are just the very minimum features for a file manager. Implementing them all by myself are tedious and problem prone, ending up with a poorly crafted product.

Plan 2.0

It occurred to me that all the features mentioned above have already been perfectly implemented in Finder. So why was I writing them myself if I can simply add in the extra features I want to the default Finder? Stupid me!

It turns out that Apple has already provided developers with a way to add in extra features to Finder, and that is Finder Sync Extension.


Note that the way I am using Finder Sync Extension is not the way Apple intended. Finder Sync Extension is designed to be used to sync local files with data on a remote server. Apple would probably reject your app’s submission to the Mac App Store if you are doing something like this. I have no plan to release it as a MAS app so it’s not a problem for me.

Architecture

Yomu is consists of a container app and of course the Finder Sync Extension. The container app is not sandboxed, since it needs run AppleScripts/shell commands and launch at login. The Finder Sync Extension, on the other hand, is sandboxed, otherwise the OS would refuse to attach it to Finder.

The extension adds a tool bar item to the Finder tool bar, and when clicked, a context menu which is generated dynamically according to the content of current directory will be shown. Each menu item in the menu is associated with an action that can be performed in the current directory, and when the user select one of the menu items, the extension will notify the container app using CFMessagePortRef. Upon receiving the notification, the main app will then execute AppleScripts or shell commands according to the user selection.

The information of all the available actions as well as their associated commands are saved in a directory inside the extension’s sandbox container, so the user can hack/tweak them if necessary. The container app also provides the GUI needed to edit/create custom actions right in the Yomu window, allowing users to create new actions effortlessly.

Current Progress

I’ve finished a quick prototype of the Finder Sync Extension and the core features of the container app. Custom actions can now be run from the Finder tool bar item, but the UI and script editor of the container app hasn’t been implemented yet.

The demo GIF below shows how I run yarn install in a directory containing package.json, as well as cd to the current directory in Hyper, all by simply clicking on the Finder tool bar item menu.

Future Work

  • Create the UI for the container app
  • Implement the script editor
  • Add more hot-key support and implement auto launch at login
  • Purchase a domain name and create a landing page
  • Polish it and invite some beta testers

I plan to get some profit from this app, so it would not be open source to GitHub for now.

Lessons Learned

  1. When you get a side project idea, consider it thoroughly before doing any actual work.

    Try to think of several approaches to achieve the result you want, then compare them carefully and choose the best solution to work on.

  2. Swift is still not production ready, IMHO.

    I tried to use Swift to develop the Plan 1.0 version of Yomu, but the experience was terrible. The SourceKitService still crashed so often that I have to toggle between files or restart Xcode to fix it. Many useful NSString and NSURL methods are not available in String and URL, so I have to create Swift extension or casting them back and forth.

    As a result I am using the good old Objective-C for Yomu. It’s old and less pretty but it can get things done without frustrating me.