Setting
Up VimWiki with when: My Minimalist Agenda Workflow
I haven’t written a blog post in a while, so… yeah, here we are again.
This time, I’m sharing how I’ve set up a minimal personal agenda
system using vimwiki and
when,
a lean calendar application that fits the Unix philosophy—do one
thing, and do it well.
⚠️ This isn’t a guide, just me documenting my setup, quirks and all. Nonetheless, read on.
Why when?
We’ll be using when
instead of something like calcurse. I tried calcurse
for a bit but… Meh, its interface isn’t for me. I wanted something
simpler, something that plays well with vimwiki.
Directory Layout
Here’s the folder structure for my life/ directory,
which I sync via Syncthing:
~/Documents/life/
├── diary/
│ └── 2025-05-21.md
├── calendar/ # Symlinked from $XDG_CONFIG_HOME/when/
│ ├── overrides.wiki
│ └── calendar.wiki
└── scripts/
└── agenda.sh # Used to insert `when` output into vimwikiThe goal here is to keep everything related to my notes, schedule, and life in one tidy place. And of course, sync it across devices seamlessly.
Declarative Symlinks with Home Manager
Sure, I could create a symlink manually:
ln -s ~/Documents/life/calendar ~/.config/whenBut come on—we’re on NixOS. We don’t do imperative
here. Here’s how to make it declarative with home-manager:
{
home.activation.symlinkWhen = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
target="$HOME/Documents/life/calendar"
link="$HOME/.config/when"
if [ -L "$link" ] || [ -e "$link" ]; then
rm -rf "$link"
fi
ln -s "$target" "$link"
'';
}Breakdown
home.activation.symlinkWhen: Custom activation step that runs when youhome-manager switch.lib.hm.dag.entryAfter [ "writeBoundary" ]: Ensures the symlink is created after files are written.Shell logic:
- Set variables:
target="$HOME/Documents/life/calendar"link="$HOME/.config/when" - If the link (or file) exists, remove it.
- Create the new symlink.
- Set variables:
Result: After activation,
~/.config/when is a symlink to your calendar folder.
When Tools Ignore Their Own Man Pages
So, according to when’s man page, config files can live
in several places, following the XDG
spec:
${WHEN_CONFIG_HOME}/preferences
${XDG_CONFIG_HOME}/when/preferences
$HOME/.config/when/preferences
$HOME/.when/preferencesGreat! So I created the file:
touch ~/.config/when/preferencesThen ran:
whenAnd got this prompt:
You can now set up your calendar. This involves creating a directory ~/.when...Wait, what?
Maybe it’s because the file is empty? So I went ahead and let
when create its stuff the way it wants to:
when
y
nvimThen moved it manually:
mv ~/.when/* ~/.config/whenVerified contents:
ls ~/.config/when
# calendar preferencesTried again:
when
# Still prompts to create ~/.whenSigh.
Maybe the Environment Variable?
export WHEN_CONFIG_HOME="$HOME/.config/when"
when
# Still no luckGoodbye XDG
So yeah, despite what the man page says, when doesn’t
seem to honor XDG_CONFIG_HOME or
WHEN_CONFIG_HOME. Back to messy $HOME we
go.
To keep things working, I updated the symlink to point to
~/.when instead:
{
home.activation.symlinkWhen = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
target="$HOME/Documents/life/calendar"
link="$HOME/.when"
if [ -L "$link" ] || [ -e "$link" ]; then
rm -rf "$link"
fi
ln -s "$target" "$link"
'';
}Despite the hiccups, I still love when. It’s minimal,
extensible, and scriptable. I just wish its advertised XDG support
worked. (If you know a fix—please reach out!)
A Test Event: Does This Actually Work?
Time to see if the setup behaves as expected.
Added this line to calendar:
w=Fri, 12:00 Class with Mr Thompson
Then ran:
when c mOutput:
tomorrow 2025 May 23 12:00 Class with Mr Thompson
Fri 2025 May 30 12:00 Class with Mr Thompson
Perfect.
Integrating when
with VimWiki
To display this in my vimwiki, I’m adding a
== Calendar == section in index.wiki. Then I
use a script to inject the output from when.
Here’s the script:
#!/bin/sh
# File to modify
file="../index.wiki"
# Generate calendar output
custom_text="$(when c m)"
# Find line number for '== Calendar =='
line_num=$(grep -n '== Calendar ==' "$file" | cut -d: -f1 | tail -n 1)
if [ -n "$line_num" ]; then
tmp_file="$(mktemp)"
head -n "$line_num" "$file" >"$tmp_file"
echo >>"$tmp_file"
echo "$custom_text" >>"$tmp_file"
mv "$tmp_file" "$file"
else
echo "No line containing '== Calendar ==' found." >&2
exit 1
fiAfter running this, the calendar section in my wiki updates automatically.
Conclusion
That’s it! My little setup for a VimWiki + when calendar
integration is complete.
It’s:
- Minimal
- Scriptable
- Easy to sync
- Fits into my notes without clutter
I’ll improve it as I go—and if any big changes come, maybe I’ll write a follow-up post.
Btw, being such a simple, useful and underground tool. I might as well do a Rust rewrite. Let’s add it to the TODO list on our VimWiki :::::v