Personalized embark actions
I adopted Embark in 2025. To be honest, it was more because it seemed to be the typical companion for vertico + consul, than because I really understood what I could do with it.
Besides some very basic use (which I routinely forget) I didn’t bother to explore it in more detail.
Until I noticed that Embark could give me a fundamental component for a mechanism I had been trying to implement in the past.
First, some context. For my job, I often have to navigate through a quite large dbt project. If I were less picky about text editors I’d just use VS Code and the PowerUser package. But, it's no mistery, I’m fond of staying inside Emacs. Where, quite incredibly, there is no dbt support package available.
One simple thing I'd particulary like is the ability of hopping from one file to another following dbt references.
A reference, in dbt, is a Jinja expression that can be used in place of a table or view name, to inform dbt of a dependency between two models (a model is, simplifying, a named SQL query, saved in a file with that name).
For example, you can write a file called us_customers.sql like this:
select * from {{ ref('mart_customers') }}
where country = 'US'
and dbt knows that the mart_customers model (contained in a file
mart_customers.sql, in some directory of the project) is an upstream
dependency of us_customers.
This is useful because then you can invoke dbt like this (notice the +
sign):
dbt run -m mart_customers+
and dbt knows that it needs to refresh mart_sustomers
PLUS its downstream dependencies, including us_customers.
A typical dbt project may contain hundreds of interdependent models, organized in a tree of directories. So, references are very convenient.
Now to my specific Emacs problem. What I'd like to be able to do is, when the cursor is on a reference, to visit the file that contains the definition of the referenced model, without having to navigate the directories to find it.
The first useful thing that Embark does is figuring out what's the
identifier I'm on with the cursor. In the example above, that would be
the string mart_customers. In Embark (and Emacs) parlance, that is
called the target at point. More precisely, in this case, that's the
identifier at point.
When I invoke embark-act (it's customary to map this function to
C-.), Embark figures what's the identifier at point, and I get a
contextual list of actions that can be applied.
Now, I need to add my personalized action to that list.
For my needs, that is just a function that, given a reference name
(the identifier at point) puts .sql at the end of the string, then
uses the result as an argument for project-root-find-file. Model files
are guaranteed to be unique across all the project (otherwise dbt does
not work), so there is no ambiguity about the file I want to visit.
Here the implementation, and how it was integrated in the Embark's identifier target list.
(defun larsen/embark-dbt-navigate-reference (reference &rest args)
"Opens the model source code for the dbt reference at point"
(interactive "sReference: ")
(project-root-find-file (string-join (list reference ".sql"))))
(use-package embark
:ensure t
:bind (("C-." . embark-act)
:map embark-identifier-map
("D" . larsen/embark-dbt-navigate-reference)))
Suburban 144
Suburban 144 is a yearly gravel bike event organized by the Bikebash group. I participated to the 2026 edition in the 125km group. It turned out to be 130, to which I added another 4 because I missed a checkpoint and I had to go back. Another group went for a 165km variation, and another even more adventurous group started the day before, riding through the night for a total of 330km.
Events of this kind are conceived as social rides rather than competitions, and I have to say they are quite effective, considering for example that even I, notoriously unable to strike up a conversation with new people, started alone but managed to arrive in a group.
We had great weather and the ride was generally great fun, even if I had problems with the rear wheel; nothing that two plugs could not solve, anyway.
You can find more pictures on the event website.
The route
Search and replace across multiple documents in Emacs
This is not something I do every day, so I end up forgetting it and having to relearn it again. Here's a workflow based on consult‑ripgrep and Embark.
consult-ripgrepto search across the filesCtrl-.to activate EmbarkEto export the list of matchesCtrl-c Ctrl-pto runwgrep-change-to-wgrep-modeand enter edit mode- Once I'm satisfied,
Ctrl-x Ctrl-sto save each of the involved buffers
Emacs config size
Let’s Play How Big Is Your Emacs Config?
In my case:
wc -l .emacs.d/lisp/larsen-* .emacs.d/init.el | ag total
2400 total
Also