Emacs: Denote version 4.1.0
Denote aims to be a simple-to-use, focused-in-scope, and effective note-taking and file-naming tool for Emacs.
Denote is based on the idea that files should follow a predictable and descriptive file-naming scheme. The file name must offer a clear indication of what the contents are about, without reference to any other metadata. Denote basically streamlines the creation of such files or file names while providing facilities to link between them (where those files are editable).
Denote’s file-naming scheme is not limited to “notes”. It can be used for all types of file, including those that are not editable in Emacs, such as videos. Naming files in a constistent way makes their filtering and retrieval considerably easier. Denote provides relevant facilities to rename files, regardless of file type.
- Package name (GNU ELPA):
denote
- Official manual: https://protesilaos.com/emacs/denote
- Change log: https://protesilaos.com/emacs/denote-changelog
- Git repositories:
- Video demo: https://protesilaos.com/codelog/2022-06-18-denote-demo/
- Backronyms: Denote Everything Neatly; Omit The Excesses. Don’t Ever Note Only The Epiphenomenal.
Below are the release notes.
Version 4.1.0 on 2025-10-17
The overarching theme of version 4.1.0
is that of continuing to
deliver on the highly hackable/flexible/powerful potential of Denote.
All the core functionality is the same as before and you still only
need a tiny configuration to use Denote productively. We are adding
more refinements and subtle improvements under the hood, while making
it even easier for advanced users/developers to piece together a
workflow that matches their particular needs.
Since version 4.0.0
, we have moved the “Denote extras” files into
their own packages. I cover their changes further down after I
elaborate on all the changes to the core Denote package:
Note that I write all the release notes by hand. The reason is that I consider this process an essential part of my role as a maintainer. Taking the time to review and document everything ensures that (i) I am well informed about the state of the package, (ii) I did not forget anything about this development cycle, and (iii) I take another look at the changes we made to ensure everything is in order.
Overview of the new features for core Denote
-
The user option
denote-directory
can be assigned to a list of directories. The original string value is also acceptable and remains the default. -
Advanced users can define a completely custom scheme for identifiers. This can be as simple as automatically assigned ordinal numbers to increasingly complex patterns that may also involve user input.
-
The command
denote-find-backlink-with-location
is likedenote-find-backlink
except it also moves to the exact location of the link in the corresponding file. -
All Denote buffer names share a common prefix, which is subject to the user option
denote-buffer-name-prefix
. This makes it easier to spot them in the buffer list. -
The command
denote-dired
(aliasdenote-sort-dired
) can sort files byrandom
andlast-modified
in addition to the methods that involve Denote file name components. -
The user option
denote-query-sorting
controls how files in all query buffers are sorted by default. This covers backlinks, query links for file contents, and any buffer produced by thedenote-grep
command. It benefits from the internal “Denote sort” mechanism, which is also used bydenote-dired
and the Org dynamic blocks of thedenote-org
package.
Remember that the release notes are true only at the time of publication. The single source of truth always is the official manual.
Set denote-directory
to a list of directories
The user option denote-directory
can optionally be bound to a list
of file system paths, each of which represents a directory root, such
as '("/home/prot/Documents/work/" "=/home/prot/Git/hut/")
(Denote
has always supported subdirectories, even for a singular denote-directory
).
When creating new files, such as with the denote
command, the first
directory on the list will be selected. This can be changed by
modifying the denote-prompts
user option so that it asks for a
directory or subdirectory thereof. Or by writing small wrapper
commands that put files in a predefined directory, like this:
(defun my-denote-for-work ()
"Like `denote' but always use the ~/Documents/work/ directory."
(interactive)
(let ((denote-use-directory "~/Documents/work/"))
(call-interactively 'denote)))
Why have many directories as part of the denote-directory
? Some
users want to maintain separate directories with Denote files, while
retaining the option of establishing links between (unlike the concept
of “silos” we support, where the directories are self-contained).
Those two directories can be their own Git repositories, for example,
and have different syncing policies for access across multiple
devices.
Thanks to Jean-Philippe Gagné Guay for providing the core functionality in pull request 609: https://github.com/protesilaos/denote/pull/609.
Jean-Philippe is a long-time contributor who has assigned copyright to
the Free Software Foundation. I made several changes on top, such as
to allow denote-dired
(alias denote-sort-dired
) to work with many
directories, by finding their common root (which would ultimately be
/
).
Define completely custom Denote identifiers
The default Denote identifier should work for most people in most cases. I have considered the Denote file-naming scheme carefully and know it is reliable. Advanced users who have a clear use-case of something out-of-the-ordinary can now get “Denoted” file names with arbitrary identifiers. Since this is an advanced feature, I will not elaborate here on the technicalities. Though I have taken the time to write at length in the manual about it, with concrete examples ranging from simple to more complex scenaria. Start with this introduction: https://protesilaos.com/emacs/denote#h:3048f558-7d84-45d6-9ef2-53055483e801.
This feature has been discussed and requested for a long time, across several related issues:
- https://github.com/protesilaos/denote/issues/278.
- https://github.com/protesilaos/denote/issues/474.
- https://github.com/protesilaos/denote/issues/581.
Thanks, in no particular order, to mentalisttraceur, juh2, Christian Tietze, and Jean-Philippe Gagné Guay for sharing their thoughts. Also thanks to Jean-Philippe Gagné Guay for contributing the patches that made this possible, the last of which is in pull request 586: https://github.com/protesilaos/denote/issues/586.
Find a backlink at its exact location in the file
Denote has two ways of working with backlinks: (i) to display them in
a dedicated buffer and (ii) to use a minibuffer prompt that supports
completion in order to pick one file out of the list. The new command
denote-find-backlink-with-location
is of the latter kind. Like its
more generic denote-find-backlink
counterpart, it uses the
minibuffer to pick a file that links to the current one. Then, it also
moves the cursor to where the link is.
I did this is in response to issue 471 as reported by johkneisl: https://github.com/protesilaos/denote/issues/471.
Denote buffer names use the denote-buffer-name-prefix
This is a new user option that takes an arbitrary string. Its value is
"[D]"
by default. It consolidates how we name all of our buffers.
Out-of-the-box, this applies to special buffers, like those produced
by the commands denote-backlinks
and denote-dired
. When the
optional minor mode denote-rename-buffer-mode
is enabled, all
buffers whose file naming scheme is that of Denote will get the
denote-buffer-name-prefix
in addition to their own denote-rename-buffer-format
.
This is related to pull request 597 by James Kalyan: https://github.com/protesilaos/denote/pull/597. James has assigned copyright to the Free Software Foundation.
The Denote sort mechanism can sort by random
and last-modified
In core Denote, this is used internally by the denote-dired
command
(alias denote-sort-dired
) and the query buffers (more in the next
section). By default, denote-dired
prompts for the sort method and
whether to reverse the order. Though there are user options to tweak
its behaviour (consult the manual). The Org dynamic blocks of the
denote-org
package also rely on this mechanism (denote-org
version 0.2.0).
Control the default sort of files in query buffers
Query buffers are those of denote-backlinks
, denote-grep
, and
denote-query-contents-link
(in the latter case, the query buffer is
produced when you click on the link). Users can now modify how they
sort matching files via the option denote-query-sorting
. The sorting
methods are by any of the Denote file names components (per
denote-sort-components
), random order, last modified, or an
arbitrary function.
Thanks to Lucas Quintana for the contribution in pull request 594: https://github.com/protesilaos/denote/pull/594. Lucas has assigned copyright to the Free Software Foundation.
Miscellaneous for core Denote
-
The
denote-dired
command (aliasdenote-sort-dired
) sets up itsrevert-buffer-function
in a more robust way, such that it does not affect the window layout under certain conditions. -
Fixed a bug with the menu entry of Denote that broke
context-menu-mode
. It addresses issue 592, as reported by artelse: https://github.com/protesilaos/denote/issues/592. Thanks to Lucas Quintana for the patch. Lucas has assigned copyright to the Free Software Foundation. - Thanks to ryota for refining the documentation of the variable
denote-use-template
and its potential interference withdenote-org-capture-identifiers
in custom user code. We discussed this in issue 545 and the patch was sent as pull request 598:- https://github.com/protesilaos/denote/issues/545.
- https://github.com/protesilaos/denote/pull/598. The change is small, meaning that ryota does not need to assign copyright to the Free Software Foundation.
-
An internal check to determine if a file has backlinks is now faster than before: it exits with a non-
nil
value as soon as it finds one match, instead of trying to collect all the backlinks. Thanks to Yann Dutrieux for addressing an omission of mine in the original implementation and then for discussing with me some further refinements. Yann’s contribution was sent as pull request 637: https://github.com/protesilaos/denote/pull/637. - Thanks to Alan Schmitt and Ashish Panigrahi for fixing a couple of typos, in pull requests 623 and 626, respectively:
Git commits for core Denote
~/Git/Projects/denote $ git shortlog 4.0.0..4.1.0 --summary --numbered
156 Protesilaos Stavrou
29 Jean-Philippe Gagné Guay
4 Lucas Quintana
2 James Kalyan
1 Alan Schmitt
1 Ashish Panigrahi
1 Hanwen Guo
1 Ryota
1 Yann Dutrieux
Changes to the extensions of Denote I maintain
This concerns all the former “Denote extras” that were shipped with
core Denote as well as consult-denote
.
consult-denote
version 0.4.0
-
The commands
consult-denote-grep
andconsult-denote-find
also work whendenote-directory
is set to a list value, as explained further above (Setdenote-directory
to a list of directories). -
There is a Consult-powered counterpart to the
denote-sequence-file-prompt
. It is for users of thedenote-sequence
package and comes into effect when theconsult-denote-mode
is enabled (that mode “Consults” all relevant minibuffer prompts Denote uses so they get the familiar preview functionality). Thedenote-sequence-file-prompt
is used by commands such asdenote-sequence
,denote-sequence-find
, anddenote-sequence-link
, among others (denote-sequence
version 0.2.0). -
The command
consult-denote-find
sorts its files by default. We discussed this with Gianluca Della Vedova and Gianluca implemented the tweak in pull request 18: https://github.com/protesilaos/consult-denote/pull/18. The change is small, meaning that Gianluca does not need to assign copyright to the Free Software Foundation.
denote-journal
version 0.2.0
- It is now possible to specify the desired interval used by the
command
denote-journal-new-or-existing-entry
to determine what “new” and “existing” mean. Users may want to, for example, maintain one file per month, with daily entries as headings or as free-form text. The user optiondenote-journal-interval
specifies the interval as a symbol amongdaily
,weekly
,monthly
, andyearly
. Thanks to Ning Xu for floating the idea of non-daily journaling in issue 18: https://github.com/protesilaos/denote-journal/issues/18.- Thanks to Alan Schmitt for catching a couple of errors in my original implementation and for suggesting fixes in pull requests 20 and 21. Also thanks to Abdelhak Bougouffa for addressing another problem in pull request 23. Further changes by me.
-
The new user option
denote-journal-signature
specifies a signature that will be applied to all new journal entries. It is the counterpart ofdenote-journal-keyword
. Possible values arenil
, for no predefined signature, a string for a constant signature, and a function that returns a string which is then used as-is. Thanks to Halogen3576 for suggesting an option for a signature in issue 13: https://github.com/protesilaos/denote-journal/issues/13.In the case of a function value, users may wish to integrate the
denote-journal
package with thedenote-sequence
package (denote-sequence
version 0.2.0). For example, each new journal entry should be defined as a new parent sequence. Thus:(setq denote-journal-signature (lambda () (denote-sequence-get-new 'parent)))
-
The user option
denote-journal-keyword
is extended to support a function value which should return a string or list of strings. -
The integration with
M-x calendar
(when the minor modedenote-journal-calendar-mode
is enabled) is more robust when highlighting dates that have a Denote journal entry. Thanks to Alan Schmitt for the patch that improves the check for visible dates only. This was done in pull request 12: https://github.com/protesilaos/denote-journal/pull/12. -
The
denote-journal-calendar
face is extended to also work when Emacs is ran in a TTY. Thanks to Ettore Berardi for the original contribution and for discussing this with me. It was done in pull request 14: https://github.com/protesilaos/denote-journal/pull/14. The contribution is less than 15 lines of code, meaning that Ettore does not need to assign copyright to the Free Software Foundation. -
The function
denote-journal-path-to-new-or-existing-entry
is tweaked to not kill the buffer of the new file it might generate. Thanks to jbwfu for the change in pull request 17: https://github.com/protesilaos/denote-journal/pull/17. The change is small, meaning that the author does not need to assign copyright to the Free Software Foundation. -
Dates with a single digit in the title of a new journal entry no longer have a space where the second digit normally is. So something like
October 1
instead ofOctober 1
. Thanks to Josh Kingsley for the patch. The change is small, meaning that Josh does not need to assign copyright to the Free Software Foundation. It was done in pull request 24: https://github.com/protesilaos/denote-journal/pull/24. -
Thanks to gk2803 for renaming a couple of old symbols to their current names in the commentary of the package. This was done in pull request 10: https://github.com/protesilaos/denote-journal/pull/10.
~/Git/Projects/denote-journal $ git shortlog 0.1.0..0.2.0 --summary --numbered 35 Protesilaos Stavrou 3 Alan Schmitt 2 Ettore Berardi 1 Abdelhak Bougouffa 1 Josh Kingsley 1 gk2803 1 jbwfu
denote-org
version 0.2.0
- A new Org dynamic block integrates with the
denote-sequence
package (denote-sequence
version 0.2.0). The block is calleddenote-sequence
and can be inserted at point with the commanddenote-org-dblock-insert-sequence
. What this block does is list the descendants of a given sequence up to a maximum depth. The presentation is a typographic list of lists to visualise the hierarchy of the complete sequence, with each set of children nested under its parent. Thanks to Peter Prevos for the original implementation in pull request 9 and for subsequent tweaks in pull request 13. Other changes by me are done to ensure tighter integration with thedenote-sequence
package. -
All Org dynamic blocks that have a
:sort-by-component
parameter can now sort byrandom
andlast-modified
. This is made possible by the aforementioned improvements to the core Denote sort mechanism (The Denote sort mechanism can sort byrandom
andlast-modified
). -
The
denote-missing-links
Org dynamic block, which can be inserted at point with the commanddenote-org-dblock-insert-missing-links
takes an optional:not-regexp
parameter. This is a regular expression of files to omit from the results. Same for thedenote-backlinks
block, which can be inserted at point with the commanddenote-org-dblock-insert-backlinks
. -
The
denote-files-as-headings
Org dynamic block, which can be inserted at point with the commanddenote-org-dblock-insert-files-as-headings
now also accepts an optional:exclude-tags
parameter. It is eithernil
or non-nil
and determines whether the heading will have the file’s#+filetags
as its own tags. Thanks to Matt Nolan for suggesting this idea in issue 14: https://github.com/protesilaos/denote-org/issues/14.~/Git/Projects/denote-org $ git shortlog 0.1.0..0.2.0 --summary --numbered 42 Protesilaos Stavrou 8 Peter Prevos
denote-sequence
version 0.2.0
-
The new commands
denote-sequence-find-next-sibling
anddenote-sequence-find-previous-sibling
move to the next or previous sibling in the given sequence. When called interactively, they work relative to the current file. When called from Lisp, they expect aSEQUENCE
argument and its correspondingRELATIVES
. -
The
denote-sequence-dired
command is updated to (i) work with a list value fordenote-directory
(Setdenote-directory
to a list of directories), as noted further above and (ii) benefit from the refinements done todenote-dired
with regard to itsrevert-buffer-function
. -
The new command
denote-sequence-rename-as-parent
makes it easier to apply the Denote file-naming scheme to an existing file and make it a new parent sequence. Thanks to Alex Carney for requesting something along those lines in issue 4: https://github.com/protesilaos/denote-sequence/issues/4.[ Remember that Denote is highly adaptable/hackable, meaning that many of these convenience commands build on top of the core with small extensions to it. The body of
denote-sequence-rename-as-parent
is only 4 lines long, two of which are for an error check. This is typical of much of what we provide and is how users can always extend Denote to do something slightly different than what we support out-of-the-box. ] -
Made several other refinements under the hood, including the addition of more tests. In this regard, thanks to Rory Molinari, Peter Prevos, and Ashton Wiersdorf for fixing three bugs in pull requests 5, 8, and 11, respectively:
- https://github.com/protesilaos/denote-sequence/pull/5.
- https://github.com/protesilaos/denote-sequence/pull/8.
- https://github.com/protesilaos/denote-sequence/pull/11.
~/Git/Projects/denote-sequence $ git shortlog 0.1.0..0.2.0 --summary --numbered 61 Protesilaos Stavrou 1 Ashton Wiersdorf 1 Peter Prevos 1 Rory Molinari
Changes to denote-markdown
Nothing of substance.
Changes to denote-silo
Nothing of substance.