# JN
A command line notetaker and basic task manager
### Features
- All your notes managed as files. No databases or sign-ups
- Create, remove, share and search your notes from the comfort of the terminal
- Small. Like, less than a megabyte
- Do everything with a fuzzy finder, including multi-selection
https://github.com/user-attachments/assets/2b73cacb-2d75-452e-9c08-1220bc6af82a
### Requirements
- fzf, fnf, or fzy (Other fuzzy finders will probably work but are untested)
`jn` will work without one but be limited.
### Installation
Download Linux and Mac builds of `jn` from the [releases page](https://github.com/joereynolds/jn/releases).
Also available on AUR as `jn-bin`
```
yay -S jn-bin
```
### Quick start
- `jn "my note title"` creates a note called `2026-01-01-my-note-title.md` and opens it in your `$EDITOR`.
- `jn` on its own will show all your "books" (directories)
- `jn todo` to complete and filter your tasks
- And so much more!
#### Command overview
Detailed info for each command is below this table.
| Command | Description | Flags |
|----------------------|------------------------------------|---------------------------------------------------------------|
| `jn` | List all books | |
| `jn
` | Create a note | |
| `jn @` | Create a note in a specific book | |
| `jn @` | List notes in a book | |
| `jn @starred` | List bookmarked notes | |
| `jn cat` | Display a note | |
| `jn edit` | Edit a note | |
| `jn ls` | List all notes | `--recent [n]` Display the N most recently edited notes
`--before` Show notes before this date (yyyy-MM-dd format)
`--after` Show notes after this date (yyyy-MM-dd format)
`--no-print-date` Hides the date display |
| `jn grep ` | Search notes by content | |
| `jn tag ` | Search notes by tag | |
| `jn mv` | Rename a note | `--plain` Whether to append dates and extension during rename |
| `jn rm` | Delete a note | |
| `jn star` | Bookmark a note | |
| `jn share` | Upload a note and get a permalink | |
| `jn todo` | Show and complete incomplete tasks | `--add [task]` Create a task
`--filter` Filter on cancelled,completed,wip, and todo states |
| `jn template` | Edit a template | |
| `jn config` | Edit the config file | |
| `jn help` | Show help | |
| `jn -h` | Get help for an individual command | |
### Config
All of `jn`s config lives in a single config.ini file.
The config file lives inside `$XDG_CONFIG_HOME/jn/config.ini`.
Usually this is `~/.config/jn/config.ini`.
You can quickly edit the config file with
```
jn conf
```
(`jn config` also works)
Complete configuration:
```
; The location that jn stores and retrieves notes from
; By default this is XDG_DOCUMENTS_DIR/jn/
; e.g. ~/.config/jn/config.ini
;
; notes_location ="~/Documents/jn/"
; The location that jn retrieves templates from
; By default this is XDG_DATA_HOME/jn/
; e.g. ~/.local/share/jn
;
; templates_location ="~/.local/share/jn"
; The prefix of the note. I.e. what to prepend the title with.
; Meaning that if you create a note called "daily journal",
; it will be saved as 2026-01-01-daily-journal.md
;
; The prefix can be any of the format patterns specified in
; https://nim-lang.org/docs/times.html
; The default if not supplied is "YYYY-MM-dd"
;
; notes_prefix="YYYY-MM-dd"
; The suffix for the note, this is just the extension.
; The default if not supplied is ".md" i.e. Markdown
;
; notes_suffix=".md"
; The fuzzy provider to use with jn. The default if not supplied is fzf.
; Valid values are "fzf" or "fzy" (others may work coincidentally)
;
; fuzzy_provider="fzy"
;
;[template.example-1]
;title_contains="gym,lift,gains"
;use_template="measurements.md"
;
;[template.example-2]
;title_contains="chocolate"
;use_template="recipe.md"
;
; [category.gym]
; title_contains="gym"
; move_to="health"
```
## Commands
### List all books
```
jn
```
### List all notes for a book
```
jn @
```
### Display a note
```
jn cat
```
This will open a fuzzy finder for your notes, select the one you want and it
will be output
### Edit a note
```
jn edit
```
This will open a fuzzy finder for your notes, select the one you want and it
will be opened in `$EDITOR`.
`jn e` also works. Most things have shorthand, see `jn -h` for the full list.
### Search your notes
```
jn grep
```
This will open up a fuzzy finder of all notes with `search-term` present.
Select one and it will open up in `$EDITOR`.
`jn / ` also works if you're used to Vim.
### Delete a note
```
jn rm
```
This will open a fuzzy finder for your notes. Select the note you want and it
will be deleted.
Once the file has been "deleted", a file containing the deleted file's content
is written to "/tmp/" (or the equivalent on Mac/Windows) so you can restore it
in the event of a mistake.
### Create a note
The complete syntax for writing a note is as follows:
```
jn @
```
The first argument is mandatory, the rest is optional.
Writing a note is as simple as:
```
jn "my note goes here"
```
This will drop you into your `$EDITOR` for you to write content. It will then
write out to your configured place (`XDG_DOCUMENTS_DIR` by default).
By default, it will save the note with a date prefix, your specified title, and
a markdown extension.
i.e.
```
jn "writing with vim"
```
Will save as
```
2025-12-05-writing-with-vim.md
```
The date and markdown extension are configurable options and can be changed if
desired.
See `note_prefix` and `note_suffix` in the config above.
Once a note is created, its location is echoed to the terminal:
```
> jn "Do the thing"
> ...
> Created ~/Documents/notes/2025-12-05-do-the-thing.md
```
### Bookmark a note
```
jn star
```
This will open a fuzzy finder for your notes. Select the note you want and it
will be bookmarked.
When a file has been bookmarked, it will appear in the special `@starred` book.
To view your bookmarks, use the `@starred` book like any other:
```
jn @starred
```
Internally, bookmarks are managed with symlinks. The original note remains in
its current location and a symlink is created in the "starred" directory to
that note.
### Rename a note
```
jn mv
```
This will open a fuzzy finder for your notes. Select the note you want and it
will prompt you for the new name.
You only need to supply the title of the note, the prefix and extension are
provided for you.
i.e. If you rename a note from `2026-01-01-important.md` to `urgent` it will be
saved as `2026-01-01-urgent.md`.
You can also pass the `--plain` flag to `jn mv` and it will do no clever
prefix/extension magic and instead, just rename the file to what you want
whilst still preserving the directory it's in.
The complete command is:
```
jn mv --plain
```
### List your notes
```
jn ls
```
This is purely for convenience. You could definitely just do `ls
~/wherever-your-notes-live` but who has that kind of brainpower?
Doing `jn ls` will list all the notes in your configured location.
You can also filter by `--recent` to get your most recently edited notes.
Handy for when you forgot what you were working on.
```
jn ls --recent 6 # return the 6 most recently edited notes
```
### Share a note
```
jn share
```
Select a note and it will be uploaded to an online service which will give you
a permalink in return.
### Creating a book
A book is optional. Conceptually it's where you store related notes. You might
have a "vim" book containing tips about vim. A "docker" book containing tips
about Docker, you get the idea.
If you don't use books, it all just goes into the root directory defined in
your config.
Books are created automatically when you make notes.
It is the last argument in the chain and begins with a "@"
E.g.:
```
jn "quitting-vim" @vim
Saved in ~/Documents/notes/vim/2025-12-07-quitting-vim.md
```
## Other Features
### Todos
`jn todo` is able to manage tasks with markdown checkbox syntax.
When invoked, it will bring up a fuzzy finder containing all of your incomplete
tasks. When an item is selected, it will mark that item/task as completed along
with today's date next to the item.
For example:
```
> jn todo
user selects and confirms their todo item
> Marked 'drink protein shake' as complete (/home/joe/Documents/jn/notes/Home.md).
```
An incomplete task has the following formatting:
```
- [ ] This is an incomplete task seen in extended Markdown examples
```
A complete task has the following formatting:
```
- [x] This is a complete task seen in extended Markdown examples
```
You can add todos with the `--add` or `-a` flag.
```
jn todo --add "Do the dishes"
```
Will add a markdown task in your `notes_location` / todo.md
#### Filtering todos
If you want to see all your done tasks (or other states), you can do with the `--filter` flag.
There are 4 states that a task can be in demonstrated below:
```
- [ ] This task's state is "todo"
- [x] This task's state is "done"
- [/] This task's state is "wip"
- [-] This task's state is "cancelled"
```
This closely mirrors how many obsidian plugins treat markdown tasks, for consistency.
To filter, you do:
```
jn todo --filter
```
e.g.
```
jn todo --filter cancelled
```
Shorthand works too, here's the exact same command:
```
jn t -f ca
```
### Tags
As you'd expect, you can search for tags via `jn`. All tags are assumed to
begin with "#".
As an example, any of the below will search for the "#vim" tag.
```
jn tag vim
jn tag "#vim"
jn tags vim
jn tags "#vim
```
Once ran, this will open up a fuzzy finder containing all notes with those
tags.
As you can see, you don't need to specify the `#` prefix in your search. Just
the word will do.
### Templates
You can tell `jn` to use a template based on a note's title.
For example, let's say that after every time you go to the gym, you want to
note down your measurements. It would be tedious to write it all out, or
manually copy and tweak a few values from an old one.
Instead, create a template, and store it in `XDG_DATA_HOME/jn` (usually this
is`~/.local/share/jn`).
Once you've done that, add this into your config:
```
[template.my-template]
title_contains = "exercise,lift,bro,gains"
use_template = "gym-measurements.md"
```
Now everytime you create a title with "exercise" or any of the other words in
that list _somewhere_ in the title, it will populate the note with the content
of `XDG_DATA_HOME/jn/gym-measurements.md`.
#### Template variables
##### Predefined variables
You can use predefined template variables in your templates.
For example, a template consiting of
```
Today is {{ today }}
```
Would be rendered as:
```
Today is 2026-01-20
```
A complete overview of the template variables is below:
| Variable | Action |
| ------------| ----------------------------------------------|
| today | Renders today's date in YYYY-MM-dd format |
| note | Renders the complete filename of the note |
Note that template variables are very fresh, so there aren't many...
If you have any suggestions on useful ones, raise an issue.
##### Shell variables
Another more powerful (and dangerous/fun) type of template variable is the
shell variable.
This allows you to shell out and fill the template with results of the shell
command.
Shell template variables start with `{%` and end with `%}`.
For example we can do:
```
The year is {% date +%Y %}.
Hello {% echo 'Joe' %} And hello {% echo 'Jim' %}.
Here is a list of my files {% ls %}.
I hope you like them {% echo 'Joe' %}.
Written on {{ today }}.
```
The onus is on you to write the command correctly. It not working is undefined behaviour.
#### Editing a template
```
jn template
```
This will open a fuzzy finder of all your templates. Select the template and it
will open up in `$EDITOR`.
### Categories
Categories allow you to automatically move a note to a book based on the name
of the note.
For example, let's say you have a book called @recipes that stores all your...
recipes. You want to have any new note that contains the word "chocolate" or
"snack to immediately be moved to recipes.
You can do so with the following:
```
[category.my-category]
title_contains = "chocolate,snack"
move_to = "recipes"
```
Now, on save of your note, it gets saved into the @recipes book.
This saves you having to manually move files around or add the note to the
correct book in the first place
## Config file locations
Config - `XDG_CONFIG_HOME/jn/` (usually this is `~/.config/jn`)
Documents - `XDG_DOCUMENTS_DIR/jn/` (usually this is `~/Documents/`) (defaults to `~/Documents/`) can be overridden with `notes_location` config key
Templates - `XDG_DATA_HOME/jn/` (usually this is `~/.local/share/jn/`)
## Roadmap
- [x] - cat subcommand
- [x] - config subcommand
- [x] - edit subcommand
- [x] - grep subcommand
- [x] - rm subcommand
- [x] - Ability to star notes
- [x] - Template support
- [x] - Categories
- [ ] - Shell completion
- [ ] - Man page
## Developers
To compile and run `jn`:
```
nimble build && jn
```
To run tests:
```
nimble test
```