A few months ago, I detailed my process for setting up a Pixelbook to code on. It wasn’t easy or simple or straightforward, but it worked in the end: I had all the power and flexibility of Linux, access to my favorite code editor (VS Code), and, of course, the slick web browsing experience that Chromebooks are known for.
Around that same time, I attempted to set up an iPad for coding. I failed miserably. I love using the iPad for writing and other creative work. It’s super portable, has great battery life, an excellent screen, and the limited multitasking keeps me focused. Unfortunately, it’s very bad for complex tasks and intentionally crippled for software development.
But I’m older and wiser now, and after an entire Saturday spent bashing my head against a wall, I’m happy to report that I can use a $799 tablet computer to write software. Will I ever actually use it for this purpose? Maybe! But we’ll get to that.
Feel free to follow in my footsteps if you, too, wish to code on the iPad. I can’t promise you it’s a worthwhile destination, but I learned a lot on my way there.
Chapter 1: The journey begins by lowering my expectations
As everyone knows, Apple is scared to death that anyone might ever run arbitrary code on one of its pristine iOS devices. It makes a little bit of sense: the strictures of iOS and the App Store are why a years-old iPad is vastly more responsive and cruft-free than a similarly aged MacBook Pro.
But it makes developing software nearly impossible. It’s ironic because the iPad is excellent for creators in so many ways like drawing, design, and music. Under the hood is the same Unix kernel that makes macOS excellent for programmers.
Anyway, you know all this.
And I was extra excited to see that CodeSandbox has a Vim mode. Vim keybindings are my preferred way to navigate around text, and it’s especially important on the iPad where you don’t have a mouse for assistance. Moving the cursor, highlighting text, deleting words or lines, moving lines, and jumping large distances in a file all require just a couple keystrokes in Vim. Contrast that to the iPad alternative: seconds spent poking at the screen with your clumsy finger, hoping iOS will discern your intent.
Basically, everything was going great. CodeSandbox was all I needed, and my iPad was suddenly an ultra useful webdev box — at least for building the sort of small experiments I gravitate toward.
Except there was one problem: the iPad doesn’t have an Escape key.
Chapter 2: What despair feels like
See, in Vim, there are different “modes.” There’s the default mode where you use the keyboard to navigate around your document. There’s the selection mode, where you use those same navigations keys to select text. And, importantly, there’s an insert mode, where you use your keyboard to type. Since you need to get out of insert mode to move your cursor again, you need some sort of command to exit insert mode. By default, that command is wired to the Escape key.
Many Vim users (like myself, for instance) map a fancy key combo like “jj” to make exiting insert mode easier, but CodeSandbox isn’t actually Vim. It just emulates some of Vim’s default keybindings. So I need an Escape key. And the iPad doesn’t even know what that means.
I’m serious! At first, I thought this was just a problem with Apple’s own Smart Keyboard Cover, which has no function row and no Escape key. So I pulled out a regular Bluetooth keyboard and hooked it up to the iPad. I jammed on the Escape key and… nothing. In the world of iOS, there is no escape.
I browsed around StackExchange and various GitHub issues in a state of despair. Yes, there are ways to emulate an Escape keypress with “Ctrl + [,” but that gets me nothing in this case. I’m stuck in insert mode for the rest of my life.
CodeSandbox, you brought me so close!
In fact, based on CodeSandbox’s rapid iteration, I wouldn’t be surprised if they solved this issue in the near future.
But in the meantime: what’s a boy to do?
Chapter 3: Okay, let’s try the cloud again
The first time I tried to set up an iPad for coding, I naturally went straight to the cloud. But the cloud isn’t a magical place where all your dreams come true. Setting up a devbox on Digital Ocean or Google Cloud requires some knowledge of Linux and SSH, and there’s no GUI Linux interface to fall back on when your command line skills fail you.
Weirdly, the debris of scattered knowledge from my last attempt at a cloud devbox setup was all I needed to quickly get everything working. I paid for the basic $5 box on Digital Ocean, put a clean install of Ubuntu on it, and provided it an SSH key I generated in Panic’s Prompt app, an SSH terminal emulator for iOS. Why was this so hard before?
After SSHing into my Digital Ocean box, I started adding the tools I need. I installed Neovim (a modern Vim alternative) and found someone’s .config file for Neovim on GitHub and copied it. Then I installed nodejs, yarn, npm, parcel, rust, gcc… all the good stuff I crave. Because the “language server” aspect of VS Code is open source, I can get many of the hints and errors I rely on so heavily when coding into Neovim, even though it lacks all the GUI bells and whistles of VS Code.
It’s hard for me to describe how I did all these things, other than a liberal application of sudo apt-get install, copying and pasting shell scripts, and careful reading of error messages. Mostly, it’s just years of trial and error in the command line. I guess DM me if you get stuck on something, and I’ll do my best to help. Have you tried modifying your $PATH?
But soon, I got frustrated: a very small fraction of my work “coding” is actually typing code. I spend most of my time reading documentation and other people’s code to try and figure out how the hell anything ever works. After a couple of minutes browsing StackOverflow, I get a notification from Prompt, warning me that my SSH session is about to disconnect because of inactivity.
The whole reason iOS is so nice and responsive is because it has almost zero multitasking unless you’re working with multiple audio apps at once. Prompt does its best to stay alive, but iOS always kills it in the end.
Chapter 4: UDP saves the day
So, I Googled for a solution and discovered Mosh. Basically, Mosh is a UDP protocol for using a terminal from an intermittent connection. You connect over SSH like usual, but then that connection is handed off to Mosh to keep it “alive” during downtime. Prompt doesn’t support Mosh, so I paid another $20 for another terminal emulator app, called Blink, and set up Mosh. It took some trial and error to get the Mosh server running on my Ubuntu box and correctly enter my login details into Blink, but once I got it working, it works great.
I can leave the terminal for days, and as soon as I open Blink I have all the sessions open from the last time. For command line warriors, this is no huge feat. They know all about “reattaching” to sessions or whatever they do. But for me, it’s a huge achievement.
In fact, in some ways, I prefer my iPad / Blink / Digital Ocean setup to coding on my Mac. I can’t do everything my Mac does — anything involving windowing or graphics, for instance, outside of a web browser, isn’t really possible — but I have the joy of knowing I’m not mucking up my Mac with all the various weird command line software I install from the internet. If my setup ever breaks beyond repair, it’s just a couple clicks to wipe my Ubuntu box and start fresh.
Also, while my Digital Ocean box is a lot slower than my MacBook Pro, it has a blazing-fast internet connection. Anything I want to git clone or npm install feels way snappier on this cloud box, thanks to its minimal latency and huge internet pipe.
Oh, and in case you were wondering: Blink supports the “Ctrl + [“ command to emulate escape. You can also map your Caps Lock key to escape if you want to be really crazy (I traditionally map Caps Lock to Ctrl, which is also supported by Blink). But, thankfully, my Neovim config maps “jj” to escape when in insert mode, so I’m golden on that front.
CodeSandbox.io includes its own console interface.
I guess my first job on this new coding setup will be to write a pull request for CodeSandbox to support the “jj” escape method.
It’s a real pickle I’ve found myself in.