Other Posts

Build A Killer Note-taking System


The proverb says, “The palest ink is better than the best memory”. Note-taking is certainly an essential part of knowledge learning, information collecting and retaining. In the fast-changing digital era, pen, ink and paper may not be able to fulfill the important job of note-taking anymore. So, what’s a killer note-taking system nowadays?

My requirements?

My dream system must be Easy, Efficient and Flexible:

  • Know where & how to write notes easily without hesitations
  • Find right notes & roll back to old changes efficiently without hassles
  • Convert notes to other formats and share them flexibly without troubles

Build it!

Note format

I love taking notes with markdown. Why markdown?

  • It’s clean for writing and reading
  • It’s efficient, almost like writing plain texts
  • It’s flexible to convert to any other formats

Note taking & organization app

I like doing everything in the terminal, so naturally, Vim is the best note-taking editor for me.

For organizing notes, in the beginning, I set up different folders for different notes. But it’s not quite close to what I want. Especially, searching note is not a straightforward task, it needs to find or grep for a while. Then I wrote a handy script pynote for helping note organization, it worked and only at “it works” level… Recently, I switched to the amazing Notational Velocity for Vim, a plugin to port famous Notational Velocity into Vim. The whole note-taking experience never becomes so smooth! 💆‍♀️

Note version-control system

It’s easy. Git is the only reasonable option I can think of. ¯\_(ツ)_/¯

git init, make note changes, git add, git commit or git revert… All the fancy version control things are already familiar under my hands.

Note auto backup system

Google Drive? OneDrive? Dropbox? Nah, they are not really Git-compatible by default. However, I got inspired by SparkleShare, an open-source file sync app powered by Git, it adds file changes and pushes them to Github or GitLab automatically.

I may achieve the same functionality by using a simple script. The idea is to run fswatch in the background and keep monitoring file changes. When file changes are happening, fswatch will trigger Git commands to add and push changes automatically.

Here is a snippet of Bash script:

#!/usr/bin/env bash
function notesync() {
  fswatch -r -0 -d "$1" -e '\.git' -m "inotify_monitor" --event=Created --event=Updated --event=Removed | xargs -0 -n 1 zsh -c "source ~/.zshrc; cd $1; git add -A; git commit -m 'Update file'; git push" &
notesync "<folder_path>"
notesync "<another_folder_path>"

fswatch part is to monitor file changes, filter out correct file change events and send the signal:

fswatch -r -0 -d "$1" -e '\.git' -m "inotify_monitor" --event=Created --event=Updated --event=Removed | ... &
  • -r: watch subdirectories recursively
  • -0: pass NUL as delimiter (no idea why it’s need…..)
  • -d: directory to monitor, the target folder full of notes
  • -e: exude paths matching regex, here I don’t want to trigger Git commands when any changes are happening in .git
  • -m: monitor, type fswatch -M to see available monitors, more details of all available monitors: here
  • –event: filter event by event flag, mainly using events related to file changes, all available events: here
  • &: last but not least, don’t forget it at the end, because it provides the ability to run fswatch command in background and detach the process

xargs part is to get signal from fswatch and execute specific commands:

... | xargs -0 -n 1 ...
  • -0: input items are terminated by null, not whitespace (no idea why it’s needed…)
  • -n: maximum argument, 1 it is

zsh command part is to run Git commands:

... zsh -c "source ~/.zshrc; cd $1; git add -A; git commit -m 'Update file'; git push" ...
  • zsh -c: execute following commands in zsh
  • source ~/.zshrc: all my SSH keys are declared in .zshrc file, this command will load configurations from .zshrc file. Otherwise, push to remove Git repository may get permission denied
  • git add -A … : Git commands to add changes and push to remote repository. Some optimization ideas: 1) git pull first, in case it’s a shared repository; 2) Put some specific texts in commit messages, maybe also including file names


This is my killer note-taking system. It’s easy, efficient and flexible:

Note format: Markdown
Note taking & organization app: Vim + Notational Velocity for Vim
Note version-control system: Git
Note auto backup system: fswatch + GitHub

So far I’m quite happy with this system. I enjoy using it not only for taking some private notes with my dirty secrets, but also for sharing notes with colleagues in my day-to-day work, like notes for exploratory testing. Oh, I almost forget, guess what I’m using now for wring this blog post?

How does your note-taking system look like? Share with me your awesome ideas?