The Macintosh Garden is a great resource in the retro Mac community. It has an archive of nearly every piece of software released in the 80s and 90s, complete with screenshots, manuals, and metadata like year of release and operating system requirements. From its debut Infinite M … | Continue reading
I was a happy user of the Dark Sky weather app for many years. Even more than the localized and timely notifications (I live in a place with predictable weather) I appreciated its Apple Watch complications. I specifically used the three-line textual summary shown in the middle of … | Continue reading
tl;dr: No, not Windows¹, but I’ve decided to expand Infinite Mac to the the black hardware that Mac users secretly lusted after in the 80s and 90s: NeXT. There is now a runnable collection of all notable NeXTStep versions, going from the initial 0.8 preview in 1988 to the final O … | Continue reading
I had previously mentioned that I ended up fixing some DingusPPC CPU emulation bugs. This was my first time working at this (lower) level of the Infinite Mac emulators, and I thought it would be interesting to write up such an investigation. There was an issue that was immediatel … | Continue reading
One of my goals for Infinite Mac is to learn more about computer architecture and other fundamentals. While fiddling with actual old hardware is not as interesting to me (the one classic Mac I own is a PowerBook 550c that I turn on about once a year), I do enjoy operating at lowe … | Continue reading
Infinite Mac has supported a limited form of persistence since its initial launch. This was done by exporting the contents of the “Saved” folder in “The Outside World” to IndexedDB when the emulator was shut down. While this worked, it had several limitations: Saving was best-ef … | Continue reading
The first proper blog post on this site was 20 years ago today. It lived under a different URL, I didn’t register persistent.info until later (when .info was a new-and-shiny top-level domain). It also looked different (I don’t have a screenshot of the first version, but I switche … | Continue reading
Here are a few highlights of what’s been happening with Infinite Mac since my last update. Improving Disk Abstractions My broad goal this time around was to make it easier to load external software. To lay the groundwork for this, I first needed to improve some of the disk abstra … | Continue reading
I finally got access to the recently-launched Slack canvas feature. This project was the last thing I worked on before I left Quip/Slack/Salesforce in April of 2022, and I was curious how it had evolved since then. Canvas started as a prototype in mid-2021 to reuse Quip technolog … | Continue reading
It doesn't feel like it's been 5 years since my last post about Reader, but I guess the past few years have suffered from time compression. For this anniversary I don't have any cool projects to unveil, but that's OK, because David Pierce wrote a great article – Who killed Google … | Continue reading
I wrote a valedictory blog post about the instrumentation we're adding to the Tailscale client to get a handle on battery life issues. It's been an interesting "full-stack" project, involving thinking about cell phone internals, hacking on the Go standard library, and exp … | Continue reading
Darwin was one of the first things Apple open-sourced (24 years ago). It's been mostly a "throw it over the wall" approach, but being able to peek under the hood has been very handy. I wrote a short tailscale.dev blog post showing how we've been able to improve Tailscale's macOS … | Continue reading
tl;dr: Infinite Mac has a new home at infinitemac.org. Using a new Emscripten port of Mini vMac, it is now able to run almost every notable version of Mac OS, from 1984’s System 1.0 to 2000’s Mac OS 9.0.4. The project is also now accepting donations (via GitHub Sponsors or PayPal … | Continue reading
One of the less visible changes in Tailscale v1.36 is that the macOS binary is 35MB smaller. I wrote a post on the Tailscale blog about the chance observation and investigations that led to this size win. If you're interested in this kind of low-level shennanigans, we are hir … | Continue reading
tl;dr: I use Masto Feeder to generate a nicely-formatted RSS feed of my timeline, and then I can read it in my preferred feed reader. A bit more than 10 years ago I wrote a post called “How I Consume Twitter”. It described how I contort Twitter to my completionist tendencies by g … | Continue reading
I worked on adding iOS and macOS Shortcuts support for Tailscale's latest release. I wrote a blog post with examples of shortcuts and automations that the Tailscale actions could be combined with. One that didn't make the cut was using sound recognition, for things like “In case … | Continue reading
I've been running lolcommits for 10 years, and it's captured some interesting moments from my time at Quip and Tailscale. I've put together a gallery, it was a fun nostalgia trip to revisit so many places and coworkers. | Continue reading
I've come to think of Infinite Mac as my forever project. There's always something to work on, whether it's expanding the library, improving compatibility, adding more platforms, improving performance, debugging data structures, bridging APIs from 30 years ago with modern web pla … | Continue reading
Account switching is one of the less fun parts of modern computing -- for a while I had registered giveupandusemultiplebrowsers.com. Even when software tries to accomodate these scenarios, the heuristics for when to switch can be tricky, and in some cases require the user to main … | Continue reading
It was a lot of fun turning Brad's Taiscale-on-Wasm prototype into Tailscale SSH Console. I wrote a post for the Tailscale blog with more details (you can tell it wasn't ghost-written because it has my link-heavy style). Almost all of the development was in the open-source repo, … | Continue reading
One of the things that attracted me to Tailscale was their in-depth technical blog posts, like Josh's hacking on Go internals to get iOS memory use down, or Dave's epic treatise on NAT traversal. It was therefore nice to be able to contribute a debugging story: The Case o … | Continue reading
At this year’s Code Conference Tim Cook discussed disagreements that he and Steve Jobs had, including whether to have a carrier subsidy for the iPhone: Cook reveals him and Jobs disagreed over launching the iPhone as subsidized by the carrier or via receiving a carrier revenue s … | Continue reading
tl;dr I’ve added a Cloudflare Durable Object-based LAN mode to Infinite Mac, allowing networked games of Marathon, Bolo and anything else that works over AppleTalk. To try it out, use demo.system7.app (or any other subdomain — it defines the “zone” where packets are broadcast and … | Continue reading
Infinite Mac has been quite a whirlwind. I wasn’t sure if it would reach the Mac (or retro computing) community, but it did, and went beyond that too, including to Ars Technica and Hacker News (twice). The most gratifying thing was seeing (and in some cases hearing from) people w … | Continue reading
Comments | Continue reading
I recently finished reading From RAINBOW to GUSTO which describes the development of the A-12 high-speed reconnaisance plane (the predecessor to/basis for the somewhat better known SR-71 Blackbird). Though a bit different from the software history/memoirs that I've also enjoyed, … | Continue reading
I recently came across James Friends’s work on porting the Basilisk II classic Mac emulator to run in the browser. One thing that I liked about his approach is that it uses SharedArrayBuffer to allow the emulator to run in a worker with minimal modifications. This system can also … | Continue reading
Mscape Software was the “label” that I used in my late teenage years for Mac shareware programs. While having such a fake company was (is?) a surprisingly common thing, it turned into a pretty real side-gig during 1999 to 2003. I spent a lot of my hobby programming time working o … | Continue reading
For a (still in-progress) digital archiving project I wanted to create a Git repository with some classic Mac OS era software. Such software relies on resource forks, which sadly Git does not support. I looked around to see if others had run into this, and found git-resource-fork … | Continue reading
Like many others I’ve spent a lot of time over the past year playing the New York Times’ Spelling Bee puzzle. For those that are not familiar with it, it’s a word game where you’re tasked with finding as many words as possible that can be spelled with the given 7 letters, with th … | Continue reading
I was recently investigating suspiciously high CPU usage while typing in documents in Quip’s Mac app. We had recently switched to WKWebView, and this was happening in the “web content” process, suggesting that it was a JavaScript-related problem, or perhaps something related to t … | Continue reading
Quip did a wholesale migration to TypeScript around this time last year. Now that the dust has settled and we've lived with the consequences for a while, Rafael and I wrote a couple of blog posts about it all: Part one describes the process that we chose, and part two has som … | Continue reading
I wrote a post on the Quip blog about the various in-product debugging tools that we've developed over the years. It's been very satisfying to make and use our tools over the years, I'm glad we're finally sharing some details about them. One of the many overlays we've created | Continue reading
A couple of weeks I was migrating some networking code in Quip's Mac app from NSURLConnection to NSURLSession when I noticed that requests were being made significantly more often than I was expecting. While this was great during the migration (since it made exercising that code … | Continue reading
JavaScriptCore (JSC) is the JavaScript engine that powers WebKit (and thus Safari). I was recently browsing through its source and noticed a few interesting things: ARM64_32 Support Apple Watch Series 4 uses the S4 64-bit ARM CPU, but running in a mode where pointers are still 3 … | Continue reading
It's now been 5 years since Google Reader was shut down. As a time capsule of that bygone era, I've resurrected readerisdead.com to host a snapshot of what Reader was like in its final moments — visit http://readerisdead.com/reader/ to see a mostly-working Reader user interface. … | Continue reading
I wrote up a post on the Quip blog about more efficiently embedding JSON data in HTML responses. The tl;dr is that moving it out of a JavaScript tag and parsing it separately with JSON.parse can significantly reduce the parse time for large data sizes. | Continue reading
I recently ran into some puzzling WebKit scrolling behavior: child iframes mysteriously causing the main window to get scrolled. This was in the context of a Quip feature still under development, but I've recreated a simple test case for it, to make it easier to follow along. The … | Continue reading
Historically, one of the differences that made hybrid mobile apps feel a bit “off” was that there would be lag when handling taps on UI elements with a straightforward click event handler. Libraries such as Fastclick were created to mitigate this by using raw touch events to imme … | Continue reading
I recently ran into an interesting quirk when using Performance.now() to measure long-ish intervals in Quip's web app. Since it does not seem to be broadly known, I thought I would document it. To mitigate the possibility of self-induced DDoS attacks, I recently added duplicate r … | Continue reading
I previously described how adding native popovers and modal dialogs to Quip’s hybrid desktop apps helped them to blend in and avoid the “uncanny valley” of web-based apps that don’t quite feel right. Another area that we focused on was the experience of creating a new window, esp … | Continue reading
tl;dr: Using the webRequest Chrome extension API it is possible to “graft” development/localhost JavaScript and CSS assets on a production web service, thus allowing rapid debugging iteration against real production data sets. Demo site and extension. During the summer of 2015 I … | Continue reading
Quip’s desktop apps are hybrid apps: both the Windows and Mac apps are composed of a web React-based UI talking to our C++ Syncer library, along with some platform-specific glue code. While this allows us to support two additional platforms with a small team we knew that architec … | Continue reading
Earlier this year I posted about WKWebView communication latency and how it’s not quite as good as UIWebView (when using WKScriptMessageHandler, the officially sanctioned mechanism). There have a been a few developments in this area, so an update seems warranted. Things appear to … | Continue reading
tl;dr: react-closure-compiler is a project that contains a custom Closure Compiler pass that understands React concepts like components, elements and mixins. It allows you to get type-aware checks within your components and compile React itself alongside your code with full minif … | Continue reading
One of the many exciting things about the modern WebKit API is that it has an officially sanctioned communication mechanism for doing JavaScript-to-native communication. Hacks should no longer be necessary to get data back out of the WKWebView. It is a simple matter of registerin … | Continue reading
tl;dr: RetroGit is a simple tool that sends you a daily (or weekly) digest of your GitHub commits from years past. Use it as a nostalgia trip or to remind you of TODOs that you never quite got around to cleaning up. Think of it as Timehop for your codebase. It's now been a bit mo … | Continue reading
Like many others, I was excited to see that Facebook is putting on a conference for the React community. Tickets were being released in three waves, and so for the last three Fridays I have been trying to get one. The first Friday I did not even manage to see an order form. The n … | Continue reading