ZtlNote is an attempt to implement a zettelkasten organization method software.
The approach of ZtlNote is to be a fast CLI tool to interact with notes a bit like Git. The implementation will be a file based store that is organized to maintain strings of notes and references.
In his book about the Zettelkasten organization (How to Take Smart Notes), Ahrens Sönke describes 3 steps:
- take flying notes about what you read/hear/see
- rework these notes in the Zettelkasten combining them with the existing ones and trash flying notes
- when you want to write a book or a blog post about a subject, extract paths of thoughts from the Zettelkasten as raw material.
The forces of the Zettelkasten lie in its organization in paths, references between notes and a taggin system. ZtlNote combine these three things.
I have written ZtlNote with my understanding of the book in an effort of testing this organization while having a coding experience with Rust.
ztln command [arguments] [options]
- info: list current topic/path with its date of last note creation/update
- init: create an Organization and initialize the structure on disk. By default, the directory is taken from the
ZTLN_BASE_DIR
environment variable but it can be passed as parameter:ztln --base-dir DIR init
. - topic
- create: create a new topic. This also creates the
main
path in that topic (maybe a--main-path
option may be added in the future to specify the name of the topic's default path)ztln topic create TOPIC
. - list: list topics in the Organization (maybe none).
ztln topic list
. - default: set the default topic for operations.
ztln topic default TOPIC
.
- create: create a new topic. This also creates the
- path
- branch: branch a path from a specified note
ztln path branch PATH [LOCATION]
. - list: list the existings paths in the current topic
ztln path list
orztln path list TOPIC
. - default: set the given path as default path
ztln path default PATH
. - remove: remove the given path
ztln path remove PATH
. There will be no warning if some notes are not in any path after this process. - reset: set the given branch to point to another location. By using this command, some notes may not being on a path and even though they are not physically lost, will not be reachable anymore.
- branch: branch a path from a specified note
- note:
- add: create a note from an existing content file
ztln note add [FILENAME] [-p PATH] [-t TOPIC]
. If the filename is not given, the editor specified with the environment variable$EDITOR
(default: vi) is launched. The file is then saved as a new note either at the default location (HEAD) or the specified topic/path. - show: show a note from a given location
ztln note show LOCATION
. - reference: create a reference from one note to another
ztln note reference LOCATION LOCATION
.
- add: create a note from an existing content file
- tag
- add: tag a note with the given keyword
ztln tag add KEYWORD [LOCATION]
. - search: search all notes tagged with the given keyword
ztln tag search KEYWORD
. - list: list all the keywords stored in the index
ztln tag list
.
- add: tag a note with the given keyword
A location is an easy way for humans to designate a note at a moment in time. Since this address mode is relative to a head and paths are supposed to evolve over time, a note location one day may not designate the same note the day after. Furthermore, a location may be relative to a current topic and path. If a unique address stable in time or an absolute address is required then the note UUID shall be used instead.
[topic/]path[:-N]
- topic: f specified, the topic designate the Tought Topic of the Note. If note specified, the current topic is used.
- path: the path followed to reach the Note. Since paths have notes in common, several paths can be used to reach the same note.
- modifier: the number of ancestor of the path head's note (default to 0)
Examples:
topic1 A ─ B ─ C - D ←main (current path)
└ ─ E ←path1
Assuming the topic1
is the current topic, the note B can be reached with the following locations:
main:-2
equivalent oftopic1/main:-2
HEAD:-2
since main is the current pathpath1:-1
Here are other examples of locations:
HEAD
ormain
ormain:-0
ortopic1/main
ortopic1/main:-0
→ note Dpath1:-2
→ note Apath1:-4
→ nothingwrongpath
→ nothingwrong/address/format#
→ Error
Organization: The Organization is the ensemble of Notes and relations between them.
Note: A Note is composed of two distinct parts: a Content and a MetaData.
Note Content: Text containing the actual information of a Note.
Note Meta Data: Technical data associated to a Note: date information & links to related notes (parent note, related notes, tags)
Note Address:
Unique way of locating a Note in the Organization. [topic/]path[:-N]
Tag: Searchable word linked to a Note.
Index: File regrouping Notes ID by tag.
Topics: A Topic is a named topic of notes linked by a parent relationship.
Thought Path (abbrev. Path): A Path is a name that points to the last Note of a branching in a Topic. Each time a Note is added to a Path, the Path points to it and the new Note points to its parent forming a path of thoughts.
Store: Technical abstraction layer to perform all the I/O needed to persist the Organization state.
Note Identifier: Unique technical identifier for a note (UUID V4).
The main file uses StructOpt
to parse the command line arguments. Each command must be a struct testable on its own:
The Organization
structure holds the information related to the Organization at least:
- base_dir
- default_topic
- store
It uses the Store
structure to perform all the I/O in order to persist its state. All methods of the Store API must indicate in which topic and path the operations happen. Default topic & path are an abstraction of the Organization.
The store is a disk based implementation:
basedir
+- index ← tag index
+- _CURRENT ← name of the default topic when exist
+- notes -+- UUID-1 ← textual content of the notes
| +- UUID-2
|
+- meta -+- UUID-1 ← meta data of the notes
| +- UUID-2
|
+- topics -+- topic_1 -+- _HEAD ← name of the default path when exist
| +- description ← long description of the topic when exist
| +- paths -+- main ← UUID of the last note published in this path
| +- path1
| +- path2
|
+- topic_2 -+- _HEAD
+- paths -+- main
+- pathN
The tag store manages the index
file which contains an association of UUID indexed by tags.