Jack Baty: Installing Fedora Workstation on the laptop

My laptop has been running Fedora’s KDE spin. I first tried the stock Fedora with Gnome, but since my desktop was running KDE, I figured I should standardize on that.

Standardization is boring. :)

I installed Fedora Workstation this morning. I’d taken notes from the last time, and those helped speed things along. Still, it was 2 hours from installer to a fully functional system. I’m typing this post in Emacs and will deploy using Hugo shortly.

For the record, here are my raw notes from the installation. I need to work on the order in which I do things, but this wasn’t bad.

Installing Gnome on the Framework 2026-02-03

- sudo dnf install syncthing
- Settings
    - Trackpad -> Disable tap to click
- Install Gnome Tweaks
    - set caps lock to control
    - Emacs Input on
- sudo dnf install -y stow just fzf zoxide ripgrep
- Install Extension Manager (Flatpak)
- Installed Dash to Dock extension (via Extension Manager)
- Installed Clipboard Indicator extension (via Extension Manager)
- Installed starship curl -sS https://starship.rs/install.sh | sh
- stow bash
- stow pandoc
- sudo dnf install pandoc
- sudo dnf install texlive-scheme-full
- sudo dnf install neovim
- sudo dnf install rust cargo # (for eza, since eza is no longer in fedora repos)
- Build and install eza
    git clone https://github.com/eza-community/eza.git
    cd eza/
    cargo install --path .
- Add berkely-mono to ~/.local/share/fonts/berkeley-mono
- sudo dnf copr enable dejan/lazygit
- sudo dnf install lazygit
- Install Signal (Flatpak)
- stow auth
- stow git
- stow gnupg
- stow jrnl
- stow pass
- stow ssh
- stow aerc
- sudo dnf install aerc
- sudo dnf install emacs
- Configure emacs
    - git clone https://github.com/jamescherti/minimal-emacs.d.git ~/.config/emacs
    - git clone [my dotemacs repo] to ~/.config/emacs-mine
    - cp ~/.config/emacs-mine/pre-early-init.el ~/.config/emacs/
    - ln -s ~/Sync/emacs/manual-packages ~/.config/emacs-mine/
- sudo dnf install fastfetch
- Add "Start Syncthing" to Startup Applications in Gnome Tweaks app
- Install FireCode Nerd Font
- ...a nearly infinite number of little tweaks that I didn't record.

Since the laptop is meant to be a sort of satellite computer orbiting my desktop Mac Mini, I don’t need everything installed. The above covers just the basics.

One day I should write a script that takes care of this for me.

✍️ Reply by email
-1:-- Installing Fedora Workstation on the laptop (Post Jack Baty)--L0--C0--2026-02-03T17:01:27.000Z

Irreal: How Punchagan Lost His Elfeed Database

A couple of weeks ago, I wrote about how Punchagan over at NOETIC NOUGHT started saving his Elfeed database after he lost it in a system crash. At the time, Punchagan didn’t know exactly what happened, only that the system crashed and he lost his Elfeed database. He wasn’t even sure that the two events were related, only that they occurred at the same time. His solution to the problem was to set up periodic saving of his Elfeed data to git.

A little later he had some time to troubleshoot the problem and discovered what happened. The Elfeed database is basically a hash table and saving it is simply a matter of dumping the binary to a file. This happens inside a with-temp-file macro, which is much like the more familiar with-temp-buffer macro except that it saves the results to a file at the end. The saving is done with write-region, which first truncates any existing file.

What happened, apparently, is that the system crashed between the truncation of the old file and writing the new file. Sadly there’s not much that can be done at the user level other than saving the file periodically.

I liked this post because it shows how easy it is to simply follow the code—which is, of course, available whenever you’re running Emacs—to see what’s happening. Emacs, to be sure, has more sophisticated tools for debugging but often simply looking at the code will reveal what’s going on. Punchagan’s post reminds me of Sacha Chua’s post on figuring out how to edit an SVG file and its source at the same time. She figured out how to do this the same way as Punchagan solved his problem: by reading the source code to see where the undesirable behavior was happening.

-1:-- How Punchagan Lost His Elfeed Database (Post Irreal)--L0--C0--2026-02-03T15:29:45.000Z

Sacha Chua: 2026-02-02 Emacs news

Links from reddit.com/r/emacs, r/orgmode, r/spacemacs, Mastodon #emacs, Bluesky #emacs, Hacker News, lobste.rs, programming.dev, lemmy.world, lemmy.ml, planet.emacslife.com, YouTube, the Emacs NEWS file, Emacs Calendar, and emacs-devel. Thanks to Andrés Ramírez for emacs-devel links. Do you have an Emacs-related link or announcement? Please e-mail me at sacha@sachachua.com. Thank you!

View org source for this post

You can comment on Mastodon or e-mail me at sacha@sachachua.com.

-1:-- 2026-02-02 Emacs news (Post Sacha Chua)--L0--C0--2026-02-02T20:03:41.000Z

Irreal: Exporting From Org To Docx

JR over at The Art Of Not Asking Why has a useful post on exporting an Org document to Docx. I’ve written about this before [1, 2, 3] and you might wonder why. After all, you can simply export directly from Org to ODT and get a Word compatible document.

The problem occurs when you’re working in an environment that requires a specific style implemented with a Word style sheet. The native Org exporter doesn’t support this so the usual solution is to use Pandoc, which does support a Word style sheet.

JTR’s post has a step-by-step recipe for making the conversion and setting up a Word style sheet using a reference document with the desired settings. He even covers the difficult areas of images and tables, which, of course, require further machinations.

None of this would be necessary if Word and its siblings would use plain text instead of an arcane, opaque file structure to store the document. After all, it’s certainly possible as Org—or, if you require even more complicated output, TeX/LaTeX—show. But, of course, that would stand in the way of editor lock in.

Regardless, if you have to produce Word documents but prefer to write in Org, take a look at JTR’s post. He shows you how to produce a good looking Word document from an easy to write Org file. He even shows how to automate the process using Álvaro Ramírez’s dwim-shell-command.

-1:-- Exporting From Org To Docx (Post Irreal)--L0--C0--2026-02-02T16:15:51.000Z

Marcin Borkowski: git-link

I have recently discovered a great little package called git-link. It is a wonderful addition to Emacs’ Git-related capabilities. Its purpose is to create links to various Git repositories (it supports GitHub, BitBucket, GitLab and several others) based on where the point is.
-1:-- git-link (Post Marcin Borkowski)--L0--C0--2026-02-02T06:00:38.000Z

TAONAW - Emacs and Org Mode: Org files to beatiful docx files with Pandoc

When it comes to sharing written documents with my co-workers, I usually need to use Word or PDFs. Org-mode includes an export option to odt files, which does the job in a pinch, but it’s a bit harder to customize, especially if I want to preserve certain formatting elements. In the past, I used to create ODT files, import them into Word, make whatever changes I needed, and save them in a docx file. The problem there, besides the manual work, is consistency. If I want to make sure I use the same style for fonts, header sizes, and table formats, things get annoying fast.

About a year ago, I discovered that Pandoc can use an external Word document (docx) as a style template. As long as I have this file accessible, every org file I convert to docx will automatically (and beautifully, I may add) retain the exact style changes I need. This, of course, can be automated later inside Emacs, so the export process is basically seamless.

The problem lies in the fact that you need to work with Word and understand how its styles. Readers of this blog know I love to complain about Microsoft’s UI and its lack of consistency, and the instructions here are one fine example in my opinion. Be it as it may, I will try to keep the snarky comments in check.

Creating the default style sheet

The first thing to do is get Pandoc to create its default style reference document as a .docx. This can be done with pandoc -o custom-reference.docx --print-default-data-file reference.docx.

What you’re telling Pandoc here is to output (-o) a file named custom-reference.docx (you can call it whatever you’d like, as long as it’s a docx, since you want to work with Word). What to output goes into this file? The default reference document.

Once you do that, you will have a custom-reference.docx in the folder you ran the command from.

Now it’s time to work inside Word.

Modifying the styles

What you will see is a rather plain file listing a bunch of styles and their name. First, you will see “Title,” and it will be nice and big because it’s using the Title style in Word. Heading 1 will use the Heading 1 style, Body Text (further down) will use the Body Text style, and so on.

What you want to do is to access these styles in Word. You will be modifying them to fit to your liking.

To do that, search for the Styles Pane. In my case, Office 365 for macOS, I can find it in the ribbon under Home, but I wouldn’t be surprised if that’s a little different if you’re using Windows, or a different version of Word.

With the Style Pane open, you will see a long list of the available styles. You can navigate this way, but I find it’s easier to just look for them in the document to the left and select them; it will then show under Current style: to the right.

Now that you have a style selected, select the name of that style from the Style Pane and choose Modify Style…1. You will see the options available to you, such as the font name, text color, alignment, etc.

Make sure that you do not change the Name: of the style! You’re modifying existing default styles that Pandoc recognizes; if you create a new one (by giving it a new name), Pandoc will not know what to do with it and will ignore it. Remember, you are modifying a reference sheet of existing styles, not creating new styles. Likewise, this means that you have no reason to change anything in the document itself (the content) - Pandoc doesn’t care about that and will ignore it. You’re only touching the options in the Modify Style… window.

That’s basically all there is to it. As you will see soon, some items can get a bit more complicated as they are not available in the same way. Save the files when you’re done modifying the styles. You will probably keep going back to this document as you export docx files, tweaking things until you like them.

Using Pandoc to export from org-mode to a docx file

The next step is to tell Pandoc to convert an existing org file to a docx file using the reference sheet we just worked on. To do that, use the following command:

pandoc -s <input_file.org> -o <output_file.docx> --reference-doc custom-reference.docx.

The idea is the same as before, but we use a stationary option, -s (the reason for that is that we’re telling Pandoc to use a “full” version of a document, needed with the reference doc option, otherwise it can’t use our reference document).

Then, we’re pointing Pandoc to our org file and using the output, -o, as the doc file we want, then finally using the reference-doc option by utilizing our reference file, custom-reference.docx (unless you change the name to something else). That’s it, Pandoc will create the file in the folder you are in.

Images and Tables

For me, things get a bit more complicated. My technical documents often include screenshots, and I need those embedded in the resulting Word docx file.

The above command will embed images in the Word document, as long as org-mode can find and display your images (using the inlineimages option in org-mode). My org-mode technical notes are all written with Denote these days, which keeps everything organized, including the images, which are inside the default data subfolder. If your workflow is different, be mindful of your path to the images; you’d probably want to use an absolute path in org-mode (use C-u C-u C-c C-l when linking an image instead of the usual C-u C-c C-l for this). There’s also the option to extract media in Pandoc (see the –extract-media option). In my opinion, it’s simpler and cleaner to dedicate a folder for your org documents, completed with a subfolder for attachments.

Another issue that stumbled me was the tables.

Pandoc’s default style for tables is minimal - without borders. This might look nice if you want to hide your tables, but if you need a table with borders and perhaps some shading, you’ll run into issues.

The problem is with Word. The style for the table is not included in the Style Pane. In order to change the style for your table in the reference doc, you need to locate Table Design in your ribbon. Notice that if you work on a small screen (like in my recording), you might have to expand your options to find it. Then, you will have to extend the pane further and locate the Modify Table Style below. Once again, this is true for my case, Office 365 on macOS. If you’re using a different Office version or on Windows, this menu might be located elsewhere.

Once you have Modify Table Style open, you can change the borders and shading to your heart’s content, but as before, make sure the style name remains Table. If you create a new style, Pandoc will ignore it.

A few tricks I picked up

Under the name of the style, in the Modify Style or Modify Table Style window, you will see the Style based on option. You can change this option and browse through different colors and fonts to find something you like, and then customize further instead of starting from scratch. As long as you don’t change the name of the style, you’re OK. I found this useful when working with tables, as I was looking for a table with shading on every other row.

Speaking of tables, the border button is the little square icon in the middle. I spent a few moments trying to find it.

Bonus: use dwim-shell-command for quick export

If you’re an Emacs user, you like shortcuts, and you like to use shell commands from within Emacs. If you haven’t yet, check out dwim-shell-command.

Here’s how I have it set up. All I have to do is mark the org file(s) I want to convert to a docx, and that’s it. It doesn’t matter if I want to export only one file or fifty; it’s the same ease of use.

(defun jtr/dwim-shell-command-pandoc-org-to-docx ()
  "uses pandoc to convert an org file to docx using a template docx file. The docx template file is stored in my Notes sync folder"
  (interactive)
  (dwim-shell-command-on-marked-files
   "converting from org to docx"
   "pandoc -s '<<f>>' -o '<<fne>>.docx' --reference-doc ~/Sync/Notes/Info/custom-reference.docx"
   :utils "pandoc"))

Footnotes

1 : Or, another way to work is to use to select the text you want to modify, then go to Format and select Style from there; you will need to then choose Modify in the window that shows.

-1:-- Org files to beatiful docx files with Pandoc (Post TAONAW - Emacs and Org Mode)--L0--C0--2026-02-01T14:55:30.000Z

Christian Tietze: Emacs Carnival 2026-01: “This Year, I’ll ...”

Welcome to 2026, and a new year of Emacs Blog Carnival post!

To start the Gregorian calendar year fresh, the blogging/writing/thinking prompt of this month is:

This year, I’ll …

What will you do differently in Emacs this year? Or will you just get started? Why?

What are you excited about to explore and tinker with? What do you want to perfect?

Are there any large projects in front of you that you’ll emacs1 with confidence?

What’s a Blog Carnival, Again?

A blog carnival is a fun way to tie together a community with shared writing prompts, and marvel at all the creative interpretations of the topic of the month. I’ve provided a couple of interpretations above, but you may think of something else entirely. That’s amazing, roll with it, that’s what makes this fun!

For future Carnivals, check out the “Carnival” page on EmacsWiki . It includes instructions, and is our community space to coordinate participants and topic ideas.

Submissions

Comment below or DM/email me with your submission! I’ll collect submissions up to, and including, February 1st (Central European Time), so that every time zone has had a chance to meet the January 31st deadline.

Ordered by submission date:

  1. I’m trying to establish a verb here. 


Hire me for freelance macOS/iOS work and consulting.

Buy my apps.

Receive new posts via email.

-1:-- Emacs Carnival 2026-01: “This Year, I’ll ...” (Post Christian Tietze)--L0--C0--2026-02-01T10:41:27.000Z

Kana: This year, I will write a shitty GUI for my Emacs clone

I've been hoping to write a GUI for my Emacs clone for a while now. And I'm putting together a list of Emacs' display features to keep compatible with when designing the GUI. Unsurprisingly, this list just keeps growing, and, nah,

Waiting to feel ready to do the thing is not doing the thing. 1

So, I really need to start writing the shittiest Emacs GUI ever.

Read more… (10 min remaining to read)

-1:-- This year, I will write a shitty GUI for my Emacs clone (Post Kana)--L0--C0--2026-01-31T21:45:00.000Z

Sacha Chua: Emacs and French: Focus flycheck-grammalecte on the narrowed part of the buffer

: Fix flycheck-checkers.

After learning about French spellcheck and grammar checking from Emacs expliqué à mes enfants, I added flycheck-grammalecte to my config. Nudged by @lann@mastodon.zaclys.com, I finally got around to figuring out why my setup sometimes worked and sometimes didn't. When I checked flycheck-verify-setup, I noticed that grammalecte kept getting disabled. A little digging around showed me that it was getting disabled because of too many errors. That was because it was trying to work on my whole file instead of just the portion that I narrowed to with org-narrow-to-subtree (ooh, just noticed an org-toggle-narrow-to-subtree command). I like having all of my French journal entries in one file because I can use consult-line (which I've bound to M-g l) to quickly look up examples of where else I've used a word. So I needed to define a checker that runs only on the narrowed part of the buffer.

(defun my-flycheck-grammalecte-buffer (checker callback)
  (let* ((temp-file-name (make-temp-file "grammalecte"))
         (output-buffer (get-buffer-create temp-file-name))
         (buffer (current-buffer))
         (cmdline (delq nil `("python3"
                              ,(expand-file-name "flycheck_grammalecte.py"
                                                 grammalecte--site-directory)
                              ,(unless flycheck-grammalecte-report-spellcheck "-S")
                              ,(unless flycheck-grammalecte-report-grammar "-G")
                              ,(unless flycheck-grammalecte-report-apos "-A")
                              ,(unless flycheck-grammalecte-report-nbsp "-N")
                              ,(unless flycheck-grammalecte-report-esp "-W")
                              ,(unless flycheck-grammalecte-report-typo "-T")
                              (option-list "-f" flycheck-grammalecte-filters)
                              (eval (flycheck-grammalecte--prepare-arg-list
                                     "-f" flycheck-grammalecte-filters-by-mode))
                              (eval (flycheck-grammalecte--prepare-arg-list
                                     "-b" flycheck-grammalecte-borders-by-mode))
                              ,temp-file-name)))
         (args (mapcan (lambda (arg) (flycheck-substitute-argument arg checker)) cmdline))
         (command (flycheck--wrap-command (car args) (cdr args))))
    (write-region (buffer-string) nil temp-file-name)
    (make-process :name "grammalecte"
                  :buffer output-buffer
                  :command command
                  :sentinel
                  (lambda (process status)
                    (let ((errors (with-current-buffer (process-buffer process)
                                    (message "%s" (buffer-string))
                                    (flycheck-parse-with-patterns
                                     (buffer-string)
                                     checker
                                     (current-buffer)))))
                      (delete-file temp-file-name)
                      (kill-buffer output-buffer)
                      ;; offset
                      (funcall
                       callback
                       'finished
                       (let ((offset (save-excursion (goto-char (point-min))
                                                     (line-number-at-pos nil t))))
                         (mapcar
                          (lambda (err)
                            (let ((new-err (copy-flycheck-error err)))
                              (setf (cl-struct-slot-value 'flycheck-error 'buffer new-err)
                                    buffer)
                              (setf (cl-struct-slot-value 'flycheck-error 'line new-err)
                                    (+ (flycheck-error-line new-err)
                                       offset -1))
                              (setf (cl-struct-slot-value 'flycheck-error '-end-line new-err)
                                    (+ (flycheck-error-end-line new-err)
                                       offset -1))
                              new-err))
                          errors))))))))

(defun my-flycheck-grammalecte-setup ()
  "Build the flycheck checker, matching your taste."
  (interactive)
  (unless (grammalecte--version)
    (advice-add 'grammalecte-download-grammalecte :after-while
                #'flycheck-grammalecte--retry-setup))
  (grammalecte--augment-pythonpath-if-needed)
  (flycheck-define-generic-checker 'my-grammalecte-narrowed
    "Report Grammalecte errors, but only for the narrowed section."
    :start #'my-flycheck-grammalecte-buffer
    :modes flycheck-grammalecte-enabled-modes
    :predicate (lambda ()
                 (if (functionp flycheck-grammalecte-predicate)
                     (funcall flycheck-grammalecte-predicate)
                   t))
    :enabled #'grammalecte--version
    :verify #'flycheck-grammalecte--verify-setup)
  (setf (flycheck-checker-get 'my-grammalecte-narrowed 'error-patterns)
        (seq-map (lambda (p)
                   (cons (flycheck-rx-to-string `(and ,@(cdr p))
                                                'no-group)
                         (car p)))
                 flycheck-grammalecte--error-patterns))
  (add-to-list 'flycheck-checkers 'my-grammalecte-narrowed)
  (flycheck-grammalecte--patch-flycheck-mode-map))

After I use my-flycheck-grammalecte-setup, I can use flycheck-select-checker to select my-grammalecte-narrowed and then use flycheck-buffer to run it. Then it will underline all the number/gender agreement issues I usually have. It's nice that I can practise editing my text with this script before I run the text through an LLM (also via flycheck) for feedback on wording.

2026-01-30_22-20-20.png
Figure 1: Screenshot of grammalecte providing grammar feedback
This is part of my Emacs configuration.
View org source for this post

You can e-mail me at sacha@sachachua.com.

-1:-- Emacs and French: Focus flycheck-grammalecte on the narrowed part of the buffer (Post Sacha Chua)--L0--C0--2026-01-31T03:22:49.000Z

A bit of a teaser:

This bit of dwim-shell-command magic works nicely:

  (defun jtr/dwim-shell-command-pandoc-org-to-docx ()
    "uses pandoc to convert an org file to docx using a template docx file. The docx template file is stored in my synced notes folder"
    (interactive)
    (dwim-shell-command-on-marked-files
     "converting from org to docx"
     "pandoc -s '<<f>>' -o '<<fne>>.docx' --reference-doc ~/Sync/Notes/custom-reference.docx"
     :utils "pandoc"))
-1:--  (Post TAONAW - Emacs and Org Mode)--L0--C0--2026-01-31T00:35:29.000Z

Sacha Chua: Emacs Carnival February 2026: Completion

For the Emacs Carnival theme for February, let's learn more about completion together. There are all sorts of cheesy puns one can make about completion and Emacs and Valentine's Day, like "You complete me," but beyond the jokes, it's actually a really good topic to help us work with Emacs more efficiently.

First, what's the Emacs Carnival?

From Christian Tietze:

A blog carnival is a fun way to tie together a community with shared writing prompts, and marvel at all the creative interpretations of the topic of the month.

You can get a sense of previous Emacs Carnivals by checking out the previous ones:

Month Host Topic
June 2025 ctietze "Take Two"
July gnewman "Writing Experience"
August takeonrules "Your Elevator Pitch for Emacs"
September rodiongoritskov "Obscure packages"
October AndyDrop "Maintenance, server or home or garden"
November donaldh "An ode to org-babel"
December GeorgeJones "The People of Emacs"
January 2026 ctietze "This year, I'll…"

You don't have to be an expert in order to post. In fact, this is a great way for all of us (beginners and otherwise) to focus on a topic together. Let's treat it like a kind of book club where we can share our notes as we learn.

What do we mean by completion in Emacs?

Completion can make it faster to enter text and to reduce errors. You can use it to find Emacs commands even if you don't know their full names or keyboard shortcuts. You can use it to expand abbreviations or even fix the typos you usually make. You can use it when you code and when you write. I've heard some people define common abbreviations across different programming languages so they don't have to remember the differences between syntaxes, and minibuffer-completion-based interfaces like consult-ripgrep let you flip through search results astoundingly quickly.

Let's start by talking about two types of completion:

  • minibuffer completion, which happens in the small window at the bottom of the screen whenever you use M-x, find a file, etc. This is where you can type a little and then find matching options so that you don't have to remember the full names of commands or files. For lots of tips, check out Understanding Minibuffer Completion - Mastering Emacs.

    For example, here's my minibuffer for M-x using vertico for the display and marginalia for annotations on the side:

    2026-01-30_12-44-23.png
    Figure 1: Screenshot of minibuffer completion
  • in-buffer completion, like when you expand an abbreviation, insert a snippet, or fill in the rest of a variable name.

    2026-01-30_14-17-45.png
    Figure 2: Screenshot of in-buffer completion

Here are some ideas for things to explore. Pick an idea or come up with your own and write a post sharing what you're figuring out!

  • Minibuffer completion
    • Do you know about S-M-x (execute-extended-command-for-buffer - available with Emacs 28.1 or higher), which suggests commands relevant to the current mode?
    • Have you gotten the hang of using M-p to go back through your history? (Did you know you can interactively search through that history with C-s and C-r?)
    • Do you know about using M-n to go into the future history?
    • Have you tried saving your minibuffer history with savehist?
    • Do you want to experiment with recursive minibuffers so that you can do something else in the middle of a completion?
    • Do you have nicer completion set up, like icomplete-vertical-mode, fido-mode or fido-vertical-mode, ido-mode or ido-vertical-mode, ivy, or vertico? This makes things like M-x (execute-extended-command) and M-y (yank-pop) soo much nicer!
    • Have you experimented with other completion styles like orderless so that you can type parts of the completion name in any order?
    • Have you checked out the convenient search and navigation commands in more complex completion frameworks like consult, counsel, or helm?
    • Have you experimented with other sort orders like the built-in historical option or more complex sorts with prescient.el?
    • Do you want to see additional information when you're choosing completions? Try out marginalia.
    • Have you checked out embark for doing other things with your completion like inserting a file name instead of opening it, or changing the command that you wanted to do, or acting on multiple items?
    • If you use Org Mode, do you want to make your own custom Org link type with completion? (I really like being able to quickly link to blog posts, parts of my config, or project files with completion)
    • Do you want to define your own completion commands, maybe even with previews, dynamic collections or asynchronous data?
  • In-buffer completion
  • Meta: What else can you bring into Emacs so that you can take advantage of all the completions that you've set up, like note-taking or e-mail? (Ex: mastodon.el + org-contacts + a little code to insert a Mastodon handle with completion = I can think of people by name instead of by handle!)

Things I want to learn about

For example, this month, I want to…

  • Minibuffer:
    • Figure out some kind of approximate speech-based minibuffer completion for commands
    • Create a custom Org Mode link type for emacswiki and other things I refer to frequently
    • Write about the completion functions I'm using to help me learn French
  • In-buffer completion:
    • Notice where I keep typing the same kinds of things and define more snippets for them
    • Borrow ideas from other people's snippets: yasnippet-snippets (css, elisp, js, python); friendly-snippets (VS Code)
    • Share my snippets in a repository
    • Figure out some kind of speech interface for expanding snippets
    • Sort out completion in programming buffers so that I can finally take advantage of LSP
    • Complete French words in-buffer ignoring accented characters
  • Organize tons of completion-related links from Emacs News onto EmacsWiki: Category Completion and other pages
  • Revisit the completion-related code in my config to dust off things that I can update, remember to use, or document with gif-screencast

I'll publish my notes on my blog and I'll add them to this post as well. I'd love to check out your notes too!

How to submit your entry/entries

Please e-mail me at sacha@sachachua.com or DM me via Mastodon with a link to your post(s) by February 28 so that I can add them to this post. I'm happy to link to multiple posts. For example, here are some things you might like to write about:

  • what you're thinking of figuring out (in case other people have suggestions)
  • your notes along the way
  • your current setup
  • things you're particularly proud of

Looking forward to hearing from you!

View org source for this post

You can comment on Mastodon or e-mail me at sacha@sachachua.com.

-1:-- Emacs Carnival February 2026: Completion (Post Sacha Chua)--L0--C0--2026-01-30T16:41:18.000Z

Irreal: Extracting Data From Journelly Entries

As you all know, I am always writing about how much I like and use Journelly. One of the things that I always say is that since Journelly saves it data as an Org mode file—or, if you prefer, as a Markdown file—the file is essentially a database that can be queried and processed to produce other files.

Álvaro Ramírez has a very interesting post that describes one such workflow. Much like I might do, Ramírez adds an entry in his Journelly when he comes across some data about a movie he might want to watch. It may be an IMDB entry, a Reddit post, or even just something someone told him so that all he has is the movie or director name. The common denominator is that he adds a tag such as #film or #watch to mark those entries having to do with movies he should watch. Journelly can, of course, search on the tags but Ramírez has a better way.

First he extracts all the entries having an appropriate tag into a watchlist.org file. That gives him a file with all the movies he might want to watch. He uses this and the Claude Code agent to look up each entry in IMDB and to retrieve all the metadata for each movie from IMDB and put it in a db.org file. Finally, he uses the db.org file to generate HTML so that he has a browsable file showing each movie along with its poster.

Take a look at his post for the details and to see the final results. As Ramírez says,

At the center of all it all my beloved org syntax. Thanks to plain text formats, we can easily peek at them, query them, poke at them, tweak them, and bend til our heart’s content. It’s just so versatile and now we can throw them at LLMs, too.

Almost none of this is something you’d expect a text editor to do but the Combination of Emacs and Journelly provides a way of moving from free form capture entries to a polished, browsable file.

-1:-- Extracting Data From Journelly Entries (Post Irreal)--L0--C0--2026-01-30T15:33:40.000Z

punchagan: Why my Elfeed index was 0 bytes

My Linux machine crashed, while I was in the middle of a video call. I restarted quickly, and continued the discussion. Later, when I was trying to sync Elfeed updates onto the Elfeed Offline app on my phone, I found it acting weird. All the bazillion things needed to get it working were in place, but it was still complaining about the Emacs Elfeed server not being accessible. I tried opening Elfeed inside Emacs and failed! The index file in Elfeed’s DB was empty! Gone! Poof!

Frustrating, but I didn’t have time to look into what happened. I would’ve been furious if I had been using Elfeed for longer and had a lot more metadata saved. But, it was only a few weeks of lost metadata - posts I read, starred, etc. I quickly setup a Git based backup to prevent future losses and moved on.

Later, I found time to dig into what might have happened…

The breadcrumbs

Elfeed stores all the metadata for all the posts in an index file with a content addressed store of the contents of each of the posts. The index file is simply a dump of the hash-table containing the metadata for the subscribed feeds, their entries and metadata like tags, read/unread status, etc.

The DB save happens in elfeed-db-save, which simply dumps the hash-table to disk inside a call to the with-temp-file macro.

(defun elfeed-db-save ()
  ; <snip>
  (with-temp-file (expand-file-name "index" elfeed-db-directory)
    ; ...
    (princ (format ";;; Elfeed Database Index (version %s)\n\n"
                       elfeed-db-version))
    ; ...
    (prin1 elfeed-db)
    ;...
    ))

with-temp-file, as its documentation says, lets you create a new buffer, evaluate the body there, and write the buffer to file. For a moment, I thought there was some temporary file involved, but nope! I guess the name comes as an extension from with-temp-buffer which does create a temporary buffer where the body of the macro gets evaluated. Stripped to its core, this function is:

`(let ((,temp-file ,file)
       (,temp-buffer (generate-new-buffer " *temp file*" t)))
   (prog1
       (with-current-buffer ,temp-buffer
         ,@body)
     (with-current-buffer ,temp-buffer
       (write-region nil nil ,temp-file nil 0))))

write-region and O_TRUNC

So, write-region is the workhorse which writes the contents of the temporary buffer to disk. It’s a roughly 300 line long C function that essentially opens the file with the flags O_WRONLY | O_CREAT | O_TRUNC (in this case) and then does something to write the contents to the file, etc. Honestly, I didn’t look at anything else too carefully after I spotted the O_TRUNC.

The man page of open explains O_TRUNC as follows:

O_TRUNC :: If the file already exists and is a regular file and the access mode allows writing (i.e., is O_RDWR or O_WRONLY) it will be truncated to length 0.

Voilà!

The write is not atomic. The file first gets truncated to length 0, and then we hope that the new contents get correctly written before something goes wrong.

It now makes sense why the file got truncated to 0 bytes. The crash happened after the open, but before the write. Somehow the crash happened in this short window, and poof!

Emacs has backup files, doesn’t it?

Temporary files with ~ in their file extensions have definitely annoyed me in the past when Emacs created them where I didn’t want them. So, I do know that Emacs has back-up mechanisms out of the box. But, it turns out that the backups occur in code paths that are more interactive, like save-buffer, write-file, etc. And not via the programmatic APIs like write-region or the higher level with-temp-file. save-buffer calls backup-buffer before writing, but write-region is much more low-level and doesn’t deal with backups.

The fix

My “fix” for this is to backup the Elfeed data in a git repository to be able to recover from any such corruptions of data, which I already wrote about here.

I know that any code that uses with-temp-file (or write-region) could be affected by this, and the right fix for this may be to write to a temporary file and rename it. Maybe next time I lose data I’ll actually fix it properly.

-1:-- Why my Elfeed index was 0 bytes (Post punchagan)--L0--C0--2026-01-30T11:28:00.000Z

Sacha Chua: Using Silero voice activity detection to automatically queue multiple transcriptions with natrys/whisper.el

I can queue multiple transcriptions with whisper.el so that they get processed sequentially with backup audio. It catches up when I pause to think. Now I want to use Silero voice activity detection to do that kind of segmentation for me automatically.

First, I need a Python server that can print out events when it notices the start or stop of a speech segment. If I print out the timestamps, I might be able to cross-reference it someday with interestingthings. For now, even just paying attention to the end of a segment is enough for what I want to do.

Python script for printing out events
import sounddevice as sd
import numpy as np
import torch
import sys
from datetime import datetime, timedelta

SILENCE_DURATION = 500
SAMPLING_RATE = 16000
CHUNK_SIZE = 512
model, utils = torch.hub.load(repo_or_dir='snakers4/silero-vad',
                              model='silero_vad',
                              force_reload=False)

(get_speech_timestamps, save_audio, read_audio, VADIterator, collect_chunks) = utils
vad_iterator = VADIterator(model, threshold=0.5, min_silence_duration_ms=SILENCE_DURATION)

stream_start_time = None

def format_iso_with_offset(offset_seconds):
    if stream_start_time is None:
        return "PENDING"
    event_time = stream_start_time + timedelta(seconds=offset_seconds)
    return event_time.astimezone().isoformat(timespec='milliseconds')

def audio_callback(indata, frames, time, status):
    global stream_start_time
    if status:
        print(status, file=sys.stderr)
    if stream_start_time is None:
        stream_start_time = datetime.now()
    tensor_input = torch.from_numpy(indata.copy()).flatten()
    speech_dict = vad_iterator(tensor_input, return_seconds=True)
    if speech_dict:
        if "start" in speech_dict:
            print(f"START {format_iso_with_offset(speech_dict['start'])}", flush=True)
        if "end" in speech_dict:
            print(f"END {format_iso_with_offset(speech_dict['end'])}", flush=True)
try:
    with sd.InputStream(samplerate=SAMPLING_RATE,
                        channels=1,
                        callback=audio_callback,
                        blocksize=CHUNK_SIZE):
        while True:
            pass
except KeyboardInterrupt:
    print("\nStopping...")

Then I can start this process from Emacs:

(defvar my-vad-events-process nil)
(defvar my-vad-events-dir "~/proj/speech/")
(defvar my-vad-events-command `(,(expand-file-name ".venv/bin/python" my-vad-events-dir)
                                "vad-events.py"))

(defun my-vad-events-filter (proc string)
  (when (and (string-match "^END" string)
             (process-live-p whisper--recording-process))
    (message "Noticed speech turn: %s" string)
    (my-whisper-continue)))

(defun my-vad-events-ensure ()
  "Start the process if it's not already running."
  (interactive)
  (unless (process-live-p my-vad-events-process)
    (let ((default-directory my-vad-events-dir)
          (process-environment
           (cons
            (format
             "PULSE_PROP=node.description='%s' media.name='%s' node.name='%s'"
             "vad" "vad" "vad")
            process-environment)))
      (setq my-vad-events-process
            (make-process
             :name "vad-events"
             :command my-vad-events-command
             :buffer (get-buffer-create "*vad-events*")
             :stderr (get-buffer-create "*vad-events-err*")
             :filter #'my-vad-events-filter)))))

Because I added Pulse properties to the process environment, I can easily use epwgraph to rewire the input so that it gets the input from my VirtualMicSink instead of the default system audio device. (Someday I'll figure out how to specify that as the input automatically.)

Now I can press my shortcut for my-whisper-continue to start the process. As I keep talking, it will continue to record. When I pause for more than a second between sentences, then it will send that chunk to the server for transcription without me having to press another button, while still listening for more speech.

How is this different from the streaming approach that many real-time speech recognition services offer? I think this gives me a bit more visibility into and control of the process. For my personal use, I don't need to have everything processed as quickly as possible, and I'm not trying to replicate live captions. I just want to be able to look back over the last five minutes to try to remember what I was talking about. I usually have a lot of quiet time as I think through my next steps, and it's fine to have it catch up then. I also like that I can save time-stamped audio files for later processing, divided according to the speech segments. Those might be a little bit easier to work with when I get around to compositing them into a video.

This is part of my Emacs configuration.
View org source for this post

You can e-mail me at sacha@sachachua.com.

-1:-- Using Silero voice activity detection to automatically queue multiple transcriptions with natrys/whisper.el (Post Sacha Chua)--L0--C0--2026-01-29T16:24:46.000Z

James Cherti: ultisnips-mode.el: An Emacs major mode for editing Ultisnips snippet files (*.snippets files)

Build Status MELPA MELPA Stable License

The ultisnips-mode is an Emacs major mode for editing Ultisnips snippet files (*.snippets files). This mode provides syntax highlighting to facilitate editing Ultisnips snippets.

(Vim’s UltiSnips is a snippet solution for Vim, and its snippets can be used in Emacs by converting them to the Yasnippet format using Ultyas.)

Features

  • Syntax highlighting for UltiSnips: snippet, endsnippet, global, endglobal, priority, comments, and placeholders in the form of ${1:value} or $1
  • Integration with outline-minor-mode or hs-minor-mode to enable folding of snippet -> endsnippet and global -> endglobal blocks.
  • Support for commenting and uncommenting UltiSnips snippets using standard Emacs commands, such as comment-or-uncomment-region.
  • Add *.snippets to auto-mode-alist to automatically enable ultisnips-mode.

Installation

To install ultisnips-mode from MELPA:

  1. If you haven’t already done so, add MELPA repository to your Emacs configuration.

  2. Add the following code to your Emacs init file to install ultisnips-mode from MELPA:

    (use-package ultisnips-mode
    :ensure t)

Frequently Asked Questions

Folding snippet blocks with hs-minor-mode

Activating hs-minor-mode provides the ability to collapse and expand snippet -> endsnippet blocks, making navigation in large snippet files much easier.

To enable hs-minor-mode automatically for Ultisnips files, add the following to the Emacs configuration:

(add-hook 'ultisnips-mode-hook #'hs-minor-mode)

NOTE: As an alternative to hs-minor-mode, ultisnips-mode also supports outline-minor-mode; however, hs-minor-mode is recommended because it can reliably fold entire blocks from snippet to endsnippet. In contrast, outline-minor-mode uses only the snippet line as a header and may hide everything between the first snippet and the next one, including comments.

For a better and more intuitive way to fold and unfold snippets, it is recommended to use the kirigami.el emacs package.

Hiding all snippets with hs-minor-mode when opening *.snippets files

The following configuration automatically folds all code blocks when ultisnips-mode is enabled, collapsing all snippets:

(defun my-ultisnips-mode-fold-all ()
  "Fold all snippet blocks using `hs-minor-mode'."
  (hs-minor-mode 1)
  (hs-hide-all))

(add-hook 'ultisnips-mode-hook #'my-ultisnips-mode-fold-all)

This ensures a cleaner view of snippets, collapsing all regions by default and allowing selective expansion as needed.

Is there a package that allows using UltiSnips directly in Emacs, or is it necessary to first convert them to the Yasnippet format?

Yes, conversion to Yasnippet is required.

A command-line tool called Ultyas facilitates the conversion of snippets from UltiSnips to Yasnippet format.

How does the author use ultisnips-mode and Ultyas?

The author maintains all snippets in their original UltiSnips format for Vim and developed a shell script that automatically scans the UltiSnips directory, generating the corresponding Yasnippet files using Ultyas.

He uses the ultisnips-mode Emacs package to edit snippets, which provides syntax highlighting and code folding via hs-minor-mode.

This workflow allows editing and storing a single set of snippets while making them available in Vim and Emacs.

Author and License

The ultisnips-mode Emacs package has been written by James Cherti and is distributed under terms of the GNU General Public License version 3, or, at your choice, any later version.

Copyright (C) 2025-2026 James Cherti

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program.

Links

Other Emacs packages by the same author:

  • minimal-emacs.d: This repository hosts a minimal Emacs configuration designed to serve as a foundation for your vanilla Emacs setup and provide a solid base for an enhanced Emacs experience.
  • compile-angel.el: Speed up Emacs! This package guarantees that all .el files are both byte-compiled and native-compiled, which significantly speeds up Emacs.
  • easysession.el: Easysession is lightweight Emacs session manager that can persist and restore file editing buffers, indirect buffers/clones, Dired buffers, the tab-bar, and the Emacs frames (with or without the Emacs frames size, width, and height).
  • vim-tab-bar.el: Make the Emacs tab-bar Look Like Vim’s Tab Bar.
  • elispcomp: A command line tool that allows compiling Elisp code directly from the terminal or from a shell script. It facilitates the generation of optimized .elc (byte-compiled) and .eln (native-compiled) files.
  • tomorrow-night-deepblue-theme.el: The Tomorrow Night Deepblue Emacs theme is a beautiful deep blue variant of the Tomorrow Night theme, which is renowned for its elegant color palette that is pleasing to the eyes. It features a deep blue background color that creates a calming atmosphere. The theme is also a great choice for those who miss the blue themes that were trendy a few years ago.
  • dir-config.el: Automatically find and evaluate .dir-config.el Elisp files to configure directory-specific settings.
  • flymake-bashate.el: A package that provides a Flymake backend for the bashate Bash script style checker.
  • flymake-ansible-lint.el: An Emacs package that offers a Flymake backend for ansible-lint.
  • inhibit-mouse.el: A package that disables mouse input in Emacs, offering a simpler and faster alternative to the disable-mouse package.
  • quick-sdcv.el: This package enables Emacs to function as an offline dictionary by using the sdcv command-line tool directly within Emacs.
  • enhanced-evil-paredit.el: An Emacs package that prevents parenthesis imbalance when using evil-mode with paredit. It intercepts evil-mode commands such as delete, change, and paste, blocking their execution if they would break the parenthetical structure.
  • stripspace.el: Ensure Emacs Automatically removes trailing whitespace before saving a buffer, with an option to preserve the cursor column.
  • persist-text-scale.el: Ensure that all adjustments made with text-scale-increase and text-scale-decrease are persisted and restored across sessions.
  • pathaction.el: Execute the pathaction command-line tool from Emacs. The pathaction command-line tool enables the execution of specific commands on targeted files or directories. Its key advantage lies in its flexibility, allowing users to handle various types of files simply by passing the file or directory as an argument to the pathaction tool. The tool uses a .pathaction.yaml rule-set file to determine which command to execute. Additionally, Jinja2 templating can be employed in the rule-set file to further customize the commands.
  • kirigami.el: The kirigami Emacs package offers a unified interface for opening and closing folds across a diverse set of major and minor modes in Emacs, including outline-mode, outline-minor-mode, outline-indent-mode, org-mode, markdown-mode, vdiff-mode, vdiff-3way-mode, hs-minor-mode, hide-ifdef-mode, origami-mode, yafolding-mode, folding-mode, and treesit-fold-mode. With Kirigami, folding key bindings only need to be configured once. After that, the same keys work consistently across all supported major and minor modes, providing a unified and predictable folding experience.
-1:-- ultisnips-mode.el: An Emacs major mode for editing Ultisnips snippet files (*.snippets files) (Post James Cherti)--L0--C0--2026-01-29T15:48:37.000Z

Irreal: Return Of The Prodigal Son

Well, not really prodigal, but the return—nonetheless—of a son assumed lost. Michał Sapka has a blog post about his return to Emacs. A while ago, Sapka left Emacs for Vim and the shell. He liked them but realized that Emacs really is different.

The way it’s different is telling. Although you can do anything in Vim and shell, Emacs is different. As Sapka puts it,

It’s not that nothing stops you from connecting Mastodon.el, Magit and Mu4e, it’s that it’s natural.

Because all of Emacs is exposed to the user, it’s easy to modify it to fit your workflow and string together disparate applications in ways that their authors never intended. Sapka makes the same point that Irreal and others have made: it’s not that Emacs has an extension language, it’s that Emacs’ source code is modifiable on the fly from within the application itself at run time. It’s a whole different thing.

Sapka admits that there are problems but says that they are solvable. Depending on your work environment, solving them may be more or less difficult but they remain solvable.

In any event, Sapka has returned to Emacs because, in the end, nothing else provides the same power and flexibility. He ends his post by noting that he’s—sort of—combined the power of Emacs and Vim by adopting Evil mode.

-1:-- Return Of The Prodigal Son (Post Irreal)--L0--C0--2026-01-29T15:29:40.000Z

Alvaro Ramirez: Film/TV bookmarks (chaos resolved)

I've been somewhat chaotically "bookmarking" things to watch for some time. The info typically goes straight to an Emacs org file primarily via Journelly.

I'm fairly forgiving in my input form. I often link to Reddit discussions, IMDB/Letterboxd links, or at times simply write movie or director names. The only real requirement is to sprinkle some hashtags (#film or #series or #watch) for retrieval.

While this flexibility is important (makes it more likely for me to actually write), it's not super practical to browse through this mixed structure when looking for something to watch. Yesterday, I finally did something about that.

Here's what my save-to-Journelly flow may look like for a Reddit link:

All entries are saved to Journelly.org, a plain text org file (Markdown is supported too), so I first extracted all relevant entries (containing #film or #series or #watch). A matching entry looks a little something like this:

* [2026-01-29 Thu 09:52] @ Home
:PROPERTIES:
:LATITUDE: 51.5007
:LONGITUDE: -0.1246
:WEATHER_TEMPERATURE: 4.2°C
:WEATHER_CONDITION: Cloudy
:WEATHER_SYMBOL: cloud
:END:
#film #hongkong #watch

https://www.reddit.com/r/movies/comments/1j85b52/just_rewatched_kung_fu_hustle_still_felt_great

Having extracted non-personal items from Journelly.org, I created a git repo with just one file: watchlist.org including entries like the one above.

With personal/private details out of the way, I decided to let the LLM robots loose. That is, hand watchlist.org over to a Claude Code agent, via Emacs agent-sell to organize my chaos.

First I asked to normalize data by extracting all film/tv info from each entry, visiting Reddit/IMDB/Letterboxd links if needed, which yielded normalized.org:

Kung Fu Hustle
https://www.imdb.com/title/tt0373074

Next I asked to generate metadata for me (using the fields I wanted from IMDB), stored in org drawers, saved to db.org:

* Kung Fu Hustle
:PROPERTIES:
:TYPE: film
:YEAR: 2004
:IMDB: https://www.imdb.com/title/tt0373074/
:IMDB_RATING: 7.7
:COUNTRY: Hong Kong
:DIRECTOR: Stephen Chow
:GENRE: action, comedy, fantasy
:RUNTIME: 99
:ADDED: [2026-01-28]
:THUMBNAIL: file:thumbnails/tt0373074.png
:IMDB_THUMBNAIL: https://m.media-amazon.com/images/M/MV5BNGU2OWVlM2ItZGZlOC00Yzk2LWE1NzEtMDYwMzE4YTE5MzQ2XkEyXkFqcGc@._V1_FMjpg_UY1024_.jpg
:END:

Finally, I asked to generate HTML from db.org so I can render and easily browse.

<div>
  <a href="https://www.imdb.com/title/tt0373074/"><img src="https://m.media-amazon.com/images/M/MV5BNGU2OWVlM2ItZGZlOC00Yzk2LWE1NzEtMDYwMzE4YTE5MzQ2XkEyXkFqcGc@._V1_FMjpg_UY1024_.jpg" alt="Kung Fu Hustle" width="150" height="225"></a>
  <p><strong>Kung Fu Hustle (2004)</strong></p>
  <p>action · comedy · fantasy</p>
  <p>Hong Kong · Stephen Chow</p>
</div>

For each transformation, Claude Code generated a python script. I've yet to decide what to do with all the resulting source code. Do I clean it up? Rewrite it?

For now, I'm happy with the results of the experiment. I managed to organize some of my chaos! In some ways, this isn't too different from me writing a quick/hacky/ugly script, when it's acceptable to do so.

At the center of it all, is my beloved org syntax. Thanks to plain text formats, we can easily peek at them, query them, poke at them, tweak them, and bend til our heart's content. It's just so versatile, and now we can throw them at LLMs too.

Oh, and if you're curious about that watch list, here you go. Do you have some movie/show suggestions for me?

12 Monkeys

12 Monkeys (2015)

tv · adventure · drama · mystery

United States

2149: The Aftermath

2149: The Aftermath (2021)

sci-fi

Canada · Benjamin Duffield

3 Body Problem

3 Body Problem (2024)

tv · adventure · drama · fantasy

United Kingdom

964 Pinocchio

964 Pinocchio (1991)

horror · sci-fi

Japan · Shozin Fukui

A Scanner Darkly

A Scanner Darkly (2006)

animation · comedy · crime

United States · Richard Linklater

A Separation

A Separation (2011)

drama

Iran · Asghar Farhadi

A Small Light

A Small Light (2023)

tv · biography · drama · history

United States

A Taxing Woman

A Taxing Woman (1987)

comedy · crime

Japan · Jûzô Itami

Absentia

Absentia (2017)

tv · crime · drama · mystery

Israel

Across the Furious Sea

Across the Furious Sea (2023)

crime · drama · mystery

China · Baoping Cao

Akira

Akira (1988)

animation · action · drama

Japan · Katsuhiro Ôtomo

Alita: Battle Angel

Alita: Battle Angel (2019)

action · adventure · sci-fi

United States · Robert Rodriguez

All About My Mother

All About My Mother (1999)

comedy · drama · romance

Spain · Pedro Almodóvar

Altered Carbon

Altered Carbon (2018)

tv · action · adventure · drama

United States

Altered Hours

Altered Hours (2016)

sci-fi · thriller

United States · Bruce Wemple

Amelie

Amelie (2001)

comedy · romance

France · Jean-Pierre Jeunet

Amores Perros

Amores Perros (2000)

drama · thriller

Mexico · Alejandro G. Iñárritu

An Elephant Sitting Still

An Elephant Sitting Still (2018)

crime · drama

China · Bo Hu

Anatomy of a Fall

Anatomy of a Fall (2023)

crime · drama · mystery

France · Justine Triet

Arcane

Arcane (2021)

tv · animation · action · adventure

United States

Archive 81

Archive 81 (2022)

tv · drama · horror · mystery

United States

As Tears Go By

As Tears Go By (1988)

crime · drama · romance

Hong Kong · Wong Kar-Wai

Asakusa Kid

Asakusa Kid (2021)

biography · drama

Japan · Gekidan Hitori

Ash Is Purest White

Ash Is Purest White (2018)

crime · drama · romance

China · Jia Zhang-ke

Asura

Asura (2023)

tv · comedy · drama

Indonesia

Band of Brothers

Band of Brothers (2001)

tv · action · drama · history

United Kingdom

Banshee

Banshee (2013)

tv · action · crime · drama

United States

Barry

Barry (2018)

tv · action · comedy · crime

United States

Battlestar Galactica

Battlestar Galactica (2004)

tv · action · adventure · drama

United States

Being Human (UK)

Being Human (UK) (2008)

tv · comedy · drama · fantasy

United Kingdom

Big Man Japan

Big Man Japan (2007)

action · comedy · sci-fi

Japan · Hitoshi Matsumoto

Black Coal, Thin Ice

Black Coal, Thin Ice (2014)

crime · drama · mystery

China · Yi'nan Diao

Black Sails

Black Sails (2014)

tv · action · adventure · drama

South Africa

Blackadder

Blackadder (1983)

tv · comedy

United Kingdom

BlackBerry

BlackBerry (2023)

biography · comedy · drama

Canada · Matt Johnson

Blade Runner

Blade Runner (1982)

action · drama · sci-fi

United States · Ridley Scott

Blade Runner 2049

Blade Runner 2049 (2017)

action · drama · mystery

United States · Denis Villeneuve

Blade Runner: Black Lotus

Blade Runner: Black Lotus (2021)

tv · animation · action · drama

United States

Bloody Hell

Bloody Hell (2020)

comedy · horror · mystery

Australia · Alister Grierson

Boardwalk Empire

Boardwalk Empire (2010)

tv · crime · drama

United States

Bojack Horseman

Bojack Horseman (2014)

tv · animation · comedy · drama

United States

Brand New Cherry Flavor

Brand New Cherry Flavor (2021)

tv · drama · horror · mystery

United States

Brazil

Brazil (1985)

drama · sci-fi · thriller

United Kingdom · Terry Gilliam

Broadchurch

Broadchurch (2013)

tv · crime · drama · mystery

United Kingdom

Burn Notice

Burn Notice (2007)

tv · action · crime · drama

United States

Burning

Burning (2018)

drama · mystery · thriller

South Korea · Lee Chang-dong

Carnivale

Carnivale (2003)

tv · drama · fantasy · mystery

United States

Castlevania

Castlevania (2017)

tv · animation · action · adventure

United States

Chungking Express

Chungking Express (1994)

comedy · crime · drama

Hong Kong · Wong Kar-Wai

City Hunter

City Hunter (2024)

action · comedy · crime

Japan · Yûichi Satô

City of God

City of God (2002)

crime · drama

Brazil · Kátia Lund

Cloud

Cloud (2024)

action · crime · drama

Japan · Kiyoshi Kurosawa

Cold Fish

Cold Fish (2010)

crime · drama · horror

Japan · Sion Sono

Colony

Colony (2016)

tv · action · adventure · drama

United States

Counterpart

Counterpart (2017)

tv · drama · sci-fi · thriller

United States

Crouching Tiger Hidden Dragon

Crouching Tiger Hidden Dragon (2000)

action · adventure · drama

Taiwan · Ang Lee

Cure

Cure (1997)

crime · horror · mystery

Japan · Kiyoshi Kurosawa

Cyberpunk: Edgerunners

Cyberpunk: Edgerunners (2022)

tv · animation · action · adventure

Japan

DaVinci's Demons

DaVinci's Demons (2013)

tv · adventure · biography · drama

United States

Days of Being Wild

Days of Being Wild (1990)

crime · drama · romance

Hong Kong · Wong Kar-Wai

Deadwind

Deadwind (2018)

tv · crime · drama · mystery

Finland

Deadwood

Deadwood (2004)

tv · crime · drama · history

United States

Dear Child

Dear Child (2023)

tv · crime · drama · mystery

Germany

Decision to Leave

Decision to Leave (2022)

crime · drama · mystery

South Korea · Park Chan-wook

Demon City

Demon City (2024)

action · adventure · crime

Japan · Seiji Tanaka

Derry Girls

Derry Girls (2018)

tv · comedy

United Kingdom

Destroyer

Destroyer (2018)

action · crime · drama

United States · Karyn Kusama

Devs

Devs (2020)

tv · drama · mystery · sci-fi

United Kingdom

Dirk Gently's Holistic Detective Agency

Dirk Gently's Holistic Detective Agency (2016)

tv · action · adventure · comedy

United States

District 9

District 9 (2009)

action · sci-fi · thriller

South Africa · Neill Blomkamp

Doom Patrol

Doom Patrol (2019)

tv · action · adventure · comedy

United States

Downton Abbey

Downton Abbey (2010)

tv · drama · romance

United Kingdom

Dredd

Dredd (2012)

action · crime · sci-fi

United Kingdom · Pete Travis

Drops of God

Drops of God (2023)

tv · drama

France

Dune

Dune (2021)

action · adventure · drama

United States · Denis Villeneuve

Dust of Angels

Dust of Angels (1992)

action · crime · drama

Taiwan · Hsiao-Ming Hsu

Edge of Tomorrow

Edge of Tomorrow (2014)

action · adventure · sci-fi

United States · Doug Liman

Edie

Edie (2017)

adventure · drama

United Kingdom · Simon Hunter

Elysium

Elysium (2013)

action · drama · sci-fi

United States · Neill Blomkamp

Encanto

Encanto (2021)

animation · comedy · family

United States · Jared Bush

Endeavour

Endeavour (2012)

tv · crime · drama · mystery

United Kingdom

Equilibrium

Equilibrium (2002)

action · drama · sci-fi

United States · Kurt Wimmer

Euphoria

Euphoria (2019)

tv · drama

United States

Extreme Job

Extreme Job (2019)

action · comedy · crime

South Korea · Lee Byeong-heon

Fair Play

Fair Play (2023)

drama · thriller

United States · Chloe Domont

Fallen Leaves

Fallen Leaves (2023)

comedy · drama · romance

Finland · Aki Kaurismäki

Fallout

Fallout (2024)

tv · action · adventure · drama

United States

Fargo

Fargo (2014)

tv · crime · drama · thriller

United States

Firefly

Firefly (2002)

tv · adventure · drama · sci-fi

United States

Foundation

Foundation (2021)

tv · drama · sci-fi

Ireland

Foyle's War

Foyle's War (2002)

tv · crime · drama · mystery

United Kingdom

Fringe

Fringe (2008)

tv · drama · mystery · sci-fi

United States

From

From (2022)

tv · drama · horror · mystery

United States

Funky Forest

Funky Forest (2005)

comedy · fantasy

Japan · Katsuhito Ishii

Future Man

Future Man (2017)

tv · action · adventure · comedy

United States

Gen V

Gen V (2023)

tv · action · adventure · comedy

United States

Ghost in the Shell

Ghost in the Shell (1995)

animation · action · crime

Japan · Mamoru Oshii

Ghostbusters Afterlife

Ghostbusters Afterlife (2021)

adventure · comedy · fantasy

United States · Jason Reitman

Godzilla Minus One

Godzilla Minus One (2023)

action · adventure · drama

Japan · Takashi Yamazaki

Going By The Book

Going By The Book (2007)

action · comedy

South Korea · Hee-chan Ra

Gomorrah

Gomorrah (2014)

tv · crime · drama · thriller

Italy

Guns & Talks

Guns & Talks (2001)

action · drama · comedy

South Korea · Jang Jin

Halt and Catch Fire

Halt and Catch Fire (2014)

tv · drama

United States

Handmaid's Tale

Handmaid's Tale (2017)

tv · drama · sci-fi · thriller

United States

Hanna

Hanna (2019)

tv · action · crime · drama

United States

Hannibal

Hannibal (2013)

tv · crime · drama · horror

United States

Hausen

Hausen (2020)

tv · drama · horror · mystery

Germany

Heavy Water War (Kampen om tungtvannet)

Heavy Water War (Kampen om tungtvannet) (2015)

tv · drama · history · war

Norway

Heroes

Heroes (2006)

tv · crime · drama · fantasy

United States

Hotel Del Luna

Hotel Del Luna (2019)

tv · action · comedy · drama

South Korea

Infernal Affairs

Infernal Affairs (2002)

crime · drama · mystery

Hong Kong · Wai Keung Lau

Inside the Yellow Cocoon Shell

Inside the Yellow Cocoon Shell (2023)

drama

Vietnam · Thien An Pham

Inspector Morse

Inspector Morse (1987)

tv · crime · drama · mystery

United Kingdom

Ip Man

Ip Man (2008)

action · biography · drama

Hong Kong · Wilson Yip

Johnny Mnemonic

Johnny Mnemonic (1995)

action · drama · sci-fi

Canada · Robert Longo

JSA: Joint Security Area

JSA: Joint Security Area (2000)

action · drama · thriller

South Korea · Park Chan-wook

Jury Duty

Jury Duty (2023)

tv · comedy

United States

Justified

Justified (2010)

tv · action · crime · drama

United States

Kaili Blues

Kaili Blues (2015)

drama · mystery

China · Bi Gan

Kalifat

Kalifat (2020)

tv · crime · drama · thriller

Sweden

Katla

Katla (2021)

tv · drama · fantasy · mystery

Iceland

Killers of the Flower Moon

Killers of the Flower Moon (2023)

crime · drama · history

United States · Martin Scorsese

Killzone (SPL)

Killzone (SPL) (2005)

action · crime · thriller

Hong Kong · Wilson Yip

Kingdom

Kingdom (2019)

tv · action · drama · horror

South Korea

Kung Fu Dunk

Kung Fu Dunk (2008)

action · comedy · sport

China · Yen-Ping Chu

Kung Fu Hustle

Kung Fu Hustle (2004)

action · comedy · fantasy

Hong Kong · Stephen Chow

La Haine

La Haine (1995)

crime · drama

France · Mathieu Kassovitz

Le Bureau des Legendes

Le Bureau des Legendes (2015)

tv · drama · thriller

France

Left Handed Girl

Left Handed Girl (2024)

drama

Taiwan · Shih-Ching Tsou

Legion

Legion (2017)

tv · action · sci-fi · thriller

United States

Les Revenants

Les Revenants (2012)

tv · drama · fantasy · horror

France

Little Fires Everywhere

Little Fires Everywhere (2020)

tv · drama · mystery · thriller

United States

Locked In

Locked In (2023)

mystery · thriller

United States · David C. Snyder

Lodge 49

Lodge 49 (2018)

tv · comedy · drama · mystery

United States

Logan Lucky

Logan Lucky (2017)

action · comedy · crime

United States · Steven Soderbergh

Loki

Loki (2021)

tv · action · adventure · fantasy

United States

Long Day's Journey Into Night

Long Day's Journey Into Night (2018)

drama · mystery · romance

China · Bi Gan

Looper

Looper (2012)

action · drama · sci-fi

United States · Rian Johnson

Lupin

Lupin (2021)

tv · action · crime · drama

France

Lust, Caution

Lust, Caution (2007)

drama · history · romance

Taiwan · Ang Lee

Man in the High Castle

Man in the High Castle (2015)

tv · drama · sci-fi · thriller

United States

Man Standing Next

Man Standing Next (2020)

thriller

South Korea · Min-ho Woo

Manhunt

Manhunt (2019)

tv · biography · crime · drama

United Kingdom

Manifest

Manifest (2018)

tv · drama · mystery · sci-fi

United States

Marco Polo

Marco Polo (2014)

tv · action · adventure · drama

United States

Marvelous Mrs Maisel

Marvelous Mrs Maisel (2017)

tv · comedy · drama

United States

Max Headroom

Max Headroom (1987)

tv · comedy · sci-fi

United States

May December

May December (2023)

comedy · drama

United States · Todd Haynes

Metropolis

Metropolis (1927)

drama · sci-fi

Germany · Fritz Lang

Midnight Mass

Midnight Mass (2021)

tv · drama · fantasy · horror

United States

Midsommar

Midsommar (2019)

drama · horror · mystery

United States · Ari Aster

Minority Report

Minority Report (2002)

action · crime · mystery

United States · Steven Spielberg

Misfits

Misfits (2009)

tv · comedy · drama · fantasy

United Kingdom

Miss King

Miss King (2024)

tv · drama · thriller

Japan

Mobland

Mobland (2024)

tv · crime · drama

United Kingdom

Mogura

Mogura (2024)

tv

Monk

Monk (2002)

tv · comedy · crime · drama

United States

Moving

Moving (2023)

tv · action · adventure · drama

South Korea

Mr Inbetween

Mr Inbetween (2018)

tv · comedy · crime · drama

Australia

Mr. Robot

Mr. Robot (2015)

tv · crime · drama · thriller

United States

Sympathy for Mr. Vengeance

Sympathy for Mr. Vengeance (2002)

crime · drama · thriller

South Korea · Park Chan-wook

Mrs. Davis

Mrs. Davis (2023)

tv · comedy · drama · sci-fi

United States

My Name

My Name (2021)

tv · action · crime · drama

South Korea

Narcos

Narcos (2015)

tv · biography · crime · drama

United States

Nine Days

Nine Days (2020)

drama · fantasy

United States · Edson Oda

No Other Choice

No Other Choice (2025)

comedy · crime · drama

South Korea · Park Chan-wook

Nobel

Nobel (2016)

tv · drama · thriller · war

Norway

Northern Exposure

Northern Exposure (1990)

tv · adventure · comedy · drama

United States

Occupied (Okkupert)

Occupied (Okkupert) (2015)

tv · drama · thriller

Norway

Oldboy

Oldboy (2003)

action · drama · mystery

South Korea · Park Chan-wook

Once Upon a Time in China

Once Upon a Time in China (1991)

action

Hong Kong · Hark Tsui

One False Move

One False Move (1992)

crime · drama · thriller

United States · Carl Franklin

Ong Bak

Ong Bak (2003)

action · crime · thriller

Thailand · Prachya Pinkaew

Oppenheimer

Oppenheimer (2023)

biography · drama · history

United States · Christopher Nolan

Orphan Black

Orphan Black (2013)

tv · drama · sci-fi · thriller

Canada

Ozark

Ozark (2017)

tv · crime · drama · thriller

United States

Pacifiction

Pacifiction (2022)

drama · thriller

France · Albert Serra

Pan's Labyrinth

Pan's Labyrinth (2006)

drama · fantasy · war

Mexico · Guillermo del Toro

Panchayat

Panchayat (2020)

tv · comedy · drama

India

Pantheon

Pantheon (2022)

tv · animation · action · adventure

United States

Past Lives

Past Lives (2023)

drama · romance

United States · Celine Song

Peacemaker

Peacemaker (2022)

tv · action · adventure · comedy

United States

Peaky Blinders

Peaky Blinders (2013)

tv · crime · drama

United Kingdom

PEN15

PEN15 (2019)

tv · comedy · drama

United States

Penny Dreadful

Penny Dreadful (2014)

tv · drama · fantasy · horror

United Kingdom

Perfect Days

Perfect Days (2023)

drama

Japan · Wim Wenders

Persepolis

Persepolis (2007)

animation · biography · drama

France · Vincent Paronnaud

Police Story

Police Story (1985)

action · comedy · crime

Hong Kong · Jackie Chan

Poor Things

Poor Things (2023)

comedy · drama · romance

Ireland · Yorgos Lanthimos

Preacher

Preacher (2016)

tv · adventure · comedy · fantasy

United States

Primo

Primo (2023)

tv · comedy

United States

Priscilla

Priscilla (2023)

biography · drama · music

Italy · Sofia Coppola

Professor T

Professor T (2015)

tv · comedy · crime · drama

Belgium

Raise the Red Lantern

Raise the Red Lantern (1991)

drama · romance

China · Yimou Zhang

Reservation Dogs

Reservation Dogs (2021)

tv · comedy · crime

United States

Riki Oh

Riki Oh (1991)

action · comedy · crime

Hong Kong · Ngai Choi Lam

Ripley

Ripley (2024)

tv · crime · drama · thriller

United States

Robocop

Robocop (1987)

action · crime · sci-fi

United States · Paul Verhoeven

Rome

Rome (2005)

tv · action · drama · romance

United Kingdom

Rurouni Kenshin

Rurouni Kenshin (2012)

action · adventure · drama

Japan · Keishi Otomo

Russian Doll

Russian Doll (2019)

tv · comedy · drama · mystery

United States

Scavengers Reign

Scavengers Reign (2023)

tv · animation · adventure · drama

United States

Scrapper

Scrapper (2023)

comedy · drama

United Kingdom · Charlotte Regan

Secret Level

Secret Level (2024)

tv · animation · action · adventure

United States

See

See (2019)

tv · action · drama · sci-fi

United States

Sex is Zero

Sex is Zero (2002)

comedy · drama · romance

South Korea · JK Youn

Shall We Dance

Shall We Dance (1996)

comedy · drama · music

Japan · Masayuki Suô

Shameless

Shameless (2011)

tv · comedy · drama

United States

Shantaram

Shantaram (2022)

tv · action · adventure · crime

United States

Shaolin Soccer

Shaolin Soccer (2001)

action · comedy · fantasy

Hong Kong · Stephen Chow

Sharp Objects

Sharp Objects (2018)

tv · crime · drama · mystery

United States

Shin Ultraman

Shin Ultraman (2022)

action · adventure · drama

Japan · Shinji Higuchi

Shinobi No Mono

Shinobi No Mono (1962)

action · drama

Japan · Satsuo Yamamoto

Shogun

Shogun (2024)

tv · action · adventure · drama

United States

Shutter Island

Shutter Island (2010)

drama · mystery · thriller

Canada · Martin Scorsese

Signal

Signal (2016)

tv · crime · drama · fantasy

South Korea

Silo

Silo (2023)

tv · drama · mystery · sci-fi

United States

Six Feet Under

Six Feet Under (2001)

tv · comedy · drama

United States

Slow Horses

Slow Horses (2022)

tv · drama · thriller

United Kingdom

Snowfall

Snowfall (2017)

tv · crime · drama

United States

Snowpiercer

Snowpiercer (2013)

action · sci-fi · thriller

South Korea · Bong Joon Ho

Somebody Somewhere

Somebody Somewhere (2022)

tv · comedy · drama

United States

Sonatine

Sonatine (1993)

action · comedy · crime

Japan · Takeshi Kitano

Spartacus

Spartacus (2010)

tv · action · adventure · biography

United States

Spiral (Engrenage)

Spiral (Engrenage) (2005)

tv · crime · drama · mystery

France

Strange Darling

Strange Darling (2023)

horror · thriller

United States · JT Mollner

Strange Days

Strange Days (1995)

crime · drama · sci-fi

United States · Kathryn Bigelow

Strike Back

Strike Back (2010)

tv · action · drama · thriller

United Kingdom

Succession

Succession (2018)

tv · comedy · drama

United States

Survive Style 5+

Survive Style 5+ (2004)

comedy · fantasy · horror

Japan · Gen Sekiguchi

Suzhou River

Suzhou River (2000)

drama · romance

Germany · Ye Lou

Taegukgi

Taegukgi (2004)

action · drama · war

South Korea · Kang Je-kyu

Talk to Her

Talk to Her (2002)

drama · mystery · romance

Spain · Pedro Almodóvar

Taxi Driver

Taxi Driver (2017)

action · drama · history

South Korea · Hun Jang

Ted Lasso

Ted Lasso (2020)

tv · comedy · drama · sport

United States

Terminal List

Terminal List (2022)

tv · action · drama · thriller

United States

Terminator

Terminator (1984)

action · adventure · sci-fi

United Kingdom · James Cameron

Tetsuo: The Iron Man

Tetsuo: The Iron Man (1989)

horror · sci-fi

Japan · Shin'ya Tsukamoto

The 8 Show

The 8 Show (2024)

tv · comedy · drama · horror

South Korea

The Americans

The Americans (2013)

tv · crime · drama · mystery

United States

The Beekeeper

The Beekeeper (2024)

action · crime · thriller

United Kingdom · David Ayer

The Boys

The Boys (2019)

tv · action · comedy · crime

United States

The Bridge (Broen/Bron)

The Bridge (Broen/Bron) (2011)

tv · crime · mystery · thriller

Sweden

The Brothers Sun

The Brothers Sun (2024)

tv · action · comedy · drama

United States

The Cabin in the Woods

The Cabin in the Woods (2011)

horror · mystery · thriller

Canada · Drew Goddard

The Detour

The Detour (2016)

tv · adventure · comedy

United States

The Electric State

The Electric State (2025)

action · adventure · comedy

United States · Anthony Russo

The Empty Man

The Empty Man (2020)

drama · horror · mystery

United States · David Prior

The End of the F***ing World

The End of the F***ing World (2017)

tv · adventure · comedy · crime

United Kingdom

The Expanse

The Expanse (2015)

tv · drama · mystery · sci-fi

United States

The Fall of the House of Usher

The Fall of the House of Usher (2023)

tv · drama · horror · mystery

United States

The Glory

The Glory (2022)

tv · drama · mystery · thriller

South Korea

The Good The Bad The Weird

The Good The Bad The Weird (2008)

action · adventure · comedy

South Korea · Kim Jee-woon

The Handmaiden

The Handmaiden (2016)

drama · romance · thriller

South Korea · Park Chan-wook

The Head

The Head (2020)

tv · drama · horror · mystery

Spain

The Holdovers

The Holdovers (2023)

comedy · drama

United States · Alexander Payne

The Host

The Host (2006)

drama · horror · sci-fi

South Korea · Bong Joon Ho

The Killer

The Killer (1989)

action · crime · drama

Hong Kong · John Woo

The Killing

The Killing (2007)

tv · crime · drama · mystery

Denmark

The Last Kingdom

The Last Kingdom (2015)

tv · action · drama · history

United Kingdom

The Last of Us

The Last of Us (2023)

tv · action · adventure · drama

Canada

The Lazarus Project

The Lazarus Project (2022)

tv · action · drama · fantasy

United Kingdom

The Leftovers

The Leftovers (2014)

tv · drama · fantasy · mystery

United States

The Legend of Vox Machina

The Legend of Vox Machina (2022)

tv · animation · action · adventure

United States

The Letdown

The Letdown (2017)

tv · comedy

Australia

The Man from Nowhere

The Man from Nowhere (2010)

action · crime · drama

South Korea · Lee Jeong-beom

The Matrix

The Matrix (1999)

action · sci-fi

United States · Lana Wachowski

The Night Comes for Us

The Night Comes for Us (2018)

action · crime · thriller

Indonesia · Timo Tjahjanto

The Other Two

The Other Two (2019)

tv · comedy

United States

The Outsider

The Outsider (2020)

tv · crime · drama · horror

United States

The Pitt

The Pitt (2025)

tv · drama

United States

The Queen's Gambit

The Queen's Gambit (2020)

tv · drama

United States

The Raid

The Raid (2011)

action · crime · thriller

Indonesia · Gareth Evans

The Raid 2

The Raid 2 (2014)

action · crime · thriller

Indonesia · Gareth Evans

The Running Man

The Running Man (1987)

action · sci-fi · thriller

United States · Paul Michael Glaser

The Shield

The Shield (2002)

tv · crime · drama · thriller

United States

The Sopranos

The Sopranos (1999)

tv · crime · drama

United States

The Taste of Things

The Taste of Things (2023)

drama · history · romance

France · Anh Hung Tran

The Tower

The Tower (2021)

tv · crime · drama · mystery

United Kingdom

The Town

The Town (2010)

crime · drama · thriller

United States · Ben Affleck

The Umbrella Academy

The Umbrella Academy (2019)

tv · action · adventure · comedy

United States

The Wire

The Wire (2002)

tv · crime · drama · thriller

United States

The Zone of Interest

The Zone of Interest (2023)

drama · history · war

United Kingdom · Jonathan Glazer

Three Colors: Blue

Three Colors: Blue (1993)

drama · music · mystery

France · Krzysztof Kieslowski

Three Colors: Red

Three Colors: Red (1994)

drama · mystery · romance

France · Krzysztof Kieslowski

Three Colors: White

Three Colors: White (1994)

comedy · drama · romance

France · Krzysztof Kieslowski

Tokyo Vice

Tokyo Vice (2022)

tv · crime · drama · thriller

Japan

Tom Yum Goong (The Protector)

Tom Yum Goong (The Protector) (2005)

action · crime · drama

Thailand · Prachya Pinkaew

Total Recall

Total Recall (1990)

action · adventure · sci-fi

United States · Paul Verhoeven

Trapped

Trapped (2015)

tv · crime · drama · mystery

Iceland

Tron

Tron (1982)

action · adventure · sci-fi

United States · Steven Lisberger

Tumbbad

Tumbbad (2018)

drama · fantasy · horror

India · Rahi Anil Barve

Upgrade

Upgrade (2018)

action · sci-fi · thriller

United States · Leigh Whannell

Us and Them

Us and Them (2018)

drama · romance

China · Rene Liu

Utopia

Utopia (2013)

tv · drama · mystery · sci-fi

United Kingdom

Violet Evergarden: The Movie

Violet Evergarden: The Movie (2020)

animation · drama · fantasy

Japan · Taichi Ishidate

Volver

Volver (2006)

comedy · drama

Spain · Pedro Almodóvar

Warped Forest

Warped Forest (2011)

comedy · fantasy

Japan · Shunichirô Miki

Warrior

Warrior (2019)

tv · action · crime · drama

United States

Wayward Pines

Wayward Pines (2015)

tv · drama · horror · mystery

United States

Weeds

Weeds (2005)

tv · comedy · crime · drama

United States

Westworld

Westworld (2016)

tv · drama · mystery · sci-fi

United States

Wild Goose Lake

Wild Goose Lake (2019)

crime · drama

China · Yi'nan Diao

Wind River

Wind River (2017)

crime · drama · mystery

United Kingdom · Taylor Sheridan

Winter's Bone

Winter's Bone (2010)

crime · drama · mystery

United States · Debra Granik

Yellowjackets

Yellowjackets (2021)

tv · drama · mystery · thriller

United States

You

You (2018)

tv · crime · drama · romance

United States

Yu Yu Hakusho

Yu Yu Hakusho (2023)

tv · action · adventure · comedy

Japan

Zero Zero Zero

Zero Zero Zero (2020)

tv · crime · drama · thriller

Italy

-1:-- Film/TV bookmarks (chaos resolved) (Post Alvaro Ramirez)--L0--C0--2026-01-29T00:00:00.000Z

Michal Sapka: RTE - Return to Emacs

OK, so (not that) long story short: I'm back inside Emacs. I deeply enjoyed the Vim side-quest, so I can now say that I use both: Vim and Emacs, but it's time to return to the main storyline. See, Emacs is just so different from anything out there, that nothing comes close. Vim may be an outstanding editor, and Shell gives me everything... but it's not the same. The thing with precompiled software is that they are black boxes, and modifying them is a huge pain in the ass. In Emacs, on the other hand, all the interesting parts are there for you to tinker. It's not that nothing stops you from connecting Mastodon.el, Magit and Mu4e, it's that it's natural. After using the standard shell I noticed that I don't care about Emacs, but what is stands for: the way software should have always been.

I want to have my entire computing experience in an open, interconnected system. What I don't want is some pesky product manager telling me how I should use their software, or fighting with my fork. Neither do I want to rent server space to run a glorified web page. Extensions are half-step; the entire program should be available for me to modify.

Now, there are problems - but none unsolvable. I am forced to do Java in day-job really soon, but we're living in the XXI century! Even such legacy language has some some tooling now. LSP works for autocomplete (not yet with our repo, but I'll fix it somehow) and refactorings are supported. Debugging is available via JDB and some Microsoft thingy (none of which work with our repo, but I'll fix it somehow). This means I will most likely not need to wash myself after work just to get the stench of IntelliJ out of me.

There are also pluses. I forced myself to do work notes, just to use org-mode... finally. This already reaps benefits, as it is miles better than a dozen Slack messages, Confluence, Microslop GitHub, and some memory. I am not the most organized person I've known, but I've heard legends of people less organized.

Happy LISPing to me! I'll need to write that html-to-gemtext converter. And yes - I am fully evil-mode now.

-1:-- RTE - Return to Emacs (Post Michal Sapka)--L0--C0--2026-01-28T20:36:26.000Z

Sacha Chua: Emacs: This year, I will... / Cette année, je vais...

In English

Inspired by the Emacs Carnival theme for January, this year, I will:

  • take more notes, perhaps with the help of speech recognition
    • Now I can manage my time better since the kiddo can study more independently, but I still have to manage interruptions from my life and from my own brain. If I write or dictate notes while I think or work, I can get back into things more easily. Speech recognition allows me to capture more thoughts, even if the results need a fair bit of reviewing and revising. I'm looking forward to checking out the ideas others have shared, such as configuring more transient.el interfaces and adding more tweaks to my Org Mode publishing.
  • stream to think out loud
    • My daily routines are gradually becoming more predictable, so I might be able to schedule streams or jump onto one to share ideas. If I do a live broadcast, I can learn from the questions and comments I get. Fridays at 10:30 AM seems like a good time for that, and when possible, I can also do it spontaneously.
  • record videos to share what I learn, and package my functions to make them reusable when possible
    • Like the previous points, sharing my ideas and my work can help others and start conversations. If I improve subed-record.el to combine video and audio recordings with screenshots and subtitles, I might be able to create videos more easily.
  • write more in French and improve my environment for this purpose
    • I like the mental stimulation of writing in another language. Lots of other people are learning languages too, so we might be able to help each other. For example, my functions for highlighting new words and grammatical errors could be useful.
  • practice speaking by making audio recordings with the help of subed-record and speech synthesis to improve my pronunciation
    • The advantage of implementing this in Emacs is that I can customize my workflow. For example, I want to write my draft and then record the audio sentence by sentence after listening to an example. I also want to see if I can more easily edit a recording of my session with my tutor so that I can keep only my last pronunciation attempts.
  • improve processes for EmacsConf and Emacs News
    • I might be able to organize much of it by myself, but other volunteers might also be able to help, which would be even better. I want to create the infrastructure to manage several virtual meetings simultaneously, probably with speech recognition, audio spatialization, and lots of keyboard shortcuts. I also want to improve my subtitling process.

The more I do in Emacs, the more I think of ideas for improvement…

En français

Sur le thème du Carnaval d'Emacs pour janvier - Cette année, je vais :

  • prendre plus de notes, peut-être avec l'aide de la reconnaissance vocale
    • Même si je peux mieux gérer mon temps maintenant que ma fille peut étudier de manière plus indépendante, je dois toujours gérer les interruptions de ma vie et de mon propre cerveau. Si j'écris ou dicte des notes pendant que je pense ou que je travaille, je reprendrai le fil de mes pensées plus facilement. La reconnaissance vocale me permet de capter plus de pensées, même si les résultats nécessitent de revoir et de réviser. Je suis enthousiasmée par les idées que d'autres partagent, comme la configuration de l'interface transient.el et l'amélioration de la publication d'Org Mode.
  • streamer pour réfléchir à voix haute
    • Mes routines quotidiennes deviennent plus prévisibles petit à petit, je peux donc planifier des événements ou me lancer dans le streaming pour partager des idées. Si je fais une diffusion en direct, je peux profiter des questions et des commentaires que je reçois. Le vendredi à 10h30 semble être un bon moment pour ça, et quand c'est possible, je peux aussi le faire spontanément.
  • enregistrer des vidéos pour partager ce que j'apprends, et packager mes fonctions pour les rendre réutilisables quand c'est possible
    • Comme les éléments précédents, partager mes idées et mon travail peut aider d'autres personnes et lancer des conversations. Si j'améliore subed-record.el pour combiner des enregistrements vidéo et audio avec des captures d'écran et des sous-titres, je peux créer des vidéos plus facilement.
  • écrire davantage en français et améliorer mon environnement à cet effet
    • J'apprécie la stimulation mentale d'écrire dans une autre langue. Beaucoup de gens apprennent d'autres langues, donc nous pouvons nous aider. Par exemple, mes fonctions pour surligner les nouveaux mots et les erreurs grammaticales pourraient être utiles.
  • pratiquer l'expression orale en faisant des enregistrements audio avec l'aide de subed-record et la synthèse vocale pour améliorer ma prononciation
    • L'avantage de l'implémentation dans Emacs est que je peux personnaliser mon flux de travail. Par exemple, je veux écrire mon brouillon, puis enregistrer l'audio phrase par phrase après l'avoir écouté. Je veux aussi modifier un enregistrement de mon rendez-vous avec ma tutrice pour que je garde seulement mes dernières essaies de prononciation.
  • améliorer les processus pour EmacsConf et Emacs News
    • Il se peut que je puisse l'organiser en grande partie par moi-même, mais il se peut aussi que d'autres bénévoles m'aident, ce qui serait encore mieux. Je veux créer l'infrastructure pour gérer plusieurs réunions virtuelles simultanément, probablement grâce à la reconnaissance vocale, la spatialisation audio, et de nombreux raccourcis clavier. Je veux aussi améliorer mon processus de sous-titrage.

Plus j'en fais dans Emacs, plus je pense à des idées d'amélioration…

Thanks to Christian Tietze for hosting!

View org source for this post

You can comment on Mastodon or e-mail me at sacha@sachachua.com.

-1:-- Emacs: This year, I will... / Cette année, je vais... (Post Sacha Chua)--L0--C0--2026-01-28T16:28:40.000Z

James Dyer: Ollama buddy now supports cloud models!

Having another look at my AI assistant - ollama-buddy, its been a while and it seems ollama has moved on since I started creating this package last year, so I have developed a new roadmap and the first step is to add ollama cloud models!

Here are some references to the project, including a youtube channel where I upload ollama-buddy demonstrations:

https://melpa.org/#/ollama-buddy

https://github.com/captainflasmr/ollama-buddy

Here is the changelog for the cloud model implementation:

<2026-01-28 Wed> 1.1

Added Ollama Cloud Models support

  • Cloud models (running on ollama.com infrastructure) now work seamlessly
  • ollama-buddy-cloud-signin to automatically open browser for authentication
  • Cloud models are proxied through the local Ollama server which handles authentication
  • Use C-u C-c m or transient menu “Model > Cloud” to select cloud models
  • Status line shows ☁ indicator when using a cloud model
  • Available cloud models include: qwen3-coder:480b-cloud, deepseek-v3.1:671b-cloud, gpt-oss:120b-cloud, minimax-m2.1:cloud, and more
-1:-- Ollama buddy now supports cloud models! (Post James Dyer)--L0--C0--2026-01-28T08:29:00.000Z

Irreal: Gruber On File Saving Ease

John Gruber, over at Daring Fireball has a post, Untitled Document Syndrome, that makes two points of interest to Irreal readers. The first involves the difficulty of initially saving what he calls “untitled documents”. He’s writing about macOS, of course, but even through I’ve used one Mac or another for almost two decades, I had a hard time figuring out what he was talking about. I guess it’s this: in some Apple text apps you can start typing without specifying a document name or a file path for where it should be saved. That means that when you first save the file you have to negotiate the file save dialog to supply this information.

Since I write everything in Emacs, this never happens to me. Part of starting a new file is executing a find-file which specifies its name and file system location. Even then, I just specify it in the minibuffer; there’s no annoying open dialog to deal with. The first time I save it is like any other time1: a simple Ctrl+x Ctrl+s.

The point of all this is that the difficulty of the initial save means that people will put it off and therefore suffer disaster when the app or system crashes. They may even lose hours of work. Happily, that first save is easy in Emacs so there’s no reason—not even a weak one like the save dialog—for putting it off.

Even if you do put it off, Emacs, like Gruber’s editor BBEdit, has you covered. It does periodic automatic backups so you never lose more than a little work.

The second point is related and concerns note taking apps. Like most of us—at least us oldtimers—Gruber stated taking notes by creating a file for each one with his editor. As we’ve all discovered, that doesn’t work all that well so he moved to Yojimbo and discovered that he was taking many more notes. As you all know, I solved the same problem with Journelly. I use it as my memo book and typically make about 10 entries per day. People think of Journelly as integrated with Emacs but it can also save its data in Markdown so it’s perfectly usable on any system and editor as long as you’re using an iPhone.

It’s amusing how 40 year old technology is still more convenient and easier to use than “modern” systems with dialog boxes for everything.

Footnotes:

1

Yes, one can just open a buffer, set the appropriate mode and start writing. When it comes time to save it, you do have specify a name and location but, of course, no one works this way.

-1:-- Gruber On File Saving Ease (Post Irreal)--L0--C0--2026-01-27T16:22:14.000Z

Charles Choi: Getting Eshell nth History to Work

As much as I enjoy using Eshell, it is not without its annoyances. In this case, I’m writing about the common shell convention of using !n to recall a previously entered command.

In Eshell, entering the history command will show you all of your previously entered commands alongside a number n.

The problem is in attempting to use !n to recall a specific command in Eshell as one would do in bash or zsh. By default it will not work as described in Info (eshell) History without configuring eshell-expand-input-functions first. (My current configuration is GNU Emacs 30.2.)

To get !n to work requires adding the function eshell-expand-history-references to the customizable variable eshell-expand-input-functions.

The following configuration Elisp will achieve this.

1
2
(add-to-list 'eshell-expand-input-functions
 #'eshell-expand-history-references)

A nice feature of eshell-expand-history-references is that it will expand using the content of an actual command instead of a number reference. So !foo will invoke the last command that you entered the string “foo” in.

It’s not clear to me whether coupling nth history support to eshell-expand-history-references is intentional or a bug. If the former, then I’d consider this yet another example of staying “on brand” with Emacs’ tendency to ship with questionable defaults. That shade aside, Eshell is still an amazing package that I could not imagine using Emacs without.

Links

-1:-- Getting Eshell nth History to Work (Post Charles Choi)--L0--C0--2026-01-27T06:15:00.000Z

Stefan van der Walt: org-mode Day Planning with Time Blocks

I’ve discovered, over the years, that setting a clear intention is closely correlated to a day well spent. I know that, when I decide what I want to do early in the morning—before being overwhelmed by email, Slack, Zulip, Discord, and all the other little attention grabbers—that I have a better chance of doing something I care about.

It seems like, in 2026, slow, intentional work is en vogue, with books like Burkeman’s “Meditations for Mortals” and Cal Newport’s “Slow Productivity” doing the rounds. As my friends know, I am fascinated (and inspired) by the Stoics and enjoy listening to the various teachers on Waking Up, many of whom echo the same idea: that mindful, focused effort is vastly more satisfying than responding to whatever seems urgent.

Time-blocking #

How we set intention is personal, and recommending any specific system feels trite. However, I have found that, for me, planning a rough schedule for the day—often called time-blocking—is a great way to think about what I want to do, how much of it I want to do, and when I want to do it.

Trying to follow such a schedule brings home many realities quickly:

  • That the hours go by more quickly than one tends to think. For me, this is a reminder that the day is precious.
  • That we often do a poor job at estimating how long work will take. Typically, we imagine we can do much more in a day than is realistic.
  • That unscheduled interruptions are common. And others, like breaks for exercise, eating, etc., should be taken into consideration.

Implementation #

I use org-mode to outline my day, and have capture templates for each week and each day. For this year, I have a file 2026.org in which I capture all those entries.

The day planner template is most relevant here:

** %u

- [ ] Scan [[mu4e:query:maildir:/INBOX flag:flagged][pinned emails]] for new tasks (max 10 mins)
- [ ] Scan [[https://github.com/notifications][GitHub]] for new tasks (max 10 mins)

*** Plan
**** 
**** Lunch + walk <%<%Y-%m-%d %a 13:00-13:45>>
**** 
**** Tidy up <%<%Y-%m-%d %a 16:45-17:00>>

*** Notes

It is then hooked up to my org-capture-templates. I use org-indent mode, so all those heading stars collapse.

The part I’d like to discuss in this post is the “Plan” section, where I outline my work for the day.

The time stamps in org-mode are neat: you’ll see the lunch entry goes from 13:00 to 13:45 (and this is how it is stored on disk), but when modifying it in org-mode it is displayed for editing in the minibuffer as 13:00+0:45. This makes it very easy to adjust the duration of an event. Note that the day timestamp (%u) is inactive, whereas the time blocks are active, so that only the latter appear in today’s Agenda view.

A screenshot of my time block planning in Emacs for 2026-01-27

My time block planning for 2026-01-27, showing active timestamps following one another.

Elisp functions #

The above template is sufficient for doing time blocking in org-mode. However, we can reduce some friction in how we use it by adding some utility functions for common activities.

Here are three such functions that help me to craft and modify my daily plan smoothly:

  1. Quickly navigate to today’s plan

    This command is invoked inside 2026.org, and navigates to the current week, then day, then to the end of the “Plan” entry.

    (defun stefanv/org-jump-to-today-plan ()
      "Jump to the end of the 'Plan' heading under today's date headline."
      (interactive)
      (let* ((today (regexp-quote (format-time-string (org-time-stamp-format nil t))))
             (today-re (concat "^\\*+ .*?" today)))
        (goto-char (point-min))
        (if (not (re-search-forward today-re nil t))
            (message "Heading matching %s not found." today)
          (org-reveal)
          (save-restriction
            (org-narrow-to-subtree)
            (goto-char (point-min))
            ;; Matches 'Plan' heading and optional trailing tags
            (if (re-search-forward "^\\*+ Plan\\(?:[ \t]*\\(:[[:alnum:]_@:]+:\\)\\)?[ \t]*$" nil t)
              (org-end-of-subtree)
              (widen)
              (message "No exact 'Plan' heading found under today's date."))))))
    

    It specifically searches for a * Plan heading, so if you modify the template be sure to update the regexp accordingly.

  2. Add a new planner entry, which follows the previous

    This function takes the end time of the previous entry, and uses it as the start time for a new entry.

    It tries to be somewhat clever at guessing your intention:

    • If you invoke it on a blank line, it searches upward for the previous timestamp, and turns the current line into a heading.
    • If invoked inside a section that already has a timestamp, it turns the next line into a timestamped heading.
    • If invoked on a heading line without a timestamp, it adds the timestamp to the end, preserving cursor position.

    (defun stefanv/org-plan-next ()
      "Create a new day plan entry following on the current or previous lines's active timestamp."
      (interactive)
      (let* ((ts-found (save-excursion
                         (end-of-line)
                         (when (re-search-backward org-ts-regexp0 nil t)
                           (let ((ctx (org-element-context)))
                             (when (eq (org-element-type ctx) 'timestamp) ctx)))))
             (is-blank (string-blank-p (buffer-substring (line-beginning-position) (line-end-position))))
             (is-header (org-at-heading-p))
             ;; Check if the found timestamp is actually on the current line
             (on-current-line (and ts-found
                                   (>= (org-element-property :begin ts-found)
                                       (line-beginning-position)))))
        (if (not ts-found)
            (user-error "No timestamp found above point")
          (cond
           ;; Already has TS OR is plain text -> new heading below
           ((or on-current-line (and (not is-blank) (not is-header)))
            (end-of-line)
            (org-insert-heading)
            (save-excursion (stefanv/insert-formatted-org-ts ts-found)))
    
           ;; Current line is blank -> turn into heading here
           (is-blank
            (org-insert-heading)
            (save-excursion (stefanv/insert-formatted-org-ts ts-found)))
    
           ;; Current line is a header (no TS) -> append TS and return cursor
           (t
            (save-excursion
              (end-of-line)
              (stefanv/insert-formatted-org-ts ts-found)))))))
    
    (defun stefanv/insert-formatted-org-ts (ts)
      "Helper to insert formatted timestamp with exactly one preceding space."
      (just-one-space)
      (insert (format "<%s %02d:%02d>"
                      (org-format-timestamp ts "%Y-%m-%d %a")
                      (or (org-element-property :hour-end ts)
                          (org-element-property :hour-start ts) 0)
                      (or (org-element-property :minute-end ts)
                          (org-element-property :minute-start ts) 0))))
    

    If you use it often, you can bind the function to a key:

    (keymap-set org-mode-map "C-c C-x p" #'stefanv/org-plan-next)
    
  3. Move all timestamps in a region forward by N minutes.

    Sometimes, a day runs away from us, or we get carried away and miss the end of a timeblock. At that point, you’d likely want to shift your entire day forward. The following function lets you select several planner items and shift them all by N minutes (positive or negative). If no region is selected, operate on the current line.

    There’s some fancy footwork to ensure that the surrounding org buffer is re-rendered, especially when using org-modern.

    (defun stefanv/org-shift-timestamps-in-region (minutes)
      "Shift all active timestamps in the region (or current line) forward by MINUTES minutes."
      (interactive "nMinutes to shift: ")
      (let* ((region-active (use-region-p))
             (beg (if region-active (region-beginning) (line-beginning-position)))
             (end (copy-marker (if region-active (region-end) (line-end-position))))
             ;; Regex for active timestamps: matches < followed by anything until >
             (active-ts-re "<\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}.*?\\)>"))
        ;; Allow undoing everything in one step
        (atomic-change-group
          (save-excursion
            (goto-char beg)
            ;; Shift active timestamps
            (while (re-search-forward active-ts-re end t)
              (save-excursion
                (goto-char (match-beginning 0))
                (org-timestamp-change minutes 'minute)
                (when (fboundp 'org-element-cache-refresh)
                  (org-element-cache-refresh (point)))))
    
            ;; Re-align tags for any headlines in the range
            (goto-char beg)
            (while (re-search-forward org-outline-regexp-bol end t)
              (org-align-tags))))
    
        ;; Refresh
        (font-lock-flush beg end)
        (set-marker end nil)
        (message "Shifted active timestamps by %s minutes." minutes)))
    

Conclusion #

I’ve presented three utility functions that help me quickly plan and organize my day. I’d love to hear from you how you plan yours!

-1:-- org-mode Day Planning with Time Blocks (Post Stefan van der Walt)--L0--C0--2026-01-27T00:00:00.000Z

Protesilaos Stavrou: Emacs: ef-themes version 2.1.0

The ef-themes are a collection of light and dark themes for GNU Emacs that provide colourful (“pretty”) yet legible options for users who want something with a bit more flair than the modus-themes (also designed by me).

Below are the release notes.


Version 2.1.0 on 2026-01-27

This version introduces two carefully designed, legible and colourful themes: ef-orange (light) and ef-fig (dark). Both draw inspiration from the fruits they are name after.

The convenience commands ef-themes-select-dark and ef-themes-select-light use the minibuffer to select+load an Ef theme that is either dark or light, respectively. The more general command is ef-themes-select.

All screen shots of the themes are updated to reflect their current status: https://protesilaos.com/emacs/ef-themes-pictures.

Remember that since version 2.0.0 the ef-themes are built on top of my modus-themes. This means that most of the changes happen to Modus and are inherited by Ef.

-1:-- Emacs: ef-themes version 2.1.0 (Post Protesilaos Stavrou)--L0--C0--2026-01-27T00:00:00.000Z

Evan Moses: Yak Power-Shears: LLMs are pretty good at Emacs

I’ve been an Emacs user for more than 25 years, and I’d say I’ve got a reasonable handle on customizing it. I can writeelisp, and I’ve got a couple decades of accumulated tweaking cruft on display in my dotfilesrepo. I’ve writtenadvice, I bind custom functions to keys, andI’m actually writing this right now with a customized mode for Hugomarkdown that I ginned up when Iwas getting annoyed by the way fill-paragraph worked inside Hugo shortcodes.

The reason Emacs is so attractive to those of us who use it is its infinite customizibility. There’s really not muchyou can’t alter or intercept or rewrite with enough effort, and over time your editor will come to fit you like awell-worn boot.

However, there are plenty of minor annoyances that I just live with. No one’s built the exact package that I want, andlearning enough to do it myself would be shaving just oneyak too many. So I do things by hand,or use the mouse instead of having a shortcut that jumps to whatever-it-is, or I deal with the hard-to-read log outputinstead of nice syntax highlighting.

LLMs: yak power-shears

LLMs, it turns out, are pretty good at elisp. There is a ton of open-source training data and gooddocumentation. So far I’ve successfully had Gemini or Claude build me:

  • A tree-sitter grammar and major mode for the Cedar policy language
  • A function to extract backtraces from a json-formatted log that my application at work emits, and pretty-print them
  • Syntax highlighting for my application’s Go test logs that plays nice with go-test-mode.

Unfortunately my biggest successes have all been for work, done on work machines with AI paid for by work, so I can’tpublish them here (at some point I’ll go through channels and see if I can open source some of it), but here’s someredacted logs that show the pretty formatting I was able to achieve:

A screenshot of my highlighted logs, with the logs heavily redacted, showing the timestamp, log level, log string, andjson data in different colors and sizes

And here’s a slightly-mangled version of the code that produces it. Note most of the comments and doc comes straightfrom Gemini:

(defgroup work-log-faces nil "Faces for Work integration test logs.");; Define faces(defface work-log-timestamp  '((t :inherit font-lock-comment-face :foreground "#6c757d"))  "Face for timestamps." :group 'work-log-faces)(defface work-log-level  '((t :inherit font-lock-keyword-face :weight bold))  "Face for log levels (INFO, WARN)." :group 'work-log-faces)(defface work-log-message  '((t :inherit font-lock-string-face :foreground "#e0e0e0"))  "Face for the log message text." :group 'work-log-faces)(defface work-log-json  '((t :inherit font-lock-constant-face :height 0.9))  "Face for the JSON payload." :group 'work-log-faces);; Define the matching rules(defvar work-log-font-lock-keywords  '(("^\\([0-9T:.-]+\\)[ \t]+\\([A-Z]+\\)[ \t]+\\(.*?\\)[ \t]+\\({.*}\\)?$"     (1 'work-log-timestamp t)     (2 'work-log-level)     (3 'work-log-message)     (4 'work-log-json)))  "Regex keywords to highlight structured logs.");; 1. Define the control flag (default to nil)(defvar -work-test-highlighting-active nil  "If non-nil, apply custom log highlighting in go-test-mode.");; 2. Define the function that checks the flag(defun my:work-apply-logs-highlight ()  "Apply highlighting only if the Work test flag is active."  (when -work-test-highlighting-active    (font-lock-add-keywords nil work-log-font-lock-keywords t)));; 3. Add it to the hook;; Note: go-test usually runs in `go-test-mode` or `compilation-mode`(add-hook 'go-test-mode-hook #'my:work-apply-logs-highlight)

Specifics

So far I’ve used two primary interfaces to LLMs: Claude Code, especially Claude-code-ide forEmacs, and the Gemini web interface. For Claude I’ve been using Opus4.5, for Gemini 3 either Thinking or Pro. Keep in mind that most of the time my company is paying for tokens, so I’mnot being particularly cost-conscious (sorry, bean-counters). I haven’t done any serious comparisons of models andinterface because…all the modern models work pretty well for this sort of thing.

For both syntax highlighting and the backtraces, I was able to simply paste in a sample of the input and describe whatI’d like, and it was able to give me some elisp I could drop into my .emacs.d.

The ts grammar and mode needed a bit more back-and-forth and some actual debugging (by both myself and Gemini). I thinkif I had less elisp experience I wouldn’t have been able to vibecode the whole solution, but I’ve never really written ats grammar or a major mode before that was more than a tweak or two, and it got me 80% of what I needed.

Go forth and customize

The code that Gemini wrote for the font-locking wasn’t revolutionary. It ended up just writing a regex, some faces, andcalling font-lock-add-keywords. But I’ve barely messed withfont-lock or face definitions myself before and I didn’t know any of the relevant functions off the top of my head. Icould have figured it out, but it wouldn’t have been worth my time. The LLM shaved most of the yak for me.

So next time you’re annoyed by a missing motion command, or ugly output, or you wish you had a command that worked justa bit differently, ask Claude/Gemini/your favorite LLM to fix it for you. Not only will you fix your problem, but ifyou take just a bit of time to review the output (and you’re not gonna just blindly throw LLM code in your .emacs right?RIGHT?), you may learn about a subsystem you didn’t know before. I’m sure you can do this with Neovim or, to a lesserextent, VSCode or other editors that have reasonable extension points, so go fix them too. Your yaks will thank you come summer.

-1:-- Yak Power-Shears: LLMs are pretty good at Emacs (Post Evan Moses)--L0--C0--2026-01-27T00:00:00.000Z

Sacha Chua: 2026-01-26 Emacs news

View org source for this post

You can e-mail me at sacha@sachachua.com.

-1:-- 2026-01-26 Emacs news (Post Sacha Chua)--L0--C0--2026-01-26T22:20:00.000Z

Irreal: Starting A Journal

A couple of weeks ago I read a lovely story in The New Yorker by Calvin Tompkins about starting a journal in his hundredth year. Tompkins was born the same year that The New Yorker was founded and, ironically, spent most of his working life writing for the magazine. Last year—his hundredth—he surprised himself by deciding to start a journal as a sort of countdown to his hundredth birthday. The story is mostly entries from the journal but I found them fascinating. Perhaps you will too. If nothing else, you’ll get a first hand glimpse of what old age really looks like. The TL;DR is that there’s good news and bad news.

In any event—although I am nowhere near my hundredth year—I was inspired to start my own journal. Of course, it was going to be written with Emacs but the question is how. There is the builtin journal app as well as some third party packages but I chose simplicity. I didn’t need anything special or complex with arcane functions so I just added an Org capture template to create a file+datetree file in Org mode. Here’s the whole thing:

("J" "Personal Journal" entry (file+datetree "~/org/personal-journal.org")
         "* %<%R: >%? \n%t" :empty-lines-before 1)

I have some startup options in the file itself to set visual-line-mode, use a variable pitch mode, and couple of other things: the same setup that I use for my blog posts. All this is simple and familiar. There’s nothing new for me to learn since it’s basically the same setup that I use everyday to write my Irreal posts.

The takeaway is that if you’d like to start a journal, it’s really easy. Just use a simple Org file with a corresponding capture template.

-1:-- Starting A Journal (Post Irreal)--L0--C0--2026-01-26T15:55:58.000Z

James Dyer: Auto-Populating Weekly Dates in Org-Mode Tables

Here is just a quick one, I was working with an org-mode table for tracking work weeks and needed to auto-populate a Date column where each row increments by exactly one week. The table structure looked like this:

The first row has a base date (2026-01-05), and I wanted subsequent rows to automatically calculate as weekly increments: 2026-01-12, 2026-01-19, and so on.

Initially, I tried several approaches that seemed logical but encountered #ERROR results and eventually settled on a working solution which is to hardcode the base date directly in the formula:

#+TBLFM: $3='(format-time-string "%Y-%m-%d" (time-add (date-to-time "2026-01-05") (* (- @# 2) 7 24 3600)))

which gave:

and I can now of course extend the table for all the weeks in the year and I don’t have to fill in manually any more!

Here’s how it works:

  • (date-to-time "2026-01-05") - Convert the hardcoded base date to Emacs time format
  • (- @# 2) - Calculate the offset from the base row
  • (* (- @# 2) 7 24 3600) - Convert the offset to seconds (weeks × days × hours × seconds)
  • time-add - Add the offset to the base date
  • format-time-string "%Y-%m-%d" - Format back to ISO date string
-1:-- Auto-Populating Weekly Dates in Org-Mode Tables (Post James Dyer)--L0--C0--2026-01-26T10:13:00.000Z

Stefan van der Walt: Using Gemini for Code Patches in Emacs

To ensure that my skepticism of LLMs did not blind me to progress, and to keep my finger on the pulse, I’ve been incorporating them into my Emacs config, starting with gptel and, more recently, macher. In December, I took another look at Gemini, and noticed a significant improvement over Flash 2.5 with the arrival of Flash 3 Preview.

In this post, I share the configuration I currently use, and mention some open questions I still hope to address.

Tools #

gptel is a beautifully clean and simple interface for LLM chat. Despite its simplicity, it actually has fairly advanced functionality, which includes MCP integration, introspection of queries, multi-modal input (such as images), and tool usage (extending LLMs with access to elisp functions of your choosing).

macher runs on top of gptel. It provides a “pseudo-agentic” workflow, in which you provide the LLM context about your current project, such as the list of files. It also defines several tools that the LLM can use, such as the ability to read files. You can use macher to generate a patch, which you then review, apply the parts you like, or ask macher for further improvements.

Configuration #

The macher installation simply follows the recommendations in its README:

(use-package macher
  :custom
  ;; better folding and source block highlighting of the reasoning process
  (macher-action-buffer-ui 'org)

  :config
  (macher-install)
  (macher-enable))

And here is the basic gptel configuration, ensuring that macher is pre-loaded:

(use-package gptel
  :commands (gptel gptel-mode)
  :config
  (require 'macher))

Now the model definition for Gemini, to access the latest 3.0 models:

;; https://ai.google.dev/gemini-api/docs/models
(setq
  gptel-model 'gemini-3-flash-preview
  gptel-backend (gptel-make-gemini "Gemini"
                  :key "<Get your key at aistudio.google.com>"
                  :stream t
                  :models '(gemini-3-flash-preview
                            gemini-3-pro-preview
                            gemini-2.5-flash
                            gemini-2.5-pro)))

Note how you list the models you want to choose from, and then pick the default.

You will need an API key, which you can generate at https://aistudio.google.com. I’m pretty sure you also need to activate billing to access gemini-3-flash-preview, but let me know if you succeed without doing that. My total cost, after playing around with it a bunch this week, was ~3 USD.

If your Emacs config lives in a public repository or on an untrusted machine, you’ll want to be careful in adding the token to it. gptel automatically uses tokens listed in ~/.authinfo. See Mastering Emacs for more on auth-source.

Adding Google search #

EDIT: I’ve since noticed that, while adding the search tool this way works, it also messes up macher. So, don’t try this yet until #750 is resolved.

The above configuration works fine, but I noticed that some answers were outdated. Gemini supports “grounding” via Google Search. For example, instead of telling you that TypeScript 5.3 is the newest release (which it was, at the time of its training), it can use Google Search to verify that, in fact, the latest version is 5.9.

gptel#750 tracks the issue, but in the meantime you can manually adjust the query sent to Google, and tell it to enable Grounding with Google Search:

;; Enable Google Search capability for gemini
(cl-defmethod gptel--request-data :around ((backend gptel-gemini) prompts)
  "Add search ability to Gemini requests."
  (plist-put (cl-call-next-method) :tools (append '(:google_search ()))))

This is obviously just a temporary hack, until #750 can be resolved.

Grounding with Search may incur additional costs, as per the Gemini API docs:

5,000 prompts per month (free), then (Coming soon**) $14 / 1,000 search queries

Usage #

To generate a patch on your current project, you must do two things:

  1. Select project: Tell macher which project you’re working on. The easiest way to do this is to open a gptel buffer (which you can give any name you like, e.g. gemini:add-tests) and then M-x cd (change directory) into your project.

    I haven’t checked, but I suspect this requires the project to be under version control.

  2. Activate macher: As part of your query, mention @macher anywhere to enable it. E.g., @macher add unit test scaffolding. C-c <enter> executes the query.

    If you type @macher and it does not get highlighted with a little box surrounding the text, then macher isn’t correctly installed. Try running M-: (macher-install) manually.

    You can add additional context to a query (e.g., a programming guidance document outside of the project) using gptel-add (this is standard gptel functionality).

While the query is executing, it displays a folded reasoning block. You can type TAB to unfold it, and watch the various steps the LLM takes. After a while, a patch will be generated in a separate window.

You can apply the entire patch using diff-apply-buffer, or single parts of the patch with diff-apply-hunk.

Issues to resolve #

With my configuration, diff-apply-buffer works fine as long as only existing files are modified. When new files need to be created, it misunderstands the file prefix in the patch, and fails to auto-complete its name. I filed an issue to discuss that with the macher author at macher#45, and hopefully can post an update soon.

Conclusion #

LLMs recently seem to have undergone a phase change in coding ability. Of course, even in this phase any code generated needs to be very carefully reviewed and tested. Andrej Karpathy’s tweet earlier today summarizes where we stand quite well (I recommend reading the top comments too).

E.g., when talking about the new capability, he also warns:

The nearest neighbor really is some kind of a junior engineer. Its ideas about what experiments to run […] have been surprisingly bad, but its execution on ideas I’ve given it have been surprisingly good. — https://x.com/karpathy/status/2015888674739912910

The mistakes have changed a lot - they are not simple syntax errors anymore, they are subtle conceptual errors that a slightly sloppy, hasty junior dev might do. The most common category is that the models make wrong assumptions on your behalf and just run along with them without checking. They also don’t manage their confusion, they don’t seek clarifications, they don’t surface inconsistencies, they don’t present tradeoffs, they don’t push back when they should, and they are still a little too sycophantic. — https://x.com/karpathy/status/2015883857489522876

So, while we should tread with care, there are exciting avenues to explore. I’ve been developing open source computational libraries for a long time, and as our ecosystem grows I notice myself spending more and more time on maintenance, and less and less time on reading papers and developing new features. My hope is that LLMs will free our small communities—who have very limited time and resources—from repetitive, tiring maintenance tasks, so we may return to what we love to do: crafting intuitive APIs around innovative algorithms that, in turn, enable real-world science.

-1:-- Using Gemini for Code Patches in Emacs (Post Stefan van der Walt)--L0--C0--2026-01-26T00:00:00.000Z

Irreal: Emacs Performance on macOS

Does Emacs run slower on macOS than it does on a similar machine running Linux? I don’t know. I’ve been running Emacs almost exclusively on macOS for somewhere around 17 years so its performance on macOS, whatever it is, seems normal to me.

Over at the Emacs reddit, staff-engineer says that he runs it on both macOS and on Linux. The Apple machine is, in fact, more powerful than the Linux one but is nevertheless less performant when running Emacs and staff-engineer wonders why.

He received several excellent answers that are definitely worth reading but I especially like the one from totbwf who explains that a large part of the problem is that macOS uses a tiny size for its pty buffers and that this can significantly slow down Emacs when it calls an external process using a process-connection-type of pty. His solution to this is to simply advise functions calling start-process to use pipes instead of ptys. He says that this can speed up these actions by a factor of 10. For Magit, he says that you can get the same result by simply setting magit-process-connection-type to nil.

Even if you don’t want to add a lot of advises to your configuration, it may be worthwhile making this one simple change to Magit if you use it a lot.

To be honest, I have no idea if these fixes will work or not but they’re easy to try if you feel Emacs is too slow on macOS. If changing the connection type helps, I would think that someone would fix it in Emacs core for macOS installations. It doesn’t sound like it would be too hard but one of the problems is that there are few Apple users helping with development.

-1:-- Emacs Performance on macOS (Post Irreal)--L0--C0--2026-01-25T15:12:23.000Z

TAONAW - Emacs and Org Mode: Why I use Denote?

When I mentioned Denote again a couple of days ago, Omar commented that whenever someone mentions using Denote or org-roam, he’s curious to know if that person tried vanilla org-mode first, without additional packages.

I get it. After all, I’ve been resisting the whole Zettelkasten bandwagon and org-roam with it for a while, keeping the same opinion about org-roam Omar seems to have about Denote (I’m speculating here, of course). In general, I don’t like the idea of Doom Emacs or Spacemacs for the same reasons. Denote, for some reason, never registered this way. I liked it from day one.

As I was answering his question and he asked for more details, I thought it might make a good post. So here we are.

Not a whole lot changed for me since I first looked into Denote. I still mostly use it for my blog posts (like the one you’re reading right now) and my info notes, which mostly contain technical how-tos to myself and to a lesser degree, some records and memos, like a list of equipment in my home or who’s who at work. At this point, I also have a third, personal folder with notes only on my Linux computer as well, which mostly contain “supplemental” notes as I call them to journal entries I want to expand on in private (I use my work iPhone with Journelly, which does a fantastic job, but I don’t trust Apple or any cloud service for that matter with my private stuff).

It has been slow progress, but I’ve improved my usability with Denote, which I recently enhanced further after having the pleasure of talking to Prot 1:1 in one of his online tutoring sessions (always a pleasure, and highly recommended if you ask me).

The main philosophy behind Denote is something I’ve been in agreement with for a long time, before I started using it, or Emacs, or even got familiar with Linux: the idea of how to date and rename files. I’ve never agreed with the American way of writing dates, and I always prefer the ISO format: yyyymmdd followed by hhmm. To me, this is how things should be organized. So when Denote came around with Prot explaining that this is how he sees files should be organized - date, followed by keywords, and then a title - it just clicked.

You can extend this file-naming scheme to all your personal files if you’d like (at least all the files you visit with Dired), and I’m in the process of doing exactly that. Because the renaming function is built into Denote, it’s easy to stay concise and avoid mistakes (for example, renaming one file 20260124 something, and then another 2026124, emitting the 0 for January). While it’s true you could easily do that without Denote, to me, this core piece was like a sign that said, “Hey, look at this, this guy is building a package that is based on something that makes sense, check it out.”

Tags are another important part of Denote. Org-mode has tags built into headers, which works, but the headers, to me, are a bit too specific to need them. For the most part, I can get the level of information I need through the header itself, and I use tags to associate a certain header with a person - but even that is not useful, as I often work with too many people for the tags to really mean anything. Meanwhile, it’s the files themselves that need tags: certain workflows are similar, but are tagged to work for different operating systems (say, how to set my work VPN on Linux vs on my Mac), or maybe I have a naming convention for different departments at work, and I want to tag the relevant departments.

I didn’t always break my different workflows and notes into files. In the past, I had one org file as a wiki: a single file with many headers explaining workflows and procedures. I often had errors there. It was one big file that I often opened and edited, so I had syncing issues, headers that got mixed up, etc. The other problem I had with the wiki was logical: at times, a certain subheader would fit under two different headers, and I would have a hard time deciding where to place something. Headers work as categories, while tags work as ,well, tags. If we take the VPN example from before, I could put my VPN instructions under “networking,” “security,” or “remote work,” but not all. I don’t have this problem with Denote.

Another, more recent skill I started using with Denote is its metadata and search features. Meta notes work as an index of other files, where I can have one file with a dynamic list (updated whenever the file is loaded) of live links to other files with the same tag or other regex I use. Meanwhile, searching with Denote using denote-grep (something I learned recently) shows a list of all the files matching my search in collapsible form, making it easy to find what I need. I can use one of many denote-query forms to filter those results even further, and of course, there’s denote-consult, which, well, if you know consult, you know what it does, and it’s excellent.

Finding stuff is a central issue for anyone keeping notes, no matter what system they use. Denote supplies me with the best tools I’ve seen for this job. It’s true that many of these tools are already available in Emacs and in org-mode. Denote doesn’t alter these existing options; rather, it builds on them. In fact, that’s a big part of Denote: the way its commands are constructed borrows from what Emacs already does, so if you’re familiar with one, you intuitively know what the same thing would do inside Denote.

Another example of the above is the org files you create with Denote. You can use Denote directly with a capture template, and each file is created with file tags that make sense if you use org-mode: #-title, #+date and #+filetags, which denote changes automatically as you rename files with it. These work together with additional options I include in my notes, such as #+STARTUP: inlineimages. In a Markdown export, such as this very post you’re reading now, Emacs knows to ignore these org-mode only options, so I don’t need to clean them out when I’m ready to post. It’s a nice touch that already exists in vanilla org-mode, but with the added benefits of Denote, like having my post tagged, dated, and easily found in a search alongside the rest of my Denote files in the future.

There are definitely more features of Denote I don’t use, or use enough (blacklinks, which I believe are more of a recent introduction, is one of them), but as I stated above, this is a process. I learn more every week, and as my notes collection increases, so does my understanding of how to use Denote in a way that works for me.

-1:-- Why I use Denote? (Post TAONAW - Emacs and Org Mode)--L0--C0--2026-01-25T14:12:09.000Z

Magnus: More on the switch to eglot

Since the switching to eglot I've ended up making a few related changes.

Replacing flycheck with flymake

Since eglot it's written to work with other packages in core, which means it integrates with flymake. The switch comprised

  • Use :ensure nil to make sure elpaca knows there's nothing to download.
  • Add a call to flymake-mode to prog-mode-hook.
  • Define two functions to toggle showing a list of diagnostics for the current buffer and the project.
  • Redefine the relevant keybindings.

The two functions for toggling showing diagnostics look like this

(defun mes/toggle-flymake-buffer-diagnostics ()
  (interactive)
  (if-let* ((window (get-buffer-window (flymake--diagnostics-buffer-name))))
      (save-selected-window (quit-window nil window))
    (flymake-show-buffer-diagnostics)))

(defun mes/toggle-flymake-project-diagnostics ()
  (interactive)
  (if-let* ((window (get-buffer-window (flymake--project-diagnostics-buffer (projectile-project-root)))))
      (save-selected-window (quit-window nil window))
    (flymake-show-project-diagnostics)))

And the changed keybindings are

flycheck flymake
flycheck-next-error flymake-goto-next-error
flycheck-previous-error flymake-goto-prev-error
mes/toggle-flycheck-error-list mes/toggle-flymake-buffer-diagnostics
mes/toggle-flycheck-projectile-error-list mes/toggle-flymake-project-diagnostics

Using with-eval-after-load instead of :after eglot

When it comes to use-package I keep on being surprised, and after the switch to elpaca I've found some new surprises. One of them was that using :after eglot like this

(use-package haskell-ng-mode
  :afer eglot
  :ensure (:type git
           :repo "git@gitlab.com:magus/haskell-ng-mode.git"
           :branch "main")
  :init
  (add-to-list 'major-mode-remap-alist '(haskell-mode . haskell-ng-mode))
  (add-to-list 'eglot-server-programs '(haskell-ng-mode "haskell-language-server-wrapper" "--lsp"))
  (setq-default eglot-workspace-configuration
                (plist-put eglot-workspace-configuration
                           :haskell
                           '(:formattingProvider "fourmolu"
                             :plugin (:stan (:global-on :json-false)))))
  ...
  :hook
  (haskell-ng-mode . eglot-ensure)
  ...)

would delay initialisation until after eglot had been loaded. However, it turned out that nothing in :init ... seemed to run and upon opening a haskell file no mode was loaded.

After a bit of thinking and tinkering I got it working by removing :after eglot and using with-eval-after-load

(use-package haskell-ng-mode
  :ensure (:type git
           :repo "git@gitlab.com:magus/haskell-ng-mode.git"
           :branch "main")
  :init
  (add-to-list 'major-mode-remap-alist '(haskell-mode . haskell-ng-mode))
  (with-eval-after-load 'eglot
    (add-to-list 'eglot-server-programs '(haskell-ng-mode "haskell-language-server-wrapper" "--lsp"))
    (setq-default eglot-workspace-configuration
                  (plist-put eglot-workspace-configuration
                             :haskell
                             '(:formattingProvider "fourmolu"
                               :plugin (:stan (:global-on :json-false))))))
  ...
  :hook
  (haskell-ng-mode . eglot-ensure)
  ...)

That change worked for haskell, and it seemed to work for python too, but after a little while I realised that python needed a bit more attention.

Getting the configuration for Python to work properly

The python setup looked like this

(use-package python
  :init
  (add-to-list 'major-mode-remap-alist '(python-mode . python-ts-mode))
  (with-eval-after-load 'eglot
    (assoc-delete-all '(python-mode python-ts-mode) eglot-server-programs)
    (add-to-list 'eglot-server-programs
                 `((python-mode python-ts-mode) . ,(eglot-alternatives
                                                    '(("rass" "python") "pylsp")))))
  ...
  :hook (python-ts-mode . eglot-ensure)
  ...)

and it worked all right, but then I visited the package (using elpaca-visit) and realised that the downloaded package was all of emacs. That's a bit of overkill, I'd say.

However, adding :ensure nil didn't have the expected effect of just using the version that's in core. Instead the whole configuration seemed to never take effect and again I was back to the situation where I had to jump to python-ts-mode manually.

The documentation for use-package says that :init is for

Code to run before PACKAGE-NAME has been loaded.

but I'm guessing "before" isn't quite before enough. Then I noticed :preface with the description

Code to be run before everything except :disabled; this can be used to define functions for use in :if, or that should be seen by the byte-compiler.

and yes, "before everything" is early enough. The final python configuration looks like this

(use-package python
  :ensure nil
  :preface
  (add-to-list 'major-mode-remap-alist '(python-mode . python-ts-mode))
  :init
  (with-eval-after-load 'eglot
    (assoc-delete-all '(python-mode python-ts-mode) eglot-server-programs)
    (add-to-list 'eglot-server-programs
                 `((python-mode python-ts-mode) . ,(eglot-alternatives
                                                    '(("rass" "python") "pylsp")))))
  ...
  :hook (python-ts-mode . eglot-ensure)
  ...)

Closing remark

I'm still not sure I have the correct intuition about how to use use-package, but hopefully it's more correct now than before. I have a growing suspicion that use-package changes behaviour based on the package manager I use. Or maybe it's just that some package managers make use-package more forgiving of bad use.

-1:-- More on the switch to eglot (Post Magnus)--L0--C0--2026-01-25T13:18:00.000Z

Protesilaos Stavrou: Emacs: tmr version 1.3.0

TMR provides facilities for setting timers using a convenient notation. Lots of commands are available to operate on timers, while there also exists a tabulated view to display all timers in a nice grid.

Below are the release notes.


Version 1.3.0 on 2026-01-25

This version adds some user options and new features to an already stable package.

Timers can be paused

The command tmr-toggle-pause will prompt for a running timer and pause it.

Users who have something like the following in their configuration, have access to tmr-toggle-pause under the P key:

;; All TMR commands are behind this prefix key.  So `tmr-toggle-pause' is C-c t P.
(define-key global-map (kbd "C-c t") #'tmr-prefix-map)

In the buffer produced by the command tmr-tabulated-view the pause functionality applies to the timer at point. The tmr-toggle-pause is invoked with the P key.

An extra column in the tabulated view shows whether a timer is paused or not. Here is an example:

Start      End        Duration   Remaining  Paused?  Acknowledge?   Description

08:49:41   09:19:46   30m        29m 17s    Yes                     Work on TMR for 30 minutes
08:49:31   08:54:31   5m         3m 53s                             Prepare tea
08:49:21   08:59:21   10m        8m 42s              Yes            Edit the description with this one instead

Configure the confirmation text for acknowledgements

When a timer is set to be acknowledged (i.e. the user must confirm that they saw it elapse) it prompts for confirmation. The default input text that confirms the acknowledgement is ack. This is now subject to configuration via the user option tmr-acknowledge-timer-text.

Change how frequently the tabulated list is refreshed

The buffer produced by tmr-tabulated-view is set to automatically refresh every 5 seconds by default. In previous versions this was every 1 second. The new user option tmr-tabulated-refresh-interval can be set to a number of seconds or nil. In the latter case, the automatic refresh is disabled.

Removed the long-obsolete tmr-tabulated.el

Its code was merged into tmr.el on 2024-10-30 and all it was doing thenceforth is issue a warning to those who would require the tmr-tabulated feature. Now (require 'tmr-tabulated) produces an error.

-1:-- Emacs: tmr version 1.3.0 (Post Protesilaos Stavrou)--L0--C0--2026-01-25T00:00:00.000Z

Jack Baty: Saturday, January 24, 2026

  • STATUS: Freezing. It’s -15°F out there.
  • PLANS: Solidifying my Linux setup. Emacs, mostly. Some Darktable.
  • READING: Half through “Anima Rising” by Christopher Moore
  • LISTENING: Tom Waits, probably.

It was -15°F while walking Alice this morning. I tried the doggy boots, but she wasn’t having it, so we barefooted it. She must be tough, because I didn’t see any signs of her feet bother her.


I don’t know why I worry about what kinds of posts belong where or whether they belong at all. No one else cares, why should I? So yeah, these daily posts are going to stay here for the moment, until I decide I was wrong.


Oh, and fuck this entire administration.

✍️ Reply by email
-1:-- Saturday, January 24, 2026 (Post Jack Baty)--L0--C0--2026-01-24T17:14:00.000Z

Spent the last day and a half on and off figuring out how to use pandoc to make my org-mode files in pretty, readable docx files, including tables. It was a challenge, but it’s worth it. The key is to use a reference doc and to know how to use it. Need to expend on that.

-1:--  (Post TAONAW - Emacs and Org Mode)--L0--C0--2026-01-24T14:48:50.000Z

Jack Baty: Linux and/or macOS

I’ve been alternating between Linux (Fedora/KDE) and macOS since the beginning of the year.

I’d describe Linux and the software running on Linux like this:

Less polish, more power.

What I find challenging is that sometimes I want the power, other times I want the polish.

Surprisingly, I am starting to prefer being in Linux than being in macOS. Linux feels like it’s mine and I like that feeling. Everything in the OS makes me believe it was done with me mind. “Me” being “the user”. Even when things are frustrating, I usually understand why. macOS used to feel this way, but has drifted from it. It’s not all Tahoe’s fault, but it certainly hasn’t helped.

What I miss most about running macOS is not macOS. It’s the software. The polish.

Most of the stuff I use on Linux also works on my Mac. That doesn’t apply the other way around. Whenever I discover some cool new app and find that it’s macOS only, it stings a little.

I want BBEdit and Tinderbox and Keyboard Maestro and Things and iA Writer and Preview. There are usually “equivalent” apps on Linux, but they’re not really. They do mostly the same things, but they’re not the same. Not even close. It’s been hard to adjust.

The other glaring omission on Linux is an easy way to share things with family and friends. How am I supposed to send funny memes to my wife when I have to jump through so many hoops first?

KDE Connect would be a great solution, but every other time I want to use it, the computer can’t see my phone, or vice versa. By the time I cycle wifi on both devices, the moment has passed. Maybe I’ll try talking everyone into switching to Signal. Ha! There’s no chance of that, so I’m on my own here.

If we’re keeping track, I’m writing this in Emacs on the Linux desktop. It’s where I’ll probably end up full time eventually, but it’s not happened yet.

d

✍️ Reply by email
-1:-- Linux and/or macOS (Post Jack Baty)--L0--C0--2026-01-24T14:10:00.000Z

Emacs APAC: UPDATED Announcing Emacs Asia-Pacific (APAC) virtual meetup, Saturday, January 31, 2026

Note: the date has been updated for this month’s meetup.

This month’s Emacs Asia-Pacific (APAC) virtual meetup is scheduled for Saturday, January 31, 2026 with BigBlueButton and #emacs on Libera Chat IRC. The timing will be 1400 to 1500 IST.

The meetup might get extended by 30 minutes if there is any talk, this page will be updated accordingly.

If you would like to give a demo or talk (maximum 20 minutes) on GNU Emacs or any variant, please contact bhavin192 on Libera Chat with your talk details:

-1:-- UPDATED Announcing Emacs Asia-Pacific (APAC) virtual meetup, Saturday, January 31, 2026 (Post Emacs APAC)--L0--C0--2026-01-24T05:00:00.000Z

Sacha Chua: Queuing multiple transcriptions with whisper.el speech recognition

I want to be able to talk out loud and have the ideas go into Emacs. I can do this in a number of different ways:

  1. I briefly demonstrated a step-by-step approach with natrys/whisper.el with a single file. I press a keyboard shortcut to start the recording, another shortcut to stop the recording, and it transcribes it in the background. But the way whisper.el is set up is that if I press the keyboard shortcut to start recording again it will offer to interrupt the transcription process, which is not what I want. I want to just keep talking and have it process results as things come in.
  2. I'm also experimenting with Google Chrome's web speech API to do continuous speech recognition, which I can get into Emacs using a web socket.
  3. What I've just figured out is how to layer a semi-continuous interface for speech recognition on top of whisper.el so that while it's processing in the background, I can just press a keyboard shortcut (I'm using numpad 9 to call my-whisper-continue) to stop the previous recording, queue it for processing, and start the next recording. If I use this keyboard shortcut to separate my thoughts, then Whisper has a much easier time making sense of the whole sentence or paragraph or whatever, instead of trying to use the sliding 30 second context window that many streaming approaches to speech recognition try to use.

Question: Did you fix the keyboard delay you've got while speech catches what you're saying?

Sometimes, when the speed recognition kicks in, my computer gets busy. When my computer gets really busy, it doesn't process my keystrokes in the right order, which is very annoying because then I have to delete the previous word and retype it. I haven't sorted that out yet, but it seems like I probably have to lower the priority on different processes. On the plus side, as I mentioned, if I dictate things instead of typing them, then I don't run into that problem at all.

Also, other notes on delays: The continuous speech recognition via Google Chrome shows up fairly quickly, but it's not very precise, and it doesn't have punctuation. Even if there's a little bit of a delay, as long as I press the my-whisper-continue shortcut after each thought, then I can get that text into my Emacs buffer using the nicer transcription from my selected model. There is going to be a bit of a delay for that one because it gets processed at the end of the thought. Also, I need to start thinking in complete sentences instead of just adding one cause after the other as my brain goes on all of these tangents. I think it's pretty promising. There's the continuous speech recognition via Google Chrome if I don't mind the lower accuracy and lack of punctuation, and I can still get the pretty version on the other side.

Why talk out loud? I liked the Bookclub Tapas presentation that Maddie Sullivan did at EmacsConf 2025. Talking out loud helps me be a lot more verbose about what I'm saying, compared to typing things out or even like having to switch to my notes or interrupting my screen with an Org capture buffer. Of course I want to clean that up for putting into a blog post, but given that my life still sometimes has random interruptions from a kiddo who must have my attention at that very minute, having that kind of record that I can at least try to reread afterwards to reconstruct what I was thinking about sounds like it might be helpful.

Still, making sense out loud is hard. I'm not actually used to talking to people that much now. This is probably a good reason for me to experiment with streaming more. Then I get the practice in talking out loud, there are backup recordings, and people can ask questions when things are unclear.

Of course, sometimes the text doesn't quite make sense because of the speech recognition errors. I can usually figure it out from the context. I save the audio as well so that I can go back and listen to it again if I really need to.

Anyway, here's the code for sending the current recording to whisper in the background and starting another recording. It assumes a lot about how things are set up. For example, I'm only testing this with a local speaches server instead of whisper.cpp. You might need to look at my other speech related configuration blog posts and sections in order to make sense of it.

Code for queuing whisper.el requests to a local server
(defvar my-whisper--queue nil)
(defun my-whisper-continue (&optional arg)
  "Send what we've got so far for transcription and then continue recording.
Call with \\[universal-argument] to signal that we can stop."
  (interactive "P")
  (require 'whisper)
  (if arg
      (my-whisper-done)
    (setq whisper--marker (point-marker) whisper--point-buffer (current-buffer))
    (when (process-live-p whisper--recording-process)
      ;; queue only if the last one is not asking for the same file
      (unless
          (string=
           (plist-get
            (car
             (last my-whisper--queue))
            :file)
           whisper--temp-file)
        (add-to-list
         'my-whisper--queue
         (list :file whisper--temp-file
               :buffer
               (format "*result: %s*" (file-name-base whisper--temp-file)))
         t))
      ;; Remove the sentinel; handle results ourselves
      (set-process-sentinel whisper--recording-process
                            (lambda (process event)
                              (my-whisper-process-queue)))
      (interrupt-process whisper--recording-process))
    (run-hooks 'whisper-before-transcription-hook)
    (whisper--setup-mode-line :show 'recording)
    (whisper--record-audio)))

(defun my-whisper-discard ()
 "Ignore the previous recording."
  (interactive)
  (when (process-live-p whisper--recording-process)
    ;; Remove the sentinel; handle results ourselves
    (set-process-sentinel whisper--recording-process
                          (lambda (process event)
                            (when (file-exists-p whisper--temp-file)
                              (delete-file whisper--temp-file))
                            (my-whisper-process-queue)))
    (interrupt-process whisper--recording-process)))

(defun my-whisper-discard-and-continue ()
 "Ignore the previous recording and continue."
  (interactive)
  (if (process-live-p whisper--recording-process)
      (progn
        ;; Remove the sentinel; handle results ourselves
        (set-process-sentinel whisper--recording-process
                              (lambda (process event)
                                (my-whisper-process-queue)
                                (my-whisper-continue)))
        (interrupt-process whisper--recording-process))
    (my-whisper-continue)))

(defun my-whisper-done ()
  (interactive)
  (when (process-live-p whisper--recording-process)
    (add-to-list
     'my-whisper--queue
     (list :file whisper--temp-file
           :buffer
           (format "*result: %s*" (file-name-base whisper--temp-file)))
     t)
    ;; Remove the sentinel; handle results ourselves
    (set-process-sentinel whisper--recording-process
                          (lambda (process event)
                            (my-whisper-process-queue)))
    (whisper--setup-mode-line :hide 'recording)
    (interrupt-process whisper--recording-process)))

(defun my-whisper-process-queue-result ()
  "Process the first part of the queue that already has results."
  (while (plist-get (car my-whisper--queue) :results)
    (let ((o (pop my-whisper--queue)))
      (unless my-whisper-target-markers
        (setq whisper--marker (point-marker)
              whisper--point-buffer (current-buffer)))
      (with-current-buffer (plist-get o :buffer)
        (erase-buffer)
        (insert (plist-get o :results)))
      ;; Only works with my fork: https://github.com/sachac/whisper.el/tree/whisper-insert-text-at-point-function
      (whisper--handle-transcription-output nil (plist-get o :buffer)))))

(defun my-whisper-process-queue ()
  (let (o)
    (while (setq o (seq-find (lambda (o) (and (plist-get o :file)
                                              (not (plist-get o :process))
                                              (not (plist-get o :results))))
                             my-whisper--queue))
      (let* ((headers (list "Content-Type: multipart/form-data"))
             (params (list (concat "file=@"
                                   (plist-get o :file))
                           "temperature=0.0"
                           "temperature_inc=0.2"
                           "response_format=json"
                           (concat "model=" whisper-model)
                           (concat "language=" whisper-language)))
             (url (format my-whisper-url-format whisper-server-host whisper-server-port))
             (command `("curl" "-s"
                        ,url
                        ,@(mapcan (lambda (h) (list "-H" h)) headers)
                        ,@(mapcan (lambda (p) (list "-F" p)) params))))
        (with-current-buffer (get-buffer-create (plist-get o :buffer))
          (erase-buffer))
        (plist-put
         o :process
         (make-process
          :name "whisper-curl"
          :command command
          :buffer (plist-get o :buffer)
          :coding 'utf-8
          :sentinel
          (lambda (process event)
            (with-current-buffer (process-buffer process)
              (let ((current my-whisper--queue-item))
                (when (and (get-buffer (plist-get current :buffer))
                           (string-equal "finished\n" event))
                  (with-current-buffer (plist-get current :buffer)
                    (goto-char (point-min))
                    (plist-put current :results
                               (or
                                (condition-case nil
                                    (gethash "text" (json-parse-buffer))
                                  (error ""))
                                "(error)"))))))
            (my-whisper-process-queue-result))))
        (plist-put o :command (string-join command " "))
        (with-current-buffer (process-buffer (plist-get o :process))
          (setq-local my-whisper--queue-item o))))))
(defvar-local my-whisper--queue-item nil)

(defun my-whisper-reprocess-queue ()
  (interactive)
  (setq whisper--marker (point-marker) whisper--point-buffer (current-buffer))
  (mapc (lambda (o)
          (when (process-live-p (plist-get o :process))
            (kill-process (plist-get o :process)))
          (when (get-buffer (plist-get o :buffer))
            (kill-buffer (plist-get o :buffer)))
          (plist-put o :process nil)
          (plist-put o :results nil))
        my-whisper--queue)
  (my-whisper-process-queue))

(defun my-whisper-clear-queue ()
  (interactive)
  (mapc (lambda (o)
          (when (process-live-p (plist-get o :process))
            (kill-process (plist-get o :process)))
          (when (get-buffer (plist-get o :buffer))
            (kill-buffer (plist-get o :buffer)))
          (plist-put o :process nil)
          (plist-put o :results nil))
        my-whisper--queue)
  (setq my-whisper--queue nil))

(keymap-global-set "<kp-9>" #'my-whisper-continue)
(keymap-global-set "<kp-8>" #'my-whisper-discard-and-continue)
(keymap-global-set "C-<kp-9>" #'my-whisper-done)
This is part of my Emacs configuration.
View org source for this post

You can comment on Mastodon or e-mail me at sacha@sachachua.com.

-1:-- Queuing multiple transcriptions with whisper.el speech recognition (Post Sacha Chua)--L0--C0--2026-01-23T19:50:37.000Z

Irreal: Casual EWW

You’ve all heard me moan many times about my failure to bring my last remaining significant application—Web browsing—into Emacs. There are some solutions but none of them come close to being sufficient. If you want full featured browsing, you’re mostly restricted to Safari, Firefox, one of the niche browsers, or the privacy violating Chrome and whatever Microsoft’s browser de jour is called.

Still, there is EWW, which some people find some sufficient for a subset of browsing tasks. Charles Choi is one of those people so naturally he’s made using EWW easier by adding Casual EWW to his Casual Suite.

You can read his announcement for the details but, as usual, it’s mainly a set of transient menus that make discovery and remembering obscure commands easier. As I’ve said before, even if you need only some of the apps, it’s worthwhile installing the Casual Suite.

-1:-- Casual EWW (Post Irreal)--L0--C0--2026-01-23T15:58:34.000Z

Alvaro Ramirez: Introducing Kitty Cards

Back in 2023, I toyed with the relevant iOS dev tools needed to create a custom Tesco Clubcard pkpass, and even showed how to scan a QR code from our beloved Emacs (of course).

Neither my friend Vaarnan nor I are strangers to the iOS ecosystem, yet we both agreed the above approach wasn't very practical (for neither devs nor the average iOS user). So we figured we should have a crack at it.

While there are some ready-made solutions out there, they often require downloading additional iOS apps or working through clunky web interfaces. We just wanted a simpler way to create our own Apple Wallet cards, and so Kitty Cards (kitty.cards) was born: no app download or sign-in required.

Hopefully not much to explain. From kitty.cards, customize a card, press the Add to Apple Wallet button, and Bobs your uncle.

Hope you enjoy Kitty Cards!

-1:-- Introducing Kitty Cards (Post Alvaro Ramirez)--L0--C0--2026-01-23T00:00:00.000Z

Charles Choi: Announcing Casual EWW

I confess to taking a perverse delight in browsing the web from within Emacs. The EWW package that comes with the standard distribution of Emacs makes this possible. On paper, Emacs really has no business trying to support web browsing with its laughably threadbare support for layout and typography, much less its lack of support for multi-threaded operation. In practice though, I’ve found browsing the web from Emacs to be surprisingly useful. To enhance my usage of EWW, I wanted easy discovery of its features via Transient menus. With that motivation, I set out to build Casual EWW, now available on MELPA in the Casual v2.13.0 update.

EWW is a minimal browser in that no CSS nor JavaScript is supported. As such, EWW is best suited for websites that treat HTML as a document specification and not as a sub-system to a web application.

Features of Casual EWW include:

  • Support for in-page paragraph and link navigation.

  • Key bindings that match Safari and Chrome on macOS.

    In particular M-[ and M-] for historical navigation and M-l for entering a URL to open are supported.

  • Menus for toggling and configuring the display of a web page (font, colors, images).

  • Support for document navigation.

    This feature distinguishes EWW from other conventional web browsers for navigating websites that support the rel attribute. For example, Texinfo uses the rel attribute in generating HTML output.

Observations and Closing Thoughts

Some observations in using EWW:

  • The implementation of bookmarks in EWW is… underwhelming.

    Note that EWW bookmarks are a different implementation from a regular Emacs bookmark. The EWW bookmark list does not provide a means for ordering a bookmark, much less for sorting and editing them.

  • The eww-readable command (bound to R) is your friend (when it works).

    EWW provides a “reader” mode via the command eww-readable which attempts to display only the main content of a web page. If successful, I’ve found it to vastly improve EWW’s utility.

    Setting the variable eww-readable-urls to include documentation from https://developer.mozilla.org will break the command css-lookup-symbol (accessible via Casual CSS) as that command expects the web page to not be in reader mode.

For Emacs users, the utility of EWW is very much a YMMV thing as it can overlap the features of other packages like the Info reader and Elfeed. Regardless of what is preferred, it is assuring to know that web browsing (however limited) is supported within Emacs.

Casual EWW is now available on MELPA in the Casual v2.13.0 update.

-1:-- Announcing Casual EWW (Post Charles Choi)--L0--C0--2026-01-22T22:20:00.000Z

TAONAW - Emacs and Org Mode: Reflection on my Emacs experience

A couple of days ago I found out org-mode capture sun menus can handle additional nested menus. To recap quickly here (see more details in the link), this means that you’d have the main menu for capture templates, which will lead to additional templates menus, and that menu can keep leading to more and more menus. I am not sure how many levels of these templates we can have, but “more than enough” is a good enough answer for me.

As I was writing the post above, I went back to my old blog and reviewed two of my older, Emacs-usage-defining posts, and added them to this blog: Org-mode in files and Submenus in org-mode capture.

Those of you who enjoy reading about the Emacs experience from a user perspective (especially someone who started out without a programming background) might want to give those a read, in the order mentioned above. Beyond explaining these crucial org-mode methods (and in my opinion, crucial to use Emacs in general), these describe the struggle and the learning process of, well, how to Emacs correctly: from realizing an option exists (of course it exists, it’s Emacs), through asking the right questions, to finding the information and implementing the solution.

I’ve spent a couple of hours re-reading and revising these posts, and reached a conclusion that many of you who are reading this over their RSS feed in Emacs would probably agree with. We, Emacs users who blog, have a critical role in the Emacs ecosystem: we provide others with ideas and questions to ask, which can later be directed to official channels, the manual, and brainstorming answers.

As I mentioned a couple of times throughout the lifetime of my blog (this one and the old one): Emacs is not just a program, it’s a lifestyle.

-1:-- Reflection on my Emacs experience (Post TAONAW - Emacs and Org Mode)--L0--C0--2026-01-22T19:56:08.000Z

Irreal: When Should You Use Visual-line-mode?

Over at the Emacs subreddit, floofcode complains that he doesn’t like the way visual-line-mode handles moving from line to line. He found that everything worked fine without visual-line-mode so he wondered when is visual-line-mode useful.

If you read his post, you’ll notice that he had visual-line-mode turned on globally. That explains a lot of his frustration. As nice as visual-line-mode can be, you definitely don’t want it enabled all the time. It would be a disaster when writing code, for example.

The thing about visual-line-mode is that it considers all the text between line feeds to be one long line and soft wraps the text to fit your screen size.That’s useful even when you’re just dealing with text locally but I find it essential for my blogging. If I set a hard line size, it gets carried onto my blog and really messes up the displays of people with smaller screens or windows such as those reading Irreal on a phone. With visual-line-mode, the text gets flowed to fit the target screen.

So the answer to floofcode’s question is that visual-line-mode is definitely useful but mostly when you’re writing prose such as in Org-mode. I use it whenever I’m writing prose but never when I’m, say, programming or using some other specialized Emacs mode. For instance, I don’t use it in my Org based tax files because they’re mostly tables and don’t include long sequence of text. I generally set it on a per file basis except for my blog where a hook recognizes blog posts and sets it and some other appropriate modes.

-1:-- When Should You Use Visual-line-mode? (Post Irreal)--L0--C0--2026-01-22T16:28:15.000Z

Mike Olson: First Week with Jujutsu VCS

I’ve spent my first week using Jujutsu (jj), a Git-compatible version control system that takes a different approach to managing commits and branches. Here are my impressions and some configuration tips I’ve picked up along the way.

Contents

Configuring Immutable Bookmarks

One of the first things I changed was the default immutability settings. Jujutsu’s default configuration locks down remote bookmarks (which are “branches” in Git terms) as immutable, which prevents accidental modifications but can be overly restrictive.

I added this to ~/.config/jj/config.toml:

[revset-aliases]
"immutable_heads()" = "present(trunk()) | tags()"

This relaxes the immutability rules to only protect the trunk (the default branch, typically main or master from the backing Git repo) and tags, giving me more flexibility to work with feature branches that have been pushed to remotes.

Emacs Integration with Majutsu

For Emacs integration, I’m using majutsu, which provides a Magit-like interface for Jujutsu. I configured it to start in a log buffer showing the branches I care about, with the ability to hit Enter to visit a commit or O to start a new commit at that point.

Here’s my configuration from my shared Emacs init:

(defun my-replace-cdrs-in-alist (old-el new-el alist)
  "Replace cdr instances of OLD-EL with NEW-EL in ALIST."
  (mapc #'(lambda (el)
            (when (eq (cdr el) old-el)
              (setcdr el new-el)))
        (symbol-value alist)))

;; Set up majutsu
(with-eval-after-load "majutsu"
  ;; Replace pop-to-buffer with switch-to-buffer for same-window behavior
  (my-replace-cdrs-in-alist 'pop-to-buffer 'switch-to-buffer
                            'majutsu-display-functions)
  (setopt majutsu-default-display-function #'switch-to-buffer))

(defun my-majutsu-log ()
  (interactive)
  (majutsu-log (or (my-project-root) default-directory)))

;; Set up keybinds
(with-eval-after-load "project"
  (keymap-set project-prefix-map "j" #'my-majutsu-log))

(keymap-global-set "C-x V j" #'my-majutsu-log)

The key customizations here:

  • Same-window display: I replaced pop-to-buffer with switch-to-buffer so that majutsu buffers open in the current window rather than splitting. This matches my preferred Magit workflow.
  • A project-aware log: The my-majutsu-log function opens the log at the detected project root, which I bind to C-x V j in my global keymap, or j when visiting a project. It will also offer to initialize jj if I haven’t done so yet.

Rebasing Stacked Branches

Rebasing stacked branches onto an updated main branch is quite nice with Jujutsu:

jj git fetch

# Rebase all commits on feature-branch that aren't already in main
jj rebase -b feature-branch -o main

The -b flag specifies the branch to rebase, and -o specifies the new base. Jujutsu handles the rebase intelligently, only moving commits that aren’t already part of main, and automatically brings over multiple bookmarks that may be on that branch.

I also have a script fragment that can update all tracked bookmarks on all Git submodules:

# excerpt - assume $d is current submodule
main_branch=$(git config -f "$topdir"/.gitmodules submodule.$d.branch || echo main)

jj bookmark track "${main_branch}" --remote=origin 2>/dev/null || true
jj git fetch

# Check for bookmark conflicts after fetch
if jj bookmark list -t 2>/dev/null | grep -q "conflict"; then
    echo "Warning: Bookmark conflicts detected in $d"
    echo "Run 'cd $d && jj bookmark list -t' to see details"
    echo "Use 'jj bookmark track <bookmark> --remote=origin' to resolve"
fi

# Rebase all tracked bookmarks (except main) onto updated main
# Get list of tracked bookmarks, excluding the main branch and @origin suffixes
other_bookmarks=$(jj bookmark list -t 2>/dev/null | \
    grep -v "^  " | \
    awk '{print $1}' | \
    sed 's/:$//' | \
    grep -v "^${main_branch}\$" || true)

if [[ -n "$other_bookmarks" ]]; then
    for bookmark in $other_bookmarks; do
        # Skip if bookmark name is empty or contains @origin
        [[ -z "$bookmark" || "$bookmark" == *"@"* ]] && continue

        # Check if bookmark has commits not in main
        if jj log -r "${main_branch}..${bookmark}" --limit 1 2>/dev/null | grep -q .; then
            echo "Rebasing ${bookmark} onto ${main_branch}"
            if ! jj rebase -b "${bookmark}" -o "${main_branch}" 2>&1; then
                echo "Warning: Failed to rebase ${bookmark} - may have conflicts"
                echo "Run 'cd $d && jj log -r \"conflict()\"' to see conflicted commits"
            fi
        fi
    done
fi

Cleaning Up After Rebases

One minor annoyance: after rebasing, you may end up with orphaned bookmarks in your jj log output that clutter the view. You’ll need to manually clean these up with jj abandon to keep a tidy log. It can be a bit tedious, but so far I’m finding that it’s worth the effort to maintain a clear picture of which stacks haven’t been merged yet.

Magit and jj - Conflict Resolution

Here’s an important gotcha I discovered: if you’re in the middle of resolving a Jujutsu merge and you run magit-status, Emacs can slow to a crawl. Magit will show hundreds of conflicting symlinks (which is how jj represents conflicts in the working directory), overwhelming the buffer.

The best practice is to stay in Jujutsu’s tooling once you start resolving conflicts there. Don’t switch to Magit mid-resolution.

This situation commonly arises when squash-merging PRs for a branch that is stacked on another. GitHub’s squash merge creates a new commit that doesn’t match the commits jj knows about, which can leave your local branch in a state where jj thinks it needs to merge.

When this happens, it can save significant time to rebase using a specific commit ID rather than a bookmark name:

# Find the commit ID of main after the squash merge
jj log -r <bookmark>

# Rebase your bookmark starting at that specific commit onto main
jj rebase -s <earliest-commit-id-of-bookmark> -o main

This explicitly tells jj which commit to move and where, avoiding the merge conflicts that arise from the squash merge mismatch. I do something similar with subset-rebases in Magit when using Git.

Magit and jj - ’@’ Branch

Using jj and then using Magit can cause Magit to be confused about what branch it’s on. Unfortunately because of the existence of @ as a branch, which comes before the typical name of the branch when showing a revision, Magit treats @ as the one that’s meaningful and doesn’t show the merge/push target for the branch I actually care about. I haven’t yet found a good solution, other than manually specifying where to push. Maybe Magit could be advised to ignore that branch at some point.

Overall Impressions

After a week, I’m finding Jujutsu’s model fairly intuitive once you get past the initial learning curve, though I’m still using Git most of the time. The automatic tracking of the working copy as a commit, the powerful revset language, and the Git compatibility does make jj an interesting alternative to keep learning.

-1:-- First Week with Jujutsu VCS (Post Mike Olson)--L0--C0--2026-01-22T00:00:00.000Z

Lars Ingebrigtsen: Some Minor eplot Tweaks for CSV Files

I finally took a peek at my outstanding issues for eplot on Microsoft Github again, and somebody asked the very reasonable question: Why can’t eplot just do the right thing, as if by magic, with files like this:

Why not indeed? So I’ve tinkered a bit, and things should work pretty automatically now. That is, load of a CSV file like that, M-x eplot-mode and then C-c C-c, and viola (enclicken to play video (don’t worry, no audio)):

The idea being that eplot should have sensible defaults, but then you can tinker with the look by hitting l to create controls, then just edit away until you have to look you’re looking for (apparently I went for a “bright goth” thing above), and then export the results.

So there you go. Hopefully I didn’t break anything much…

-1:-- Some Minor eplot Tweaks for CSV Files (Post Lars Ingebrigtsen)--L0--C0--2026-01-21T18:48:27.000Z

Irreal: Saving The Elfeed Database

I’ve written before that one of things I love about Elfeed is that it keeps a database of all your feed entries. That makes it easy to find earlier content if you need to revisit or reference it for some reason. It has an excellent search capability that makes this mostly painless.

Punchagan over at NOETIC NOUGHT has a sobering tale about losing his Elfeed database. He thinks it probably happened during a system crash that occurred at the same time his Elfeed database was being saved. Depending on how you use your feed, that may be more or less disastrous.

If you depend on your feed for research, the loss would be serious. Punchagan uses his Elfeed all the time so he decided to automate the backing up of Elfeed’s database. He shows the code in his post so you can take a look. It’s pretty straightforward. Whenever a tag changes or a new entry is added, he schedules a database save and backup to Git.

If you’re an ordinary user, you may not need such immediate backups. You could for example, schedule a backup once or twice a day so even if you lost the active database the loss would be minimal. On the other hand, if you really depend on your feed, Punchagan’s solution may be just what you need.

-1:-- Saving The Elfeed Database (Post Irreal)--L0--C0--2026-01-21T15:52:31.000Z

Jack Baty: Blogging with org-mode and ox-hugo again

For a few years (a few years ago) I wrote all my blog posts using one big Org mode outline and let ox-hugo generate the Markdown files for Hugo. I eventually decided it was a layer of abstraction that I didn’t need, so I fell back to writing in Markdown directly.

I’m really into using Emacs for everything again (still?), so I dusted off and updated my old ox-hugo config and here I am, typing this with Emacs in a big Org mode outline.

I have a (ya)snippet for generating the posts, like so:

# -*- mode: snippet -*-
# name: Hugo blog post
# key: blog
# uuid: blog
# --
**** TODO ${1:title}
:PROPERTIES:
:EXPORT_FILE_NAME: index.md
:EXPORT_HUGO_BUNDLE: `(format-time-string "%Y-%m-%d")`-${1:$(replace-regexp-in-string " " "-" (downcase yas-text))}
:EXPORT_HUGO_SLUG: ${1:$(replace-regexp-in-string " " "-" (downcase yas-text))}
:EXPORT_HUGO_CUSTOM_FRONT_MATTER: :coverCaption ""
:END:

#+begin_description

#+end_description

$0

The snippet prompts for a title, then creates the appropriate properties for the post.

One nice thing about this is that once the Markdown is generated, I no longer need the .org file. Writing this way is a bonus, but not a requirement.

✍️ Reply by email
-1:-- Blogging with org-mode and ox-hugo again (Post Jack Baty)--L0--C0--2026-01-21T09:55:00.000Z

Please note that planet.emacslife.com aggregates blogs, and blog authors might mention or link to nonfree things. To add a feed to this page, please e-mail the RSS or ATOM feed URL to sacha@sachachua.com . Thank you!