Skip to content
Tech News
← Back to articles

Building iOS Apps with Doom Emacs

read original get Doom Emacs iOS App → more articles
Why This Matters

This article highlights how developers can leverage Doom Emacs and command-line tools to build and manage iOS apps outside of Xcode, offering a more personalized and efficient workflow. It underscores the potential for customization and automation in the iOS development process, empowering developers to work within their preferred environments.

Key Takeaways

I shipped SPEEM, my first iOS app, from Doom Emacs. Not from Xcode.

I don’t mean I just edited a few files in Emacs and switched back when it was time to build. I mean the whole loop: write Swift, build, boot a simulator, install the app, launch it, stream logs, restart LSP, scaffold new projects. All from inside Emacs, all driven by SPC i keybindings I wrote myself.

This post is about how, and why it’s even possible.

Apple ships a small army of command-line tools, xcodebuild , xcrun simctl , xcrun swift-format , sourcekit-lsp , and most iOS developers never touch them directly. Xcode is just a fancy wrapper around them (of course with many other utilities built into it). If you’re willing to glue those tools together yourself, you can build a real iOS workflow in any editor that lets you run shell commands and read process output. Doom Emacs happens to be very, very good at that (or any Emacs distro for that matter really).

The result, for me, is a ~1000-line modules/ios.el that gives me an SPC i b to build, SPC i s to install and launch on selected simulators, SPC i l to stream filtered logs, SPC i n to scaffold a new SwiftUI project, and a few more things I’ll walk through below.

Why I did this#

I live in Emacs. I’ve been using Doom Emacs daily for 4 years: Rust, Elixir, Kotlin/Android, web, org-mode, Magit, all of it. When I came back to iOS development for SPEEM, I tried Xcode for two weeks and it felt like wearing someone else’s shoes. Not bad shoes. Just not mine.

I also have a multi-language config. I have a modules/rust.el , a modules/elixir.el , a modules/kotlin-android.el , a modules/web.el , and so on. Each language has the same shape: a major mode, LSP, keybindings for build/run/test. iOS being the one exception felt wrong.

So I sat down and wrote modules/ios.el . This is what’s in it.

What Apple actually gives you on the command line#

... continue reading