I read somebody recently complaining that installing Swift projects was hard because SwiftPM has no install command. Avoiding going into my opinion on that (I don’t want SwiftPM to go there), I disagree that maintaining a Homebrew tap is hard. I do it for swift-sh, and I even have Travis set up to automatically update the tap for me so I don’t have to do anything.

For example installing swift-sh is this easy:

brew install mxcl/made/swift-sh

And Homebrew will keep it up-to-date.

Why Should I Do This?

I maintain that a super large hindrance to the success of your work is adoption pain. You need

As part of my one‐week‐one‐open‐source series this year I have released Workbench.

Workbench is (currently) a small app that monitors changes in your “dotfiles”, uploading them to your private iCloud account when changed.

There are many “dotfile” backup solutions out there, but I found they all were limited or tedious in some manner. Hence I made my own.

Use of iCloud for services like Workbench is something I’d like to see more of from other developers. It is truly zero‐conf, giving your apps sign‐in‐less access to secure and private cloud‐data storage.

I have already tested it for clean-installs, and it works a treat.

Check it out!

This year I will release a new open source project EVERY WEEK.

I’m already at five projects this year:

  • swift-sh: trivially run Swift scripts with third party dependencies.
  • Path.swift a delightful, robust, cross-platform and chainable file-pathing library.
  • LegibleError a tool for displaying Swift errors to the user that are less The operation couldn’t be completed. (ThirdPartyModule.(unknown context at 0xx10d6b4a44).SomeError error 0.) and more legible and useful.
  • Version a µ‐framework for representing, comparing, encoding and utilizing semantic versions.
  • AppUpdater a µ‐framework for updating your open source macOS app based on your repo’s GitHub releases.

Update, now eight:

Workbench, Chalk, Cake.

Who are you exactly?


I have released Version.

A real version object is essential as soon as you have to parse one. And this is often enough, I mean, every app you make has one in its Info.plist.

I have for years used the Version.swift that is part of the Swift Package Manager, and this library is that code, extracted, documented, tested and enhanced. Relative to the original implementation it has:

  1. A more compact Codable implementation †
  2. It implements LosslessStringConvertible
  3. Is not a massive-single-source-file (MSSF)
  4. Has online documentation (100% documented)
  5. Extensions for Bundle and ProcessInfo
  6. Removal of the potentially fatal ExpressibleByStringLiteral conformance
  7. A…

LegibleError’s goal is to prevent you showing the user a string like this:

The operation couldn’t be completed. (ThirdPartyModule.(unknown context at 0xx10d6b4a44).SomeError error 0.)

That string is the default localizedDescription for a Swift Error. Instead use LegibleError and you’ll get something more like this:

The operation couldn’t be completed. (ThirdPartyModule.SomeError.networkFailure)

This way both you and the user are less confused and more informed.

LegibleError also provides a method to give better strings for logging and debug, providing all the information we can get from the runtime.

Check it out.

If your Swift project uses swift test on Linux then you are aware that you need to run swift test --generate-linuxmain in order to get for free what you get on Apple platforms, ie. for XCTest to know which tests it runs. The command generates several extra files that are only used on Linux and must be committed to your repository if you want test your product on Linux in CI.

A pain point in Swift’s early life for sure, but for now it’s just extra boilerplate. …

Last time I talked about deploying and maintaining a Linux server. This time we’re talking about how to commuincate with the APNs communication portal.

What is Canopy?

Canopy has apps for macOS and iOS, and it’s available here.


The Apple Push Notification service. Why is the “s” lowercase? Nobody knows.

The service is a black box on the Internet. Your server connects to it securely and sends small JSON payloads, each for a specific device; Apple then send that to the device. If the device isn’t powered they will “hold” it for a little, if it has power it arrives pretty much instantly.

Last time I talked about Swift on Linux from the Cloud provider side, this week is about the Linux side, and considering I expect my audience to have little to no server-side experience, we will be talking about Linux sub-systems.

What is Canopy?

Canopy has apps for macOS and iOS, and it’s available here.


I used AWS, and thus used Amazon’s Route 53 for DNS, this makes it easy to assign your Elastic IP (which we talked about in part 3). You don’t have to buy the domain through Amazon, but they make it easy and all the registrars cost about the same…

Last week I talked about how how I chose Perfect as the base for Canopy’s Server. This week I’ll be talking about cloud providers, Swift on Linux, the development process and deployment.

What is Canopy?

Canopy has apps for macOS and iOS, and it’s available here.

Cloud Providers

If you chose Vapor, they provide free hosting for your server-side app, up to a limit. But it can make it a great choice for getting started, and depending on how much load you expect, it may be fine for good.

Kitura (by IBM) also offer simple deployment and hosting solutions.

One of the reasons I liked…

Deploying new releases of your open source libraries should be automated so that you deploy as often as possible. The more work for you, the less often you will do it.

Firstly you need to add your CocoaPods trunk token as a secret token for Travis to expose to the environment of your CI process. You can do this in the repository’s settings. Your token is stored in ~/.netrc.

Now generate a new one for your computer.

Next I suggest adapting your .travis.yml to use the new(er) Travis Build Stages format. …

Max Howell

Open source. Swift. Creator of Homebrew.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store