More from elementary Blog
July is Disability Pride Month, an opportunity for us to consider how we’re serving our disabled community and work on breaking down barriers to access. Last year we had the pleasure of being introduced to Florian—a fully blind cybersecurity enthusiast—and thanks to his feedback we completely rewrote navigation in Onboarding to be more keyboard and screen reader friendly, as well as took another look at Installation and Initial Setup to vastly improve our entire first run experience for blind folks. Plus, we implemented the screen reader interface in the Alt + Tab window switcher. Thanks to this feedback, elementary OS 8 can be installed and set up completely blind, an important win for maintaining your independence as a person with vision disabilities. Danielle Foré Founder & CEO Wed, Jul 3, 2024 7 min read Since the release of OS 8 we’ve been working on things like improving contrast, support for Dark Mode screenshots and brand colors in AppCenter, turning on or snoozing Dark Mode without canceling your schedule, expanding the scope of the “Reduce Motion” setting, and adding more options to reduce distracting notification bubbles. Plus, thanks to feedback from Aaron who you may know from his blog series on Linux accessibility, Notifications and the Shortcut Overlay both got releases that add screen reader support. As a community that includes folks with a range of disabilities ourselves, we’re deeply invested in improving access to Open Source software. We succeed at our mission when we build open computing experiences that are available regardless of ability and fail when accessibility is considered an afterthought or a nice-to-have. This month and always, Inclusive Design is at the core of what we do and we will continue to strive towards that ideal. If you want to follow along or help us address accessibility issues in elementary OS, we’d love your help! We’re tracking issues in this GitHub project. If you discover a new issue—accessibility related or otherwise—we’d love to get your feedback and we have a handy contributor guide to help you file a report here. Code A big new release of Code is here, thanks primarily to Jeremy. This release closes 19 reported issues including a couple of crashers. The “Open in…” menu is now sorted and includes an option for the Terminal pane. Plus the Terminal pane now follows Natural Copy/Paste settings from the Terminal app. The Vala symbols pane now shows a lot more information about symbols in their tooltips. Numbered lists are now handled correctly by the Markdown plugin. The Highlight Word Selection plugin now works with selections of more than one word. Several enhancements were made to managing git branches including sorting branch names alphabetically, the ability to switch to remote branches, and you’ll now be asked how to handle uncommitted changes when switching branches. You can now create edit marks by clicking in the source view gutter. They can be jumped between via the context menu or with the keyboard shortcuts Alt + ← / →. If you’re using the Flatpak version of Code on another OS, the “Open in…” menu is no longer empty and operations that require a network should now work. Plus performance was improved in several cases. Window Manager & Dock This month Leonhard and Leo closed another 19 issue reports in our window manager, including several issues related to multi-monitor, the Multitasking View, and Dock behavior. A crash that could occur when closing LibreOffice windows was fixed. Picture-in-picture will now select the correctly window when its area selection is drawn over an app’s shadow. Non-flatpak apps that don’t correctly match their launchers can now sometimes be matched by the Dock anyways. If you have “activate hotcorners in fullscreen” turned on, you can also now access the Applications Menu with Super while playing a fullscreen game, for example. Plus we made some performance improvements to drawing shadows. System Settings In Keyboard → Shortcuts → Custom you can now choose from a list of installed apps and their actions—in addition to being able to execute custom commands—thanks to Leo. This makes it super straightforward to add a keyboard shortcut for your most common workflows like composing a new email or adding a new Calendar event. You can now create custom keyboard shortcuts for apps and their actions System Settings will also now warn you if your desired keyboard shortcut conflicts with a common system shortcut like “Copy”, “Paste”, or “New Tab”. Plus we fixed an issue that would prevent certain Housekeeping configurations from running, and the “Automatic” accent color option now works more reliably. And More The Screencast Portal now features an improved design for selecting which display or window should be captured, as well as respecting options for capturing the pointer. Plus we fixed issues that prevented screenshots from including window shadows in some cases, and screenshot notifications now open the Image Viewer when clicked. Screencasts portal has a new design Jeremy fixed a number of issues in the latest release of Files including issues related to file renaming, drag-and-drop, ejecting removable drives, and an issue activating context menus from certain parts of the sidebar. And he also fixed an issue preventing bluetooth file sharing from working. Plus, Leo made sure that panel transparency and orientation lock settings get synced to the Login & Lock screen. Get These Updates As always, pop open System Settings → System on elementary OS 8 and hit “Update All” to get these updates plus your regular security, bug fix, and translation updates. Or set up automatic updates and get a notification when updates are ready to install! Early Access Bluetooth Settings got a redesign and a reworking of its list sorting logic that should improve performance, reliability, and its screen reader experience. Especially of note, we now sort out more bluetooth devices so the list of nearby devices should be more concise and useful. Plus we fixed a few issues related to devices that require a passcode to pair, like some keyboards. This includes some fairly large changes so we could really use help testing for regressions before releasing this update for everyone. Bluetooth settings has a new design We’re also now building daily ARM64 Native images thanks to new contributer NN708. This is a universal ARM UEFI image, which means it should be a single image that runs on platforms like Raspberry Pi, Pinebook Pro, and Apple M-series Macs. This makes it a lot simpler for us to support ARM processors in future releasses of elementary OS. Please test these images on your ARM devices and report back! We now include additional processor architecture options in our issue report template to track any problems you experience. Download ARM64 Builds Sponsors At the moment we’re at 23% of our monthly funding goal and 322 Sponsors on GitHub! Shoutouts to everyone helping us reach our goals here. Your monthly sponsorship funds development and makes sure we have the resources we need to give you the best version of elementary OS we can! Monthly release candidate builds and daily Early Access builds are available to GitHub Sponsors from any tier! Beware that Early Access builds are not considered stable and you will encounter fresh issues when you run them. We’d really appreciate reporting any problems you encounter with the Feedback app or directly on GitHub.
Questionable puns aside, it’s Pride Month and we’re excited to celebrate by bringing you these updates hand-made by real LGBTQIA+ community members from around the world!—and possibly some straight cis folks too. This rainbow of releases includes some important accessibility updates, tons of bug fixes, and of course a few new features. Window Manager & Dock Another absolutely massive release of our window manager is out that fixes about 20 reported issues and a brand new Gesture Controller thanks to Leonhard and Leo. You can now Swipe up in Multitasking View to close windows, app titles in Multitasking View are now always shown—making them accessible for touch screen setups—and screenshots taken with a keyboard shortcut will send a notification that you can use to view it in Files, just to name a few headlining features. If you want to read the full release notes, Good Luck Babe they’re quite long. A new release of our Dock is also out which brings back a couple of old Plank features: showing multiple dots for apps with multiple running windows and cycling through app windows when you hold a drag-n-drop over its icon. Plus you can now open context menus with a long-press. And there’s a number of bug fixes including things related to hide modes and memory usage. Thanks again to Leo and Leonhard for their hard work here. System Settings Leonhard fixed a crash when setting custom hotcorner commands and we now only show the Applications Menu hotcorner action in its corresponding panel corner—that’s top-left for folks reading left-to-right and top-right for folks reading right-to-left. Plus there’s a new option to enable hotcorners even while an app is fullscreened. As a follow up to last month’s fixes, choosing light or dark mode in System Settings will now properly snooze your schedule instead of disabling it all together—a great convenience for those of us who suffer from eye strain or headaches and need to occasionally reach for that dark mode during the day. Plus, the Reduce Motion setting now covers a whole new range of animations—perfect for folks who get motion sick or find animations distracting. Leonardo tackled a couple of crashes in Display settings including one when mirroring, and another when new displays are attached while System Settings is open. We fixed an issue that prevented CalDAV accounts from connecting in Online Accounts settings. And Alain snuck in a few design tweaks, fixing button alignments etc. And More Thanks to feedback from Aaron, Notifications and the Shortcut Overlay both got releases that add screen reader support. Corentin addressed some Flatpak sandbox issues with an updated Apparmor Profile—especially notable if you’d had trouble with Steam. We now use BeaconDB as our location services provider. And thanks to Ryo we’re now shipping the latest version of GNOME Web which brings improved performance and web compatibility as well as a redesigned bookmarks sidebar. Get These Updates As always, pop open System Settings → System on elementary OS 8 and hit “Update All” to get these updates plus your regular security, bug fix, and translation updates. Or set up automatic updates and get a notification when updates are ready to install! Community Pride I want to take a little space to say that our community is for everyone regardless of gender or sexual identity. We’ve long been made up of lots of different kinds of folks and I’m really proud of that. Open Source software should never be a space that is restricted to a narrow set of identities. In a time where many companies are withdrawing their support for the LGBTQIA+ community, I think it’s incredibly important that we make a strong statement against hate and don’t give in to the pressure to erase queer people in some sad attempt to be “apolitical”. Free Software has always been political, and its politics are freedom and inclusivity and so are ours. Sponsors At the moment we’re at 23% of our monthly funding goal and 336 Sponsors on GitHub! Shoutouts to everyone helping us reach our goals here. Your monthly sponsorship funds development and makes sure we have the resources we need to give you the best version of elementary OS we can! Monthly release candidate builds and daily Early Access builds are available to GitHub Sponsors from any tier! Beware that Early Access builds are not considered stable and you will encounter fresh issues when you run them. We’d really appreciate reporting any problems you encounter with the Feedback app or directly on GitHub.
In mid-March we released a big bug fix update—elementary OS 8.0.1—and since then we’ve been hard at work on even more bug fixes and some new exciting features that I’m excited to share with you today! Read ahead to find out what we’ve released recently and what you can help us test in Early Access. Quick Settings Quick Settings has a new “Prevent Sleep” toggle Leo added a new “Prevent Sleep” toggle. This is useful when you’re giving a presentation or have a long-running background task where you want to temporarily avoid letting the computer go to sleep on its normal schedule. We also fixed a bug where the “Dark Mode” toggle would cancel the dark mode schedule when used. We now have proper schedule snoozing, so when you manually toggle Dark Mode on or off while using a timed or sunset-to-sunrise schedule, your schedule will resume on the next schedule change instead of being canceled completely. Vishal also fixed an issue that caused some apps to report being improperly closed on system shutdown or restart and on the lock screen we now show the “Suspend” button rather than the “Lock” button. System Settings Locale settings has a fresh layout thanks to Alain with its options aligned more cleanly and improved links to additional settings. Locale Settings has a more responsive design We’ve also added the phrase “about this device” as a search term for the System page and improved interface copy when a restart is required to finish installing updates based on your feedback. Plus, Stanisław improved stylus detection in Wacom settings preventing a crash when no stylus is found. AppCenter We now show a small label next to the download button for apps which contain in-app purchases. This is especially useful for easily identifying free-to-play games or alt stores like Steam or Heroic Games Launcher. AppCenter now shows when apps have in-app purchases Plus, we now reload app icons on-the-fly as their data is processed, thanks to Italo. That means you’ll no longer get occasionally stuck with an AppCenter which shows missing images for app’s who have taken a bit longer than usual to load. Get These Updates As always, pop open System Settings → System on elementary OS 8 and hit “Update All” to get these updates plus your regular security, bug fix, and translation updates. Or set up automatic updates and get a notification when updates are ready to install! Early Access Our development focus recently has been on some of the bigger features that will likely land for either elementary OS 8.1 or 9. We’ve got a new app, big changes to the design of our desktop itself, a whole lot of under-the-hood cleanup, and the return of some key system services thanks to a new open source project. Monitor We’re now shipping a System Monitor app by default By popular demand—and thanks to the hard work of Stanisław—we have a new system monitor app called “Monitor” shipping in Early Access. Monitor provides usage information for your processor, GPU, memory, storage, network, and currently running processes. You can optionally see system information in the panel with Monitor You can also optionally get a ton of glanceable information shown in the panel. There’s currently a lot of work happening to port Monitor to GTK4 and improve its functionality under the Secure Session, so make sure to report any issues you find! Multitasking The Dock is getting a workspace switcher Probably the biggest change to the Pantheon shell since its early inception, the Dock is getting a new workspace switcher! The workspace switcher works in a familiar way to the one you may have seen in the Multitasking View: Your currently open workspaces are represented as tiles with the icons of apps running on them; You can select a workspace to switch to it; You can drag-and-drop workspaces to rearrange them; And you can use the “+” button to create a new blank workspace. One new trick however is that selecting the workspace you’re already on will launch Multitasking View. The new workspace switcher makes it so much more accessible to multitask with just the mouse and get an overview of your workflows without having to first enter the Multitasking View. We’re really excited to hear what people think about it! You can close apps from Multitasking View by swiping up Another very satisfying feature for folks using touch input, you can now swipe up windows in the Multitasking View to close them. This is a really familiar gesture for those of us with Android and iOS devices and feels really natural for managing a big stack of windows without having to aim for a small “x” button. GTK4 Porting We’ve recently landed the port of Tasks to GTK4. So far that comes with a few fixes to tighten up its design, with much more possible in the future. Please make sure to help us test it thoroughly for any regressions! Tasks has a slightly tightened up design We’re also making great progress on porting the panel to GTK4. So far we have branches in review for Nightlight, Bluetooth, Datetime, and Network indicators. Power, Keyboard, and Quick Settings indicators all have in-progress branches. That leaves just Applications, Sound, and Notifications. So far these ports don’t come with major feature changes, but they do involve lots of cleaning up and modernizing of these code bases and in some cases fixing bugs! When the port is finished, we should see immediate performance gains and we’ll have a much better foundation for future releases. You can follow along with our progress porting everything to GTK4 in this GitHub Project. And More When you take a screenshot using keyboard shortcuts or by secondary-clicking an app’s window handle, we now send a notification letting you know that it was succesful and where to find the resulting image. Plus there’s a handy button that opens Files with your screenshot pre-selected. We’re also testing beaconDB as a replacement for Mozilla Location Services (MLS). If you’re not aware, we relied on MLS in previous versions of elementary OS to provide location information for devices that don’t have a GPS radio. Unfortunately Mozilla discontinued the service last June and we’ve been left without a replacement until now. Without these services, not only did maps and weather apps cease to function, but system features like automatic timezone detection and features that rely on sunset and sunrise times no longer work properly. beaconDB offers a drop-in replacement for MLS that uses Wireless networks, bluetooth devices, and cell towers to provide location data when requested. All of its data is crowd-sourced and opt-in and several distributions are now defaulting to using it as their location services data provider. I’ve set up a small sponsorship from elementary on Liberapay to support the project. If you can help support beaconDB either by sponsoring or providing stumbler data, I’d highly encourage you to do so! Sponsors At the moment we’re at 23% of our monthly funding goal and 336 Sponsors on GitHub! Shoutouts to everyone helping us reach our goals here. Your monthly sponsorship funds development and makes sure we have the resources we need to give you the best version of elementary OS we can! Monthly release candidate builds and daily Early Access builds are available to GitHub Sponsors from any tier! Beware that Early Access builds are not considered stable and you will encounter fresh issues when you run them. We’d really appreciate reporting any problems you encounter with the Feedback app or directly on GitHub.
It’s been a little over 100 days since elementary OS 8 was released, and we’re proud to announce another round of updates, including a fresh new download. We’ve been hard at work this winter addressing issues that you reported and we’ve added a couple new creature comforts along the way. This bug fix release also includes the latest Ubuntu LTS Hardware Enablement Kernel, so it’s worth checking out if you downloaded OS 8.0 and it disagreed with your hardware. AppCenter We now properly use dark mode brand colors and dark mode screenshots thanks to Italo. Plus, when developers provide screenshots for multiple desktop environments, we now prefer the ones intended for our desktop environment, Pantheon. We support the new <Developer> Appstream tag, thanks to Juan. And we now support the contribute URL type. AppCenter now shows dark mode screenshots when available Italo also fixed some issues with release notes overflowing out of their container, and we slightly redesigned the release notes window in the Updates page. He also addressed a few other issues in the Updates page that could occur while things were being updated or refreshed and made sure AppCenter recovers gracefully when its cache is emptied. Release notes dialogs have been slightly redesigned Search is also much faster thanks to Leonhard. And for developers, Ryo fixed loading your local metadata for testing with the --load-local terminal option. Files & Terminal Jeremy fixed another half-dozen reported issues in Files, including an issue that prevented entering file paths in search mode, an issue that prevented scrolling after deleting files, and an issue where files would disappear when dropped on an unmounted drive. The New file submenu now respects the hierarchy of folders in Templates. We now also respect the admin:// uri protocol for opening a path as an administrator, and Files is now styled correctly when run as administrator. He also fixed an issue where Terminal tabs took multiple clicks to focus, and an issue where keyboard shortcuts stopped working for tabs that had been dragged into their own new window. Plus, file paths and names are also now properly quoted when drag-and-dropped from Files into Terminal. System Settings System Settings now allows configuring its notifications in System Settings → Notications. So you can turn off bubbles if you don’t want to receive notifications about updates, for example. We’ll also no longer automatically download updates when on metered connections and send a notification instead, thanks to Leonhard. Plus we no longer check for updates in Demo Mode. Updates now show their download size and you can see progress towards our monthly sponsorship goal In System, Vishal made sure we show how large an update will be before downloading it and that we skip held-back packages—such as phased or staged updates—when preparing the updates bundle so that it will more reliably succeed. Alain added a progress bar while downloading. And Ryo made sure the last refresh time is more accurate when no updates are available. Alain also added a new progress bar that represents how close we are to meeting our monthly sponsorship goal. In Applications, you can now disallow notifications access. This is especially useful for apps which use the notifications portal, but don’t properly report their notification usage and can’t be controlled in the Notifications settings page. Reign in apps that don’t appear in Notifications settings In Network there are two new settings: whether a network should be automatically connected to when available and whether to reduce background data usage when connected to that network. Disable autoconnect or mark a network as metered We also updated the pointer icons in Mouse & Touchpad settings and the checkmarks in Locale settings will now respect your chosen accent color. Plus settings pages with sidebars now remember the width you adjusted them to, thanks to Alain. Installation & Onboarding David fixed a crash with certain partitioning schemes in the Installer’s custom install view. And the Encryption step was redesigned to fit on a single page, solving an issue with confusing navigation. Plus, onboarding will now always stay centered on the screen, even when resized. Panel & Quick Settings Ilya fixed an issue with the panel height when using the Classic session and HiDPI displays. The app context menu in the Applications menu now shows a “Keep in Dock” checkbox, just like in the Dock thanks to Stella. In the Power menu, we now show the device model if available, and avoid erroneously showing an empty battery icon thanks to Alain. In the Sound menu, Dmitry fixed loading album art from certain apps like Google Chrome, and we fixed an issue where player icons could become too large. See who else is logged in and quickly switch accounts from Quick Settings In Quick settings, Leonhard fixed an issue with performing updates while shutting down. And Alain added a new page where you can see which other people are logged in and quickly switch between accounts. Dock Leo added a bit more spacing between launchers and their running indicators, and fixed an issue where larger icons could be clipped at the peak of their bounce animation. Apps who don’t notify on startup will no longer bounce in the dock indefinitely, thanks to Leonhard. We fixed an issue where the dock would still receive click events while hidden in the Classic session. Plus the dock now has an opaque style when “Panel Translucency” is turned off in System Settings → Desktop → Dock & Panel. Window Manager We have another huge release of our window manager thanks to Leonhard and Leo. This release fixes five potential crashes, over a dozen reported issues, fixes related to both the Classic and Secure sessions, issues related to HiDPI, and more, plus performance improvements. It’s worth reading the full release notes on GitHub if you have been waiting for the fix for a specific issue. And More OS 8.0.1 includes the latest long-term support Hardware Enablement stack from Ubuntu, including Linux 6.11. This brings improved performance for AMD processors, support for Intel “Lunar Lake” processors, and filesystem performance improvements in some cases. Plus support for certain webcams, USB network devices, joysticks, and more. Leo fixed an issue where connecting Bluetooth devices could cause the Lock Screen to freeze. You can now close the captive network assistant with the keyboard shortcut Ctrl + Q, thanks to Stanisław. And Alain fixed copying screenshots to the clipboard. We fixed an issue where wired network connections could fail to connect due to a change in Ubuntu. We’re pursuing this issue upstream and working on a way to ship the fix as an update, but for now fixing this issue requires either manual intervention through Terminal or a reinstall. We also now pre-install an AppArmor profile that fixes a number of Flatpak-related issues like not being to install certain runtime updates or apps not launching in the guest session or Demo mode. Special thanks to Uncle Tallest for investigating this issue and helping folks in our Discord who ran into it. And of course this release comes with a ton of translation updates! Special thanks to our hard-working internationalization community and especially Ryo who fixed a number of issues with things that couldn’t be localized properly in the previous release. Get elementary OS 8.0.1 elementary OS 8.0.1 is available as a pay-what-you-can purchase at elementary.io today. Localized direct downloads and a torrent magnet link are provided. OS 8 FAQ Download elementary OS 8.0.1 Sponsors have been able to download OS 8.0.1 release candidates since last week, so if getting things before anyone else is important to you, consider sponsoring us on GitHub
More in programming
We don’t want to bury the lede: we have raised a $100M Series B, led by a new strategic partner in USIT with participation from all existing Oxide investors. To put that number in perspective: over the nearly six year lifetime of the company, we have raised $89M; our $100M Series B more than doubles our total capital raised to date — and positions us to make Oxide the generational company that we have always aspired it to be. If this aspiration seems heady now, it seemed absolutely outlandish when we were first raising venture capital in 2019. Our thesis was that cloud computing was the future of all computing; that running on-premises would remain (or become!) strategically important for many; that the entire stack — hardware and software — needed to be rethought from first principles to serve this market; and that a large, durable, public company could be built by whomever pulled it off. This scope wasn’t immediately clear to all potential investors, some of whom seemed to latch on to one aspect or another without understanding the whole. Their objections were revealing: "We know you can build this," began more than one venture capitalist (at which we bit our tongue; were we not properly explaining what we intended to build?!), "but we don’t think that there is a market." Entrepreneurs must become accustomed to rejection, but this flavor was particularly frustrating because it was exactly backwards: we felt that there was in fact substantial technical risk in the enormity of the task we put before ourselves — but we also knew that if we could build it (a huge if!) there was a huge market, desperate for cloud computing on-premises. Fortunately, in Eclipse Ventures we found investors who saw what we saw: that the most important products come when we co-design hardware and software together, and that the on-premises market was sick of being told that they either don’t exist or that they don’t deserve modernity. These bold investors — like the customers we sought to serve — had been waiting for this company to come along; we raised seed capital, and started building. And build it we did, making good on our initial technical vision: We did our own board designs, allowing for essential system foundation like a true hardware root-of-trust and end-to-end power observability. We did our own microcontroller operating system, and used it to replace the traditional BMC. We did our own platform enablement software, eliminating the traditional UEFI BIOS and its accompanying flotilla of vulnerabilities. We did our own host hypervisor, assuring an integrated and seamless user experience — and eliminating the need for a third-party hypervisor and its concomitant rapacious software licensing. We did our own switch — and our own switch runtime — eliminating entire universes of integration complexity and operational nightmares. We did our own integrated storage service, allowing the rack-scale system to have reliable, available, durable, elastic instance storage without necessitating a dependency on a third party. We did our own control plane, a sophisticated distributed system building on the foundation of our hardware and software components to deliver the API-driven services that modernity demands: elastic compute, virtual networking, and virtual storage. While these technological components are each very important (and each is in service to specific customer problems when deploying infrastructure on-premises), the objective is the product, not its parts. The journey to a product was long, but we ticked off the milestones. We got the boards brought up. We got the switch transiting packets. We got the control plane working. We got the rack manufactured. We passed FCC compliance. And finally, two years ago, we shipped our first system! Shortly thereafter, more milestones of the variety you can only get after shipping: our first update of the software in the field; our first update-delivered performance improvements; our first customer-requested features added as part of an update. Later that year, we hit general commercial availability, and things started accelerating. We had more customers — and our first multi-rack customer. We had customers go on the record about why they had selected Oxide — and customers describing the wins that they had seen deploying Oxide. Customers starting landing faster now: enterprise sales cycles are infamously long, but we were finding that we were going from first conversations to a delivered product surprisingly quickly. The quickening pace always seemed to be due in some way to our transparency: new customers were listeners to our podcast, or they had read our RFDs, or they had perused our documentation, or they had looked at the source code itself. With growing customer enthusiasm, we were increasingly getting questions about what it would look like to buy a large number of Oxide racks. Could we manufacture them? Could we support them? Could we make them easy to operate together? Into this excitement, a new potential investor, USIT, got to know us. They asked terrific questions, and we found a shared disposition towards building lasting value and doing it the right way. We learned more about them, too, and especially USIT’s founder, Thomas Tull. The more we each learned about the other, the more there was to like. And importantly, USIT had the vision for us that we had for ourselves: that there was a big, important market here — and that it was uniquely served by Oxide. We are elated to announce this new, exciting phase of the company. It’s not necessarily in our nature to celebrate fundraising, but this is a big milestone, because it will allow us to address our customers' most pressing questions around scale (manufacturing scale, system scale, operations scale) and roadmap scope. We have always believed in our mission, but this raise gives us a new sense of confidence when we say it: we’re going to kick butt, have fun, not cheat (of course!), love our customers — and change computing forever.
I'm way too discombobulated from getting next month's release of Logic for Programmers ready, so I'm pulling a idea from the slush pile. Basically I wanted to come up with a mental model of arrays as a concept that explained APL-style multidimensional arrays and tables but also why there weren't multitables. So, arrays. In all languages they are basically the same: they map a sequence of numbers (I'll use 1..N)1 to homogeneous values (values of a single type). This is in contrast to the other two foundational types, associative arrays (which map an arbitrary type to homogeneous values) and structs (which map a fixed set of keys to heterogeneous values). Arrays appear in PLs earlier than the other two, possibly because they have the simplest implementation and the most obvious application to scientific computing. The OG FORTRAN had arrays. I'm interested in two structural extensions to arrays. The first, found in languages like nushell and frameworks like Pandas, is the table. Tables have string keys like a struct and indexes like an array. Each row is a struct, so you can get "all values in this column" or "all values for this row". They're heavily used in databases and data science. The other extension is the N-dimensional array, mostly seen in APLs like Dyalog and J. Think of this like arrays-of-arrays(-of-arrays), except all arrays at the same depth have the same length. So [[1,2,3],[4]] is not a 2D array, but [[1,2,3],[4,5,6]] is. This means that N-arrays can be queried on any axis. ]x =: i. 3 3 0 1 2 3 4 5 6 7 8 0 { x NB. first row 0 1 2 0 {"1 x NB. first column 0 3 6 So, I've had some ideas on a conceptual model of arrays that explains all of these variations and possibly predicts new variations. I wrote up my notes and did the bare minimum of editing and polishing. Somehow it ended up being 2000 words. 1-dimensional arrays A one-dimensional array is a function over 1..N for some N. To be clear this is math functions, not programming functions. Programming functions take values of a type and perform computations on them. Math functions take values of a fixed set and return values of another set. So the array [a, b, c, d] can be represented by the function (1 -> a ++ 2 -> b ++ 3 -> c ++ 4 -> d). Let's write the set of all four element character arrays as 1..4 -> char. 1..4 is the function's domain. The set of all character arrays is the empty array + the functions with domain 1..1 + the functions with domain 1..2 + ... Let's call this set Array[Char]. Our compilers can enforce that a type belongs to Array[Char], but some operations care about the more specific type, like matrix multiplication. This is either checked with the runtime type or, in exotic enough languages, with static dependent types. (This is actually how TLA+ does things: the basic collection types are functions and sets, and a function with domain 1..N is a sequence.) 2-dimensional arrays Now take the 3x4 matrix i. 3 4 0 1 2 3 4 5 6 7 8 9 10 11 There are two equally valid ways to represent the array function: A function that takes a row and a column and returns the value at that index, so it would look like f(r: 1..3, c: 1..4) -> Int. A function that takes a row and returns that column as an array, aka another function: f(r: 1..3) -> g(c: 1..4) -> Int.2 Man, (2) looks a lot like currying! In Haskell, functions can only have one parameter. If you write (+) 6 10, (+) 6 first returns a new function f y = y + 6, and then applies f 10 to get 16. So (+) has the type signature Int -> Int -> Int: it's a function that takes an Int and returns a function of type Int -> Int.3 Similarly, our 2D array can be represented as an array function that returns array functions: it has type 1..3 -> 1..4 -> Int, meaning it takes a row index and returns 1..4 -> Int, aka a single array. (This differs from conventional array-of-arrays because it forces all of the subarrays to have the same domain, aka the same length. If we wanted to permit ragged arrays, we would instead have the type 1..3 -> Array[Int].) Why is this useful? A couple of reasons. First of all, we can apply function transformations to arrays, like "combinators". For example, we can flip any function of type a -> b -> c into a function of type b -> a -> c. So given a function that takes rows and returns columns, we can produce one that takes columns and returns rows. That's just a matrix transposition! Second, we can extend this to any number of dimensions: a three-dimensional array is one with type 1..M -> 1..N -> 1..O -> V. We can still use function transformations to rearrange the array along any ordering of axes. Speaking of dimensions: What are dimensions, anyway Okay, so now imagine we have a Row × Col grid of pixels, where each pixel is a struct of type Pixel(R: int, G: int, B: int). So the array is Row -> Col -> Pixel But we can also represent the Pixel struct with a function: Pixel(R: 0, G: 0, B: 255) is the function where f(R) = 0, f(G) = 0, f(B) = 255, making it a function of type {R, G, B} -> Int. So the array is actually the function Row -> Col -> {R, G, B} -> Int And then we can rearrange the parameters of the function like this: {R, G, B} -> Row -> Col -> Int Even though the set {R, G, B} is not of form 1..N, this clearly has a real meaning: f[R] is the function mapping each coordinate to that coordinate's red value. What about Row -> {R, G, B} -> Col -> Int? That's for each row, the 3 × Col array mapping each color to that row's intensities. Really any finite set can be a "dimension". Recording the monitor over a span of time? Frame -> Row -> Col -> Color -> Int. Recording a bunch of computers over some time? Computer -> Frame -> Row …. This is pretty common in constraint satisfaction! Like if you're conference trying to assign talks to talk slots, your array might be type (Day, Time, Room) -> Talk, where Day/Time/Room are enumerations. An implementation constraint is that most programming languages only allow integer indexes, so we have to replace Rooms and Colors with numerical enumerations over the set. As long as the set is finite, this is always possible, and for struct-functions, we can always choose the indexing on the lexicographic ordering of the keys. But we lose type safety. Why tables are different One more example: Day -> Hour -> Airport(name: str, flights: int, revenue: USD). Can we turn the struct into a dimension like before? In this case, no. We were able to make Color an axis because we could turn Pixel into a Color -> Int function, and we could only do that because all of the fields of the struct had the same type. This time, the fields are different types. So we can't convert {name, flights, revenue} into an axis. 4 One thing we can do is convert it to three separate functions: airport: Day -> Hour -> Str flights: Day -> Hour -> Int revenue: Day -> Hour -> USD But we want to keep all of the data in one place. That's where tables come in: an array-of-structs is isomorphic to a struct-of-arrays: AirportColumns( airport: Day -> Hour -> Str, flights: Day -> Hour -> Int, revenue: Day -> Hour -> USD, ) The table is a sort of both representations simultaneously. If this was a pandas dataframe, df["airport"] would get the airport column, while df.loc[day1] would get the first day's data. I don't think many table implementations support more than one axis dimension but there's no reason they couldn't. These are also possible transforms: Hour -> NamesAreHard( airport: Day -> Str, flights: Day -> Int, revenue: Day -> USD, ) Day -> Whatever( airport: Hour -> Str, flights: Hour -> Int, revenue: Hour -> USD, ) In my mental model, the heterogeneous struct acts as a "block" in the array. We can't remove it, we can only push an index into the fields or pull a shared column out. But there's no way to convert a heterogeneous table into an array. Actually there is a terrible way Most languages have unions or product types that let us say "this is a string OR integer". So we can make our airport data Day -> Hour -> AirportKey -> Int | Str | USD. Heck, might as well just say it's Day -> Hour -> AirportKey -> Any. But would anybody really be mad enough to use that in practice? Oh wait J does exactly that. J has an opaque datatype called a "box". A "table" is a function Dim1 -> Dim2 -> Box. You can see some examples of what that looks like here Misc Thoughts and Questions The heterogeneity barrier seems like it explains why we don't see multiple axes of table columns, while we do see multiple axes of array dimensions. But is that actually why? Is there a system out there that does have multiple columnar axes? The array x = [[a, b, a], [b, b, b]] has type 1..2 -> 1..3 -> {a, b}. Can we rearrange it to 1..2 -> {a, b} -> 1..3? No. But we can rearrange it to 1..2 -> {a, b} -> PowerSet(1..3), which maps rows and characters to columns with that character. [(a -> {1, 3} ++ b -> {2}), (a -> {} ++ b -> {1, 2, 3}]. We can also transform Row -> PowerSet(Col) into Row -> Col -> Bool, aka a boolean matrix. This makes sense to me as both forms are means of representing directed graphs. Are other function combinators useful for thinking about arrays? Does this model cover pivot tables? Can we extend it to relational data with multiple tables? Systems Distributed Talk (will be) Online The premier will be August 6 at 12 CST, here! I'll be there to answer questions / mock my own performance / generally make a fool of myself. Sacrilege! But it turns out in this context, it's easier to use 1-indexing than 0-indexing. In the years since I wrote that article I've settled on "each indexing choice matches different kinds of mathematical work", so mathematicians and computer scientists are best served by being able to choose their index. But software engineers need consistency, and 0-indexing is overall a net better consistency pick. ↩ This is right-associative: a -> b -> c means a -> (b -> c), not (a -> b) -> c. (1..3 -> 1..4) -> Int would be the associative array that maps length-3 arrays to integers. ↩ Technically it has type Num a => a -> a -> a, since (+) works on floats too. ↩ Notice that if each Airport had a unique name, we could pull it out into AirportName -> Airport(flights, revenue), but we still are stuck with two different values. ↩
Create a small example app and send payloads from the server to the client using RSC's
Every 6 months or so, I decide to leave my cave and check out what the cool kids are doing with AI. Apparently the latest trend is to use fancy command line tools to write code using LLMs. This is a very nice change, since it suddenly makes AI compatible with my allergy to getting out of the terminal. The most popular of these tools seems to be Claude Code. It promises to be able to build in total autonomy, being able to use search code, write code, run tests, lint, and commit the changes. While this sounds great on paper, I’m not keen on getting locked into vendor tools from an unprofitable company. At some point, they will either need to raise their prices, enshittify their product, or most likely do both. So I went looking for what the free and open source alternatives are. Picking a model There’s a large amount of open source large language models on the market, with new ones getting released all the time. However, they are not all ready to be used locally in coding tasks, so I had to try a bunch of them before settling on one. deepseek-r1:8b Deepseek is the most popular open source model right now. It was created by the eponymous Chinese company. It made the news by beating numerous benchmarks while being trained on a budget that is probably lower than the compensation of some OpenAI workers. The 8b variant only weights 5.2 GB and runs decently on limited hardware, like my three years old Mac. This model is famous for forgetting about world events from 1989, but also seems to have a few issues when faced with concrete coding tasks. It is a reasoning model, meaning it “thinks” before acting, which should lead to improved accuracy. In practice, it regularly gets stuck indefinitely searching where it should start and jumping from one problem to the other in a loop. This can happen even on simple problems, and made it unusable for me. mistral:7b Mistral is the French alternative to American and Chinese models. I have already talked about their 7b model on this blog. It is worth noting that they have kept updating their models, and it should now be much more accurate than two years ago. Mistral is not a reasoning model, so it will jump straight to answering. This is very good if you’re working with tasks where speed and low compute use are a priority. Sadly, the accuracy doesn’t seem good enough for coding. Even on simple tasks, it will hallucinate functions or randomly delete parts of the code I didn’t want to touch. qwen3:8b Another model from China, qwen3 was created by the folks at Alibaba. It also claims impressive benchmark results, and can work as both a reasoning or non-thinking model. It was made with modern AI tooling in mind, by supporting MCPs and a framework for agentic development. This model actually seems to work as expected, providing somewhat accurate code output while not hanging in the reasoning part. Since it runs decently on my local setup, I decided to stick to that model for now. Setting up a local API with Ollama Ollama is now the default way to download and run local LLMs. It can be simply installed by downloading it from their website. Once installed, it works like Docker for models, by giving us access to commands like pull, run, or rm. Ollama will expose an API on localhost which can be used by other programs. For example, you can use it from your Python programs through ollama-python. Pair programming with aider The next piece of software I installed is aider. I assume it’s pronounced like the French word, but I could not confirm that. Aider describes itself as a “pair programming” application. Its main job is to pass context to the model, let it write the output to files, run linters, and commit the changes. Getting started It can be installed using the official Python package or via Homebrew if you use Mac. Once it is installed, just navigate to your code repository and launch it: export OLLAMA_API_BASE=http://127.0.0.1:11434 aider --model ollama_chat/qwen3:8b The CLI should automatically create some configuration files and add them to the repo’s .gitignore. Usage Aider isn’t meant to be left alone in complete autonomy. You’ll have to guide the AI through the process of making changes to your repository. To start, use the /add command to add files you want to focus on. Those files will be passed entirely to the model’s context and the model will be able to write in them. You can then ask questions using the /ask command. If you want to generate code, a good strategy can be to starting by requesting a plan of actions. When you want it to actually write to the files, you can prompt it using the /code command. This is also the default mode. There’s no absolute guarantee that it will follow a plan if you agreed on one previously, but it is still a good idea to have one. The /architect command seems to automatically ask for a plan, accept it, and write the code. The specificity of this command is that it lets you use different models to plan and write the changes. Refactoring I tried coding with aider in a few situations to see how it performs in practice. First, I tried making it do a simple refactoring on Itako, which is a project of average complexity. When pointed to the exact part of code where the issues happened, and explained explicitly what to do, the model managed to change the target struct according to the instructions. It did unexpectedly change a function that was outside the scope of what I asked, but this was easy to spot. On paper, this looks like a success. In practice, the time spent crafting a prompt, waiting for the AI to run and fixing the small issue that came up immensely exceeds the 10 minutes it would have taken me to edit the file myself. I don’t think coding that way would lead me to a massive performance improvement for now. Greenfield project For a second scenario, I wanted to see how it would perform on a brand-new project. I quickly set up a Python virtual environment, and asked aider to work with me at building a simple project. We would be opening a file containing Japanese text, parsing it with fugashi, and counting the words. To my surprise, this was a disaster. All I got was a bunch on hallucination riddled python that wouldn’t run under any circumstances. It may be that the lack of context actually made it harder for the model to generate code. Troubleshooting Finally, I went back to Itako, and decided to check how it would perform on common troubleshooting tasks. I introduced a few bugs to my code and gathered some error messages. I then proceeded to simply give aider the files mentioned by the error message and just use /ask to have it explain the errors to me, without requiring it to implement the code. This part did work very well. If I compare it with Googling unknown error messages, I think this can cut the time spent on the issue by half This is not just because Google is getting worse every day, but the model having access to the actual code does give it a massive advantage. I do think this setup is something I can use instead of the occasional frustration of scrolling through StackOverflow threads when something unexpected breaks. What about the Qwen CLI? With everyone jumping on the trend of CLI tools for LLMs, the Qwen team released its own Qwen Code. It can be installed using npm, and connects to a local model if configured like this: export OPENAI_API_KEY="ollama" export OPENAI_BASE_URL="http://localhost:11434/v1/" export OPENAI_MODEL="qwen3:8b" Compared to aider, it aims at being fully autonomous. For example, it will search your repository using grep. However, I didn’t manage to get it to successfully write any code. The tool seems optimized for larger, online models, with context sizes up to 1M tokens. Our local qwen3 context only has a 40k tokens context size, which can get overwhelmed very quickly when browsing entire code repositories. Even when I didn’t run out of context, the tool mysteriously failed when trying to write files. It insists it can only write to absolute paths, which the model doesn’t seem to agree with providing. I did not investigate the issue further.
Ideals are supposed to be unattainable for the great many. If everyone could be the smartest, strongest, prettiest, or best, there would be no need for ideals — we'd all just be perfect. But we're not, so ideals exist to show us the peak of humanity and to point our ambition and appreciation toward it. This is what I always hated about the 90s. It was a decade that made it cool to be a loser. It was the decade of MTV's Beavis and Butt-Head. It was the age of grunge. I'm generationally obliged to like Nirvana, but what a perfectly depressive, suicidal soundtrack to loser culture. Naomi Wolf's The Beauty Myth was published in 1990. It took a critical theory-like lens on beauty ideals, and finding it all so awfully oppressive. Because, actually, seeing beautiful, slim people in advertising or media is bad. Because we don't all look like that! And who's even to say what "beauty" is, anyway? It's all just socially constructed! The final stage of that dead-end argument appeared as an ad here in Copenhagen thirty years later during the 2020 insanity: I passed it every day biking the boys to school for weeks. Next to other slim, fit Danes also riding their bikes. None of whom resembled the grotesque display of obesity towering over them on their commute from Calvin Klein. While this campaign was laughably out of place in Copenhagen, it's possible that it brought recognition and representation in some parts of America. But a celebration of ideals it was not. That's the problem with the whole "representation" narrative. It proposes we're all better off if all we see is a mirror of ourselves, however obese, lazy, ignorant, or incompetent, because at least it won't be "unrealistic". Screw that. The last thing we need is a patronizing message that however little you try, you're perfect just the way you are. No, the beauty of ideals is that they ask more of us. Ask us to pursue knowledge, fitness, and competence by taking inspiration from the best human specimens. Thankfully, no amount of post-modern deconstruction or academic theory babble seems capable of suppressing the intrinsic human yearning for excellence forever. The ideals are finally starting to emerge again.