Not long ago, we released Butler – Client For Jenkins, a new mobile Jenkins client for the iPhone, supporting 3D Touch and many other features designed to make using Jenkins on mobile devices a smoother, more enjoyable and more productive experience.

Butler is an open source project and we are always happy for contributions of any kind.

This post will go into detail about the motivation behind creating Butler, the features that we decided to implement as well as challenges that presented themselves while creating this application.


We at MobiLab have used Jenkins for Continuous Integration for a long time before moving over to Travis for various reasons. It is this history with the tool, that lead us to create Jenkins for Android and that again lead us to create Butler.

We saw creating Jenkins for Android as a way to give back to the community that provided us with amazing tools. The same goes for Butler. This time, however, with open sourcing the complete application, we went a step further.

Jenkins for Android has been a great success. Many people are using the app and enjoying the experience we deliver. We did not feel as if the same level of quality for Jenkins applications existed on the iOS app store yet. Therefore, we decided to create it ourselves, even if it meant building a whole new application from the ground up.


With Butler, we aimed to create a feature rich mobile application that supports every major Jenkins feature that is actually needed on mobile platforms. Those include but are not limited to:

  • Full support for viewing your Jobs, Builds, Test Cases, Folders and more
  • Triggering Builds with and without parameters
  • Full 3D touch support
  • Add Jobs and Builds to your favorites to keep an eye on them
  • Today Widget for even faster access to your favorites
  • Connecting to Jenkins instances over http and https
  • Fully open source!


Along the way of creating Butler, I had to overcome a few challenges both concerning environmental factors (the Jenkins API) as well as concerning the iOS ecosystem. Listing all of those small challenges would not only be a long endeavor but also quite boring. The following are therefore two examples that I deem to be more interesting and worthwhile than the others.

Understanding the Jenkins API

Unfortunately, the Jenkins API documentation is not exactly complete. Many calls lack information about the concrete data points that are returned and as a result of some of the plugins that the mobile application was supposed to support, the effect of those on the returned data had to be considered, too. Fortunately, we were able to extrapolate a lot from Jenkins for Android, only having to translate from Java to Swift along the way.

Understanding an API that has little to no documentation can be a daunting task. However, most questions about the general structure of the API could be cleared up looking at the Jenkins for Android sources and questions that went into more detail could be answered or at least approximated by simply having a look into the returned JSON-data.

What turned out to be especially challenging were the API differences between versions of Jenkins. Some versions return an array of test result child cases while others return an array of test result suites. There are quite a few of these undocumented differences that can only be circumvented by intensive testing using different Jenkins instances. Furthermore, triggering builds on jobs is a task that has multiple different facets, too. The procedure of triggering a build is different when there are parameters that need to be provided vs when CSRF protection is enabled vs when both are en- or disabled. Again, through trying out a lot of variations, this part of the application could be brought to work.

If you have concrete questions about how to use the Jenkins API, simply send us an email. I will try to answer your questions as far as I can. Perhaps, there will be a blog post about precisely that topic in the future.

Creating the Today Extension

One of the application’s key features is the Today Widget that provides the user with up-to-date information about his or her favorite Builds and Jobs. For that purpose, both the persisted Job and Build as well as the account information have to be shared between the main application and the app extension.

On iOS, this can be done easily with App Groups and Keychain Sharing. Butler therefore persists its favorites data as well as general information about the various accounts that are saved to a shared container between the app extension and the main application. Then, the information that should be kept securely (e.g. passwords) are written into a shared keychain. That way, both parts of the application can use the same data. To then share the same Model and Service classes between extension and main app, a runtime flag was introduced that determined the exact location of the files and the exact way to decode those.

Conclusion and What’s next for Butler

So far, creating Butler has been a valuable experience for me and I am excited to see what kinds of features the community would like to see in this project.

It is my goal to make Butler an application that is both easy and enjoyable to use and also as capable as possible. To achieve that goal, feedback from the community would be greatly appreciated. Simply send us an email at

As many other open source projects, we are very happy about contributions of any kind. If you are interested, the code is hosted on GitHub here.

Robert is a junior iOS developer at MobiLab and he’s in charge of developing the Butler project. To get in touch with him, simply send him an email at .

Do you want to create amazing mobile experiences, too? Find more information here!