# Technical Documentation: jrnl-org/jrnl

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/jrnl-org/jrnl)

### Overview (`README.md`)

<p align="center">
<a href="https://jrnl.sh">
<img align="center" src="https://raw.githubusercontent.com/jrnl-org/jrnl/main/docs_theme/assets/readme-header.png"/>
</a>
</p>

jrnl
 [](https://github.com/jrnl-org/jrnl/actions?query=workflow%3ATesting)
 [](https://pepy.tech/project/jrnl)
 [](https://pypi.python.org/pypi/jrnl/)
 [](https://formulae.brew.sh/formula/jrnl)
 [](https://gitter.im/jrnl-org/jrnl)
 [](https://github.com/jrnl-org/jrnl/blob/main/CHANGELOG.md)
====

_To get help, [submit an issue](https://github.com/jrnl-org/jrnl/issues/new/choose) on
GitHub._

`jrnl` is a simple journal application for the command line.

You can use it to easily create, search, and view journal entries. Journals are
stored as human-readable plain text, and can also be encrypted using  [AES
encryption](http://en.wikipedia.org/wiki/Advanced_Encryption_Standard).

## In a Nutshell

To make a new entry, just enter

``` sh
jrnl yesterday: Called in sick. Used the time to clean the house and write my
book.
```

`yesterday:` is  interpreted by `jrnl` as a timestamp. Everything until the
first sentence ending (either `.`, `?`, or `!`) is interpreted as the title, and
the rest as the body. In your journal file, the result will look like this:

    [2012-03-29 09:00] Called in sick.
    Used the time to clean the house and write my book.

If you just call `jrnl`, you will be prompted to compose your entry - but you
can also configure _jrnl_ to use your external editor.

For more information, please read the
[documentation](https://jrnl.sh).

## Contributors

### Maintainers

Our maintainers help keep the lights on for the project:

 * Jonathan Wren ([wren](https://github.com/wren))
 * Micah Ellison ([micahellison](https://github.com/micahellison))
 * Aaron Lichtman ([alichtman](https://github.com/alichtman))

Please thank them if you like `jrnl`!

### Code Contributors

This project is made with love by the many fabulous people who have contributed.
`jrnl` couldn't exist without each and every one of you!

<a href="https://github.com/jrnl-org/jrnl/graphs/contributors"><img
src="https://opencollective.com/jrnl/contributors.svg?width=890&button=false"
/></a>

If you'd also like to help make `jrnl` better, please see our [contributing
documentation](docs/contributing.md).

### Financial Backers

Another way show support is through direct financial contributions. These funds
go to covering our costs, and are a quick way to show your appreciation for
`jrnl`.

[Become a financial contributor](https://opencollective.com/jrnl/contribute)
and help us sustain our community.

<a href="https://opencollective.com/jrnl"><img
src="https://opencollective.com/jrnl/individuals.svg?width=890"></a>

---

### Overview (`docs/overview.md`)

# Overview

`jrnl` is a simple journal application for the command line.

You can use it to easily create, search, and view journal entries. Journals are
stored as human-readable plain text, and can also be encrypted using [AES
encryption](http://en.wikipedia.org/wiki/Advanced_Encryption_Standard).

`jrnl` has most of the features you need, and few of the ones you don't.

## Plain Text

`jrnl` stores each journal in plain text. You can store `jrnl` files anywhere,
including in shared folders to keep them synchronized between devices. Journal
files are compact (thousands of entries take up less than 1 MiB) and can be read
by almost any electronic device, now and for the foreseeable future.

## Tags

To make it easier to find entries later, `jrnl` includes support for inline tags
(the default tag symbol is `@`). You can find and filter entries by using tags
along with other search criteria.

## Support for Multiple Journals
  
`jrnl` includes support for the creation of multiple journals, each of which
can be stored as a single file or as a set of files. Entries are automatically
timestamped in a human-readable format that makes it easy to view multiple
entries at a time. `jrnl` can easily find the entries you want so that you can
read them or edit them.

## Support for External Editors

`jrnl` plays nicely with your favorite text editor. You may prefer to write
journal entries in an editor. Or you may want to make changes that require a
more comprehensive application. `jrnl` can filter specific entries and pass them
to the [external editor](./external-editors.md) of your choice.

## Encryption
  
`jrnl` includes support for [AES
encryption](http://en.wikipedia.org/wiki/Advanced_Encryption_Standard). See the
[encryption page](./encryption.md) for more information.

## Import and Export

`jrnl` makes it easy to import entries from other sources. Existing entries can
be exported in a variety of [formats](./formats.md).

## Multi-Platform Support

`jrnl` is compatible with most operating systems. You can [download](./installation.md) it using one
of a variety of package managers, or you can build from source.

## Open-Source

`jrnl` is written in [Python](https://www.python.org) and maintained by a
[friendly community](https://github.com/jrnl-org/jrnl) of open-source software
enthusiasts.

---

### Advanced (`docs/advanced.md`)

# Advanced Usage

## Configuration File

`jrnl` has a wide variety of options that can be customized through the config file,
including templates, formats, multiple journals, and more. See
the [configuration file reference](./reference-config-file.md) for details
or read on for some common use cases.

### Multiple journal files

You can configure `jrnl`to use with multiple journals (eg.
`private` and `work`) by defining more journals in your [config file](./reference-config-file.md),
for example:

``` yaml
journals:
  default: ~/journal.txt
  work: ~/work.txt
```

The `default` journal gets created the first time you start `jrnl`
Now you can access the `work` journal by using `jrnl work` instead of
`jrnl`, eg.

``` sh
jrnl work at 10am: Meeting with @Steve
jrnl work -n 3
```

will both use `~/work.txt`, while `jrnl -n 3` will display the last
three entries from `~/journal.txt` (and so does `jrnl default -n 3`).

You can also override the default options for each individual journal.
If your `jrnl.yaml` looks like this:

``` yaml
encrypt: false
journals:
  default: ~/journal.txt
  work:
    journal: ~/work.txt
    encrypt: true
  food: ~/my_recipes.txt
```

Your `default` and your `food` journals won't be encrypted, however your
`work` journal will!

You can override all options that are present at
the top level of `jrnl.yaml`, just make sure that at the very least
you specify a `journal: ...` key that points to the journal file of
that journal.

Consider the following example configuration

``` yaml
editor: vi -c startinsert 
journals: 
  default: ~/journal.txt 
  work: 
    journal: ~/work.txt 
    encrypt: true 
    display_format: json 
    editor: code -rw 
  food:
    display_format: markdown 
    journal: ~/recipes.txt 
```

The `work` journal is encrypted, prints to `json` by default, and is edited using an existing window of VSCode. Similarly, the `food` journal prints to markdown by default, but uses all the other defaults.

### Modifying Configurations from the Command line 

You can override a configuration field for the current instance of `jrnl` using `--config-override CONFIG_KEY CONFIG_VALUE` where `CONFIG_KEY` is a valid configuration field, specified in dot notation and `CONFIG_VALUE` is the (valid) desired override value. The dot notation can be used to change config keys within other keys, such as `colors.title` for the `title` key within the `colors` key.

You can specify multiple overrides as multiple calls to `--config-override`.

!!! note
    These overrides allow you to modify ***any*** field of your jrnl configuration. We trust that you know what you are doing. 

#### Examples: 

``` sh
# Create an entry using the `stdin` prompt, for rapid logging
jrnl --config-override editor ""

# Populate a project's log
jrnl --config-override journals.todo "$(git rev-parse --show-toplevel)/todo.txt" todo find my towel 

# Pass multiple overrides 
jrnl --config-override display_format fancy --config-override linewrap 20 \
--config-override colors.title green
```

### Using an alternate config

You can specify an alternate configuration file for the current instance of `jrnl` using `--config-file CONFIG_FILE_PATH` where
`CONFIG_FILE_PATH` is a path to an alternate `jrnl` configuration file. 

#### Examples:

``` sh
# Use personalised configuration file for personal journal entries
jrnl --config-file ~/foo/jrnl/personal-config.yaml

# Use alternate configuration file for work-related entries
jrnl --config-file ~/foo/jrnl/work-config.yaml

# Use default configuration file (created on first run)
jrnl
```

---

### Contributing (`docs/contributing.md`)

# Contributing to jrnl

We welcome contributions to jrnl, whether it's through reporting bugs, improving the documentation, testing releases, engaging in discussion on features and bugs, or writing code.

## Table of Contents
 * [Code of Conduct](#code-of-conduct)
 * [Reporting Bugs](#reporting-bugs)
 * [Editing Documentation](#editing-documentation)
 * [Testing](#testing)
 * [Submitting feature requests and ideas](#submitting-feature-requests-and-ideas)
 * [Developing jrnl](#developing)

## Code of Conduct

Before starting, please read the [Code of Conduct](https://github.com/jrnl-org/jrnl/blob/main/CODE_OF_CONDUCT.md).

## Reporting Bugs

Please report bugs by [opening a new issue](https://github.com/jrnl-org/jrnl/issues/new/choose) and describing it as well as possible. Many bugs are specific to a particular operating system and Python version, so please include that information!

## Editing Documentation

If you find a typo or a mistake in the docs, please fix it right away and send a pull request. If you're unsure what to change but still see a problem, you can [open a new issue](https://github.com/jrnl-org/jrnl/issues/new/choose) with the "Documentation change" type.

To edit the documentation, edit the `docs/*.md` files on the **main** branch. You can see the result by running `poe docs-run` inside the project's root directory, then navigating your browser to [localhost:8000](http://localhost:8000).

### External editors and tips and tricks

If you'd like to share a jrnl command line trick that you find useful, you may find it worthwhile to add it to the ["Tips and Tricks" section](tips-and-tricks.md). For advice on how to integrate a particular external editor, you can add to the ["External Editors" section](external-editors.md).

## Testing

Much of the work of maintaining jrnl involves testing rather than coding.

The nature of jrnl means we deal with extremely sensitive data, and can't risk data loss. While jrnl does have a comprehensive automated testing suite, user testing is crucial to mitigating this risk.

### Prereleases

[Prereleases are deployed through PyPi much like normal releases](https://pypi.org/project/jrnl/#history). You can use [pipx](https://pypi.org/project/pipx/) to fetch them and test them. See the [changelog](https://github.com/jrnl-org/jrnl/blob/main/CHANGELOG.md) for information on what has changed with each release.

### Pull requests

If you are comfortable enough with git, feel free to fetch particular [pull requests](https://github.com/jrnl-org/jrnl/pulls), test them yourself, and report back your findings. Bonus points if you can add a screencast of how the new feature works.

### Confirm bug reports

There are always [open bugs among our GitHub issues](https://github.com/jrnl-org/jrnl/issues?q=is%3Aissue+is%3Aopen+label%3Abug) and many are specific to a particular OS, Python version, or jrnl version. A simple comment like "Confirmed on jrnl v2.2, MacOS 10.15, Python 3.8.1" would be extremely helpful in tracking down bugs.

### Automate tests

See the develop section below for information on how to contribute new automated tests.

## Submitting feature requests and ideas

If you have a feature request or idea for jrnl, please [open a new issue](https://github.com/jrnl-org/jrnl/issues/new/choose) and describe the goal of the feature, and any relevant use cases. We'll discuss the issue with you, and decide if it's a good fit for the project.

When discussing new features, please keep in mind our design goals. jrnl strives to
[do one thing well](https://en.wikipedia.org/wiki/Unix_philosophy). To us, that means:

* being _nimble_
* having a simple interface
* avoiding duplicating functionality

## Developing

### Getting your environment set up

You will need to install [poetry](https://python-poetry.org/) to develop jrnl. It will take care of all of the project's other dependencies.

### Understanding the branches

jrnl uses two primary branches:

 * `main` - for ongoing development
 * `release` - for releases

In general, pull requests should be made on the `main` branch.

#### Updating an existing clone after the `develop` → `main` rename

If you have a clone from before the default branch was renamed from `develop` to `main`, update it with:

```bash
git checkout develop
git branch -m develop main
git fetch origin
git remote prune origin
git branch -u origin/main main
git remote set-head origin -a
```

If you have other local branches based on `develop`, rebase them onto `main`:

```bash
git rebase --onto main develop <your-branch>
```

### Common development commands

You can find an inventory of commands in the `pyproject.toml`. Users can run the commands by typing `poe` followed by the name of the command ([Poe the Poet](https://github.com/nat-n/poethepoet) can be installed on its own, or as part of `poetry install`).

A typical development workflow includes:

 * Installing dependencies:
    * `poetry install`
 * Activate virtual environment:
    * `poetry shell`
 * Running the source in a virtual environment:
    * `jrnl` (with or without arguments as necessary)
 * Running tests:
     * `poe test`
 * Formatting the code to standardize its style:
     * `poe format`

### Updating automated tests

When resolving bugs or adding new functionality, please add tests to prevent that functionality from breaking in the future. If you notice any functionality that isn't covered in the tests, feel free to submit a test-only pull request as well.

For testing, jrnl uses [pytest](https://docs.pytest.org) for unit tests, and [pytest-bdd](https://pytest-bdd.readthedocs.io/) for integration testing. All tests are in the `tests` folder.

Many tests can be created by only editing `*.feature` files with the same format as other tests. For more complicated functionality, you may need to implement steps in `tests/lib/` which are then executed by your tests in the `feature` files.

### Submitting pull requests

When you're ready, feel free to submit a pull request (PR). The jrnl maintainers generally review the pull requests every two weeks, but the continuous integration pipeline will run on automated tests on it within a matter of minutes and will report back any issues it has found with your code across a variety of environments.

The pull request template contains a checklist full of housekeeping items. Please fill them out as necessary when you submit.

If a pull request contains failing tests, it probably will not be reviewed, and it definitely will not be approved. However, if you need help resolving a failing test, please mention that in your PR.

### Finding things to work on

You can search the [jrnl GitHub issues](https://github.com/jrnl-org/jrnl/issues) by [label](https://github.com/jrnl-org/jrnl/labels) for things to work on. Here are some labels worth searching:

* [critical](https://github.com/jrnl-org/jrnl/labels/critical)
* [help wanted](https://github.com/jrnl-org/jrnl/labels/help%20wanted)
* [bug](https://github.com/jrnl-org/jrnl/labels/bug)
* [enhancement](https://github.com/jrnl-org/jrnl/labels/enhancement)

You can also get a feel for the project's priorities by reviewing the [milestones](https://github.com/jrnl-org/jrnl/milestones).

### A note for new programmers and programmers new to python

Although jrnl has grown quite a bit since its inception, the overall complexity (for an end-user program) is fairly low, and we hope you'll find the code easy enough to understand.

If you have a question, please don't hesitate to ask! Python is known for its welcoming community and openness to novice programmers, so feel free to fork the code and play around with it! If you create something you want to share with us, please create a pull request. We never expect pull requests to be perfect, idiomatic, instantly mergeable code. We can work through it together!

---

### Encryption (`docs/encryption.md`)

# Encryption

## A Note on Security

While `jrnl` follows best practices, total security is never possible in the
real world. There are a number of ways that people can at least partially
compromise your `jrnl` data. See the [Privacy and Security](./privacy-and-security.md) page
for more information.

There is one relevant security advisory for encryption-related security issues: [GHSA-rhx6-37mm-5q9r](https://github.com/jrnl-org/jrnl/security/advisories/GHSA-rhx6-37mm-5q9r).

## Encryption Behavior Overview

- Encrypted journals are now written in the jrnl v3 format.
- jrnl v1 and v2 encrypted files are read-only formats. They can still be opened and decrypted, but new encrypted writes are always v3.

## jrnl v3 Encrypted File Format

jrnl v3 uses a random 16-byte salt per encrypted write, stored in a JSON
header after a magic prefix. This avoids the static-salt weakness from v2.

File layout:

| Field | Size | Description |
| --- | --- | --- |
| `JRNLv3` | 6 bytes | Magic prefix |
| `header_len` | 2 bytes (uint16 BE) | Length of the header field, max 64KB |
| header | `header_len` bytes | Base64-encoded JSON, includes `salt` (base64url-encoded 16-byte salt) |
| Fernet token | Remaining bytes | Ciphertext |

Additional header fields may be added in future without changing the format version.

!!! note
    Journals encrypted with v3 before this format was base64-encoded store
    raw JSON in the header field instead. These are still read correctly;
    the base64-encoded format is written on the next save.

## Encrypting and Decrypting from the CLI

To encrypt a journal, run:

``` sh
jrnl --encrypt [FILENAME]
```

You can then enter a new password, and the unencrypted file will replaced with
the new encrypted file.

This command also works to change the password for a journal file that is
already encrypted. `jrnl` will prompt you for the current password and then new
password.

Conversely, run this to decrypt a journal:

``` sh
jrnl --decrypt [FILENAME]
```

replaces the encrypted journal file with a plain text file. You can also specify
a filename, e.g., `jrnl --decrypt plain_text_copy.txt`, to leave the original
encrypted file untouched and create a new plain text file next to it.

!!! note
    Changing `encrypt` in your [config file](./reference-config-file.md) to
    a different value will not encrypt or decrypt your
    journal file. It merely says whether or not your journal
    is encrypted. Hence manually changing
    this option will most likely result in your journal file being
    impossible to load. This is why the above commands are necessary.

## Storing Passwords in Your Keychain

Nobody can recover or reset your `jrnl` password. If you lose it,
your data will be inaccessible forever.

For this reason, when encrypting a journal, `jrnl` asks whether you would like
to store the password in your system's keychain. An added benefit is that you
will not need to enter the password when interacting with the journal file.

If you don't initially store the password in your keychain but decide to do so
later---or if you want to store it in one computer's keychain but not in another
computer's---you can run `jrnl --encrypt` on an encrypted journal and use the
same password again. This will trigger the keychain storage prompt.

## Manual Decryption

The easiest way to decrypt your journal is with `jrnl --decrypt`, but you could
also decrypt your journal manually if needed. To do this, you can use any
program that supports the AES algorithm (specifically AES-CBC), and you'll need
the following relevant information for decryption:

- **Key:** The key used for encryption is the
    [SHA-256](https://en.wikipedia.org/wiki/SHA-2) hash of your password.
- **Initialization vector (IV):** The IV is stored in the first 16 bytes of
    your encrypted journal file.
- **The actual text of the journal** (everything after the first 16 bytes in
    the encrypted journal file) is encoded in
    [UTF-8](https://en.wikipedia.org/wiki/UTF-8) and padded according to
    [PKCS\#7](https://en.wikipedia.org/wiki/PKCS_7) before being encrypted.

If you'd like an example of what this might look like in script form, please
see below for some examples of Python scripts that you could use to manually
decrypt your journal.



!!! note
    These are only examples, and are only here to illustrate that your journal files
    will still be recoverable even if `jrnl` isn't around anymore. Please use
    `jrnl --decrypt` if available.

**Example for jrnl v2 files**:
``` python
#!/usr/bin/env python3
"""
Decrypt a jrnl v2 encrypted journal.

Note: the `cryptography` module must be installed (you can do this with
something like `pip3 install crytography`)
"""

import base64
import getpass
from pathlib import Path

from cryptography.fernet import Fernet
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC

filepath = input("journal file path: ")
password = getpass.getpass("Password: ")

with open(Path(filepath), "rb") as f:
    ciphertext = f.read()

password = password.encode("utf-8")
kdf = PBKDF2HMAC(
    algorithm=hashes.SHA256(),
    length=32,
    salt=b"\xf2\xd5q\x0e\xc1\x8d.\xde\xdc\x8e6t\x89\x04\xce\xf8",
    iterations=100_000,
    backend=default_backend(),
)

key = base64.urlsafe_b64encode(kdf.derive(password))

print(Fernet(key).decrypt(ciphertext).decode("utf-8"))
```

**Example for jrnl v1 files**:
``` python
#!/usr/bin/env python3
"""
Decrypt a jrnl v1 encrypted journal.

Note: the `pycrypto` module must be installed (you can do this with something
like `pip3 install pycrypto`)
"""

import argparse
import getpass
import hashlib

from Crypto.Cipher import AES

parser = argparse.ArgumentParser()
parser.add_argument("filepath", help="journal file to decrypt")
args = parser.parse_args()

pwd = getpass.getpass()
key = hashlib.sha256(pwd.encode("utf-8")).digest()

with open(args.filepath, "rb") as f:
    ciphertext = f.read()

crypto = AES.new(key, AES.MODE_CBC, ciphertext[:16])
plain = crypto.decrypt(ciphertext[16:])
plain = plain.strip(plain[-1:])
plain = plain.decode("utf-8")
print(plain)
```

---

### External Editors (`docs/external-editors.md`)

# External editors

Configure your preferred external editor by updating the `editor` option
in your [configuration file](./reference-config-file.md#editor). If your editor is not 
in your operating system's `PATH` environment variable, then you will have to 
enter the full path of your editor.

Once it's configured, you can create an entry as a new document in your editor using the `jrnl` 
command by itself:

``` text
jrnl
```

You can specify the time and title of the entry as usual on the first line of the document. 

If you want, you can skip the editor by including a quick entry with the `jrnl` command:

``` text
jrnl yesterday: All my troubles seemed so far away.
```

If you want to start the entry on the command line and continue writing in your chosen editor, 
use the `--edit` flag. For example:

``` text
jrnl yesterday: All my troubles seemed so far away. --edit
```

!!! note
    To save and log any entry edits, save and close the file.

All editors must be [blocking processes](https://en.wikipedia.org/wiki/Blocking_(computing)) to work with jrnl. Some editors, such as [micro](https://micro-editor.github.io/), are blocking by default, though others can be made to block with additional arguments, such as many of those documented below. If jrnl opens your editor but finishes running immediately, then your editor is not a blocking process, and you may be able to correct that with one of the suggestions below.

Please see [this section](./privacy-and-security.md#editor-history) about how
your editor might leak sensitive information and how to mitigate that risk.

## Sublime Text

To use [Sublime Text](https://www.sublimetext.com/), install the command line
tools for Sublime Text and configure your `jrnl.yaml` like this:

```yaml
editor: "subl -w"
```

Note the `-w` flag to make sure `jrnl` waits for Sublime Text to close the
file before writing into the journal.

## Visual Studio Code

[Visual Studio Code](https://code.visualstudio.com) also requires a flag
that tells the process to wait until the file is closed before exiting:

```yaml
editor: "code --wait"
```

On Windows, `code` is not added to the path by default, so you'll need to
enter the full path to your `code.exe` file, or add it to the `PATH` variable.

## MacVim

Also similar to Sublime Text, MacVim must be started with a flag that tells
the the process to wait until the file is closed before passing control
back to journal. In the case of MacVim, this is `-f`:

```yaml
editor: "mvim -f"
```

## Vim/Neovim

To use any of the Vim derivatives as editor in Linux, simply set the `editor`
to the executable:

```yaml
editor: "vim"
# or
editor: "nvim"
```

## iA Writer

On OS X, you can use the fabulous [iA
Writer](http://www.iawriter.com/mac) to write entries. Configure your
`jrnl.yaml` like this:

```yaml
editor: "open -b pro.writer.mac -Wn"
```

What does this do? `open -b ...` opens a file using the application
identified by the bundle identifier (a unique string for every app out
there). `-Wn` tells the application to wait until it's closed before
passing back control, and to use a new instance of the application.

If the `pro.writer.mac` bundle identifier is not found on your system,
you can find the right string to use by inspecting iA Writer's
`Info.plist` file in your shell:

```sh
grep -A 1 CFBundleIdentifier /Applications/iA\ Writer.app/Contents/Info.plist
```

## Notepad++ on Windows

To set [Notepad++](http://notepad-plus-plus.org/) as your editor, edit
the `jrnl` config file (`jrnl.yaml`) like this:

```yaml
editor: "C:\\Program Files (x86)\\Notepad++\\notepad++.exe -multiInst -nosession"
```

The double backslashes are needed so `jrnl` can read the file path
correctly. The `-multiInst -nosession` options will cause `jrnl` to open
its own Notepad++ window.


## emacs

To use `emacs` as your editor, edit the `jrnl` config file (`jrnl.yaml`) like this:

```yaml
editor: emacsclient -a "" -c
```

When you're done editing the message, save and `C-x #` to close the buffer and stop the emacsclient process.

## gedit

To use [gedit](https://gedit-text-editor.org/) as your editor, edit the `jrnl` config
file (`jrnl.yaml`) like this:

```yaml
editor: "gedit -w"
```

The `-w` (`--wait`) flag tells `gedit` to wait until the file is closed before
passing control back to `jrnl`.

## Other editors

If you're using another editor and would like to share, feel free to [contribute documentation](./contributing.md#editing-documentation) on it.

---

### Formats (`docs/formats.md`)

# Formats

`jrnl` supports a variety of alternate formats. These can be used to display your
journal in a different manner than the `jrnl` default, and can even be used to pipe data
from your journal for use in another program to create reports, or do whatever you want
with your `jrnl` data.

Any of these formats can be used with a search (e.g. `jrnl -contains "lorem ipsum"
--format json`) to display the results of that search in the given format, or can be
used alone (e.g. `jrnl --format json`) to display all entries from the selected journal.

This page shows examples of all the built-in formats, but since `jrnl` supports adding
more formats through plugins, you may have more available on your system. Please see
`jrnl --help` for a list of which formats are available on your system.

Any of these formats can be used interchangeably, and are only grouped into "display",
"data", and "report" formats below for convenience.

## Display Formats
These formats are mainly intended for displaying your journal in the terminal. Even so,
they can still be used in the same way as any other format (like written to a file, if
you choose).

### Pretty
``` sh
jrnl --format pretty
# or
jrnl -1 # any search
```

This is the default format in `jrnl`. If no `--format` is given, `pretty` will be used.

It displays the timestamp of each entry formatted to by the user config followed by the
title on the same line. Then the body of the entry is shown below.

This format is configurable through these values from your config file (see
[Advanced Usage](./advanced.md) for more details):

- `colors`
    - `body`
    - `date`
    - `tags`
    - `title`
- `indent_character`
- `linewrap`
- `timeformat`

**Example output**:
``` sh
2020-06-28 18:22 This is the first sample entry
| This is the sample body text of the first sample entry.

2020-07-01 20:00 This is the second sample entry
| This is the sample body text of the second sample entry, but
| this one has a @tag.

2020-07-02 09:00 This is the third sample entry
| This is the sample body text of the third sample entry.
```

### Short

``` sh
jrnl --format short
# or
jrnl --short
```

This will shorten entries to display only the date and title. It is essentially the
`pretty` format but without the body of each entry. This can be useful if you have long
journal entries and only want to see a list of entries that match your search.

**Example output**:
``` sh
2020-06-28 18:22 This is the first sample entry
2020-07-01 20:00 This is the second sample entry
2020-07-02 09:00 This is the third sample entry
```

### Fancy (or Boxed)
``` sh
jrnl --format fancy
# or
jrnl --format boxed
```

This format outlines each entry with a border. This makes it much easier to tell where
each entry starts and ends. It's an example of how free-form the formats can be, and also
just looks kinda ~*~fancy~*~, if you're into that kind of thing.

**Example output**:
``` sh
┎──────────────────────────────────────────────────────────────────────╮2020-06-28 18:22
┃ This is the first sample entry                                       ╘═══════════════╕
┠╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
┃ This is the sample body text of the first sample entry.                              │
┖──────────────────────────────────────────────────────────────────────────────────────┘
┎──────────────────────────────────────────────────────────────────────╮2020-07-01 20:00
┃ This is the second sample entry                                      ╘═══════════════╕
┠╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
┃ This is the sample body text of the second sample entry, but this one has a @tag.    │
┖──────────────────────────────────────────────────────────────────────────────────────┘
┎──────────────────────────────────────────────────────────────────────╮2020-07-02 09:00
┃ This is the third sample entry                                       ╘═══════════════╕
┠╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
┃ This is the sample body text of the third sample entry.                              │
┖──────────────────────────────────────────────────────────────────────────────────────┘
```

## Data Formats
These formats are mainly intended for piping or exporting your journal to other
programs. Even so, they can still be used in the same way as any other format (like
written to a file, or displayed in your terminal, if you want).

!!! note
You may see boxed messages like "2 entries found" when using these formats, but
those messages are written to `stderr` instead of `stdout`, and won't be piped when
using the `|` operator.

### JSON

``` sh
jrnl --format json
```

JSON is a very handy format used by many programs and has support in nearly every
programming language. There are many things you could do with JSON data. Maybe you could
use `jq` ([project page](https://github.com/stedolan/jq)) to filter through the fields in your journal.
Like this:

``` sh
$ j -3 --format json | jq '.entries[].date'                                                                                                                            jrnl-GFqVlfgP-py3.8 
"2020-06-28"
"2020-07-01"
"2020-07-02"
```

Or why not create a [beautiful timeline](http://timeline.knightlab.com/) of your journal?

**Example output**:
``` json
{
  "tags": {
    "@tag": 1
  },
  "entries": [
    {
      "title": "This is the first sample entry",
      "body": "This is the sample body text of the first sample entry.",
      "date": "2020-06-28",
      "time": "18:22",
      "tags": [],
      "starred": false
    },
    {
      "title": "This is the second sample entry",
      "body": "This is the sample body text of the second sample entry, but this one has a @tag.",
      "date": "2020-07-01",
      "time": "20:00",
      "tags": [
        "@tag"
      ],
      "starred": false
    },
    {
      "title": "This is the third sample entry",
      "body": "This is the sample body text of the third sample entry.",
      "date": "2020-07-02",
      "time": "09:00",
      "tags": [],
      "starred": false
    }
  ]
}
```

### Markdown

``` sh
jrnl --format markdown
# or
jrnl --format md
```

Markdown is a simple markup language that is human readable and can be used to be
rendered to other formats (html, pdf). `jrnl`'s
[README](https://github.com/jrnl-org/jrnl/blob/main/README.md) for example is
formatted in markdown, then Github adds some formatting to make it look nice.

The markdown format groups entries by date (first by year, then by month), and adds
header markings as needed (e.g. `#`, `##`, etc). If you already have markdown header
markings in your journal, they will be incremented as necessary to make them fit under
these new headers (i.e. `#` will become `##`).

This format can be very useful, for example, to export a journal to a program that
converts markdown to html to make a website or a blog from your journal.

**Example output**:
``` markdown
# 2020

## June

### 2020-06-28 18:22 This is the first sample entry

This is the sample body text of the first sample entry.

## July

### 2020-07-01 20:00 This is the second sample entry

This is the sample body text of the second sample entry, but this one has a @tag.

### 2020-07-02 09:00 This is the third sample entry

This is the sample body text of the third sample entry.
```

### Plain Text

``` sh
jrnl --format text
# or
jrnl --format txt
```

This outputs your journal in the same plain-text format that `jrnl` uses to store your
journal on disk. This format is particularly useful for importing and exporting journals
within `jrnl`.

You can use it, for example, to move entries from one journal to another, or to create a
new journal with search results from another journal.

**Example output**:
``` sh
[2020-06-28 18:22] This is the first sample entry
This is the sample body text of the first sample entry.

[2020-07-01 20:00] This is the second sample entry
This is the sample body text of the second sample entry, but this one has a @tag.

[2020-07-02 09:00] This is the third sample entry
This is the sample body text of the third sample entry.
```

### XML
``` sh
jrnl --format xml
```

This outputs your journal into XML format. XML is a commonly used data format and is
supported by many programs and programming languages.

**Example output**:
``` xml
<?xml version="1.0" ?>
<journal>
        <entries>
                <entry date="2020-06-28T18:22:00" starred="">This is the first sample entry This is the sample body text of the first sample entry.</entry>
                <entry date="2020-07-01T20:00:00" starred="">
                        <tag name="@tag"/>
                        This is the second sample entry This is the sample body text of the second sample entry, but this one has a @tag.
                </entry>
                <entry date="2020-07-02T09:00:00" starred="">*This is the third sample entry, and is starred This is the sample body text of the third sample entry.</entry>
        </entries>
        <tags>
                <tag name="@tag">1</tag>
        </tags>
</journal>
```

### YAML
``` sh
jrnl --format yaml --file 'my_directory/'
```

This outputs your journal into YAML format. YAML is a commonly used data format and is
supported by many programs and programming languages. [Exporting to directories](#exporting-to-directories) is the
only supported YAML export option and each entry will be written to a separate file.

**Example file**:
``` yaml
title: This is the second sample entry
date: 2020-07-01 20:00
starred: False
tags: tag

This is the sample body text of the second sample entry, but this one has a @tag.
```

## Report formats
Since formats use your journal data and display it in different ways, they can also be
used to create reports.

### Tags

``` sh
jrnl --format tags
# or
jrnl --tags
```

This format is a simple example of how formats can be used to create reports. It
displays each tag, and a count of how many entries in which tag appears in your journal
(or in the search results), sorted by most frequent.

Example output:
``` sh
@one                 : 32
@two                 : 17
@three               : 4
```

## Options

### Exporting with `--file`

Example: `jrnl --format json --file /some/path/to/a/file.txt`

By default, `jrnl` will output entries to your terminal. But if you provide `--file`
along with a filename, the same output that would have been to your terminal will be
written to the file instead. This is the same as piping the output to a file.

So, in bash for example, the following two statements are equivalent:

``` sh
jrnl --format json --file myjournal.json
```

``` sh
jrnl --format json > myjournal.json
```

#### Exporting to directories

If the `--file` argument is a directory, jrnl will export each entry into an individual file:

``` sh
jrnl --format yaml --file my_entries/
```

The contents of `my_entries/` will then look like this:

``` output
my_entries/
|- 2013_06_03_a-beautiful-day.yaml
|- 2013_06_07_dinner-with-gabriel.yaml
|- ...
```

---

### Installation (`docs/installation.md`)

# Getting started

## Installation

The easiest way to install `jrnl` is using
[pipx](https://pipx.pypa.io/stable/installation/)
with [Python](https://www.python.org/) 3.11+:

``` sh
pipx install jrnl
```

!!! tip
     Do not use `sudo` while installing `jrnl`. This may lead to path issues.

The first time you run `jrnl` you will be asked where your journal file
should be created and whether you wish to encrypt it.

## Quickstart

To make a new entry, just type

``` text
jrnl yesterday: Called in sick. Used the time to clean, and spent 4h on writing my book.
```

and hit return. `yesterday:` will be interpreted as a time stamp.
Everything until the first sentence mark (`.?!:`) will be interpreted as
the title, the rest as the body. In your journal file, the result will
look like this:

``` output
2012-03-29 09:00 Called in sick.
Used the time to clean the house and spent 4h on writing my book.
```

If you just call `jrnl`, you will be prompted to compose your entry -
but you can also [configure](advanced.md) *jrnl* to use your external editor.

---

### Journal Types (`docs/journal-types.md`)

# Journal Types
`jrnl` can store your journal in a few different ways:

 - a single text file (encrypted or otherwise)
 - a folder structure organized by date containing unencrypted text files
 - the DayOne Classic format

There is no need to specify what type of journal you'd like to use. Instead,
`jrnl` will automatically detect the journal type based on whether you're
referencing a file or a folder in your [config file](advanced.md),
and if it's a folder, whether or not DayOne Classic content exists in it.

## Single File
The single file format is the most flexible, as it can be [encrypted](encryption.md).
To use it, enter any path that is a file or does not already exist. You can
use any extension. `jrnl` will automatically create the file when you save
your first entry.

## Folder
The folder journal format organizes your entries into subfolders for the year
and month and `.txt` files for each day. If there are multiple entries in a day,
they all appear in the same `.txt` file.

The directory tree structure is in this format: `YYYY/MM/DD.txt`. For instance, if
you have an entry on May 5th, 2021 in a folder journal at `~/folderjournal`, it will
be located in: `~/folderjournal/2021/05/05.txt`

!!! note
Creating a new folder journal can be done in two ways:

* Create a folder with the name of the journal before running `jrnl`. Otherwise, when you run `jrnl` for the first time, it will assume that you are creating a single file journal instead, and it will create a file at that path.
* Create a new journal in your [config_file](advanced.md) and end the path with a ``/`` (on a POSIX system like Linux or MacOSX) or a ``\`` (on a Windows system). The folder will be created automatically if it doesn't exist.

!!! note
Folder journals can't be encrypted.

## Day One Classic
`jrnl` supports the original data format used by DayOne. It's similar to the folder
journal format, except it's identified by either of these characteristics:

* the folder has a `.dayone` extension
* the folder has a subfolder named `entries`

This is not to be confused with the DayOne 2.0 format, [which is very different](https://help.dayoneapp.com/en/articles/1187337-day-one-classic-is-retired).

!!! note
DayOne Classic journals can't be encrypted.

## Changing your journal type
You can't simply modify a journal's configuration to change its type. Instead,
define a new journal as the type you'd like, and use
[piping](https://en.wikipedia.org/wiki/Redirection_(computing)#Piping)
to export your old journal as `txt` to an import command on your new journal.

For instance, if you have a `projects` journal you would like to import into
a `new` journal, you would run the following after setting up the configuration
for your `new` journal:
```
jrnl projects --format txt | jrnl new --import
```

---

### Privacy And Security (`docs/privacy-and-security.md`)

# Privacy and Security

`jrnl` is designed with privacy and security in mind, but like any other
program there are some limitations to be aware of.

## Password strength

`jrnl` doesn't enforce password strength requirements. Short or commonly-used
passwords can be easily circumvented by someone with basic security skills
to access to your encrypted `jrnl` file.

## Plausible deniability

You may be able to hide the contents of your journal behind a layer of encryption,
but if someone has access to your configuration file, then they can figure out that
you have a journal, where that journal file is, and when you last edited it.
With a sufficient power imbalance, someone may be able to force you to unencrypt
it through non-technical means.

## Spying

While `jrnl` can protect against unauthorized access to your journal entries while
it isn't open, it cannot protect you against an unsafe computer/location.
For example:

- Someone installs a keylogger, tracking what you type into your journal.
- Someone watches your screen while you write your entry.
- Someone installs a backdoor into `jrnl` or poisons your journal into revealing your entries.

## Saved Passwords

When creating an encrypted journal, you'll be prompted as to whether or not you
want to "store the password in your keychain." This keychain is accessed using
the [Python keyring library](https://pypi.org/project/keyring/), which has different
behavior depending on your operating system.

In Windows, the keychain is the Windows Credential Manager (WCM), which can't be locked
and can be accessed by any other application running under your username. If this is
a concern for you, you may not want to store your password.

## Shell history

Since you can enter entries from the command line, any tool that logs command
line actions is a potential security risk. See below for how to deal with this
problem in various shells.

### bash

You can disable history logging for jrnl by adding this line into your
`~/.bashrc` file:

``` sh
HISTIGNORE="$HISTIGNORE:jrnl *"
```

To delete existing `jrnl` commands from `bash` history, simply delete them from
your bash history file. The default location of this file is `~/.bash_history`,
but you can run `echo "$HISTFILE"` to find it if needed.  Also, you can run
`history -c` to delete all commands from your history.

### zsh

You can disable history logging for jrnl by adding this to your `~/.zshrc`
file:

``` sh
setopt HIST_IGNORE_SPACE
alias jrnl=" jrnl"
```

To delete existing `jrnl` commands from `zsh` history, simply remove them from
your zsh history file. The default location of this file is `~/.zsh_history`,
but you can run `echo "$HISTFILE"` to find it if needed. Also, you can run
`history -c` to delete all commands from your history.

### fish

By default `fish` will not log any command that starts with a space. If you
want to always run jrnl with a space before it, then you can add this to your
`~/.config/fish/config.fish` file:

``` sh
abbr --add jrnl " jrnl"
```

To delete existing jrnl commands from `fish` history, run `history delete --prefix 'jrnl '`.

### Windows Command Prompt

Windows doesn't log history to disk, but it does keep it in your command prompt
session. Close the command prompt or press `Alt`+`F7` to clear your history
after journaling.

## Files in transit from editor to jrnl

When creating or editing an entry, `jrnl` uses a unencrypted temporary file on
disk in order to give your editor access to your journal. After you close your
editor, `jrnl` then deletes this temporary file.

So, if you have saved a journal entry but haven't closed your editor yet, the
unencrypted temporary remains on your disk. If your computer were to shut off
during this time, or the `jrnl` process were killed unexpectedly, then the
unencrypted temporary file will remain on your disk. You can mitigate this
issue by only saving with your editor right before closing it. You can also
manually delete these files from your temporary folder. By default, they
are named `jrnl*.jrnl`, but if you use a
[template](reference-config-file.md#template), they will have the same
extension as the template.

## Editor history

Some editors keep usage history stored on disk for future use. This can be a
security risk in the sense that sensitive information can leak via recent
search patterns or editor commands.

### Visual Studio Code

Visual Studio Code stores the contents of saved files to allow you to restore or
review the contents later. You can disable this feature for all files by unchecking
the `workbench.localHistory.enabled` setting in the
[Settings editor](https://code.visualstudio.com/docs/getstarted/settings#_settings-editor).

Alternatively, you can disable this feature for specific files by configuring a
[pattern](https://code.visualstudio.com/docs/editor/codebasics#_advanced-search-options)
in the `workbench.localHistory.exclude` setting. To exclude unencrypted temporary files generated
by `jrnl`, you can set the `**/jrnl*.jrnl` (unless you are using a
[template](reference-config-file.md#template)) pattern for the `workbench.localHistory.exclude` setting
in the [Settings editor](https://code.visualstudio.com/docs/getstarted/settings#_settings-editor).

!!! note
    On Windows, the history location is typically found at
    `%APPDATA%\Code\User\History`.

Visual Studio Code also creates a copy of all unsaved files that are open.
It stores these copies in a backup location that's automatically cleaned when
you save the file. However, if your computer shuts off before you save the file,
or the Visual Studio Code process stops unexpectedly, then an unencrypted
temporary file may remain on your disk. You can manually delete these files
from the backup location.

!!! note
    On Windows, the backup location is typically found at
    `%APPDATA%\Code\Backups`.

### Vim

Vim stores progress data in a so called Viminfo file located at `~/.viminfo`
which contains all sorts of user data including command line history, search
string history, search/substitute patterns, contents of register etc. Also to
be able to recover opened files after an unexpected application close Vim uses
swap files.

These options as well as other leaky features can be disabled by setting the
`editor` key in the Jrnl settings like this:

``` yaml
editor: "vim -c 'set viminfo= noswapfile noundofile nobackup nowritebackup noshelltemp history=0 nomodeline secure'"
```

To disable all plugins and custom configurations and start Vim with the default
configuration `-u NONE` can be passed on the command line as well. This will
ensure that any rogue plugins or other difficult to catch information leaks are
eliminated. The downside to this is that the editor experience will decrease
quite a bit.

To instead let Vim automatically detect when a Jrnl file is being edited an
autocommand can be used. Place this in your `~/.vimrc`:

``` vim
autocmd BufNewFile,BufReadPre *.jrnl setlocal viminfo= noswapfile noundofile nobackup nowritebackup noshelltemp history=0 nomodeline secure
```

!!! note
    If you're using a [template](reference-config-file.md#template), you will
    have to use the template's file extension instead of `.jrnl`.

See `:h <option>` in Vim for more information about the options mentioned.

### Neovim

Neovim strives to be mostly compatible with Vim and has therefore similar
functionality as Vim. One difference in Neovim is that the Viminfo file is
instead called the ShaDa ("shared data") file which resides in
`~/.local/state/nvim` (`~/.local/share/nvim` pre Neovim v0.8.0). The ShaDa file
can be disabled in the same way as for Vim.

``` yaml
editor: "nvim -c 'set shada= noswapfile noundofile nobackup nowritebackup noshelltemp history=0 nomodeline secure'"
```

`-u NONE` can be passed here as well to start a session with the default configs.

As for Vim above we can create an autocommand in Vimscript:

``` vim
autocmd BufNewFile,BufReadPre *.jrnl setlocal shada= noswapfile noundofile nobackup nowritebackup noshelltemp history=0 nomodeline secure
```

or the same but in Lua:

``` lua
vim.api.nvim_create_autocmd( {"BufNewFile","BufReadPre" }, {
  group = vim.api.nvim_create_augroup("PrivateJrnl", {}),
  pattern = "*.jrnl",
  callback = function()
    vim.o.shada = ""
    vim.o.swapfile = false
    vim.o.undofile = false
    vim.o.backup = false
    vim.o.writebackup = false
    vim.o.shelltemp = false
    vim.o.history = 0
    vim.o.modeline = false
    vim.o.secure = true
  end,
})
```

!!! note
    If you're using a [template](reference-config-file.md#template), you will
    have to use the template's file extension instead of `.jrnl`.

Please see `:h <option>` in Neovim for more information about the options mentioned.

## Notice any other risks?

Please let the maintainers know by [filing an issue on GitHub](https://github.com/jrnl-org/jrnl/issues).

---

### Reference Command Line (`docs/reference-command-line.md`)

# Command Line Reference

## Synopsis
```
usage: jrnl [--debug] [--help] [--version] [--list] [--encrypt] [--decrypt]
            [--import] [-on DATE] [-today-in-history] [-month DATE]
            [-day DATE] [-year DATE] [-from DATE] [-to DATE] [-contains TEXT]
            [-and] [-starred] [-n [NUMBER]] [-not [TAG]] [--edit] [--delete]
            [--format TYPE] [--tags] [--short]
            [--config-override CONFIG_KEY CONFIG_VALUE]
            [--config-file CONFIG_FILE_PATH]
            [[...]]
```

## Standalone Commands

These commands will exit after they complete. You may only run one at a time.

### --help
Show a help message.

### --version
Print version and license information.

### --list
List the config file location, all configured journals, and their locations.

### --encrypt
Encrypt a journal. See [encryption](encryption.md) for more information.

### --decrypt
Decrypt a journal. See [encryption](encryption.md) for more information.


### --import
Import entries from another journal. If any entries have the exact same content
and timestamp, they will be deduplicated.

Optional parameters:
```sh
--file FILENAME
```
Specify a file to import. If not provided, `jrnl` will use STDIN as the data source.

```sh
--format TYPE
```
Specify the format of the file that is being imported. Defaults to the same data
storage method that jrnl uses. See [formats](formats.md) for more information.

## Writing new entries
See [Basic Usage](usage.md).

## Searching

To find entries from your journal, use any combination of the below filters.
Only entries that match all the filters will be displayed.

When specifying dates, you can use the same kinds of dates you use for new
entries, such as `yesterday`, `today`, `Tuesday`, or `2021-08-01`.

| Search Argument | Description |
| --- | --- |
| -on DATE | Show entries on this date |
| -today-in-history | Show entries of today over the years |
| -month DATE | Show entries on this month of any year |
| -day DATE | Show entries on this day of any month |
| -year DATE | Show entries of a specific year |
| -from DATE | Show entries after, or on, this date |
| -to DATE | Show entries before, or on, this date (alias: -until) |
| -contains TEXT | Show entries containing specific text (put quotes around text with spaces) |
| -and | Show only entries that match all conditions, like saying "x AND y" (default: OR) |
| -starred | Show only starred entries (marked with *) |
| -tagged | Show only tagged entries (marked with the [configured tagsymbols](reference-config-file.md#tagsymbols)) |
| -n [NUMBER] | Show a maximum of NUMBER entries (note: '-n 3' and '-3' have the same effect) |
| -not [TAG] | Exclude entries with this tag |
| -not -starred | Exclude entries that are starred |
| -not -tagged | Exclude entries that are tagged |

## Searching Options
These help you do various tasks with the selected entries from your search.
If used on their own (with no search), they will act on your entire journal.

### --edit
Opens the selected entries in your configured editor. It will fail if the
`editor` key is not set in your config file.

Once you begin editing, you can add multiple entries and delete entries
by modifying the text in your editor. When your editor closes, jrnl reads
the temporary file you were editing and makes the changes to your journal.

### --delete
Interactively deletes selected entries. You'll be asked to confirm deletion of
each entry.

### --change-time DATE
Interactively changes the time of the selected entries to the date specified,
or to right now if no date is specified. You'll be asked to confirm each entry,
unless you are using this with `--edit` on a single entry.

### --format TYPE
Display selected entries in an alternate format. See [formats](formats.md).

#### Optional parameters
```sh
--file FILENAME
```
Write output to file instead of STDOUT. In most shells, the
same effect can be achieved using `>`.

### --tags

Alias for '--format tags'. Returns a list of all tags and the number of times
they occur within the searched entries. If there are no tags found, `jrnl` will output a message saying so.

### --short
Only shows the date and titles of the searched entries.

## Configuration arguments

### --config-override CONFIG_KEY CONFIG_VALUE

Override configured key-value pair with CONFIG_KV_PAIR for this command invocation only. To access config keys that aren't at the top level, separate the keys with a dot, such as `colors.title` to access the `title` key within the `colors` key. Read [advanced usage](./advanced.md) for examples.

### --config-file CONFIG_FILE_PATH

Use the config file at CONFIG_FILE_PATH for this command invocation only.
Read [advanced usage](./advanced.md) for examples.

## Other Arguments

### --debug
Prints information useful for troubleshooting while `jrnl` executes.

### --diagnostic

Prints diagnostic information useful for [reporting issues](https://github.com/jrnl-org/jrnl/issues).

---

### Reference Config File (`docs/reference-config-file.md`)

# Configuration File Reference

`jrnl` stores its information in a YAML configuration file.

!!! note
    Backup your journal and config file before editing. Changes to the config file
    can have destructive effects on your journal!

## Config location
You can find your configuration file location by running:
`jrnl --list`

By default, the configuration file is `~/.config/jrnl/jrnl.yaml`.
If you have the `XDG_CONFIG_HOME` variable set, the configuration
file will be saved as `$XDG_CONFIG_HOME/jrnl/jrnl.yaml`.

!!! note
    On Windows, the configuration file is typically found at
    `%USERPROFILE%\.config\jrnl\jrnl.yaml`.


## Config format
The configuration file is a [YAML](https://yaml.org/) file and can be edited with
a text editor.

## Config keys

### journals

Describes each journal used by `jrnl`. Each indented key after this key is
the name of a journal.

If a journal key has a value, that value will be interpreted as the path
to the journal. Otherwise, the journal needs the additional indented key
`journal` to specify its path.

Example:

```yaml
journals:
  default:
    journal: /home/user/journals
```

All keys below can be specified for each journal at the same level as the
`journal` key. If a key conflicts with a top-level key, the journal-specific
key will be used instead.

### editor
If set, executes this command to launch an external editor for
writing and editing your entries. The path to a temporary file
is passed after it, and `jrnl` processes the file once
the editor returns control to `jrnl`.

Some editors require special options to work properly, since they must be
blocking processes to work with `jrnl`. See [External Editors](external-editors.md)
for details.

### encrypt
If `true`, encrypts your journal using AES. Do not change this
value for journals that already have data in them.

### template
The path to a text file to use as a template for new entries. Only works when you
have the `editor` field configured. If you use a template, the editor's
[temporary files](privacy-and-security.md#files-in-transit-from-editor-to-jrnl)
will have the same extension as the template.

### tagsymbols
Symbols to be interpreted as tags.

!!! note
    Although it seems intuitive to use the `#`
    character for tags, there's a drawback: on most shells, this is
    interpreted as a meta-character starting a comment. This means that if
    you type

    > `jrnl Implemented endless scrolling on the #frontend of our website.`

    your bash will chop off everything after the `#` before passing it to
      `jrnl`. To avoid this, wrap your input into quotation marks like
      this:

    > `jrnl "Implemented endless scrolling on the #frontend of our website."`

  Or use the built-in prompt or an external editor to compose your
  entries.

### default_hour and default_minute
Entries will be created at this time if you supply a date but no specific time (for example, `last thursday`).

### timeformat
Defines how to format the timestamps as they are stored in your journal.
See the [python docs](http://docs.python.org/library/time.html#time.strftime) for reference.

Do not change this for an existing journal, since that might lead
to data loss.

!!! note
    `jrnl` doesn't support the `%z` or `%Z` time zone identifiers.

### highlight
If `true`, tags will be highlighted in cyan.

### linewrap
Controls the width of the output. Set to `false` if you don't want to
wrap long lines. Set to `auto` to let `jrnl` automatically determine
the terminal width.

### colors
A dictionary that controls the colors used to display journal entries.
It has four subkeys, which are: `body`, `date`, `tags`, and `title`.

Current valid values are: `BLACK`, `RED`, `GREEN`, `YELLOW`, `BLUE`,
`MAGENTA`, `CYAN`, `WHITE`, and `NONE`.

`colorama.Fore` is used for colorization, and you can find the [docs here](https://github.com/tartley/colorama#colored-output).

To disable colored output, set the value to `NONE`.

### display_format
Specifies formatter to use by default. See [formats](formats.md).

### version
`jrnl` automatically updates this field to the version that it is running.
There is no need to change this field manually.

---

### Tips And Tricks (`docs/tips-and-tricks.md`)

# Tips and Tricks

This page contains tips and tricks for using `jrnl`, often in conjunction
with other tools, including external editors.

## Co-occurrence of tags

If I want to find out how often I mentioned my flatmates Alberto and
Melo in the same entry, I run

```sh
jrnl @alberto --tags | grep @melo
```

And will get something like `@melo: 9`, meaning there are 9 entries
where both `@alberto` and `@melo` are tagged. How does this work? First,
`jrnl @alberto` will filter the journal to only entries containing the
tag `@alberto`, and then the `--tags` option will print out how often
each tag occurred in this filtered journal. Finally, we pipe this to
`grep` which will only display the line containing `@melo`.

## Combining filters

You can do things like

```sh
jrnl @fixed -starred -n 10 -to "jan 2013" --short
```

To get a short summary of the 10 most recent, favourite entries before
January 1, 2013 that are tagged with `@fixed`.

## Statistics

How much did I write last year?

```sh
jrnl -from "jan 1 2013" -to "dec 31 2013" | wc -w
```

Will give you the number of words you wrote in 2013. How long is my
average entry?

```sh
expr $(jrnl --export text | wc -w) / $(jrnl --short | wc -l)
```

This will first get the total number of words in the journal and divide
it by the number of entries (this works because `jrnl --short` will
print exactly one line per entry).

## Importing older files

If you want to import a file as an entry to `jrnl`, you can just do `jrnl < entry.ext`. But what if you want the modification date of the file to
be the date of the entry in `jrnl`? Try this

```sh
echo `stat -f %Sm -t '%d %b %Y at %H:%M: ' entry.txt` `cat entry.txt` | jrnl
```

The first part will format the modification date of `entry.txt`, and
then combine it with the contents of the file before piping it to jrnl.
If you do that often, consider creating a function in your `.bashrc` or
`.bash_profile`

```sh
jrnlimport () {
  echo `stat -f %Sm -t '%d %b %Y at %H:%M: ' $1` `cat $1` | jrnl
}
```

## Using Templates

!!! note
    Templates require an [external editor](./advanced.md) be configured.

Templates are text files that are used for creating structured journals.
There are three ways you can use templates:

### 1. Use the `--template` command line argument and the default $XDG_DATA_HOME/jrnl/templates directory

`$XDG_DATA_HOME/jrnl/templates` is created by default to store your templates! Create a template (like `default.md`) in this directory and pass `--template FILE_IN_DIR`.

```sh
jrnl --template default.md
```

### 2. Use the `--template` command line argument with a local / absolute path

You can create a template file with any text. Here is an example:

```sh
# /tmp/template.txt
My Personal Journal
Title:

Body:
```

Then, pass the absolute or relative path to the template file as an argument, and your external
editor will open and have your template pre-populated.

```sh
jrnl --template /tmp/template.md
```

### 3. Set a default template file in `jrnl.yaml`

If you want a template by default, change the value of `template` in the [config file](./reference-config-file.md)
from `false` to the template file's path, wrapped in double quotes:

```sh
...
template: "/path/to/template.txt"
...
```

!!! tip
    To read your journal entry or to verify the entry saved, you can use this
    command: `jrnl -n 1` (Check out [Formats](./formats.md) for more options).

```sh
jrnl -n 1
```

## Prompts on shell reload

If you'd like to be prompted each time you refresh your shell, you can include
this in your `.bash_profile`:

```sh
function log_question()
{
   echo $1
   read
   jrnl today: ${1}. $REPLY
}
log_question 'What did I achieve today?'
log_question 'What did I make progress with?'
```

Whenever your shell is reloaded, you will be prompted to answer each of the
questions in the example above. Each answer will be logged as a separate
journal entry at the `default_hour` and `default_minute` listed in your
`jrnl.yaml` [config file](../advanced/#configuration-file).

## Display random entry

You can use this to select one title at random and then display the whole
entry. The invocation of `cut` needs to match the format of the timestamp.
For timestamps that have a space between data and time components, select
fields 1 and 2 as shown. For timestamps that have no whitespace, select
only field 1.

```sh
jrnl -on "$(jrnl --short | shuf -n 1 | cut -d' ' -f1,2)"
```


## Launch a terminal for rapid logging
You can use this to launch a terminal that is the `jrnl` stdin prompt so you can start typing away immediately.

```bash
jrnl --config-override editor ""
```

Bind this to a keyboard shortcut.

Map `Super+Alt+J` to launch the terminal with `jrnl` prompt

- **xbindkeys**
In your `.xbindkeysrc`

```ini
Mod4+Mod1+j
 alacritty -t floating-jrnl -e jrnl --config-override editor "",
```

- **I3 WM** Launch a floating terminal with the `jrnl` prompt

```ini
bindsym Mod4+Mod1+j exec --no-startup-id alacritty -t floating-jrnl -e jrnl --config-override editor ""
for_window[title="floating *"] floating enable
```
## Visualize Formatted Markdown in the CLI

Out of the box, `jrnl` can output journal entries in Markdown. To visualize it, you can pipe to [mdless](https://github.com/ttscoff/mdless), which is a [less](https://en.wikipedia.org/wiki/Less_(Unix))-like tool that allows you to visualize your Markdown text with formatting and syntax highlighting from the CLI. You can use this in any shell that supports piping.

The simplest way to visualize your Markdown output with `mdless` is as follows:
```sh
jrnl --export md | mdless
```

This will render your Markdown output in the whole screen.

Fortunately, `mdless` has an option that allows you to adjust the screen width by using the `-w` option as follows:

```sh
jrnl --export md | mdless -w 70
```

If you want Markdown to be your default display format, you can define this in your config file as follows:

```yaml
display_format: md
# or
display_format: markdown
```

For more information on how `jrnl` outputs your entries in Markdown, please visit the [Formats](./formats.md) section.


## Jump to end of buffer (with vi)

To cause vi to jump to the end of the last line of the entry you edit, in your config file set:

```yaml
editor: vi + -c "call cursor('.',strwidth(getline('.')))"
```

---

### Usage (`docs/usage.md`)

# Basic Usage #

`jrnl` has two modes: **composing** and **viewing**. Whenever you don't enter
any arguments that start with a dash (`-`) or double-dash (`--`), you're in
composing mode, meaning that you can write your entry on the command line.

We intentionally break a convention on command line arguments: all arguments
starting with a _single dash_ (`-`) will _filter_ your journal before viewing
it. Filter arguments can be combined arbitrarily. Arguments with a _double dash_
(`--`) will _control_ how your journal is displayed or exported. Control
arguments are mutually exclusive (i.e., you can only specify one way to display
or export your journal at a time).

For a list of commands, enter `jrnl --help`.

## Composing Entries ##

Composing mode is entered by either starting `jrnl` without any arguments --
which will launch an external editor -- or by just writing an entry on the
command line:

```text
jrnl today at 3am: I just met Steve Buscemi in a bar! What a nice guy.
```

!!! note
    Most shells contain a certain number of reserved characters, such as `#` and
    `*`. These characters, as well as unbalanced single or double quotation
    marks, parentheses, and others, likely will cause problems. Although
    reserved characters can be escaped using `\`, this is not ideal for
    long-form writing. The solution: first enter `jrnl` and hit `return`. You
    can then enter the text of your journal entry. Alternatively, you can [use
    an external editor](./advanced.md).

You can also import an entry directly from a file:

```sh
jrnl < my_entry.txt
```

### Specifying Date and Time ###

If you don't specify a date and time (e.g., `jrnl finished writing letter to brother`), `jrnl` will create an entry using the current date and time. For retrospective entries, you can use a timestamp to tell `jrnl` where to put the entry. Timestamps can be entered using a variety of formats. Here are some that work:

- at 6am
- yesterday
- last monday
- sunday at noon
- 2 march 2012
- 7 apr
- 5/20/1998 at 23:42
- 2020-05-22T15:55-04:00

If you don't use a timestamp, `jrnl` will create an entry using the current
time. If you use a date only (no time), `jrnl` will use the default time
specified in your [configuration file](./reference-config-file.md#default_hour-and-default_minute).
Behind the scenes, `jrnl` reorganizes entries in chronological order.

### Using Tags ###

`jrnl` supports tags. The default tag symbol is `@` (largely because `#` is a
reserved character). You can specify your own tag symbol in the
[configuration file](./reference-config-file.md#tagsymbols). To use tags, preface the
desired tag with the symbol:

```sh
jrnl Had a wonderful day at the @beach with @Tom and @Anna.
```

Although you can use capitals while tagging an entry, searches by tag are
case-insensitive.

There is no limit to how many tags you can use in an entry.

#### Similar Tag Warning ####

When you write an entry, `jrnl` checks whether any of its tags closely resemble
tags you've used before. If so, it prints a warning:

```
The tag '@works' is similar to: @work

Was this intentional? If not, re-open the entry with 'jrnl --edit' to fix it.
```

This is just a warning — `jrnl` will not ask for confirmation or block the
entry from being saved. This is intentional: some similar-looking tags are
perfectly meaningful to keep separate. For example:

- `@health` and `@wealth` — related topics, but distinct goals
- `@friend` and `@fiend` — very different meanings
- `@hiking` and `@biking` — different activities worth tracking separately
- `@learn` and `@lean` — different intentions entirely

If the warning appears and you did make a typo, run `jrnl --edit` to fix it.

### Starring Entries ###

To mark an entry as a favorite, simply "star" it using an asterisk (`*`):

```sh
jrnl last sunday *: Best day of my life.
```

If you don't want to add a date (i.e., you want the date to be entered as
_now_), the following options are equivalent:

- `jrnl *: Best day of my life.`
- `jrnl *Best day of my life.`
- `jrnl Best day of my life.*`

!!! note
    Make sure that the asterisk (`*`) is **not** surrounded by whitespaces.
    `jrnl Best day of my life! *` will not work because the `*` character has a
    special meaning in most shells.

## Viewing and Searching Entries ##

`jrnl` can display entries in a variety of ways.

To view all entries, enter:
```sh
jrnl -to today
```

`jrnl` provides several filtering commands, prefaced by a single dash (`-`), that
allow you to find a more specific range of entries. For example,

```sh
jrnl -n 10
```

lists the ten most recent entries. `jrnl -10` is even more concise and works the
same way. If you want to see all of the entries you wrote from the beginning of
last year until the end of this past March, you would enter

```sh
jrnl -from "last year" -to march
```

Filter criteria that use more than one word require surrounding quotes (`""`).

To see entries on a particular date, use `-on`:
```sh
jrnl -on yesterday
```

### Text Search ###

The `-contains` command displays all entries containing the text you enter after it.
This may be helpful when you're searching for entries and you can't remember if you
tagged any words when you wrote them.

You may realize that you use a word a lot and want to turn it into a tag in all
of your previous entries.

```sh
jrnl -contains "dogs" --edit
```

opens your external editor so that you can add a tag symbol (`@` by default) to
all instances of the word "dogs."

### Filtering by Tag ###

You can filter your journal entries by tag. For example,

```sh
jrnl @pinkie @WorldDomination
```

displays all entries in which either `@pinkie` or `@WorldDomination`
occurred. Tag filters can be combined with other filters:

```sh
jrnl -n 5 @pinkie -and @WorldDomination
```

displays the last five entries containing _both_ `@pinkie` _and_
`@worldDomination`. You can change which symbols you'd like to use for tagging
in the [configuration file](./reference-config-file.md#tagsymbols).

!!! note
    Entering `jrnl @pinkie @WorldDomination` will display entries in which both
    tags are present because, although no command line arguments are given, all
    of the input strings look like tags. `jrnl` will assume you want to filter
    by tag, rather than create a new entry that consists only of tags.

To view a list of all tags in the journal, enter:

```sh
jrnl --tags
```

### Viewing Starred Entries ###

To display only your favorite (starred) entries, enter

```sh
jrnl -starred
```

## Editing Entries ##

You can edit entries after writing them. This is particularly useful when your
journal file is encrypted. To use this feature, you need to have an external
editor configured in your [configuration file](./reference-config-file.md#editor). You
can also edit only the entries that match specific search criteria. For example,

```sh
jrnl -to 1950 @texas -and @history --edit
```

opens your external editor displaying all entries tagged with `@texas` and
`@history` that were written before 1950. After making changes, save and close
the file, and only those entries will be modified (and encrypted, if
applicable).

If you are using multiple journals, it's easy to edit specific entries from
specific journals. Simply prefix the filter string with the name of the journal.
For example,

```sh
jrnl work -n 1 --edit
```

opens the most recent entry in the 'work' journal in your external editor.

## Deleting Entries ##

The `--delete` command opens an interactive interface for deleting entries. The
date and title of each entry in the journal are presented one at a time, and you
can choose whether to keep or delete each entry.

If no filters are specified, `jrnl` will ask you to keep or delete each entry in
the entire journal, one by one. If there are a lot of entries in the journal, it
may be more efficient to filter entries before passing the `--delete` command.

Here's an example. Say you have a journal into which you've imported the last 12
years of blog posts. You use the `@book` tag a lot, and for some reason you want
to delete some, but not all, of the entries in which you used that tag, but only
the ones you wrote at some point in 2004 or earlier. You're not sure which
entries you want to keep, and you want to look through them before deciding.
This is what you might enter:

```sh
jrnl -to 2004 @book --delete
```

`jrnl` will show you only the relevant entries, and you can choose the ones you
want to delete.

You may want to delete _all_ of the entries containing `@book` that you wrote in
2004 or earlier. If there are dozens or hundreds, the easiest way would be to
use an external editor. Open an editor with the entries you want to delete...

```sh
jrnl -to 2004 @book --edit
```

...select everything, delete it, save and close, and all of those entries are
removed from the journal.

## Listing Journals ##

To list all of your journals:

```sh
jrnl --list
```

The journals displayed correspond to those specified in the `jrnl`
[configuration file](./reference-config-file.md#journals).

---

--- METRICS ---
- Files Extracted: 14
- Estimated Token Budget: ~19165 tokens
- Canonical Reference: https://codewiki.google/github.com/jrnl-org/jrnl
