We all want apps that are easy to run, easy to build and easy to modify. What I call freewheeling apps accomplish this via 3 constraints:
- They depend on a tiny, stable, widely-available platform that is itself open and easy to build.
- They come with all source code and can be edited without lots of tooling and with good error messages when you make mistakes.
- They encourage promiscuous forking, and help direct people to the best fork for their needs.
Compared to other systems in the Malleable catalog, there are few affordances for configuring apps without modifying the source code. I believe that any malleability at the product level is inherently self-limiting. The way to support arbitrary recombination and reuse is to expose the naked code of an app. (Whether it’s textual or graphical, whatever the author uses to create it.) The challenge then is to keep the app simple enough that people of all levels can make changes to its code, even before they know much about programming.
The biggest lever in building freewheeling apps comes from the choice of platform. Constraint 1 sets a high bar, and so far the winner seems to be LÖVE, a minimalist game engine for programming in Lua. Lua is 12kLoC and extremely easy to build. LÖVE itself is larger and more complex, but still easiest to build among the alternatives. And it provides prebuilt binaries for the major PC OS’s. To run one of my freewheeling apps, just download one 5MB binary for your OS.
Other platforms seem like larger compromises. Most languages and IDEs are unconcerned about sprawling dependencies and so non-trivial to build from source. Uxn is excellent for tiny apps but the absence of types makes it easy to trample over memory and hard to give good error messages when you do. You’re also on your own to build it on Windows. Pico-8 is not open source, but its TIC-80 clone might be worth considering for apps that can make do with a 240x136 pixel screen. It does have the advantage of supporting mobile platforms, which is worth considering even if it gives up some stability in the build processes. LÖVE on the other hand emphasizes stability; most APIs have changed little in 8 years, and new releases happen every 1.5-2 years.
All the freewheeling apps I’ve built so far are editable in one of two ways:
- Some of them can be edited from inside the app using a keyboard shortcut. The app stops while being edited.
- Newer ones can be edited while they run, by opening up a second freewheeling app (driver.love). Same 5MB platform, new ~5KLoC of Lua. The driver can also be edited using a second meta-driver, which differs from the driver in just 3 lines of code.
The editing tools are not yet mature; I periodically need to bump down to more powerful tools. This has been getting rare though with the driver, and I’m starting to prefer using these tools for UX ideas like:
Most freewheeling apps so far have been created by modifying an existing freewheeling app. Starting with the initial app – a plain text editor – each repo’s Readme (example) points to the upstream repo it was forked from and its downstream forks. I’m trying to foster a culture of inclusivity in listing forks for others to discover even if they make changes that upstreams disagree with and compete for attention. The hope is that forks will provide an escape hatch and keep any individual app from growing increasingly complex over time.
Very interesting, I need to check these out in more detail soon!
About forking, I wonder if it would help to support the whole fork creation and publishing workflow from inside these kinds of apps so you can stay “in the flow” of app while still sharing your changes with others? That could be a lot of work to add to this kind of platform though…?
This is a good idea that’s been on my mind as well. There’s two impediments:
The way LÖVE apps work introduces some mechanical difficulties. There’s no platform-independent API to open other programs like git. Even just sharing changes with others is non-trivial due to such limitations. LÖVE doesn’t permit modifying the app, so mutated files live in a different directory and you have to manually move them from outside the app before you can share your changes with others. Maybe these should be dealbreakers for using LÖVE…
I have some rudimentary support for tracking version history within the app, and I distribute them using git, and the two currently don’t work well together at all. If you fork my app, make some edits and then
git pull the app breaks completely. I need to completely rethink the on-disk representation of these apps.
I really like the command palette and spatial interfaces. I’m curious about what the target audience would be and how apps should be distributed. Are you imagining this as a more app-driven alternative to the web or would apps be sent from individual to individual?
There are lots of possibilities here.
I think it’s possible to have a web for documents and hyperlinks (think Web 2.0 blogosphere or Gemini) separate from a web for sandboxed applications. If you have a good sandboxing model built into the OS, you might be able to safely
curl |install to the point where needing a bazillion-LoC web browser to run sandboxed apps will seem perverse.
In the absence of that sandbox, I think it’s still possible to feel more comfortable locally installing a minimalist app with open sources by someone you trust than you would running a web app by some faceless behemoth that runs on a web browser built by a second or potentially same faceless behemoth.
Either of these feels like an improvement over the world we have. And they aren’t the only options.
I like this approach a lot. To the point that I have actually played with your LÖVE apps. Which works as advertised!
However, my main target platform would be Android, because I am transferring more and more of my workflows to my Android e-book reader, which is both portable and has an eye-friendly e-ink screen. There’s LÖVE for Android, and your apps work fine on it. However, there is what I see as a major restriction: you can add only pure Lua code, not anything that requires compilation. With many Lua libraries building on compiled C code, that becomes a serious restriction.
The platform I plan to explore next is Emacs, which was just published for Android (on F-Droid). While it’s not very convenient to use Emacs as an editor without an external keyboard, it looks very doable to prepare a freewheeling app with a keyboard (or even on a desktop) but use it via the touch screen.
Yes, I really appreciate you trying them out, @khinsen. And I’m very glad you’re experimenting with Android, that’s certainly in the freewheeling ethos.
Are you able to compile native libraries for Emacs on Android? Or does it have more batteries included? Or does it support installing any Emacs package from ELPA?
Also, I’m curious if there were specific Lua libraries you found yourself wishing for.
Emacs for Android comes with a lot of Unix utilities precompiled. I don’t know yet if it can use Termux binaries, that would be a sufficient supply. I guess the binaries should work, but probably Emacs cannot access them where Termux puts them, due to Android’s sandboxing. ELPA is supposed to work, but probably not ELPA packages that compile C code (sqlite comes to mind).
As for Lua libraries, I am mostly looking for system and network interfaces. Sending and receiving mail, for example, as I use mail as the main messaging system between my devices. The only Lua library I found that looked adequate(SMTP and IMAP support) required compiled C code for socket access. And I didn’t find anything at all for Android-specific stuff, such as accessing sensors, location, etc.
Another platform I have briefly looked at it Common Lisp (via Common Lisp REPL app for android and iOS). What I dislike there is Qt as only way to get any form of GUI support. Much too heavyweight for my taste.
Yes, LÖVE comes with socket access precompiled in but only for http. Https is in v12, but there’s no ETA on when it will be available.
Android-specific stuff like sensors and location is hard for any option right now, right? You need to compile an Android app with those primitives and publish it? Does any programmable Android app give you clean access to them?
Ooh, there’s some support for Android sensors in v12 as well!
Aside: I recently installed F-Droid, and it’s come along a lot over the years. I didn’t need to root my phone or anything. This has definitely started to get some gears turning in my head.
v12 sounds promising!
The best programmable interface to Android I know of is Termux. It comes with command-line utilities that contain Android interfaces. But Termux is fragile, it might not work with future Android versions. The current version is no longer allowed on the Play Store, for example, for violating recent Google guidelines. You need F-Droid to get Termux. And of course there is no GUI support at all, other than running an X11 server (which I consider unusable).
Ah hmm, but your “driver” app can edit the code of another app while it runs… Is that a different mechanism from “modifying the app” that’s being blocked?
Maybe the whole source of the app could live in (maybe dumped there on first startup…?) the “mutated files” place to start with.
Is that a different mechanism from “modifying the app” that’s being blocked?
Yeah. First, the app is never blocked. Second, the driver isn’t editing the code directly. Instead it’s querying the app over a back-channel in various ways, displaying the results, sending changes back to the app.
Maybe the whole source of the app could live in (maybe dumped there on first startup…?) the “mutated files” place to start with.
The way it works is:
- LÖVE can read from 2 locations: the running app (directory or zip file) and a “save directory” corresponding to the app, something like
~/.local/share/love/<app>/. The two locations are shadowed: if a path exists in the save directory it’s read from there, otherwise the app directory/zip.
- LÖVE can only write to 1 location: the save directory.
I actually don’t know what would happen if you cloned an app to
~/.local/share/love and tried to run it from there. Probably something bad Worth an experiment!
(maybe dumped there on first startup…?)
The hard part isn’t getting stuff into the mutated files place, it’s getting it out. Eventually you have to go to that directory to manually
%APPDATA% seems like a difficult place to instruct newcomers to download to…
Pretty interesting @akkartik! I wonder if you have a social context or community of practice where you can test your apps/ideas and their usage/adoption beyond a single user. In my case such community, born in the local hackerspace, was one of the major advantages of my inquiries/research regarding malleable systems.
We, at the Grafoscopio community have used Lua as part of our self publishing toolkit. For example, we made the customized Pandoc filters to deal with the limitations of Markdown and translate the HedgeDoc extended syntax for admonitions to produce the equivalent one for the PDF version of Documetathon: agile and resilient tools and techniques to write and publish together (Spanish). Thanks to Lua, we can take custom markup like
:::warning and create a beautiful PDF output admonitions, via LaTeX, like this:
Regarding portable notes in Android, @khinsen , what I’m using is TiddlyWiki (TW) on Android (I think is called Tiddloid or something like that). It’s is pretty responsive and I could, in the future, synchronize notes between devices, thanks to TW’s JSON storage and version them via TiddlyWikiPharo.
Unfortunately I haven’t yet found a community that finds my work useful. The social context so far has been:
- Needs I find in my own life.
- Little toys for my kids. e.g. I built a matrix of the numbers to 100 because my son asked why his wooden number board didn’t have 0. A program to enumerate anagrams of my kids’ names. A little gravity simulator. The end of that list starts feeling like a stretch, where I’m having fun and my kids aren’t really benefiting.
- One person in the LÖVE community who wanted to use one of my apps on an iPad. So I spent some time making something that worked for them. Initially I was just sending them builds to test since I don’t own an iPad. But eventually it became clear that what they wanted was subtly different from what I offered, and I made a custom app for them. Before; After.
As I said, I’d appreciate suggestions on finding a real context for this sort of work. In particular, do keep me in mind as y’all continue to work with Lua. If there’s a tool you need or a question you’d like to chat about I’d love to help. I don’t know Spanish, which creates some barrier. But my kids are learning it, so I wouldn’t mind being immersed in it. My LÖVE app is certainly not comparable with Smalltalk when it comes to the fluidity with which one can bounce from source code to running behavior and back. Yet. I’d be happy to brainstorm specific things you wish you could improve.
I am using Tiddloid as well, mostly for consulting my org-roam database on my Android devices. That was my first use of TiddlyWiki, which I started exploring following your experience reports on the GT Discord. For now it’s a one-way conversion, though I hope to make it bi-directional in the future.
Overall I find TiddlyWiki quite suitable for consulting information and for light edits. For a mobile device, that’s OK. On the desktop, I can’t get used to in-browser editing for larger tasks. Which is why Emacs remains my primary platform for notes.
So, my proposal is: let’s find a social context and a (learning/usage) need there and let’s see if some synergy can bootstrap malleability in such community/context. This was roughly my research approach. Let’s see if we can use it also to bootstrap some conversations among us, here and with the external communities.
Let me know what you think of this staring project.
I use TW mostly for small edits, in browser, desktop and mobile. But my writing is also split between:
- GT for coding and data narratives/visualization
- TW for almost anything else (quick notes, TTRPG’s)
- HedgeDoc for online real-time collective notes (workshops and classes), Zettlr for offline Markdown (mainly for my students).
- minor usage of VS Codium/Code, TextAdept, for non Pharo code,
- TeXmacs for most of my “sciency/mathy/structured” documents, and
- LibreOffice for legacy documents I exchange with work colleagues.
- Minor explorations of Doom Emacs, but I need to fight a lot against my muscle memory and get lost in some mode (despite enabling CUA).
- Sometimes Leo, which was one my primary outliner (ala OrgMode) for several years and one of the primary inspirations for making my own one in Pharo, called Grafoscopio, as you may know.
So it’s a pretty fractured writing experience, informed by several tools/places/traditions. As I have been migrating some lessons from Grafoscopio to Lepiter/GT, mainly with the MiniDocs package, the writing experience is mostly happening between GT and TW, with minor spicing from those other tools/places. Pharo/GT are my malleable desktop system, while TW is the web counterpart, with TiddlyWikiPharo as a bridge.
I would like something with the outlining capabilities of Leo/OrgMode, the programming capabilities of Pharo/GT and the writing experience of TeXmacs. Grafoscopio was my attempt to combine several traditions and put such combination in a particular social context (our local hackerspace). But there is still a long path ahead. Maybe with the recent port of Lepiter/GT to Android, we could have a more integrated multidevice writing experience for short and long notes. While this evolves, I still will need this combination of tools, with Pharo/GT as our main enabler of what we call interstitial programming: extending sociotechnical systems by addressing/changing what happens in the gaps/bridges in between.
Wow… another long pots… it seems that I have been missing you people to nerding out stuff
Are you thinking about totally replacing the JS of TW with Lua? Or something more targeted?