New command line tools
Andrew McKnight – 30 September 2018

Over the last few weeks I’ve written two new tools for the command line: rebuild-sims and sync-forks. They join a small but growing family of tools to help with software development. Here’s a bit about the newcomers and how I see that collection growing and staying organized.


At some point a few weeks ago I found I’d corrupted my installs of iOS simulators. I tried fixing it myself to no avail, partly because I was trying to wrap up a release for an app update (of course, with yhr timing). I looked around for a drop in solution online and found this gist: simulator populator xcode, but I had some issues with it:

So, I took the opportunity to rewrite it a bit to improve performance, and serve it in a Gem for ease of distribution and use.


I find a lot of useful code on GitHub, and when I want to use something in a project I try to safely isolate the dependency, part of which involves forking it.

Forking a repository in a DVCS really just means creating a new mirror, a new node in the graph of “remotes” (even your local clones of repositories are really remotes: try cloning from a local repository on your machine, and then look at that clone’s git remotes–they’ll be local paths), to which GitHub adds some helpful UX: if you fork a repo via the GitHub UI, your repository is tagged with information about the original one. Hence, the little “forked from original-owner/repository-name” link under a fork’s name on its GitHub page.

I currently have around 80 forks. I’ve tried keeping them up to date locally to maintain as much control as possible over my fate as a dependee, but that’s a lot of work. For a while I’ve wanted a way to automatically ensure I have a local copy of each fork.

sync-forks uses the GitHub API via the github_api Gem to get a list of all your repositories and clone those that are forks. In each local repo, the git remote origin will point to your fork, and sync-forks will add a new remote named upstream that points to the original.

Eventually, I’d like a way to automatically fetch new commits from upstreams and apply them (using --ff-only for safety) to the local default branch, and then push to origin. Maybe later a more sophisticated approach using git pull --rebase and a stored rerere strategy could be used for customized forks.

Here’s another pie-in-the-sky idea: automate forking for all your dependencies. I’m not perfect about going around and forking all the repos for dependencies I use in my apps, or even in these Gems. While it is true that package managers may leave caches or checkouts of dependencies in various places, it might be nice to archive them all on a personal server, perhaps. If sync-forks could crawl all of my Gem or CocoaPod dependencies, fork them on their respective platforms (if possible–GitHub would work, but a privately hosted Git repo probably won’t) and do the usual sync work, then you’d have a total mirror of all the software your apps need to work!


These are distributed in a Ruby Gem named tworingtools, which provided a nice little learning opportunity to me, since this is the first Gem I’ve created. I also have a set of tools distibuted via Homebrew in tworingsoft/homebrew-formulae, but I’ve found that approach tougher. Going forward, I’d like to merge these collections.

tworingtools is currently all housed in a single repository, including specs, which I like. I currently have the Homebrew specs stored in a separate repo from the tools, introducing more complexity. Ultimately I’d like to combine those source repositories into tworingtools, and add them appropriately to the gemspec. All the better if I can also host the Homebrew specs in that same repository, and target both package managers.

Enjoy the post? Please help support more like it by buying me a cup of coffee! I am also available for contracting.