DSM-9: The Best Tooling for Physical Flash Cards

DSM-9: usage

Current version: v2.0


While tools such as Mnemosyne and Anki are designed to store cards on the computer and test you while you use the device, DSM-9 takes a different approach. DSM-9 expects you to keep a physical deck of cards - or a file on an eReader, or a notebook, or a plain file on the computer; you should use whatever approach works for you. For simplicity’s sake, we use the term "deck." This provides a much greater degree of flexibility. DSM-9 provides a number of tools to make life easier, without making decisions for you.

To accommodate this, two files are needed per deck. The first file, a , provides a name for every card in the deck, and optionally includes their contents. This file is to be managed by you. When you add a new card to your deck, simply mark a unique name on the physical card, and add that name to a line in the .deck file. A simple hierarchical naming scheme for a chemistry deck, for instance, might contain entries like this:











A single deck may contain up to 65,534 cards. Cards are formatted with between to three fields. The first field, which is mandatory, is the unique name. The second and third are both optional, and are the front and back of the card respectively. The fields are separated with three at symbols (@@@), a sequence which is not allowed to ever appear within a field. The front and back may be stored in any plain text format - unadorned text, markdown, HTML, or anything else.

Note that, despite the front and back being optional, the delimiter is currently required.


In addition to the deck file, there is a log file, which is managed entirely by DSM-9. All that you need to know, as the user, is that the log file must be kept in the same folder as the deck file, and must have the same name (with the only difference being the file extension). Details are provided here for completeness; this section is not important to usage of DSM-9. Every line in a log file contains three fields, each separated by the three-at-symbol delimiter: a card name, the timestamp at which the card was tested, and the grade given at the time of testing. On startup, every line is processed, each line is mapped to a card via the name, and the card’s due date is updated. When a new value is logged, it is written to the file, and the internal values are updated.


DSM-9 is split into a few pieces: the library, and a few clients. The library handles the deck and log files, and the core logic (updating card info when a new log entry is produced, scheduling due cards, etc). The due client prints the list of due cards for a given deck. The log client prompts for grades for cards in the order in which they are due. The intended usage is to maintain a list of physical cards, schedule them using the due client, test them, update the logs using the log client, and repeat ad infinatum.


dsm9/due [-c count] [-o offset] deck

dsm9/due prints out the list of due cards. By default, it prints out the first 30 due cards. This can be overridden by setting the count via -c. Setting the offset with -o skips to after the specified offset. For instance, if there are 45 due cards, and the invocation is dsm9/due -c 10 -o 30 , 10 due cards starting at the 31st due card will be printed out.

dsm9/log [-t timestamp] [-s] [-c max] deck

dsm9/log is a useful logging tool for when cards are tested in the order in which they are due, with no divergence. It prompts for grades for cards in the due order, and produces the appropriate log entries. By default, it marks the timestamp of the test as the moment the client was started; this can be overridden by specifying a timestamp with -t.

The -s option enables "sequential mode," in which cards are tested according to their order in the deck, instead of the due date. This is especially useful when you plan on testing a full deck anyways.

By default, 12 cards are prompted for. This limit can be changed by overriding the maximum with -c.

dsm9/log prints the name of the card being tested, then prompts for user input. Either a grade in [0, 5] should be entered, or the letter ’q’ to quit.

The interactive client

dsm9/cli is an interactive client, which displays cards and prompts for their grades. However, it depends intrinsically on plan9 functionality such as the plumber, and is thus only supported on plan9.

dsm9/cli [-a] [-h] [-o offset] [-c max] deck

dsm9/cli treats cards either as roff inputs or as HTML. Each card gets rendered, plumbed, and finally graded as with dsm9/log. HTML cards get wrapped with a header with asserts that they are encoded in UTF-8. roff cards get processed through eqn, then via troff into the device-independent troff language. Processed cards get plumbed either to the postscript channel (for roff cards) or the web channel (for HTML cards).

The plumber can be configured to handle cards in any manner deemed appropriate. By default, roff cards go to page, and HTML cards go to the configured web browser (typically mothra, though I recommend Phil9’s NetSurf frontend).

cli first renders the front, then waits for user input. After the user acknowledges the front, the back of the card is rendered, and the user is prompted for the grade.

Further Uses

dsm9/due and dsm9/log will not cover every conceivable use case, not by a long shot. There are multiple options for handling further behavior. First, one can write a new client. This is actually very easy - the official due client is only 56 lines of code, of which 12 is just the inclusion of headers for POSIX and Plan9, and roughly 22 are configuration handling. The DSM-9 v2 API has been designed to be extremely easy; of the 47 meaningful lines in dsm9.h, 23 are comments, 17 are the definition of the internal deck format, and a mere seven define the exposed functions. The DSM-9 API is extremely well-documented.

The other option, which is even more suitable for certain simple use cases, is to interact with the deck and log files directly. Writing a POSIX shell script to append a new card to the deck if and only if it is not already present is trivial, for instance (e.g. cat foo.deck | grep "^$name" -q || already_exists). An alternative logger that uses dsm9/due to find cards can simply produce timestamps via date and generate log entries, for instance.