I find the terminal lack of graphical output hard to deal with. I have found a few ways to overcome the terminal limitations:

External file managers

E.g.: xfce thunar. They are difficult to integrate with note system workflow, only works for images and documents

Graphical tools to display images in the shell.

E.g.: kitty Inspired by what emacs can do, there are some libraries/terminals that can display images. As far as I know there is no simple way to make them work with vim or neovim at the moment. I think they would suffer similar layout limitations to emacs.

markdown previewers

There are some tools like markdown-preview that run a web server and synchronise the files when edited. The main inconvenient of these tools is the amount of requirements they have and the difficulty of having a two window workflow.

It is also possible to have something like pandoc rendering the pages when requested.

Independent tools

I tried a few tools available in debian:

  • retext: too simple, non vim friendly
  • ghostwriter: I couldn’t make the links work with vimwiki. It was also missing some features like code rendering or mermaid
  • obsidian: Most of the features needed, big community. But electron based and not open source
  • zettlr: Slightly less user friendly than obsidian but with most of the features. And open source.

From all the choices evaluated I went for zettlr. It is easier to use for displaying the documents and making small changes.

How to make vimwiki and zettlr work together

There are a few issues that make vimwiki and most of the markdown tools not work well together:

Note creation

As I am using the vim plugin vim-zettel for zettel note creation creation, I needed to change the default format in my .vimrc

let g:zettel_format = "%Y%m%d%H%M%S-%title"

vim-zettel offers some of the features that zettlr offers, like a link creation command and key binding to copy the link to the current file.

Zettlr uses [[link]] whereas vimwiki uses [text](link). Zettlr will launch a new instance when cliking the vimwiki style link, as it considers it a “external link”. vimwiki recognises [[link]] but it doesn’t count them for backlinking.

zettlr also has a different interpretation of the link content. The 14 digits without the text can make the link work, and the number might be inside the file rather than part of the title. vimwiki only works with relative paths to the current path. zettlr doesn’t work if there is any directory or ../ in the name, as if all of the files were in the same folder.

A few practical examples:

Assuming a file wiki/dir/20220910210000-description.md

  • [[20220910210000]] is a valid zettlr link but would not work in vimwiki
  • [link](dir/20220910210000-description) is a valid vimwiki link but would not work in zettlr.
  • [[dir/20220910210000-description]] is a valid vimwiki link but would not work in zettlr. vimwiki would not find it in backlinks
  • [[20220910210000]] [ ](dir/20220910210000-description) would work in both environments

Originally I tried changing the note format in zettlr to match []() links, but I couldn’t make it work. Instead I have emulated part of zettlr’s behaviour in vimwiki by overriding the function VimwikiLinkHandler

function! VimwikiLinkHandler(link)
let link = a:link
if link =~ '^\d\{14\}$'
  let filepath = system('find ~/wiki -name ' . fnameescape(link) . '*.md')
  let wikipath = system('realpath --relative-to=/home/user/wiki ' . filepath)
  let wikipath = wikipath[:-5]
  echo wikipath
  exe 'cd ~/wiki'
  exe 'VimwikiGoto ' . wikipath
  return 1
  return 0

I have found that having both links together work best [[zettlr_format]] [ ](vimwiki_format)). In the section below I’ll show how to make vimwiki generate the link automatically when pressing enter.

Tags, headers and templates

vimwiki default header is #header, while in zettlr that is a tag. zettler requires a whitespace to make it a header # header

The only way I have found to make vimwiki tags and headers work the same is through changing vimwiki_syntax_variables . The original code is in vimwiki_markdown.vim. My changes in .vimr look like this:

let g:vimwiki_syntax_variables = {}
let g:vimwiki_syntax_variables["markdown"] = {'option1': 'value1',
 \ '...': '...',

Which copied all of the values from vimwiki_markdown.vim and changes some of them:

 \ 'rxTags': '\%(^\|\s\)\@<=:\%([^:[:space:]]\+:\)\+\%(\s\|$\)\@=',
 \ 'tag_search': '\(^\|\s\)#\zs\([A-Za-z0-9_]\+\)\ze\(\s\|$\)',
 \ 'tag_match': '\(^\|\s\):\([^:''[:space:]]\+:\)*__Tag__:\([^:[:space:]]\+:\)*\(\s\|$\)',
 \ 'rxH1_Template': '# __Header__',
 \ 'rxH2_Template': '## __Header__',
 \ 'Weblink1Template': '[[__LinkDescription__]] [ ](__LinkUrl__)',

Restricting zettlr access to the network

Another advantage that vimwiki has over zettlr is that it is impossible to load anything from the network unless I request it. Zettlr can load youtube videos, external images and send its own data.

Fortunately I can restrict zettlr access to network with the following shell script using unshare:


exec unshare -m -n -c /usr/bin/Zettlr $@