carnet: a note taking logbook helper

Presentation

carnet(1) is a logbook and note taking helper. It provides a way to record seamlessly journal entries, along automated recording of the time and date. As an option, it can also record all sorts of interesting information, like recorded calendar(1) activities, or what could be playing on music players like mocp(1).

The log book is a set of text files, one per week, made of entries separated by a time stamp, and specific markers to separate days of the week; this avoids exploding the file size of a long running log file typed for a while by a proficient writer, while also avoiding the explosion of file numbers that could appear with compulsive writers.

In a hurry? You can download the latest version at the bottom of this page, but you may want to go through the whole page if this is your first contact with the utility.

Warning: while the utility is now available to the public, there are several rough edges, several documented in the BUGS file, and probably many more that flown below my radar.

Use cases

Fulfill compulsive writing needs

The main purpose of carnet is to open a scratch pad in which to take notes that may be easily retrieved, without having to go through the hurdles of finding in which location to store the note, how to name the file, things like that. Just type in your prompt:

$ carnet

and boom! You can go ahead and type in your note in your favorite text editor:

2025-25.txt - semaine précédente
2025-27.txt - semaine suivante
2024-42.txt - première semaine

Journal de bord, an 2025, semaine 26

________________________________________________________________________
Date : dimanche (2025-06-29)

22:52 : sur fond de : Yes - Close To The Edge
J'aime bien le morceau en train de passer à la radio.  :)

carnet will try hard to pass the right options to start edition straight at the end of the file, after having appended all the timestamps and informations that give context to the entry. Only the last line, highlighted in the hard-copy here above, has been typed in. Of course, when a proficient writer fills thick entries, the decorum gives way to the content.

There also exists an option --activity which is purposed to gratify the writer with a sense of achievement after a well filled week:

$ carnet -a
       0   4   8  12  16  20  24  28  32  36  40  44  48  52  56  60  64  68  72  76  80  84  88
2024-42|===|===|===|===|===|===|===|===|===|===|===|=
2024-43|===|===|===|===|===|===
[…]
2025-25|===|===|===|===|===|===|===|===|===
2025-26|===|===|===|===|===|===|===|===|===|===|===|===|===|===|===|===|===|===|===|===|===
       0   4   8  12  16  20  24  28  32  36  40  44  48  52  56  60  64  68  72  76  80  84  88
Dist.: |        .O    |-------|=======#======|---------------|                            O    .
Deci.: |        -     -      - -   -  -   -  -  -            -                                 -
Perc.: |        ===   =+   ===## =+==#-+ #=# # +==  =    +   =                =           =    =
       0   4   8  12  16  20  24  28  32  36  40  44  48  52  56  60  64  68  72  76  80  84  88
Apparent size: 1233.9kiB  raw: 1300kiB  density: 94.91%
Mean apparent size per week: 33.3kiB  raw: 35.1kiB
Number of entries: 3117  of weeks: 37

The first part is the histogram per week, trimmed for the sake of brevity, showing the information stored in each week. Each character amounts for 1kiB. The second part paints a box-and-whiskers plot of the distribution of size of entries for each week, and the Deciles and Percentiles lines attempt to represent the same values with an ASCII heat map of activities per week. Yes, it takes some getting used to to notice that weekly activity happens following a pattern which resembles to a Poisson distribution; it will make more sense as entries are going to be added during day to day activities. Then some random information follows, with relation to the size occupancy of the carnet in the file system. The Deciles and Percentiles require the Perl variant of the carnet_activity script.

Fill a time sheet

I have found it tremendously beneficial to prepare time sheets thanks to the timestamped information stored in the carnet. As I work, I fire `carnet` to record what I do, for example :

________________________________________________________________________
Date : mardi (2025-06-24)

08:06 :
I arrived at the office.

10:13 :
Since I arrived, I worked on the foo project.

Date and timing information are automatically fed by carnet, I just have to write down what I was doing since the last entry. This can be especially useful if it is necessary to estimate time spent on given projects for whatever billing reason. This is where the --search function shines:

$ carnet -s '\<foo\>'
2025-25.txt : lundi (2025-06-17) : 10:01 :
I attended the kick-off meeting of the foo project.


________________________________________________________________________
2025-26.txt : mardi (2025-06-24) : 10:13 :
Since I arrived today, I worked on the foo project.

carnet also includes a configurable option to prevent risks of doing overtime hours, through the CARNET_OVERTIME environment variable, indicating in hours the normal duration of a work day:

________________________________________________________________________
Date : Wednesday (2025-07-09)

09:23 :
Starting the day,

[…]

18:42 : warning: overtime for 19m.
Ouch, I'm running late, it's time to go.

Information storage and retrieval

As seen above, the --search option takes regular expressions in argument that are directly fed to awk. This makes the retrieval of entries on a certain topics seamless to the extent that one is fluent with regular expressions. Let's say that I want to prepare a document summarising my activity of setting up and configuring my mail server; assuming I took good not of what I was doing, compulsively. Retrieving most of the information would look like:

$ carnet -s 'exim|mail'
[…]
________________________________________________________________________
2025-08.txt : vendredi (2025-02-21) : 19:31 :
En passant les mises à jour, j'ai vu passer des changements dans le
fichier de configuration de mon serveur mail motorisé par exim4.  J'ai
passé un peu de temps à faire le tri entre les nouveautés et mes propre
changements de configuration.
[…]

Note that this is an excerpt of the output. The full set of entries is actually much larger at the time of writing:

$ carnet -s 'exim|mail' | wc -l
936

Task tracking

Since version 1.4.0, the carnet implements basic functionalities to record tasks needing to be achieved at some point, but not immediately. This is useful to avoid the sense of urgency that might induce e.g. a zero inbox email policy. To record a todo item, just run the carnet and mark work needed with a stylized ascii checkbox like "[ ]" at the beginning of a line, or more simply by starting a paragraph with "TODO:"

23:07 :
TODO: describe the use case for todo items.

23:08 :
[ ] Demonstrate multiple ways to materialize todo items.

The option --todo of the carnet command will faciliate easy retrieval of all items still non-achieved that have been recorded in the carnet:

$ carnet --todo
2025-30.txt : lundi (2025-07-21T23:07) :
TODO: describe the use case for todo items.

________________________________________________________________________
2025-30.txt : lundi (2025-07-21T23:08) :
[ ] Demonstrate multiple ways to materialize todo items.

Resolving a todo item amounts to either mark the begining of the paragraph as "DONE:" or to check the stylized box with e.g. "[*]" or "[x]":

23:07 :
DONE: describe the use case for todo items.

23:08 :
[*] Demonstrate multiple ways to materialize todo items.

carnet conventiently provides a --done option to facilitate retrieving of resolved issues:

$ carnet --done
2025-30.txt : lundi (2025-07-21T23:07) :
DONE: describe the use case for todo items.

________________________________________________________________________
2025-30.txt : lundi (2025-07-21T23:08) :
[*] Demonstrate multiple ways to materialize todo items.

The --todo and --done command line argument also admit an optional parameter to specify alternate states, like for marking tasks pending, cancelled, or low priority. These are mostly free form texts within the brackets, so can be used with any state one may imagine:

$ carnet --todo cancelled
2025-29.txt : vendredi (2025-07-18T17:40) :
[cancelled] J'ai une quantité d'informations stockées dans le carnet
rédigé en Anglais qu'il faudra à un moment que j'importe dans mon fil de
carnet personnel.

Interlinking ideas

While assembling a Zettelkasten engine was not the initial goal of carnet, it is possible to interlink the different feuillets of the carnet by referencing them via their timestamp, using the YYYY-MM-DDThh:mm time and date format, and to feed this time stamp to the option --feuillet since v1.3.0. To this end, --search and other read-only options will output each entry with their timestamp highlighted to this time format, in order to facilitate retrival and cross references:

$ carnet --search zettelkasten
[…]
2025-27.txt : samedi (2025-07-05T22:25) : sur fond de : Canvas Solaris - The Binaural Beat
J'ai publié la version 1.2.3 de carnet afin d'avoir quelque chose
d'opérationnel avant de commencer à rajouter une option pour supporter
un usage en mode Zettelkasten.  Le fonctionnement restera assez
sommaire : comme écrit plus tôt (Cf: 2025-07-05T18:23), je compte
fournir un format de date et d'heure qui pourra être passé en argument
pour ressortir une entrée de journal en particulier.  La navigation dans
le Zettelkasten se fera en copiant et collant la date comme paramêtre de
l'option.
[…]

$ carnet --feuillet 2025-07-05T18:23
File: /home/emollier/doc//carnet/2025-27.txt
18:23 :
J'ai passé un petit coup de balai.  Pour l'idée de faire un Zettelkasten
en utilisant le carnet (Cf: 2025-07-05T11:25), il me faut deux choses :

  * construire facilement un marqueur pour référencer un ticket par sa
    date et son heure, ce que je peux faire très simplement en ajustant
    le format de sortie de la fonction de recherche ; manifestement je
    pars sur un format YYYY-MM-DDThh:mm, parce que c'est ce qui me
    semble le plus évident ;
  * ajouter une option pour référencer une entrée par son marqueur ;
    j'hésite sur le nom de l'option, peut-être quelque chose comme
    --feuillet ?

This is not the best example at hand, but it will do. The idea is that one can surf between ideas, and eventually discover unexpected relations between thoughts. A strongly interlinked Zettelkasten is a tool designed for organising one's ideas in the perspective of publications, plural.

Dependencies

carnet presents itself as a shell script which, at t time, is mostly used on Debian 13 trixie and later. Portability issues are to be expected to other operating systems, having tested it on NetBSD 10 and witnessed several issues on that operating system level. The dependencies set is thus mostly usual, with a need for a Bourne compatible Shell like dash, coreutils, you name it.

carnet also requires a text editor and a pager, but one can bring one's own utilities. The idea is not to write a complete software suite, but glue together components appropriate to anyone's ergonomics.

Gnu Awk motorizes most of the queries and search abilities of carnet.

carnet also embeds a companion script written in Perl, to practically extract and report the activity in the carnet as weeks go on. Versions of carnet 1.0.y stuck to using shell scripting for the activity report if pulling the Perl interpreter is a big no-no. Note that carnet versions 1.1.y will need Perl for the activity report, but will otherwise run fine without it; this is merely a cosmetic option.

As mentioned above, certain utilities will enhance the content of the carnet, without impeding its usability when they are missing. A well maintained calendar(1) will be able to provide the schedule of the upcoming week when starting a new one, before listing the first entries. If playing music with MOC, the carnet will be capable of recording the track currently airing. None of these options are fundamental to the carnet, but are niceties to give context to some entries.

Installation

For the moment, carnet is rather confidential: I don't plan to provide operating system packages of it, unless there proves to be wide interest in carnet. To install it, download the latest version made available at the end of this page, verify its integrity and extract it. For example with the version 1.1.1:

$ gpg --verify carnet-1.1.1.tar.xz.asc 
gpg: assuming signed data in 'carnet-1.1.1.tar.xz'
gpg: Signature made Sun Jun 29 20:27:31 2025 CEST
gpg:                using RSA key 8F91B227C7D6F2B1948C8236793CF67E8F0D11DA
gpg: Good signature from "Étienne Mollier <emollier@emlwks999.eu>" [ultimate]
gpg:                 aka "Étienne Mollier <emollier@debian.org>" [ultimate]
gpg:                 aka "Étienne Mollier <etienne.mollier@mailoo.org>" [ultimate]
Primary key fingerprint: 8F91 B227 C7D6 F2B1 948C  8236 793C F67E 8F0D 11DA

$ tar xvf carnet-1.1.1.tar.xz 
carnet-1.1.1/
carnet-1.1.1/scripts/
carnet-1.1.1/scripts/gen_test_carnet.pl
carnet-1.1.1/BUGS
carnet-1.1.1/LICENSE
carnet-1.1.1/TODO
carnet-1.1.1/carnet_activity.pl
carnet-1.1.1/carnet
carnet-1.1.1/makefile
carnet-1.1.1/carnet.fodg

The carnet presents itself under the form of a shell script which may be installed, along companion script and manual page if applicable, using usual make targets:

$ make 
echo '[REPORTING BUGS]' > BUGS.roff
sed 's/^$/.PP/' BUGS >> BUGS.roff
help2man \
	--name 'note taking logbook helper' \
	--section 1 \
	--locale C.UTF-8 \
	--include BUGS.roff \
	--output carnet.1 \
	--no-info \
	./carnet
gzip --verbose --force --best --keep carnet.1
carnet.1:	50.5% -- created carnet.1.gz

$ sudo make install
mkdir -p /usr/local/bin
install carnet /usr/local/bin
chmod 0755 /usr/local/bin/carnet
install carnet_activity.pl /usr/local/bin
chmod 0755 /usr/local/bin/carnet_activity.pl
mkdir -p /usr/local/share/man/man1
install carnet.1.gz /usr/local/share/man/man1

But it can also be deployed by hand, to avoid the need to depend on html2man. The shell script carnet is mostly self sufficient, notably the argument --help provides most of the useful information transcribed automatically to the manual page. It is even useful even if its companion Perl script for the statistics activity page is not around; one would simply have to make without the --activity option.

Remark: carnet versions 1.0.y did not depend on the companion script for displaying activity statistics, at the cost of more difficult portability outside Debian, and a performance penalty of the shell script compared to the perl script.

Configuration

For now, most of the configurable options of the carnet are provided under the form of environment variables, but note that it has also been designed to avoid the need for extra configuration before getting started. Currently accounted environment variables are:

License

This software is copyright 2024-2025, Étienne Mollier. It is shipped under AGPL-3+, the Gnu Affero General Public License, at version 3 or any later version. See the LICENSE file for more details.

Download

Several versions are made available, to preserve history to some extent, especially while the git tree is not published. Note that each archive is signed with my gpg key 8F91 B227 C7D6 F2B1 948C 8236 793C F67E 8F0D 11DA advertised on my whoami page and also used for Debian Development purpose; thus it should be well known by multiple independent channels. Archives and signatures are available in the present directory:

[ICO]NameLast modifiedSize
[PARENTDIR]Parent Directory  -
[DIR]archives/2025-08-13 20:50 -
[   ]carnet-1.6.5.tar.xz2025-08-13 20:49 31K
[   ]carnet-1.6.5.tar.xz.asc2025-08-13 20:49 833
[IMG]carnet.svg2025-06-29 22:43 13K
Apache/2.4.65 (Debian) Server at emlwks999.eu Port 443