Zettels
Zettels is command line tool which implements Niklas Luhmann's system of a "Zettelkasten". It uses libzettels as a backend.
If you have no idea what a Zettelkasten is, read below at "What the heck is a Zettelkasten?"
Code and crate
Zettels is written in Rust. Find code and crate here:
Zettels is still in alpha stage and probably buggy.
Installation
It's probably easiest to install via Rust's cargo
cargo install zettels
What does Zettels do?
Zettels is a tool to index markdown files (your zettels). It takes a directory (your Zettelkasten's root directory) containing Markdown files (which may be in sub-directories) with a YAML metadata block (as defined by pandoc).
Zettels bundles the information about the relations between these files (your zettels) in a queryable index. To populate this index, Zettels does two things:
- It inspects the fields
title,keywordsandfollowupsof the YAML metadata block.
---
title: 'Example Zettel'
keywords: [example, question]
followups: [file.md, subdir/anotherfile.md, ../yetanotherfile.md]
foo: 'Potentially more data ignored by libzettels.'
...
- It parses the inline-style links (like
[example](afile.md)) of the markdown document body and extracts the targets of these links.
The resulting index contains the metadata and the targets of the hyperlinks.
Have a look at the files in examples/Zettelkasten and examples/index.yaml
to get a better idea.
It's intended to be used for a "Zettelkasten" like Niklas Luhmann used it.
What the heck is a Zettelkasten?
"Zettel" is German for "note" or "slip of paper". "Kasten" is German for "box". Think of old style library catalogues.
Obviously, this piece of software is not a box of paper sheets. However, Niklas Luhmann used such a box in a very specific way for his academic work.
A wonderful introduction in Luhmann's system of a Zettelkasten are the slides of a talk by Daniel Lüdecke: Introduction to Luhmann's Zettelkasten-Thinking
In Luhmann's own words: Communicating with Slip Boxes (translation of "Kommunikation mit Zettelkästen").
If you speak German, there's more:
- Luhmann, Niklas (1981): Kommunikation mit Zettelkästen. Ein Erfahrungsbericht. in: H. Baier / H.M. Kepplinger / K. Reumann (Eds.), Öffentliche Meinung und sozialer Wandel. Opladen: Westdeutscher Verlag. pp. 22-28
- Daniel Lüdecke: Luhmanns Arbeitsweise im elektronischen Zettelkasten
- Thomas Schlesinger: Wissen konservieren und kuratieren mit dem Zettelkasten nach Niklas Luhmann
- Universität Bielefeld: Video - Einblicke in das System der Zettel - Geheimnis um Niklas Luhmanns Zettelkasten
Alternatives
If you're looking for a GUI, all-in-one approach to implementing Luhmann's idea into software, I can recommend Daniel Lüdecke's Zettelkasten (sjPlot/Zettelkasten).
Zettel format
Zettels doesn't require your markdown files to have a metadata block. But to
be really effective parts of your Zettelkasten, a YAML metadata block
containing an entry for title, keywords and followups is necessary.
---
title: 'Example Zettel'
keywords: [example, question]
followups: [file.md, subdir/anotherfile.md, ../yetanotherfile.md]
...
If no such metadata is present, Zettels will replace it with appropriate "empty" values in the index:
title: "untitled"keywords: "[]"followups: "[]"
Instead of finishing the metadata block with ... you can also use ---.
---
title: 'Example Zettel'
keywords: [example, question]
followups: [file.md, subdir/anotherfile.md, ../yetanotherfile.md]
---
In fact, a zettel file may contain several YAML-blocks. However, Zettels will
only parse the first one.
The metadata block may contain a variety of other entries (e.g. author,
date) – maybe for other tools, like pandoc – but those other entries are
ignored by Zettels and do not become part of Zettels' index.
To manually link between zettels, use the "inline syntax" for markdown hyperlinks:
[link text](url)
Links between zettel files should be relative links. The same is true for
entries in followups.
Usage
tl;dr
- run
zettels setupfor config - run
zettels -hto see usage info
Search and inspect
There are two main ways of querying the Zettelkasten.
1. Search
Searching is a means to find an entry into the Zettelkasten.
Zettels implements searching the title and keywords fields
of the zettel.
Just for the sake of completeness: searching the contents of the zettel
is not a functionality of zettels. For that there are specialized tools
like grep oder ripgrep out there.
Search for keywords -k, --keywords:
zettels -k foo
Search for title -t, --title or -e, --exacttitle:
zettels -t foo
Both can be combined:
zettels -k foo -t bar
Results can be limited to zettels that match all queries: -a, --all
zettels -k foo -t bar -a
And of course, that applies to mor than one search term, too.
zettels -k foo bar -a
2. Inspect
Inspecting the relations between zettels is the second way of querying the zettelkasten. Inspection requires a "scope", meaning a list of zettels to inspect. This scope is either specified by the user, or it's the result of search or it's the whole zettelkasten.
For inspecting the "followup" relation, a key concept are "sequences". When a zettel designates another as a followup, they form a sequence. Further followups extend that sequence or might branch into subsequences.

Show to which sequences zettels specified by SCOPE belong -s, --sequences:
zettels -s file1.md
Show all zettels of the sequences specified by SCOPE -z, --zettels:
zettels -z file1.md
Show zettels that belong to the sequence(s) specified by SCOPE, plus all
ancestors of SCOPE -f, --family:
zettels -f file1.md
Show zettels that belong to the sequence(s) specified by SCOPE, plus all
ancestors of SCOPE, plus all descendants of those ancestors -w,
--wholefamily:
zettels -w file1.md
For inspecting the "link" relation, we can inspect SCOPE's outgoing links
-l, --links:
zettels -l file1.md
or incoming links -i, --incoming:
zettels -i file1.md
Both
As mentioned before, the result of a search can be used as SCOPE for inspection. So this will show all outgoing links of zettels that have the word "foo" in their titles:
zettels -t foo -l