Back to notes

My knowledge management system

Keywords: zettelkasten, notes, notetaking, knowledge management, second brain, notierenarchiv


Command / action Description
zet 'my new note' Create a new note from the shell
:Zet my new note Create a new note from within Vim
zetbl Update backlinks for each note from the shell
<leader>-w-f Search all local notes
C-x C-f Autocomplete local note filename


My knowledge management system is built for maximum personal utility. It's subject to change as needs arise. It's not pure Zettelkasten; anything goes as long as it helps me to accumulate, organize, and relate thoughts, ideas, and knowledge. I like my system to be rather minimal, only adding features to it when it becomes necessary. My base is Vimwiki and I build from there.

Some features I've added:

  • macro for creating a new note (inspired by this)
  • command for searching local notes
  • configuration that allows filename autocompletion for links to local notes
  • script for finding backlinks and listing them in the frontmatter of each file

Some features I'm considering:

  • fuzzy link autocompletion (currently only works if the title of the note is correctly typed to a point)
  • a smarter link autocompletion that allows for autocompleting notes that match keywords



  • Vim - for writing notes

  • VimWiki - provides a system alongside Vim for writing and organizing our notes

  • Ripgrep - makes our backlinks script and custom WikiRg search function possible

  • FZF - makes our custom WikiRg search possible via internal function and provides fuzzy-finding for files in the current working directory

  • Custom code 1: in .vimrc, set autochdir for vimwiki filetypes

autocmd FileType vimwiki set autochdir
  • Custom code 2: in .vimrc, create WikiRg function for searching notes with Ripgrep
command! -bang -nargs=* WikiRg call fzf#vim#grep('rg 
      \ --column --line-number --no-heading --color=never 
      \ --smart-case --type md <q-args> "/Users/<user>/vimwiki"',
      \ 1, fzf#vim#with_preview(), <bang>0)
autocmd FileType vimwiki nnoremap <buffer> <leader>wf :WikiRg<Space>
  • Optional custom code 3: in .vimrc, set global variable vimwiki_list as needed
let g:vimwiki_list = [{'path': '~/vimwiki/',
                      \ 'syntax': 'markdown', 'ext': '.md'}]
  • Custom code 4: create file ~/.vim/autoload/local/zettel.vim with function for automatically creating a new note file with frontmatter
func! local#zettel#edit(...)

  " build the file name
  let l:sep = ''
  if len(a:000) > 0
    let l:sep = '-'
  let l:fname = expand('~/vimwiki/') . 'zett' . l:sep . join(a:000, '-') . l:sep . strftime("%Y-%m-%d-%H%M") . '.md'

  " build title-case title
  let l:tctitle = substitute(join(a:000, ' '), '\(^.\)', '\u&', '')

  " build frontmatter
  let l:frontmatter = "---\ntitle: " . tctitle  . "\ndate: " . strftime("%Y-%m-%d") . "\nkeywords: \n---\n"

  " write frontmatter to new file
  0put = l:frontmatter
  exec 'w ' . l:fname

  " edit the new file
  exec 'e ' . l:fname
  • Custom code 5: in file ~/.vim/plugin/local.vim, register :Zet command to enable calling the function in zettel.vim
command! -nargs=* Zet call local#zettel#edit(<f-args>)
  • Custom code 6: in shell profile, register function to enable opening Vim and immediately calling the function in zettel.vim with arguments
zet () {
  vim -c "Zet $1"
  • Custom code 7:
    • for backlinks script, see section below entitled "Compute backlinks and add to frontmatter of each note"
    • once you have the script working locally (AKA it's successfully adding the correct backlinks to your frontmatter, with proper formatting), add alias zetbl='path/to/script' to your shell profile


Creating a new note

  • From the terminal:

    zet 'my new note'

  • From within Vim:

    :Zet my new note

The newly created note will look like this:

title: My new note
date: 2020-08-09

Writing a new note

My system uses Vimwiki with pandoc, so pandoc markdown syntax should be used when writing notes. I chose pandoc for its flexibility.

  1. Use one of the commands above to begin a new note. The title will be generated from the string argument given and added to the frontmatter of the new note, along with the date and a place to list keywords, which are tag-like metadata that allow for easy searching and categorizing of notes.
  2. Enter a comma-delimited list of a few keywords to describe the current note.
  3. Write the body of the note below the frontmatter section using pandoc markdown.
  4. When finished, save and quit (:wq)
title: My new note
date: 2020-08-09
keywords: note, new, mine

My note body

Compute backlinks and add to frontmatter of each note

I wrote a nice Perl script for this that uses Ripgrep to search all notes for links to each file and then lists the locations of those links under a frontmatter item called backlinks. I use YAML for frontmatter.

This script is available on Github. As always, execute with caution. Please examine the code to understand what it's doing before you run it.

Search local notes

I built a custom function (:WikiRg) in my .vimrc for searching local notes with Ripgrep. To be consistent with Vimwiki's keybinding syntax, I mapped this function to <leader>-w-f ("wiki find").

The search will return all matching Vimwiki files and show a detail pane displaying the context of each match.

Autocomplete links to local notes

Because autochdir is set to ~/vimwiki/ for vimwiki filetypes, the default Vim keybinding for autocompleting a filename will work for autocompleting references to any file in the ~/vimwiki/ directory.

To create a new link to another note, follow these steps:

  1. Create the link normally, using markdown's []() syntax:
[my link](
  1. Vimwiki notes in the knowledge management system are prefixed with "zett-", so begin by typing that:
[my link]( zett-
  1. Press C-x C-f to activate Vim's filename completion, which will list all files beginning with "zett-". Use this to help search for the right file. If necessary, run a search on local notes to find the correct note for linking.
[my link]( zett-the-web-2020-08-09-1436.md )