I deal with a number of long-running projects in my day-to-day, so I like to keep an Org Mode file for each project, and whenever I work on a project I add a headline to the Org file with the day's date and a little explanation of what was going on, eg
* <2025-10-11 Sat> developed the query to do the thing
I have always been terrible at keeping a journal, so one thing I like to do is actually develop in a code block underneath the headline, executing the code with C-c C-c
in lieu of a REPL or an edit-save-execute loop with a file, so that when I have a working version, I also have a copy in my notes. That way, I don't forget to leave an update in the journal when I finish a task.
This works well when working with a database, using a method similar to the one Ryan Prior outlines here for data analysis or development of queries/schema, or with command-line tools. For me it simultaneously replaces tools like Postman and psql
with the added benefit of record keeping with no extra effort.
It's very nice to be able to start writing a code block, using a snippet of course, so typing <src TAB
expands to #+begin_SRC
and #+END_SRC
, develop an API call or some other command. Each time I press C-c C-c
the result is rewritten, and then when I'm finished, have a little example saved with both the command and its output, which will look something like this:
#+begin_src fish :results output
whois 1.1.1.1 | head -n 5
#+end_src
#+RESULTS:
: % [whois.apnic.net]
: % Whois data copyright terms http://www.apnic.net/db/dbcopyright.html
:
: % Information related to '1.1.1.0 - 1.1.1.255'
:
I find this to be super useful because I don't have to copy-paste the output to my journal to remember to save it. When I'm done developing the code in the source block, I'm finished and there's no extra step to copy it into my notes; it's already there. In some cases I can even go ahead and :tangle
the code to wherever it needs to go, and then all I have to do is go check it in, and it is copied into both my journal and the final location.
However, I haven't been able to figure out a good workflow for recording work in my journal when the task involves many small edits in different files, as in normal software development, in contrast to operational tasks or data analysis. In this case, it still makes sense to edit in-place. It's just more ergonomic.
Nonetheless, every so often I would like to capture what I've been doing in my notes. It recently occurred to me that Org still makes this relatively easy, by letting me generate diffs to display in-line in the document. That way I can see how specific pieces of code appeared a certain period of time, and comment if I want.
I can do this by defining a code block that runs git
in the project working directory and record a diff into my notes:
The only quirk is that if I edit the diff with org-edit-src-code
it gets indented, breaking the highlighting 😢 but since it's output I probably won't be editing it, anyway, so it shouldn't matter very much. Maybe after I publish this post, someone will send me an email and tell me how to address this quirk.
In any case, this is really handy as a way to grab a snapshot of some change that I've made, and it's handy that the tool isn't prescriptive about how the diff is generated, but also allows me to record how I generated the diff.
For those who are new to Org, I want to describe the different options used in this example, because at first glance this seems like a lot of typing. Org blocks (the things that begin with #+begin_
) take special options called "header arguments" that can be specified using a :key value
pattern on the same line as #+begin_
, so here I have a #+begin_src
block of type fish
where I specified:
:results output
so that Org inserts the raw output from the command instead of interpreting it as a table, which is the default, and:dir
which tells Org which directory the code block should be executed in:wrap source diff
which tells Org to put #+begin_src diff
before the result and #+end_src
after it. The wrap
directive is what tells Emacs to render the output as a diff when displaying it in the Org buffer.Then when I press C-c C-c
to call org-babel-execute-src-block
on the source code under the cursor, the diff is automatically updated using the command defined and rendered as a diff by Emacs inline with the rest of my notes.
Very, very cool, Emacs.
To avoid typing these options in every code block, the header arguments can be specified as shown for each Org Babel block, or for a specific sub-tree (using a ":PROPERTIES:
drawer") or for the entire file (using #+PROPERTY:
directives), and there's probably a way to do with through .dir-locals.el
too, if you wanted to do it for a whole project. However, I will leave this as an exercise for the reader, as this post is long enough as is. 👋