[[!meta title="æmacs: having a hoot with a guile emacs"]]
[[!meta copyright="Copyright © 2026 Akira Kyle"]]
[[!inline pages="internal(2026/info/guile-nav)" raw="yes"]]
# æmacs: having a hoot with a guile emacs
Akira Kyle (he/him) - , @akira.social on bsky, @akyle@mathstodon.xyz on fediverse,
[[!inline pages="internal(2026/info/guile-before)" raw="yes"]]
I spend most of my computing time split between two programs: Emacs and a
web browser, and only one of them sparks joy. That's what drove my
pandemic project, emacs-webkit, which put a browser inside pgtk Emacs. I
came away thinking the more emacs-y design would be the other way around:
an emacs that lives within the web platform. I've since tried starting on
it more times than I'd like to admit, from attempting to rebase the
original guile-emacs, to deleting as much C as I could get away with, to
compiling Emacs with emscripten. Each attempt left me better
understanding how GNU Emacs became *the* emacs, but the human-hours
needed to disentangle, let alone port, the [horrors](https://emacshorrors.com/) from the depths of `src/` haunted
my dreams.
Meanwhile, pieces of this puzzle of bringing emacs 2 da web
started falling into place. In 2023 the Spritely Institute announced
Hoot: compiling Guile Scheme to WebAssembly with Wasm GC. Then at
EmacsConf 2024, Robin Templeton announced the revival of the OG Guile
Emacs, building on work by Larry Valkama (lyrra), who successfully
rebased the decade-old branch onto GNU Emacs 31. Finally, LLM agents
started seemingly autonomously coding compilers from scratch. With
human-hours apparently no longer a barrier, why not try? After all, if
the web is evolving toward a polyglot wasm environment, it ought to have
an emacs! I'd either find out the limits of agentic coding, or end up
with my "perfect emacs" (a win-win, or so I thought).
æmacs is the
result: my apologetically vibe-coded step towards that idea. The æmacs
frontend is implemented in Guile, compiled to wasm with Hoot, and renders
the UI in a webview. The backend is my fork of lyrra's exploratory
"guilemacs" branch, which, after a year of slogging through slop, is now
a pure Guile Scheme implementation of Emacs Lisp: no C `src/` horrors
remain! All state lives in this backend, which talks to a frontend over a
sexp websocket protocol, letting the UI render on a different machine.
Perhaps someday, Hoot may compile guilemacs itself for the browser.
æmacs/guilemacs breaks with full GNU Emacs compatibility (e.g. unicode
only), but loads most of Emacs' lisp/ unmodified, plus packages like
org-mode and magit. Focusing on bootstrapping myself into æmacs as my
main editor has kept the scope somewhat sane. But bootstrapping an editor
with LLMs inevitably led to bootstrapping a coding harness into it too.
gptel-agent allowed me to retreat from Claude Code's we-know-best,
one-size-fits-all TUI back into the zen of an emacs' diy kitchen sink,
and vibe code æmacs inside æmacs.
That's how I got what I've wanted since
I started using Emacs: smooth, continuous, inertial scrolling, not just
through org-mode buffers full of images, but through PDFs with aemacs-pdf
and web pages with aemacs-webkit. Doing this takes hacks in GNU Emacs,
but no disrespect, emacs is built for hacking. Unfortunately, while LLMs
never tire of hacking, I do. The limits I found were my own, but at least
æmacs is now my imperfect emacs.
About the speaker:
I'm a PhD
student who has been trying to live inside emacs for over a decade. I've
desperately wanted org literate notebooks with inline interactive
plotting, so I wrote emacs-webkit as a pandemic project. I came away from
thinking it would be far more Emacs-y to have Emacs run inside a browser
instead. Unfortunately the estimated human-hours of work were far too
much, even for a grad student. So the idea percolated until it seemed
like maybe it might be possible to prototype with LLM assistance. This is
the story of my journey so far with emacs, web browsers, and now
for-better-and-worse, LLM agents.
[[!inline pages="internal(2026/info/guile-after)" raw="yes"]]
[[!inline pages="internal(2026/info/guile-nav)" raw="yes"]]