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?"
Zettels is still in alpha stage and probably buggy.
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:
1. It inspects the fields title
, keywords
and followups
of 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.'
...
``
2. It parses the inline-style links (like
example`) 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.
"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:
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).
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]
```
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:
[.markdown]
[link text](url)
Links between zettel files should be relative links. The same is true for
entries in followups
.
zettels setup
for configzettels -h
to see usage infoThere are two main ways of querying the Zettelkasten.
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
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
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