Ironically, starting from the former, I've now turned my tmux into the latter with so many utility apps integrated into it. But now I can see the benefits of each approach. Maintaining "super apps" is more challenging due to the coupling of so many pieces to each other.
However, I am suspicious about the dependency of Lem on Webkit, which for me is rather associated with inefficiency and low performance than with the instant reactions that I expect from programming text editors, terminal emulators and tiled window managers.
The main problem is that it is very difficult for any replacement of Emacs to offer everything that already exists for Emacs.
In my opinion, the only way in which such a replacement would succeed would be if it would include an automatic translator from Elisp to CommonLisp scripts executable by it, with equivalent functionality.
I really like Spacemacs. It's discoverable, extendable, quite consistent.
Maybe, why not?
This has always been my problem with adopting Emacs or Obsidian or any other app that purports to do this. Who are y'all working for that you can bring professional stuff onto the same system as personal stuff? I don't want my personal emails on my work computer, and my boss would be rather upset if I brought work emails onto my personal computer. I'd love one of these do everything apps that lets me tag and sync just stuff that ought to be synced.
Lem is great and I'm happy there's finally something out there to challenge Emacs' hegemony, yet pragmatically, unless someone builds a way to run Elisp in Lem, it's unlikely to overthrow Emacs anytime soon, and that's just not gonna happen.
Org-mode, Magit, and thousands of packages aren't just "Elisp code" - they depend on Emacs' specific buffer model, text properties, overlays, markers, the display engine, process handling, and countless quirks packages rely on (intentionally or not). A Lem Elisp interpreter that didn't also reimplement all of that faithfully would run trivial `.el` files and choke on anything real. At that point you've reimplemented Emacs inside Lem.
Elisp is not the biggest point here and Neovim proves that with pivoting to Lua; the crux is the runtime and the corpus, and reimplementing those is the actual mountain. That is real ecosystem for whatever reason you're choosing to simply ignore.
I've got vscode for that.
But I understand this particular horror. I might even agree... :D
People iterating on a problem space over time is the best way we have found to improve things.
The JS ecosystem is not that old and also attempts to solve hundreds of unrelated problems like running software without peoples consent.
Yes, I agree, which is why my tmux slowly devours my numerous small utility apps into itself! I haven't tried Spacemacs yet, too Vim-pilled at the moment..
Probably, though, many are just using personal as not strictly personal, but the kind of personal things you might do while at a desk job.
You do know that Spacemacs defaults to Vim bindings, right?
What it could at least let you do is view JS code using more "Pythonic" syntax rendering. The semantics would still be JS, but you could get rid of the curly braces while you were reading it if you just preferred semantic indentation, for example
I hate to tell ya this... LiveScript was renamed to JavaScript in 1995, and the first ECMAScript standard was published in 1997. So not 40 years old, but 31 years old.
NodeJS (liberating JavaScript from the browser) was first released in 2009... so again, not 40 years old, but old enough to have a drivers license.
I agree with you on the other side though: despite the language being relatively old and stable, it feels like the wheel's getting reinvented over and over again and "this will be a good enough pattern for the next decade" hasn't ever really shaken out, unlike Lisp or even Python.
And... yeah the consent thing is messy. There's a kind of implicit consent in knowing that a user that does not consent can block scripts. But then it can quickly become coerced consent if there's some IRL reason you need to use the page and it absolutely does not work without JS.
That said, I'm a JS-webapp UI guy. Partly that's just what I've built my career on, largely because it was the new field emerging as I was coming up. I could learn things quickly and convert what I learned into a salary. But the second reason is that I'm disillusioned with HTML as the wire format for the web. If you choose to render HTML on your server, you're centralizing costs in a way that will eventually force you towards an extractive relationship with your users. Not only are you centralizing the cost of rendering and transmitting the HTML, but you're also centralizing the cost of building and maintaining the UI layer.
This is (partly) because HTML failed at being a semantic language. There was a brief flicker of hope with XML and XSLT -- for a hot second you could write a compact semantic document and send it over the wire. No longer...
I had to reinvent iteration to get both perf and abstraction at the same time: https://docs.bablr.org/architecture/spacetime
I also had to create records and deep freezing: https://es.discourse.group/t/proposal-records-a-new-one/2546...
I fully agree that it is reaching a more stable place now than it was 5 or 10 years ago. It is still nowhere near as old as elisp.
What would have happened if Emacs' default buffer had been a terminal emulator? Conceptually, from the outside, it would be perceived as a terminal on steroids with Lisp as its scripting language. Maybe we would be talking about iTerm2 vs Emacs, or Kitty vs Emacs, or even Bash vs Emacs. And what if the default buffer had been Dired, the file manager? History might have created rivalries such as Total Commander vs Emacs, or Finder vs Emacs.
But history took another path. We already know that if you launch an Emacs instance without any configuration whatsoever, what you see is a buffer with the following message:
;; This buffer is for text that is not saved, and for Lisp evaluation.
;; To create a file, visit it with ‘C-x C-f’ and enter text in its buffer.
A notepad with an embedded Lisp interpreter. Its natural rival is Vim with an embedded interpreter (Vimscript). However, the editor that made us all memorize :q! stayed in the buffer, while Emacs kept expanding with more and more software until it became an interface to the operating system.
I'm an Emacs enthusiast, and maybe that costs this article some credibility. However, I'm not here to tell you how fantastic the GNU editor is, nor to convince you to use it. My goal is to explain why the web browser is its true natural rival, and why Emacs is a Lispboard where you build the way you want to work.
To set the stage, let's do a little thought experiment.
Suppose I want to work in a single place for all my contexts, both personal and professional. That way I memorize my shortcuts, apply my configurations and never have to switch contexts. Everything lives under the same window.
It's a problem, because it means merging programs that have nothing to do with each other but need to collaborate. For example, a terminal emulator, an email client and a code editor (or IDE). With a layout system, inside the same window, I could have one column with my email inbox, another with the terminal and a third with my IDE ready to write whatever I need. In this space, it would be easy to write a bash script, launch it from the terminal and receive an email with the result. All in the same window, without switching context, with the same shortcuts, the same typography and the same theme. I could even add a fourth column with a Git client to version the script and push it to a remote repository. Or while we're at it, a fifth column with my favorite AI agent, able to read both my code and the rest of the panels.
We have just created an interface.
But this wouldn't be the most useful part: the programs would be integrated with each other, each one living in its own scope and, at the same time, in a global one. That means that if I enable the spell checker in the code editor with a certain configuration, it also becomes active in the terminal, in the email client when composing messages, or when I write commits. All with the same interactivity and configuration. They are not four isolated binaries connected with pipes: they are programs written in the same language, running on the same runtime and sharing the same event bus.
We have just created a connector.
Now let's remove an unnecessary layer: the bash script. If I already have an interpreter embedded in this very window, I can create my own scripts. I don't need an external binary. I no longer need to leave the window, nor touch the operating system. All my scripts, prototypes and workflows can live together.
We have just created a habitat.
There's only one problem left with the runtime: tomorrow I'll change laptops, or I'll want to work from a server, and I have no intention of rebuilding my environment from scratch. I want my scripts to work exactly the same regardless of the operating system and the hardware. A script should behave the same way on Windows, on a Raspberry Pi or on a cheap Android device. I need the whole environment to be a cross-platform runtime with bytecode that runs anywhere.
We have just created a virtual machine.
Now, to round off the idea, we'll use Lisp as the scripting language and we'll call the whole thing Emacs. Although I prefer to call it something else: a Lispboard. Like an electronics breadboard, a board where every module you plug in shares a bus with all the others, except here the modules are written in Lisp.
And if during this exercise you thought "this sounds familiar: tabs, applications and a cross-platform virtual machine... that's my browser", hold on to that intuition. We'll come back to it at the end of the article.
With everything mentioned so far, I want to debunk some myths surrounding Emacs:
What it is: a Lisp interpreter and a framework that run on top of the operating system in the most agnostic way possible, and that reimplement a good part of the programs it offers.
When you think: "I'm going to write a simple bash script to automate a task", I think: "I'm going to write an Elisp function". And on top of that, I'll give it a graphical interface if I need flags or text input.
For example, suppose you need to create a script for yourself, not for a CI/CD process or cron. The goal is to back up a specific folder (maybe to the cloud). You could end up with a command like this:
./backup.sh /home/user/folder /home/user/backup
But you also include a flag to create a zip:
./backup.sh -z /home/user/folder /home/user/backup
Well, instead of going through the terminal, I create an Elisp function that does the same thing, and I add a small panel to it.
I run:
M-x my/backup RET
And a buffer will show up with an interface like this:
Folder backup
Folder: [ /home/user/folder ]
Target: [ /home/user/backup ]
[ ] Compress into zip
[ Cancel ] [ Run ]
With inputs, checkboxes and buttons. Without having to remember where it was, or its parameters, or their order.
If you have worked with Lisp before, you'll see the code is very basic:
(require 'widget)
;; Logic
(defun my/backup-run (folder target zip)
"Sync FOLDER into TARGET with rsync, or compress it to a zip when ZIP."
(let* ((folder (expand-file-name folder))
(target (expand-file-name target))
(command
(if zip
(format "zip -r %s %s"
(shell-quote-argument
(expand-file-name
(format-time-string "backup-%Y-%m-%d.zip") target))
(shell-quote-argument folder))
(format "rsync -a %s/ %s"
(shell-quote-argument folder)
(shell-quote-argument target)))))
(async-shell-command command "*Backup log*")))
;; UI
(defun my/backup ()
"Open a panel to back up a folder."
(interactive)
(switch-to-buffer "*Backup*")
(kill-all-local-variables)
(let ((inhibit-read-only t))
(erase-buffer))
(remove-overlays)
(widget-insert "Folder backup\n\n")
(let* ((folder (widget-create 'editable-field
:format "Folder: %v\n"
"/home/user/folder"))
(target (widget-create 'editable-field
:format "Target: %v\n"
"/home/user/backup"))
(zip (widget-create 'checkbox nil)))
(widget-insert " Compress into zip\n\n")
(widget-create 'push-button
:notify (lambda (&rest _) (kill-buffer))
"Cancel")
(widget-insert " ")
(widget-create 'push-button
:notify (lambda (&rest _)
(my/backup-run (widget-value folder)
(widget-value target)
(widget-value zip))
(kill-buffer))
"Run"))
(use-local-map widget-keymap)
(widget-setup))
And this scales beyond toys. With this same approach I have built systems of all kinds. For example, this blog's newsletter: I manage subscribers, generate the emails' HTML from org files, send them out, send myself previews and analyze the data. All in Elisp, local, and with a simple control panel integrated with other tools.
The key of the example is that I'm not writing a script for an operating system or an interpreter, but a function for my working environment. I'm building a new workflow, in a space where I can program my own tools, connect them to each other or build one on top of another. I could create an asynchronous notification system to alert me when something finishes, and later connect it to the previous tool at no cost.
And I can do all of this because I have an embedded scripting language, a set of libraries (like widget.el to build graphical interfaces) and a cross-platform runtime that guarantees my scripts will work the same on any operating system. That is a Lispboard.
I want to stress that I separate tasks or environments by tabs. And inside each tab I have a layout with the buffers (or software) I need.
In the IDE tab I usually open:
Although I keep weaving in temporary ones such as the file manager (Dired, with or without TRAMP), the terminal (vterm), the HTTP client (verb), Docker (docker.el), the web browser (eww) or the project manager (Projectile).
Working in Emacs with this level of integration is a pleasure that's hard to describe. You understand why it makes those who program in it fall in love.
Everything I think, plan or study ends up in plain text. The foundation is org-mode: notes, tasks and planning. On top of it, I manage my study notes with Denote: each note is a file with the metadata in its own name, all linked to each other. And when the study material is a PDF or an EPUB, I read it without leaving, with pdf-tools or nov.
Around them orbit small pieces that complete the routine, like jit-spell underlining my mistakes on the fly (remember the spell checker you configure once and it works everywhere? This is it) and wallabag to read or save articles I want to study later, calmly.
Although it may not seem like it, over the decades the community has built an excellent pack of communication tools. Even for the same protocol there are several implementations, and each one has its advantages.
In my case, I have a tab exclusively for email with mu4e. It covers every need I can expect from an email client: composing, replying, forwarding, filtering, searching, tagging, marking as read/unread, etc. And it had better do it well, because it's the most important communication channel I have: mailing lists, discussions around a Pull Request, messages from other developers, service notifications, and everything that comes with a personal and professional life.
In another tab I keep a set of chats:
I only leave for Teams and Discord, both communication channels at my job. And WhatsApp, whose use in Emacs still doesn't convince me.
My main source of information is RSS with Elfeed, almost all personal blogs. I use clients for the aggregators, hackernews-modern and lobsters (both made by me). With Gnus I read some Usenet newsgroups (it's still alive, and it reads wonderfully) and with Elpher I wander around Gemini and Gopher. When I want to open a web link, I give eww, the Emacs web browser, a chance. If it's unreadable, then I go to Firefox or the like (I have a shortcut).
The workday is more pleasant with some music playing, hence EMMS backed by mpv. And when I want to disconnect for a while, I like playing chess with chess, either alone or with a friend online. After all, the board is also there to have fun.
The community has an expression for this way of working: living in Emacs. People have been writing about it for decades, and at the end of the article I leave you the readings that have marked me the most. But notice that living in Emacs describes a habit; what I have tried to show you is the consequence. Everything you've seen is not a collection of programs, it's a single board where every module shares a bus with the rest. An interface, a connector, a habitat and a virtual machine (literally: Elisp compiles to bytecode). A Lispboard to play with, or to make your work more efficient.
Its rival is the web browser. It meets more of the requirements than we like to admit: it's a cross-platform virtual machine (for JavaScript) and half of humanity lives inside it, with their email, their chat, their music and their office suite. But it fails at the essential part: tabs are silos that don't share a bus, you can't wire your email to your chat, and no module is yours: each one belongs to a third party that can change it, fill it with ads or shut it down tomorrow. On top of that, access to the host itself is limited: it's not easy to touch the disk or talk to the operating system. The browser is a rented Lispboard, with a landlord. Emacs is the only one you can own.
To wrap up, I want to make clear that using Emacs is not nostalgia: it's that nothing comparable has appeared yet. The 0.1% of us who use it and squeeze it daily do so because it lets us work in a way no other software allows. We will probably have a lifelong relationship with our configuration. There's always something to tweak, improve or automate. And if there isn't, we create it. Emacs is not free because of its GPL license, but because it's the only place where you can live and work your way.