10954 lines
492 KiB
Plaintext
10954 lines
492 KiB
Plaintext
|
|
HLEDGER(1) hledger User Manuals HLEDGER(1)
|
|
|
|
NAME
|
|
hledger - a robust, friendly plain text accounting app (command line
|
|
version).
|
|
|
|
SYNOPSIS
|
|
hledger
|
|
or
|
|
hledger COMMAND [OPTS] [ARGS]
|
|
DESCRIPTION
|
|
hledger is a robust, user-friendly, cross-platform set of programs for
|
|
tracking money, time, or any other commodity, using double-entry ac-
|
|
counting and a simple, editable file format. hledger is inspired by
|
|
and largely compatible with ledger(1), and largely interconvertible
|
|
with beancount(1).
|
|
|
|
This manual is for hledger's command line interface, version 1.51.99.
|
|
It also describes the common options, file formats and concepts used by
|
|
all hledger programs. It might accidentally teach you some bookkeep-
|
|
ing/accounting as well! You don't need to know everything in here to
|
|
use hledger productively, but when you have a question about function-
|
|
ality, this doc should answer it. It is detailed, so do skip ahead or
|
|
skim when needed. You can read it on hledger.org, or as an info manual
|
|
or man page on your system. You can also open a built-in copy, at a
|
|
point of interest, by running
|
|
hledger --man [CMD], hledger --info [CMD] or hledger help [TOPIC].
|
|
|
|
(And for shorter help, try hledger --tldr [CMD].)
|
|
|
|
The main function of the hledger CLI is to read plain text files de-
|
|
scribing financial transactions, crunch the numbers, and print a useful
|
|
report on the terminal (or save it as HTML, CSV, JSON or SQL). Many
|
|
reports are available, as subcommands. hledger will also detect other
|
|
hledger-* executables as extra subcommands.
|
|
|
|
hledger usually reads from (and appends to) a journal file specified by
|
|
the LEDGER_FILE environment variable (defaulting to
|
|
$HOME/.hledger.journal); or you can specify files with -f options. It
|
|
can also read timeclock files, timedot files, or any CSV/SSV/TSV file
|
|
with a date field.
|
|
|
|
Here is a small journal file describing one transaction:
|
|
|
|
2015-10-16 bought food
|
|
expenses:food $10
|
|
assets:cash
|
|
|
|
Transactions are dated movements of money (etc.) between two or more
|
|
accounts: bank accounts, your wallet, revenue/expense categories, peo-
|
|
ple, etc. You can choose any account names you wish, using : to indi-
|
|
cate subaccounts. There must be at least two spaces between account
|
|
name and amount. Positive amounts are inflow to that account (debit),
|
|
negatives are outflow from it (credit). (Some reports show revenue,
|
|
liability and equity account balances as negative numbers as a result;
|
|
this is normal.)
|
|
|
|
hledger's add command can help you add transactions, or you can install
|
|
other data entry UIs like hledger-web or hledger-iadd. For more exten-
|
|
sive/efficient changes, use a text editor: Emacs + ledger-mode, VIM +
|
|
vim-ledger, or VS Code + hledger-vscode are some good choices (see
|
|
https://hledger.org/editors.html).
|
|
|
|
To get started, run hledger add and follow the prompts, or save some
|
|
entries like the above in $HOME/.hledger.journal, then try commands
|
|
like:
|
|
|
|
$ hledger print -x
|
|
$ hledger aregister assets
|
|
$ hledger balance
|
|
$ hledger balancesheet
|
|
$ hledger incomestatement
|
|
|
|
Run hledger to list the commands. See also the "Starting a journal
|
|
file" and "Setting opening balances" sections in PART 5: COMMON TASKS.
|
|
|
|
PART 1: USER INTERFACE
|
|
Input
|
|
hledger reads one or more data files, each time you run it. You can
|
|
specify a file with -f, like so
|
|
|
|
$ hledger -f FILE [-f FILE2 ...] print
|
|
|
|
Files are most often in hledger's journal format, with the .journal
|
|
file extension (.hledger or .j also work); these files describe trans-
|
|
actions, like an accounting general journal.
|
|
|
|
When no file is specified, hledger looks for .hledger.journal in your
|
|
home directory.
|
|
|
|
But most people prefer to keep financial files in a dedicated folder,
|
|
perhaps with version control. Also, starting a new journal file each
|
|
year is common (it's not required, but helps keep things fast and or-
|
|
ganised). So we usually configure a different journal file, by setting
|
|
the LEDGER_FILE environment variable, to something like ~/fi-
|
|
nance/2023.journal. For more about how to do that on your system, see
|
|
Common tasks > Setting LEDGER_FILE.
|
|
|
|
Text encoding
|
|
hledger expects non-ascii input to be decodable with the system lo-
|
|
cale's text encoding. (For CSV/SSV/TSV files, this can be overridden
|
|
by the encoding CSV rule.)
|
|
|
|
So, trying to read non-ascii files which have the wrong text encoding,
|
|
or when no system locale is configured, will fail. To fix this, con-
|
|
figure your system locale appropriately, and/or convert the files to
|
|
your system's text encoding (using iconv on unix, or powershell or
|
|
notepad on Windows). See Install: Text encoding for more tips.
|
|
|
|
hledger's output will use the system locale's encoding.
|
|
|
|
hledger's docs and example files mostly use UTF-8 encoding.
|
|
|
|
Data formats
|
|
Usually the data file is in hledger's journal format, but it can be in
|
|
any of the supported file formats, which currently are:
|
|
|
|
Reader: Reads: Automatically used for
|
|
files with extensions:
|
|
-----------------------------------------------------------------------------
|
|
journal hledger journal files and some .journal .j .hledger
|
|
Ledger journals, for transactions .ledger
|
|
timeclock timeclock files, for precise time .timeclock
|
|
logging
|
|
timedot timedot files, for approximate .timedot
|
|
time logging
|
|
csv Comma- or other delimiter-sepa- .csv
|
|
rated values, for data import
|
|
ssv Semicolon separated values .ssv
|
|
tsv Tab separated values .tsv
|
|
rules CSV/SSV/TSV/other separated val- .rules
|
|
ues, alternate way
|
|
|
|
These formats are described in more detail below.
|
|
|
|
hledger detects the format automatically based on the file extensions
|
|
shown above. If it can't recognise the file extension, it assumes
|
|
journal format. So for non-journal files, it's important to use a
|
|
recognised file extension, so as to either read successfully or to show
|
|
relevant error messages.
|
|
|
|
You can also force a specific reader/format by prefixing the file path
|
|
with the format and a colon. Eg, to read a .dat file containing tab
|
|
separated values:
|
|
|
|
$ hledger -f tsv:/some/file.dat stats
|
|
|
|
Standard input
|
|
The file name - means standard input:
|
|
|
|
$ cat FILE | hledger -f- print
|
|
|
|
If reading non-journal data in this way, you'll need to write the for-
|
|
mat as a prefix, like timeclock: here:
|
|
|
|
$ echo 'i 2009/13/1 08:00:00' | hledger print -f timeclock:-
|
|
|
|
Multiple files
|
|
You can specify multiple -f options, to read multiple files as one big
|
|
journal. When doing this, note that certain features (described below)
|
|
will be affected:
|
|
|
|
o Balance assertions will not see the effect of transactions in previ-
|
|
ous files. (Usually this doesn't matter as each file will set the
|
|
corresponding opening balances.)
|
|
|
|
o Some directives will not affect previous or subsequent files.
|
|
|
|
If needed, you can work around these by using a single parent file
|
|
which includes the others, or concatenating the files into one, eg: cat
|
|
a.journal b.journal | hledger -f- CMD.
|
|
|
|
Strict mode
|
|
hledger checks input files for valid data. By default, the most impor-
|
|
tant errors are detected, while still accepting easy journal files
|
|
without a lot of declarations:
|
|
|
|
o Are the input files parseable, with valid syntax ?
|
|
|
|
o Are all transactions balanced ?
|
|
|
|
o Do all balance assertions pass ?
|
|
|
|
With the -s/--strict flag, additional checks are performed:
|
|
|
|
o Are all accounts posted to, declared with an account directive ?
|
|
(Account error checking)
|
|
|
|
o Are all commodities declared with a commodity directive ? (Commodity
|
|
error checking)
|
|
|
|
o Are all commodity conversions declared explicitly ?
|
|
|
|
You can use the check command to run individual checks - the ones
|
|
listed above and some more.
|
|
|
|
Commands
|
|
hledger provides various subcommands for getting things done. Most of
|
|
these commands do not change the journal file; they just read it and
|
|
output a report. A few commands assist with adding data and file man-
|
|
agement. Some often-used commands are add, print, register, bal-
|
|
ancesheet and incomestatement.
|
|
|
|
To show a summary of commands, run hledger with no arguments. You can
|
|
see the same commands summary at the start of PART 4: COMMANDS below.
|
|
|
|
To use a particular command, run hledger CMD [CMDOPTS] [CMDARGS],
|
|
|
|
o CMD is the full command name, or its standard abbreviation shown in
|
|
the commands list, or any unambiguous prefix of the name.
|
|
|
|
o CMDOPTS are command-specific options, if any. Command-specific op-
|
|
tions must be written after the command name. Eg: hledger print -x.
|
|
|
|
o CMDARGS are additional arguments to the command, if any. Most
|
|
hledger commands accept arguments representing a query, to limit the
|
|
data in some way. Eg: hledger reg assets:checking.
|
|
|
|
To list a command's options, arguments, and documentation in the termi-
|
|
nal, run hledger CMD -h. Eg: hledger bal -h.
|
|
|
|
Add-on commands
|
|
In addition to the built-in commands, you can install add-on commands,
|
|
which will also appear in hledger's commands list. Some of these can
|
|
be installed as separate packages; others can be found in hledger's
|
|
bin/ directory, documented at https://hledger.org/scripts.html.
|
|
|
|
Add-on commands are programs or scripts in your shell's PATH, whose
|
|
name starts with "hledger-" and ends with no extension or a recognised
|
|
extension (".bat", ".com", ".exe", ".hs", ".js", ".lhs", ".lua",
|
|
".php", ".pl", ".py", ".rb", ".rkt", or ".sh"), and (on unix and mac)
|
|
which has executable permission for the current user.
|
|
|
|
You can run add-on commands directly: hledger-ui --watch.
|
|
|
|
Or you can run them with hledger, like built-in commands: hledger ui
|
|
--watch. In this case hledger's config file will be used, so you can
|
|
set custom options for the addon there. (Before hledger 1.50, an --
|
|
argument was needed before addon options, but not any more.)
|
|
|
|
Options
|
|
Run hledger -h to see general command line help. Options can be writ-
|
|
ten either before or after the command name. These options are spe-
|
|
cific to the hledger CLI:
|
|
|
|
Flags:
|
|
--conf=CONFFILE Use extra options defined in this config file. If
|
|
not specified, searches upward and in XDG config
|
|
dir for hledger.conf (or .hledger.conf in $HOME).
|
|
-n --no-conf ignore any config file
|
|
|
|
And the following general options are common to most hledger commands:
|
|
|
|
General input/data transformation flags:
|
|
-f --file=[FMT:]FILE Read data from FILE, or from stdin if FILE is -,
|
|
inferring format from extension or a FMT: prefix.
|
|
Can be specified more than once. If not specified,
|
|
reads from $LEDGER_FILE or $HOME/.hledger.journal.
|
|
--rules=RULESFILE Use rules defined in this rules file for
|
|
converting subsequent CSV/SSV/TSV files. If not
|
|
specified, uses FILE.csv.rules for each FILE.csv.
|
|
--alias=A=B|/RGX/=RPL transform account names from A to B, or by
|
|
replacing regular expression matches
|
|
--auto generate extra postings by applying auto posting
|
|
rules ("=") to all transactions
|
|
--forecast[=PERIOD] Generate extra transactions from periodic rules
|
|
("~"), from after the latest ordinary transaction
|
|
until 6 months from now. Or, during the specified
|
|
PERIOD (the equals is required). Auto posting rules
|
|
will also be applied to these transactions. In
|
|
hledger-ui, also make future-dated transactions
|
|
visible at startup.
|
|
-I --ignore-assertions don't check balance assertions by default
|
|
--txn-balancing=... how to check that transactions are balanced:
|
|
'old': use global display precision
|
|
'exact': use transaction precision (default)
|
|
--infer-costs infer conversion equity postings from costs
|
|
--infer-equity infer costs from conversion equity postings
|
|
--infer-market-prices infer market prices from costs
|
|
--pivot=TAGNAME use a different field or tag as account names
|
|
-s --strict do extra error checks (and override -I)
|
|
--verbose-tags add tags indicating generated/modified data
|
|
|
|
General output/reporting flags (supported by some commands):
|
|
-b --begin=DATE include postings/transactions on/after this date
|
|
-e --end=DATE include postings/transactions before this date
|
|
(with a report interval, will be adjusted to
|
|
following subperiod end)
|
|
-D --daily multiperiod report with 1 day interval
|
|
-W --weekly multiperiod report with 1 week interval
|
|
-M --monthly multiperiod report with 1 month interval
|
|
-Q --quarterly multiperiod report with 1 quarter interval
|
|
-Y --yearly multiperiod report with 1 year interval
|
|
-p --period=PERIODEXP set begin date, end date, and/or report interval,
|
|
with more flexibility
|
|
--today=DATE override today's date (affects relative dates)
|
|
--date2 match/use secondary dates instead (deprecated)
|
|
-U --unmarked include only unmarked postings/transactions
|
|
-P --pending include only pending postings/transactions
|
|
-C --cleared include only cleared postings/transactions
|
|
(-U/-P/-C can be combined)
|
|
-R --real include only non-virtual postings
|
|
-E --empty Show zero items, which are normally hidden.
|
|
In hledger-ui & hledger-web, do the opposite.
|
|
--depth=DEPTHEXP if a number (or -NUM): show only top NUM levels
|
|
of accounts. If REGEXP=NUM, only apply limiting to
|
|
accounts matching the regular expression.
|
|
-B --cost show amounts converted to their cost/sale amount
|
|
-V --market Show amounts converted to their value at period
|
|
end(s) in their default valuation commodity.
|
|
Equivalent to --value=end.
|
|
-X --exchange=COMM Show amounts converted to their value at period
|
|
end(s) in the specified commodity.
|
|
Equivalent to --value=end,COMM.
|
|
--value=WHEN[,COMM] show amounts converted to their value on the
|
|
specified date(s) in their default valuation
|
|
commodity or a specified commodity. WHEN can be:
|
|
'then': value on transaction dates
|
|
'end': value at period end(s)
|
|
'now': value today
|
|
YYYY-MM-DD: value on given date
|
|
-c --commodity-style=S Override a commodity's display style.
|
|
Eg: -c '.' or -c '1.000,00 EUR'
|
|
--pretty[=YN] Use box-drawing characters in text output? Can be
|
|
'y'/'yes' or 'n'/'no'.
|
|
If YN is specified, the equals is required.
|
|
|
|
General help flags:
|
|
-h --help show command line help
|
|
--tldr show command examples with tldr
|
|
--info show the manual with info
|
|
--man show the manual with man
|
|
--version show version information
|
|
--debug=[1-9] show this much debug output (default: 1)
|
|
--pager=YN use a pager when needed ? y/yes (default) or n/no
|
|
--color=YNA --colour use ANSI color ? y/yes, n/no, or auto (default)
|
|
|
|
Usually hledger accepts any unambiguous flag prefix, eg you can write
|
|
--tl instead of --tldr or --dry instead of --dry-run.
|
|
|
|
You can combine short flags which don't take arguments, eg you can
|
|
write -MAST instead of -M -A -S -T. Flags requiring an argument can't
|
|
be combined in this way (-If FILE won't work).
|
|
|
|
If the same option appears more than once in a command line, usually
|
|
the last (right-most) wins. Similarly, if mutually exclusive flags are
|
|
used together, the right-most wins. (When flags are mutually exclu-
|
|
sive, they'll usually have a group prefix in --help.)
|
|
|
|
With most commands, arguments are interpreted as a hledger query which
|
|
filter the data. Some queries can be expressed either with options or
|
|
with arguments.
|
|
|
|
Below are more tips for using the command line interface - feel free to
|
|
skip these until you need them.
|
|
|
|
Special characters
|
|
In commands you type at the command line, certain characters have spe-
|
|
cial meaning and sometimes need to be "escaped" or "quoted", by prefix-
|
|
ing backslashes or enclosing in quotes.
|
|
|
|
If you are able to minimise the use of special characters in your data,
|
|
you won't have to deal with this as much. For example, you could use
|
|
hyphen - or underscore _ instead of spaces in account names, and you
|
|
could use the USD currency code instead of the $ currency symbol in
|
|
amounts.
|
|
|
|
But if you prefer to use spaced account names and $, it's fine. Just
|
|
be aware of this topic so you can check this doc when needed. (These
|
|
examples are mostly tested on unix; some details might need to be
|
|
adapted if you're on Windows.)
|
|
|
|
Escaping shell special characters
|
|
These are some characters which may have special meaning to your shell
|
|
(the program which interprets command lines):
|
|
|
|
o SPACE, <, >, (, ), |, \, %
|
|
|
|
o $ if followed by a word character
|
|
|
|
So for example, to match an account name containing spaces, like
|
|
"credit card", don't write:
|
|
|
|
$ hledger register credit card
|
|
|
|
Instead, enclose the name in single quotes:
|
|
|
|
$ hledger register 'credit card'
|
|
|
|
On unix or in Windows powershell, if you use double quotes your shell
|
|
will silently treat $ as variable interpolation. So you should proba-
|
|
bly avoid double quotes, unless you want that behaviour, eg in a
|
|
script:
|
|
|
|
$ hledger register "assets:$SOMEACCT"
|
|
|
|
But in an older Windows CMD.EXE window, you must use double quotes:
|
|
|
|
C:\Users\Me> hledger register "credit card"
|
|
|
|
On unix or in Windows powershell, as an alternative to quotes you can
|
|
write a backslash before each special character:
|
|
|
|
$ hledger register credit\ card
|
|
|
|
Finally, since hledger's query arguments are regular expressions (de-
|
|
scribed below), you could also fill that gap with . which matches any
|
|
character:
|
|
|
|
$ hledger register credit.card
|
|
|
|
Escaping regular expression special characters
|
|
Some characters also have special meaning in regular expressions, which
|
|
hledger's arguments often are. Those include:
|
|
|
|
o ., ^, $, [, ], (, ), |, \
|
|
|
|
To escape one of these, write \ before it. But note this is in addi-
|
|
tion to the shell escaping above. So for characters which are special
|
|
to both shell and regular expressions, like \ and $, you will sometimes
|
|
need two levels of escaping.
|
|
|
|
For example, a balance report that uses a cur: query restricting it to
|
|
just the $ currency, should be written like this:
|
|
|
|
$ hledger balance cur:\\$
|
|
|
|
Explanation:
|
|
|
|
1. Add a backslash \ before the dollar sign $ to protect it from regu-
|
|
lar expressions (so it will be matched literally with no special
|
|
meaning).
|
|
|
|
2. Add another backslash before that backslash, to protect it from the
|
|
shell (so the shell won't consume it).
|
|
|
|
3. $ doesn't need to be protected from the shell in this case, because
|
|
it's not followed by a word character; but it would be harmless to
|
|
do so.
|
|
|
|
But here's another way to write that, which tends to be easier: add
|
|
backslashes to escape from regular expressions, then enclose with
|
|
quotes to escape from the shell:
|
|
|
|
$ hledger balance cur:'\$'
|
|
|
|
Escaping in other situations
|
|
hledger options and arguments are sometimes used in places other than
|
|
the command line, where the escaping/quoting rules are different. For
|
|
example, backslash-quoting may not be available. Here's a quick refer-
|
|
ence:
|
|
|
|
In unix shell Use single quotes and/or backslash (or double quotes
|
|
for variable interpolation)
|
|
In Windows power- Use single quotes (or double quotes for variable in-
|
|
shell terpolation)
|
|
In Windows cmd Use double quotes
|
|
In hledger-ui's Use single or double quotes
|
|
filter prompt
|
|
In hledger-web's Use single or double quotes
|
|
search form
|
|
In an argument Don't use spaces, don't shell-escape, do regex-es-
|
|
file cape, write one argument/option per line
|
|
In a config file Use single or double quotes, and enclose the whole
|
|
argument ('desc:a b' not desc:'a b')
|
|
In ghci (the Use double quotes, and enclose the whole argument
|
|
Haskell REPL)
|
|
|
|
Unicode characters
|
|
hledger is expected to handle non-ascii characters correctly:
|
|
|
|
o they should be parsed correctly in input files and on the command
|
|
line, by all hledger tools (add, iadd, hledger-web's search/add/edit
|
|
forms, etc.)
|
|
|
|
o they should be displayed correctly by all hledger tools, and
|
|
on-screen alignment should be preserved.
|
|
|
|
This requires a well-configured environment. Here are some tips:
|
|
|
|
o A system locale must be configured, which can decode the characters
|
|
being used. This is essential - see Text encoding and Install: Text
|
|
encoding.
|
|
|
|
o Your terminal software (eg Terminal.app, iTerm, CMD.exe, xterm..)
|
|
must support unicode. On Windows, you may need to use Windows Termi-
|
|
nal.
|
|
|
|
o The terminal must be using a font which includes the required unicode
|
|
glyphs.
|
|
|
|
o The terminal should be configured to display wide characters as dou-
|
|
ble width (for report alignment).
|
|
|
|
o On Windows, for best results you should run hledger in the same kind
|
|
of environment in which it was built. Eg hledger built in the stan-
|
|
dard CMD.EXE environment (like the binaries on our download page)
|
|
might show display problems when run in a cygwin or msys terminal,
|
|
and vice versa. (See eg #961).
|
|
|
|
Regular expressions
|
|
A regular expression (regexp) is a small piece of text where certain
|
|
characters (like ., ^, $, +, *, (), |, [], \) have special meanings,
|
|
forming a tiny language for matching text precisely - very useful in
|
|
hledger and elsewhere. To learn all about them, visit regular-expres-
|
|
sions.info.
|
|
|
|
hledger supports regexps whenever you are entering a pattern to match
|
|
something, eg in query arguments, account aliases, CSV if rules,
|
|
hledger-web's search form, hledger-ui's / search, etc. You may need to
|
|
wrap them in quotes, especially at the command line (see Special char-
|
|
acters above). Here are some examples:
|
|
|
|
Account name queries (quoted for command line use):
|
|
|
|
Regular expression: Matches:
|
|
------------------- ------------------------------------------------------------
|
|
bank assets:bank, assets:bank:savings, expenses:art:banksy, ...
|
|
:bank assets:bank:savings, expenses:art:banksy
|
|
:bank: assets:bank:savings
|
|
'^bank' none of those ( ^ matches beginning of text )
|
|
'bank$' assets:bank ( $ matches end of text )
|
|
'big \$ bank' big $ bank ( \ disables following character's special meaning )
|
|
'\bbank\b' assets:bank, assets:bank:savings ( \b matches word boundaries )
|
|
'(sav|check)ing' saving or checking ( (|) matches either alternative )
|
|
'saving|checking' saving or checking ( outer parentheses are not needed )
|
|
'savings?' saving or savings ( ? matches 0 or 1 of the preceding thing )
|
|
'my +bank' my bank, my bank, ... ( + matches 1 or more of the preceding thing )
|
|
'my *bank' mybank, my bank, my bank, ... ( * matches 0 or more of the preceding thing )
|
|
'b.nk' bank, bonk, b nk, ... ( . matches any character )
|
|
|
|
Some other queries:
|
|
|
|
desc:'amazon|amzn|audible' Amazon transactions
|
|
cur:EUR amounts with commodity symbol containing EUR
|
|
cur:'\$' amounts with commodity symbol containing $
|
|
cur:'^\$$' only $ amounts, not eg AU$ or CA$
|
|
cur:....? amounts with 4-or-more-character symbols
|
|
tag:.=202[1-3] things with any tag whose value contains 2021, 2022 or 2023
|
|
|
|
Account name aliases: accept . instead of : as account separator:
|
|
|
|
alias /\./=: replaces all periods in account names with colons
|
|
|
|
Show multiple top-level accounts combined as one:
|
|
|
|
--alias='/^[^:]+/=combined' ( [^:] matches any character other than : )
|
|
|
|
Show accounts with the second-level part removed:
|
|
|
|
--alias '/^([^:]+):[^:]+/ = \1'
|
|
match a top-level account and a second-level account
|
|
and replace those with just the top-level account
|
|
( \1 in the replacement text means "whatever was matched
|
|
by the first parenthesised part of the regexp"
|
|
|
|
CSV rules: match CSV records containing dining-related MCC codes:
|
|
|
|
if \?MCC581[124]
|
|
|
|
Match CSV records with a specific amount around the end/start of month:
|
|
|
|
if %amount \b3\.99
|
|
& %date (29|30|31|01|02|03)$
|
|
|
|
hledger's regular expressions
|
|
hledger's regular expressions come from the regex-tdfa library. If
|
|
they're not doing what you expect, it's important to know exactly what
|
|
they support:
|
|
|
|
1. they are case insensitive
|
|
|
|
2. they are infix matching (they do not need to match the entire thing
|
|
being matched)
|
|
|
|
3. they are POSIX ERE (extended regular expressions)
|
|
|
|
4. they also support GNU word boundaries (\b, \B, \<, \>)
|
|
|
|
5. backreferences are supported when doing text replacement in account
|
|
aliases or CSV rules, where backreferences can be used in the re-
|
|
placement string to reference capturing groups in the search regexp.
|
|
Otherwise, if you write \1, it will match the digit 1.
|
|
|
|
6. they do not support mode modifiers ((?s)), character classes (\w,
|
|
\d), or anything else not mentioned above.
|
|
|
|
7. they may not (I'm guessing not) properly support right-to-left or
|
|
bidirectional text.
|
|
|
|
Some things to note:
|
|
|
|
o In the alias directive and --alias option, regular expressions must
|
|
be enclosed in forward slashes (/REGEX/). Elsewhere in hledger,
|
|
these are not required.
|
|
|
|
o In queries, to match a regular expression metacharacter like $ as a
|
|
literal character, prepend a backslash. Eg to search for amounts
|
|
with the dollar sign in hledger-web, write cur:\$.
|
|
|
|
o On the command line, some metacharacters like $ have a special mean-
|
|
ing to the shell and so must be escaped at least once more. See Spe-
|
|
cial characters.
|
|
|
|
Argument files
|
|
You can save a set of command line options and arguments in a file, and
|
|
then use them by writing @FILE.args as a hledger command argument. The
|
|
.args file extension is conventional, but not required. In an argument
|
|
file,
|
|
|
|
o Each line can contain one argument, flag, or option.
|
|
|
|
o Blank lines or lines beginning with # are ignored.
|
|
|
|
o An option's flag and value should be joined by =.
|
|
|
|
o An option value or an argument may contain spaces. Don't use single
|
|
or double quotes.
|
|
|
|
o And generally, use one less level of quoting/escaping than at the
|
|
command line. Eg cur:\$, not cur:\\$ as on the command line.
|
|
|
|
For example:
|
|
|
|
# cash.args
|
|
|
|
assets:cash
|
|
assets:charles schwab:sweep
|
|
cur:\$
|
|
-c=$1.
|
|
|
|
$ hledger bal @cash.args
|
|
|
|
Config files
|
|
With hledger 1.40+, you can save extra command line options and argu-
|
|
ments in a more featureful hledger config file. Here's a small exam-
|
|
ple:
|
|
|
|
# General options are listed first, and used with hledger commands that support them.
|
|
--pretty
|
|
|
|
# Options following a `[COMMAND]` heading are used with that hledger command only.
|
|
[print]
|
|
--explicit --infer-costs
|
|
|
|
To use a config file, specify it with the --conf option. Its options
|
|
will be inserted near the start of your command line, so you can over-
|
|
ride them with command line options if needed.
|
|
|
|
Or, you can set up an automatic config file that is used whenever you
|
|
run hledger, by creating hledger.conf in the current directory or
|
|
above, or .hledger.conf in your home directory (~/.hledger.conf), or
|
|
hledger.conf in your XDG config directory (~/.con-
|
|
fig/hledger/hledger.conf).
|
|
|
|
Here is another example config you could start with:
|
|
https://github.com/simonmichael/hledger/blob/master/hledger.conf.sample
|
|
|
|
You can put not only options, but also arguments in a config file. If
|
|
the first word in a config file's top (general) section does not begin
|
|
with a dash (eg: print), it is treated as the command argument (over-
|
|
riding any argument on the command line).
|
|
|
|
On unix machines, you can add a shebang line at the top of a config
|
|
file, set executable permission on the file, and use it like a script.
|
|
Eg (the -S is needed on some operating systems):
|
|
|
|
#!/usr/bin/env -S hledger --conf
|
|
|
|
You can ignore config files by adding the -n/--no-conf flag to the com-
|
|
mand line. This is useful when using hledger in scripts, or when trou-
|
|
bleshooting. When both --conf and --no-conf options are used, the
|
|
right-most wins.
|
|
|
|
To inspect the processing of config files, use --debug or --debug=8.
|
|
Or, run the setup command, which will display any active config files.
|
|
(setup is not affected by config files itself, unlike other commands.)
|
|
|
|
Warning!
|
|
|
|
There aren't many hledger features that need a warning, but this is
|
|
one!
|
|
|
|
Automatic config files, while convenient, also make hledger less pre-
|
|
dictable and dependable. It's easy to make a config file that changes
|
|
a report's behaviour, or breaks your hledger-using scripts/applica-
|
|
tions, in ways that will surprise you later.
|
|
|
|
If you don't want this,
|
|
|
|
1. Just don't create a hledger.conf file on your machine.
|
|
|
|
2. Also be alert to downloaded directories which may contain a
|
|
hledger.conf file.
|
|
|
|
3. Also if you are sharing scripts or examples or support, consider
|
|
that others may have a hledger.conf file.
|
|
|
|
Conversely, once you decide to use this feature, try to remember:
|
|
|
|
1. Whenever a hledger command does not work as expected, try it again
|
|
with -n (--no-conf) to see if a config file was to blame.
|
|
|
|
2. Whenever you call hledger from a script, consider whether that call
|
|
should use -n or not.
|
|
|
|
3. Be conservative about what you put in your config file; try to con-
|
|
sider the effect on all your reports.
|
|
|
|
4. To troubleshoot the effect of config files, run with --debug or
|
|
--debug 8.
|
|
|
|
The config file feature was added in hledger 1.40.
|
|
|
|
Shell completions
|
|
If you use the bash or zsh shells, you can optionally set up con-
|
|
text-sensitive autocompletion for hledger command lines. Try pressing
|
|
hledger<SPACE><TAB><TAB> (should list all hledger commands) or hledger
|
|
reg acct:<TAB><TAB> (should list your top-level account names). If
|
|
completions aren't working, or for more details, see Install > Shell
|
|
completions.
|
|
|
|
Output
|
|
Output destination
|
|
hledger commands send their output to the terminal by default. You can
|
|
of course redirect this, eg into a file, using standard shell syntax:
|
|
|
|
$ hledger print > foo.txt
|
|
|
|
Some commands (print, register, stats, the balance commands) also pro-
|
|
vide the -o/--output-file option, which does the same thing without
|
|
needing the shell. Eg:
|
|
|
|
$ hledger print -o foo.txt
|
|
$ hledger print -o - # write to stdout (the default)
|
|
|
|
Output format
|
|
Some commands offer other kinds of output, not just text on the termi-
|
|
nal. Here are those commands and the formats currently supported:
|
|
|
|
command txt html csv/tsv fods beancount sql json
|
|
--------------------------------------------------------------------------------------------
|
|
aregister Y Y Y Y Y
|
|
balance Y Y Y Y Y
|
|
balancesheet Y Y Y Y Y
|
|
balancesheetequity Y Y Y Y Y
|
|
cashflow Y Y Y Y Y
|
|
incomestatement Y Y Y Y Y
|
|
print Y Y Y Y Y Y Y
|
|
register Y Y Y Y Y
|
|
|
|
You can also see which output formats a command supports by running
|
|
hledger CMD -h and looking for the -O/--output-format=FMT option,
|
|
|
|
You can select the output format by using that option:
|
|
|
|
$ hledger print -O csv # print CSV to standard output
|
|
|
|
or by choosing a suitable filename extension with the -o/--out-
|
|
put-file=FILE.FMT option:
|
|
|
|
$ hledger balancesheet -o foo.csv # write CSV to foo.csv
|
|
|
|
The -O option can be combined with -o to override the file extension if
|
|
needed:
|
|
|
|
$ hledger balancesheet -o foo.txt -O csv # write CSV to foo.txt
|
|
|
|
Here are some notes about the various output formats.
|
|
|
|
Text output
|
|
This is the default: human readable, plain text report output, suitable
|
|
for viewing with a monospace font in a terminal. If your data contains
|
|
unicode or wide characters, you'll need a terminal and font that render
|
|
those correctly. (This can be challenging on MS Windows.)
|
|
|
|
Some reports (register, aregister) will normally use the full window
|
|
width. If this isn't working or you want to override it, you can use
|
|
the -w/--width option.
|
|
|
|
Balance reports (balance, balancesheet, incomestatement...) use what-
|
|
ever width they need. Multi-period multi-currency reports can often be
|
|
wider than the window. Besides using a pager, helpful techniques for
|
|
this situation include --layout=bare, -X COMM, cur:, --transpose,
|
|
--tree, --depth, --drop, switching to html output, etc.
|
|
|
|
Box-drawing characters
|
|
hledger draws simple table borders by default, to minimise the risk of
|
|
display problems caused by a terminal/font not supporting box-drawing
|
|
characters.
|
|
|
|
But your terminal and font probably do support them, so we recommend
|
|
using the --pretty flag to show prettier tables in the terminal. This
|
|
is a good flag to add to your hledger config file.
|
|
|
|
Colour
|
|
hledger tries to automatically detect ANSI colour and text styling sup-
|
|
port and use it when appropriate. (Currently, it is used rather mini-
|
|
mally: some reports show negative numbers in red, and help output uses
|
|
bold text for emphasis.)
|
|
|
|
You can override this by setting the NO_COLOR environment variable to
|
|
disable it, or by using the --color/--colour option, perhaps in your
|
|
config file, with a y/yes or n/no value to force it on or off.
|
|
|
|
Paging
|
|
In unix-like environments, when displaying large output (in any output
|
|
format) in the terminal, hledger tries to use a pager when appropriate.
|
|
(You can disable this with the --pager=no option, perhaps in your con-
|
|
fig file.)
|
|
|
|
The pager shows one page of text at a time, and lets you scroll around
|
|
to see more. While it is active, usually SPACE shows the next page, h
|
|
shows help, and q quits. The home/end/page up/page down/cursor keys,
|
|
and mouse scrolling, may also work.
|
|
|
|
hledger will use the pager specified by the PAGER environment variable,
|
|
otherwise less if available, otherwise more if available. (With one
|
|
exception: hledger help -p TOPIC will always use less, so that it can
|
|
scroll to the topic.)
|
|
|
|
The pager is expected to display hledger's ANSI colour and text
|
|
styling. If you see junk characters, you might need to configure your
|
|
pager to handle ANSI codes. Or you could disable colour as described
|
|
above.
|
|
|
|
If you are using the less pager, hledger automatically appends a number
|
|
of options to the LESS variable to enable ANSI colour and a number of
|
|
other conveniences. (At the time of writing: --chop-long-lines
|
|
--hilite-unread --ignore-case --no-init --quit-at-eof
|
|
--quit-if-one-screen --RAW-CONTROL-CHARS --shift=8
|
|
--squeeze-blank-lines --use-backslash ). If these don't work well, you
|
|
can set your preferred options in the HLEDGER_LESS variable, which will
|
|
be used instead.
|
|
|
|
HTML output
|
|
HTML output can be styled by an optional hledger.css file in the same
|
|
directory.
|
|
|
|
HTML output will be a HTML fragment, not a complete HTML document.
|
|
Like other hledger output, for non-ascii characters it will use the
|
|
system locale's text encoding (see Text encoding).
|
|
|
|
CSV / TSV output
|
|
In CSV or TSV output, digit group marks (such as thousands separators)
|
|
are disabled automatically.
|
|
|
|
FODS output
|
|
FODS is the OpenDocument Spreadsheet format as plain XML, as accepted
|
|
by LibreOffice and OpenOffice. If you use their spreadsheet applica-
|
|
tions, this is better than CSV because it works across locales (decimal
|
|
point vs. decimal comma, character encoding stored in XML header, thus
|
|
no problems with umlauts), it supports fixed header rows and columns,
|
|
cell types (string vs. number vs. date), separation of number and
|
|
currency (currency is displayed but the cell type is still a number ac-
|
|
cessible for computation), styles (bold), borders. Btw. you can still
|
|
extract CSV from FODS/ODS using various utilities like libreoffice
|
|
--headless or ods2csv.
|
|
|
|
Beancount output
|
|
This is Beancount's journal format. You can use this to export your
|
|
hledger data to Beancount, eg to use the Fava web app.
|
|
|
|
hledger will try to adjust your data to suit Beancount, automatically.
|
|
Be cautious and check the conversion until you are confident it is
|
|
good. If you plan to export to Beancount often, you may want to follow
|
|
its conventions, for a cleaner conversion:
|
|
|
|
o use Beancount-friendly account names
|
|
|
|
o use currency codes instead of currency symbols
|
|
|
|
o use cost notation instead of equity conversion postings
|
|
|
|
o avoid virtual postings, balance assignments, and secondary dates.
|
|
|
|
There is one big adjustment you must handle yourself: for Beancount,
|
|
the top level account names must be Assets, Liabilities, Equity, In-
|
|
come, and/or Expenses. You can use account aliases to rewrite your ac-
|
|
count names temporarily, if needed, as in this hledger2beancount.conf
|
|
config file.
|
|
|
|
2024-12-20: Some more things not yet handled for you:
|
|
|
|
o P directives are not converted automatically - convert those your-
|
|
self.
|
|
|
|
o Balance assignments are not converted (Beancount doesn't support
|
|
them) - replace those with explicit amounts.
|
|
|
|
Beancount account names
|
|
Aside from the top-level names, hledger will adjust your account names
|
|
to make valid Beancount account names, by capitalising each part, re-
|
|
placing spaces with -, replacing other unsupported characters with
|
|
C<HEXBYTES>, prepending A to account name parts which don't begin with
|
|
a letter or digit, and appending :A to account names which have only
|
|
one part.
|
|
|
|
Beancount commodity names
|
|
hledger will adjust your commodity names to make valid Beancount com-
|
|
modity/currency names, which must be 2-24 uppercase letters, digits, or
|
|
', ., _, -, beginning with a letter and ending with a letter or digit.
|
|
hledger will convert known currency symbols to ISO 4217 currency codes,
|
|
capitalise letters, replace spaces with -, replace other unsupported
|
|
characters with C<HEXBYTES>, and prepend or append C if needed.
|
|
|
|
Beancount virtual postings
|
|
Beancount doesn't allow virtual postings; if you have any, they will be
|
|
omitted from beancount output.
|
|
|
|
Beancount metadata
|
|
hledger tags will be converted to Beancount metadata (except for tags
|
|
whose name begins with _). Metadata names will be adjusted to be Bean-
|
|
count-compatible: beginning with a lowercase letter, at least two char-
|
|
acters long, and with unsupported characters encoded. Metadata values
|
|
will use Beancount's string type.
|
|
|
|
In hledger, objects can have the same tag repeated with multiple val-
|
|
ues. Eg an assets:cash account might have both type:Asset and
|
|
type:Cash tags. For Beancount these will be combined into one, with
|
|
the values combined, comma separated. Eg: type: "Asset, Cash".
|
|
|
|
Beancount costs
|
|
Beancount doesn't allow redundant costs and conversion postings as
|
|
hledger does. If you have any of these, the conversion postings will
|
|
be omitted. Currently we support at most one cost + conversion post-
|
|
ings group per transaction.
|
|
|
|
Beancount operating currency
|
|
Declaring an operating currency (or several) improves Beancount and
|
|
Fava reports. Currently hledger will declare each currency used in
|
|
cost amounts as an operating currency. If needed, replace these with
|
|
your own declaration, like
|
|
|
|
option "operating_currency" "USD"
|
|
|
|
SQL output
|
|
SQL output is expected to work at least with SQLite, MySQL and Post-
|
|
gres.
|
|
|
|
The SQL statements are expected to be executed in the empty database.
|
|
If you already have tables created via SQL output of hledger, you would
|
|
probably want to either clear data from these (via delete or truncate
|
|
SQL statements) or drop the tables completely before import; otherwise
|
|
your postings would be duplicated.
|
|
|
|
For SQLite, it is more useful if you modify the generated id field to
|
|
be a PRIMARY KEY. Eg:
|
|
|
|
$ hledger print -O sql | sed 's/id serial/id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL/g' | ...
|
|
|
|
This is not yet much used; feedback is welcome.
|
|
|
|
JSON output
|
|
Our JSON is rather large and verbose, since it is a faithful represen-
|
|
tation of hledger's internal data types. To understand its structure,
|
|
read the Haskell type definitions, which are mostly in
|
|
https://github.com/simonmichael/hledger/blob/mas-
|
|
ter/hledger-lib/Hledger/Data/Types.hs. hledger-web's OpenAPI specifi-
|
|
cation may also be relevant.
|
|
|
|
hledger stores numbers with sometimes up to 255 significant digits.
|
|
This is too many digits for most JSON consumers, so in JSON output we
|
|
round numbers to at most 10 decimal places. (We don't limit the number
|
|
of integer digits.) If you find this causing problems, please let us
|
|
know. Related: #1195
|
|
|
|
This is not yet much used; feedback is welcome.
|
|
|
|
Commodity styles
|
|
When displaying amounts, hledger infers a standard display style for
|
|
each commodity/currency, as described below in Commodity display style.
|
|
|
|
If needed, this can be overridden by a -c/--commodity-style option (ex-
|
|
cept for cost amounts and amounts displayed by the print command, which
|
|
are always displayed with all decimal digits). For example, the fol-
|
|
lowing will force dollar amounts to be displayed as shown:
|
|
|
|
$ hledger print -c '$1.000,0'
|
|
|
|
This option can be repeated to set the display style for multiple com-
|
|
modities/currencies. Its argument is as described in the commodity di-
|
|
rective. Note that omitting the commodity symbol will set the display
|
|
style for just the no-symbol commodity, not all commodities.
|
|
|
|
In some cases hledger will adjust number formatting to improve their
|
|
parseability (such as adding trailing decimal marks when needed).
|
|
|
|
Debug output
|
|
We intend hledger to be relatively easy to troubleshoot, introspect and
|
|
develop. You can add --debug[=N] to any hledger command line to see
|
|
additional debug output. N ranges from 1 (least output, the default)
|
|
to 9 (maximum output). Typically you would start with 1 and increase
|
|
until you are seeing enough. Debug output goes to stderr, and is not
|
|
affected by -o/--output-file (unless you redirect stderr to stdout, eg:
|
|
2>&1). It will be interleaved with normal output, which can help re-
|
|
veal when parts of the code are evaluated. To capture debug output in
|
|
a log file instead, you can usually redirect stderr, eg:
|
|
|
|
hledger bal --debug=3 2>hledger.log
|
|
|
|
(This option doesn't work in a config file yet.)
|
|
|
|
Environment
|
|
These environment variables affect hledger:
|
|
|
|
HLEDGER_LESS If less is your pager, this variable specifies the less
|
|
options hledger should use. (Otherwise, LESS + custom options are
|
|
used.)
|
|
|
|
LEDGER_FILE The default journal file, to be used when no -f/--file op-
|
|
tion is provided. For example, it could be ~/finance/main.journal.
|
|
This can also be a glob pattern, eg ./2???.journal. (If the glob
|
|
matches multiple files, only the alphanumerically first one is used.)
|
|
If LEDGER_FILE points to a non-existent file, an error will be raised.
|
|
If the value is the empty string, it is ignored.
|
|
|
|
If LEDGER_FILE is not set and -f is not provided, the default journal
|
|
file is $HOME/.hledger.journal (or if a home directory can't be de-
|
|
tected, ./.hledger.journal).
|
|
|
|
See also Common tasks > Setting LEDGER_FILE.
|
|
|
|
NO_COLOR If this environment variable exists (with any value, including
|
|
empty), hledger will not use ANSI color codes in terminal output, un-
|
|
less overridden by an explicit --color=y or --colour=y option.
|
|
|
|
PART 2: DATA FORMATS
|
|
Journal
|
|
hledger's usual data source is a plain text file containing journal en-
|
|
tries in hledger journal format. If you're looking for a quick refer-
|
|
ence, jump ahead to the journal cheatsheet (or use the table of con-
|
|
tents at https://hledger.org/hledger.html).
|
|
|
|
This file represents an accounting General Journal. The .journal file
|
|
extension is most often used, though not strictly required. The jour-
|
|
nal file contains a number of transaction entries, each describing a
|
|
transfer of money (or any commodity) between two or more named ac-
|
|
counts, in a simple format readable by both hledger and humans.
|
|
|
|
hledger's journal format is compatible with most of Ledger's journal
|
|
format, but not all of it. The differences and interoperation tips are
|
|
described at hledger and Ledger. With some care, and by avoiding in-
|
|
compatible features, you can keep your hledger journal readable by
|
|
Ledger and vice versa. This can useful eg for comparing the behaviour
|
|
of one app against the other.
|
|
|
|
You can use hledger without learning any more about this file; just use
|
|
the add or web or import commands to create and update it.
|
|
|
|
Many users, though, edit the journal file with a text editor, and track
|
|
changes with a version control system such as git. Editor add-ons such
|
|
as ledger-mode or hledger-mode for Emacs, vim-ledger for Vim, and
|
|
hledger-vscode for Visual Studio Code, make this easier, adding colour,
|
|
formatting, tab completion, and useful commands. See Editors at
|
|
hledger.org for the full list.
|
|
|
|
A hledger journal file can contain three kinds of thing: comment lines,
|
|
transactions, and/or directives (including periodic transaction rules
|
|
and auto posting rules). Understanding the journal file format will
|
|
also give you a good understanding of hledger's data model. Here's a
|
|
quick cheatsheet/overview, followed by detailed descriptions of each
|
|
part.
|
|
|
|
Journal cheatsheet
|
|
# Here is the main syntax of hledger's journal format
|
|
# (omitting extra Ledger compatibility syntax).
|
|
|
|
###############################################################################
|
|
|
|
# 1. These are comment lines, for notes or temporarily disabling things.
|
|
; They begin with # or ;
|
|
|
|
comment
|
|
Or, lines can be enclosed within "comment" / "end comment".
|
|
This is a block of
|
|
commented lines.
|
|
end comment
|
|
|
|
# Some journal entries can have semicolon comments at end of line ; like this
|
|
# Some of them require 2 or more spaces before the semicolon.
|
|
|
|
###############################################################################
|
|
|
|
# 2. Directives customise processing or output in some way.
|
|
# You don't need any directives to get started.
|
|
# But they can add more error checking, or change how things are displayed.
|
|
# They begin with a word, letter, or symbol.
|
|
# They are most often placed at the top, before transactions.
|
|
|
|
account assets ; Declare valid account names and display order.
|
|
account assets:savings ; A subaccount. This one represents a bank account.
|
|
account assets:checking ; Another. Note, 2+ spaces after the account name.
|
|
account assets:receivable ; Accounting type is inferred from english names,
|
|
account passifs ; or declared with a "type" tag, type:L
|
|
account expenses ; type:X
|
|
; A follow-on comment line, indented.
|
|
account expenses:rent ; Expense and revenue categories are also accounts.
|
|
; Subaccounts inherit their parent's type.
|
|
|
|
commodity $0.00 ; Declare valid commodities and their display styles.
|
|
commodity 1.000,00 EUR
|
|
|
|
decimal-mark . ; The decimal mark used in this file (if ambiguous).
|
|
|
|
payee Whole Foods ; Declare a valid payee name.
|
|
|
|
tag trip ; Declare a valid tag name.
|
|
|
|
P 2024-03-01 AAPL $179 ; Declare a market price for AAPL in $ on this date.
|
|
|
|
include other.journal ; Include another journal file here.
|
|
|
|
# Declare a recurring "periodic transaction", for budget/forecast reports
|
|
~ monthly set budget goals ; <- Note, 2+ spaces before the description.
|
|
(expenses:rent) $1000
|
|
(expenses:food) $500
|
|
|
|
# Declare an auto posting rule, to modify existing transactions in reports
|
|
= revenues:consulting
|
|
liabilities:tax:2024:us *0.25 ; Add a tax liability & expense
|
|
expenses:tax:2024:us *-0.25 ; for 25% of the revenue.
|
|
|
|
###############################################################################
|
|
|
|
# 3. Transactions are what it's all about.
|
|
# They are dated events, usually movements of money between 2 or more accounts.
|
|
# They begin with a numeric date.
|
|
# Here is their basic shape:
|
|
#
|
|
# DATE DESCRIPTION ; The transaction's date and optional description.
|
|
# ACCOUNT1 AMOUNT ; A posting of an amount to/from this account, indented.
|
|
# ACCOUNT2 AMOUNT ; A second posting, balancing the first.
|
|
# ... ; More if needed. Amounts must sum to zero.
|
|
# ; Note, 2+ spaces between account names and amounts.
|
|
|
|
2024-01-01 opening balances ; At the start, declare pre-existing balances this way.
|
|
assets:savings $10000 ; Account names can be anything. lower case is easy to type.
|
|
assets:checking $1000 ; assets, liabilities, equity, revenues, expenses are common.
|
|
liabilities:credit card $-500 ; liabilities, equity, revenues balances are usually negative.
|
|
equity:start ; One amount can be left blank. $-10500 is inferred here.
|
|
; Some of these accounts we didn't declare above,
|
|
; so -s/--strict would complain.
|
|
|
|
2024-01-03 ! (12345) pay rent
|
|
; Additional transaction comment lines, indented.
|
|
; There can be a ! or * after the date meaning "pending" or "cleared".
|
|
; There can be a parenthesised (code) after the date/status.
|
|
; Amounts' sign shows direction of flow.
|
|
assets:checking $-500 ; Minus means removed from this account (credit).
|
|
expenses:rent $500 ; Plus means added to this account (debit).
|
|
|
|
; Keeping transactions in date order is optional (but helps error checking).
|
|
|
|
2024-01-02 Gringott's Bank | withdrawal ; Description can be PAYEE | NOTE
|
|
assets:bank:gold -10 gold
|
|
assets:pouch 10 gold
|
|
|
|
2024-01-02 shopping
|
|
expenses:clothing 1 gold
|
|
expenses:wands 5 gold
|
|
assets:pouch -6 gold
|
|
|
|
2024-01-02 receive gift
|
|
revenues:gifts -3 "Chocolate Frogs" ; Complex commodity symbols
|
|
assets:pouch 3 "Chocolate Frogs" ; must be in double quotes.
|
|
|
|
2024-01-15 buy some shares, in two lots ; Cost can be noted.
|
|
assets:investments:2024-01-15 2.0 AAAA @ $1.50 ; @ means per-unit cost
|
|
assets:investments:2024-01-15-02 3.0 AAAA @@ $4 ; @@ means total cost
|
|
; ^ Per-lot subaccounts are sometimes useful.
|
|
assets:checking $-7
|
|
|
|
2024-01-15 assert some account balances on this date
|
|
; Balances can be asserted in any transaction, with =, for extra error checking.
|
|
; Assertion txns like this one can be made with hledger close --assert --show-costs
|
|
;
|
|
assets:savings $0 = $10000
|
|
assets:checking $0 = $493
|
|
assets:bank:gold 0 gold = -10 gold
|
|
assets:pouch 0 gold = 4 gold
|
|
assets:pouch 0 "Chocolate Frogs" = 3 "Chocolate Frogs"
|
|
assets:investments:2024-01-15 0.0 AAAA = 2.0 AAAA @ $1.50
|
|
assets:investments:2024-01-15-02 0.0 AAAA = 3.0 AAAA @@ $4
|
|
liabilities:credit card $0 = $-500
|
|
|
|
2024-02-01 note some event, or a transaction not yet fully entered, on this date
|
|
; Postings are not required.
|
|
|
|
# Consistent YYYY-MM-DD date format is recommended,
|
|
# but you can use . or / and omit leading zeros if you prefer.
|
|
2024.01.01
|
|
2024/1/1
|
|
|
|
Comments
|
|
Lines in the journal will be ignored if they begin with a hash (#) or a
|
|
semicolon (;). (See also Other syntax.) hledger will also ignore re-
|
|
gions beginning with a comment line and ending with an end comment line
|
|
(or file end). Here's a suggestion for choosing between them:
|
|
|
|
o # for top-level notes
|
|
|
|
o ; for commenting out things temporarily
|
|
|
|
o comment for quickly commenting large regions (remember it's there, or
|
|
you might get confused)
|
|
|
|
Eg:
|
|
|
|
# a comment line
|
|
; another commentline
|
|
comment
|
|
A multi-line comment block,
|
|
continuing until "end comment" directive
|
|
or the end of the current file.
|
|
end comment
|
|
|
|
Some hledger entries can have same-line comments attached to them, from
|
|
; (semicolon) to end of line. See Transaction comments, Posting com-
|
|
ments, and Account comments below.
|
|
|
|
Transactions
|
|
Transactions are the main unit of information in a journal file. They
|
|
represent events, typically a movement of some quantity of commodities
|
|
between two or more named accounts.
|
|
|
|
Each transaction is recorded as a journal entry, beginning with a sim-
|
|
ple date in column 0. This can be followed by any of the following op-
|
|
tional fields, separated by spaces:
|
|
|
|
o a status character (empty, !, or *)
|
|
|
|
o a code (any short number or text, enclosed in parentheses)
|
|
|
|
o a description (any remaining text until end of line or a semicolon)
|
|
|
|
o a comment (any remaining text following a semicolon until end of
|
|
line, and any following indented lines beginning with a semicolon)
|
|
|
|
o 0 or more indented posting lines, describing what was transferred and
|
|
the accounts involved (indented comment lines are also allowed, but
|
|
not blank lines or non-indented lines).
|
|
|
|
Here's a simple journal file containing one transaction:
|
|
|
|
2008/01/01 income
|
|
assets:bank:checking $1
|
|
income:salary $-1
|
|
|
|
Dates
|
|
Simple dates
|
|
Dates in the journal file use simple dates format: YYYY-MM-DD or
|
|
YYYY/MM/DD or YYYY.MM.DD, with leading zeros optional. The year may be
|
|
omitted, in which case it will be inferred from the context: the cur-
|
|
rent transaction, the default year set with a Y directive, or the cur-
|
|
rent date when the command is run. Some examples: 2010-01-31,
|
|
2010/01/31, 2010.1.31, 1/31.
|
|
|
|
(The UI also accepts simple dates, as well as the more flexible smart
|
|
dates documented in the hledger manual.)
|
|
|
|
Posting dates
|
|
You can give individual postings a different date from their parent
|
|
transaction, by adding a posting comment containing a tag (see below)
|
|
like ; date:DATE. (There's also a Ledger-compatible syntax, ; [DATE],
|
|
which can be convenient.)
|
|
|
|
This is probably the best way to control posting dates precisely. Eg
|
|
in this example the expense should appear in May reports, and the de-
|
|
duction from checking should be reported on 6/1 for easy bank reconcil-
|
|
iation:
|
|
|
|
2015/5/30
|
|
expenses:food $10 ; food purchased on saturday 5/30
|
|
assets:checking ; bank cleared it on monday, date:6/1
|
|
|
|
$ hledger -f t.j register food
|
|
2015-05-30 expenses:food $10 $10
|
|
|
|
$ hledger -f t.j register checking
|
|
2015-06-01 assets:checking $-10 $-10
|
|
|
|
DATE should be a simple date; if the year is not specified it will use
|
|
the year of the transaction's date.
|
|
The date: tag must have a valid simple date value if it is present, eg
|
|
a date: tag with no value is not allowed.
|
|
|
|
Status
|
|
Transactions (or individual postings within a transaction) can have a
|
|
status mark, which is a single character before the transaction de-
|
|
scription (or posting account name), separated from it by a space, in-
|
|
dicating one of three statuses:
|
|
|
|
mark status
|
|
------------------
|
|
unmarked
|
|
! pending
|
|
* cleared
|
|
|
|
When reporting, you can filter by status with the -U/--unmarked,
|
|
-P/--pending, and -C/--cleared flags (and you can combine these, eg -UP
|
|
to match all except cleared things). Or you can use the status:, sta-
|
|
tus:!, and status:* queries, or the U, P, C keys in hledger-ui.
|
|
|
|
(Note: in Ledger the "unmarked" state is called "uncleared"; in hledger
|
|
we renamed it to "unmarked" for semantic clarity.)
|
|
|
|
Status marks are optional, but can be helpful eg for reconciling with
|
|
real-world accounts. Some editor modes provide highlighting and short-
|
|
cuts for working with status. Eg in Emacs ledger-mode, you can toggle
|
|
transaction status with C-c C-e, or posting status with C-c C-c.
|
|
|
|
What "uncleared", "pending", and "cleared" actually mean is up to you.
|
|
Here's one suggestion:
|
|
|
|
status meaning
|
|
--------------------------------------------------------------------------
|
|
uncleared recorded but not yet reconciled; needs review
|
|
pending tentatively reconciled (if needed, eg during a big reconcil-
|
|
iation)
|
|
cleared complete, reconciled as far as possible, and considered cor-
|
|
rect
|
|
|
|
With this scheme, you would use -PC to see the current balance at your
|
|
bank, -U to see things which will probably hit your bank soon (like un-
|
|
cashed checks), and no flags to see the most up-to-date state of your
|
|
finances.
|
|
|
|
Code
|
|
After the status mark, but before the description, you can optionally
|
|
write a transaction "code", enclosed in parentheses. This is a good
|
|
place to record a check number, or some other important transaction id
|
|
or reference number.
|
|
|
|
Description
|
|
After the date, status mark and/or code fields, the rest of the line
|
|
(or until a comment is begun with ;) is the transaction's description.
|
|
Here you can describe the transaction (called the "narration" in tradi-
|
|
tional bookkeeping), or you can record a payee/payer name, or you can
|
|
leave it empty.
|
|
|
|
Transaction descriptions show up in print output and in register re-
|
|
ports, and can be listed with the descriptions command.
|
|
|
|
You can query by description with desc:DESCREGEX, or pivot on descrip-
|
|
tion with --pivot desc.
|
|
|
|
Payee and note
|
|
Sometimes people want a dedicated payee/payer field that can be queried
|
|
and checked more strictly. If you want that, you can write a | (pipe)
|
|
character in the description. This divides it into a "payee" field on
|
|
the left, and a "note" field on the right. (Either can be empty.)
|
|
|
|
You can query these with payee:PAYEEREGEX and note:NOTEREGEX, list
|
|
their values with the payees and notes commands, or pivot on payee or
|
|
note.
|
|
|
|
Note: in transactions with no | character, description, payee, and note
|
|
all have the same value. Once a | is added, they become distinct. (If
|
|
you'd like to change this behaviour, please propose it on the mail
|
|
list.)
|
|
|
|
If you want more strict error checking, you can declare the valid payee
|
|
names with payee directives, and then enforce these with hledger check
|
|
payees. (Note: because of the above, for this you'll need to ensure
|
|
every transaction description contains a | and therefore a checkable
|
|
payee name, even if it's empty.)
|
|
|
|
Transaction comments
|
|
Text following ;, after a transaction description, and/or on indented
|
|
lines immediately below it, form comments for that transaction. They
|
|
are reproduced by print but otherwise ignored, except they may contain
|
|
tags, which are not ignored.
|
|
|
|
2012-01-01 something ; a transaction comment
|
|
; a second line of transaction comment
|
|
expenses 1
|
|
assets
|
|
|
|
Postings
|
|
A posting is an addition of some amount to, or removal of some amount
|
|
from, an account. Each posting line begins with at least one space or
|
|
tab (2 or 4 spaces is common), followed by:
|
|
|
|
o (optional) a status character (empty, !, or *), followed by a space
|
|
|
|
o (required) an account name (any text, optionally including single
|
|
spaces. If anything follows the account name on the same line, the
|
|
account name must be ended by two or more spaces.)
|
|
|
|
o (optional) an amount
|
|
|
|
o (optional) a same-line posting comment, beginning with a semicolon
|
|
(;).
|
|
|
|
If the amount is positive, it is being added to the account; if nega-
|
|
tive, it is being removed from the account.
|
|
|
|
The posting amounts in a transaction must sum up to zero, indicating
|
|
that the inflows and outflows are equal. We call this a balanced
|
|
transaction. (You can read more about the details of transaction bal-
|
|
ancing below.)
|
|
|
|
If no amount is written, it will be calculated automatically from the
|
|
other postings in the transaction, so as to balance the transaction.
|
|
In other words, in any transaction you can leave one posting amountless
|
|
to save typing.
|
|
|
|
Debits and credits
|
|
The traditional accounting concepts of debit and credit of course exist
|
|
in hledger, but we represent them with numeric sign. Positive and neg-
|
|
ative posting amounts represent debits and credits respectively.
|
|
|
|
You don't need to remember that, but if you would like to - eg for
|
|
helping newcomers or for talking with your accountant - here's a handy
|
|
mnemonic:
|
|
|
|
debit / plus / left / short words
|
|
credit / minus / right / longer words
|
|
|
|
Account names
|
|
Accounts are the main way of categorising things in hledger. As in
|
|
Double Entry Bookkeeping, they can represent real world accounts (such
|
|
as a bank account), or more abstract categories such as "money spent on
|
|
food" or "money borrowed from Frank".
|
|
|
|
Account names are flexible. They may be capitalised or not; they may
|
|
contain letters, numbers, punctuation, symbols, or single spaces; they
|
|
may be in any language.
|
|
|
|
Typically we use the five traditional accounting categories as the
|
|
starting point for account names. In english they are:
|
|
|
|
assets, liabilities, equity, revenues, expenses
|
|
|
|
These will be discussed more in Account types below. In hledger docs
|
|
you may see them referred to as A, L, E, R, X for short.
|
|
|
|
Two space delimiter
|
|
Note the two or more spaces delimiter that's sometimes required after
|
|
account names. hledger's account names, inherited from Ledger, are
|
|
very permissive; they may contain pretty much any kind of text, includ-
|
|
ing single spaces and semicolons. Because of this, they must be termi-
|
|
nated by two or more spaces if there is anything following them on the
|
|
same line. For example, if an amount, balance assignment, or same-line
|
|
comment follows an account name, they must be preceded by two or more
|
|
spaces, else they would be considered part of the account name:
|
|
|
|
bad: assets:accounts receivable $10 ; <- too close!
|
|
good: assets:accounts receivable $10
|
|
|
|
bad: assets:accounts receivable =$1000 ; <- too close!
|
|
good: assets:accounts receivable =$1000
|
|
|
|
bad: assets:accounts receivable ; comment. <- too close!
|
|
good: assets:accounts receivable ; comment
|
|
|
|
This two-space delimiter appears in a few places in hledger, such as
|
|
after account names in postings or account directives; also after the
|
|
period expression in periodic transaction rules. When you are starting
|
|
out, expect it to catch you out at least once. It's annoying some-
|
|
times, but it lets us use expressive account names while still keeping
|
|
the syntax light.
|
|
|
|
Account hierarchy
|
|
For more precise reporting, we usually divide accounts into more de-
|
|
tailed subaccounts, subsubaccounts, and so on, by writing a full colon
|
|
between account name parts. For example, instead of writing assets and
|
|
expenses, we might write assets:bank:checking and expenses:food. From
|
|
these names hledger will infer this hierarchy of five accounts:
|
|
|
|
assets
|
|
assets:bank
|
|
assets:bank:checking
|
|
expenses
|
|
expenses:food
|
|
|
|
Or as an outline:
|
|
|
|
assets
|
|
bank
|
|
checking
|
|
expenses
|
|
food
|
|
|
|
hledger reports can summarise the account tree to any depth, so you can
|
|
make your subcategories as detailed as you like. But don't go over-
|
|
board, especially when getting started; simpler categories can be less
|
|
work.
|
|
|
|
Other account name features
|
|
Enclosing the account name in parentheses or brackets, like (ex-
|
|
penses:food), enables a non-standard bookkeeping feature: virtual post-
|
|
ings.
|
|
|
|
Account names can be rewritten and restructured, temporarily or perma-
|
|
nently, by account aliases.
|
|
|
|
Amounts
|
|
After the account name, there is usually an amount. (Remember: between
|
|
account name and amount, there must be two or more spaces.)
|
|
|
|
hledger's amount format is flexible, supporting several international
|
|
formats. Here are some examples. Amounts have a number (the "quan-
|
|
tity"):
|
|
|
|
1
|
|
|
|
..and usually a currency symbol or commodity name (more on this below),
|
|
to the left or right of the quantity, with or without a separating
|
|
space:
|
|
|
|
$1
|
|
4000 AAPL
|
|
3 "green apples"
|
|
|
|
Amounts can be preceded by a minus sign (or a plus sign, though plus is
|
|
the default), The sign can be written before or after a left-side com-
|
|
modity symbol:
|
|
|
|
-$1
|
|
$-1
|
|
|
|
One or more spaces between the sign and the number are acceptable when
|
|
parsing (but they won't be displayed in output):
|
|
|
|
+ $1
|
|
$- 1
|
|
|
|
Scientific E notation is allowed:
|
|
|
|
1E-6
|
|
EUR 1E3
|
|
|
|
Decimal marks
|
|
A decimal mark can be written as a period or a comma:
|
|
|
|
1.23
|
|
1,23
|
|
|
|
Both of these are common in international number formats, so hledger is
|
|
not biased towards one or the other. Because hledger also supports
|
|
digit group marks (eg thousands separators), this means that a number
|
|
like 1,000 or 1.000 containing just one period or comma is ambiguous.
|
|
In such cases, hledger by default assumes it is a decimal mark, and
|
|
will parse both of those as 1.
|
|
|
|
To help hledger parse such ambiguous numbers more accurately, if you
|
|
use digit group marks, we recommend declaring the decimal mark explic-
|
|
itly. The best way is to add a decimal-mark directive at the top of
|
|
each data file, like this:
|
|
|
|
decimal-mark .
|
|
|
|
Or you can declare it per commodity with commodity directives, de-
|
|
scribed below.
|
|
|
|
hledger also accepts numbers like 10. with no digits after the decimal
|
|
mark (and will sometimes display numbers that way to disambiguate them
|
|
- see Trailing decimal marks).
|
|
|
|
Digit group marks
|
|
In the integer part of the amount quantity (left of the decimal mark),
|
|
groups of digits can optionally be separated by a digit group mark - a
|
|
comma or period (whichever is not used as decimal mark), or a space
|
|
(several Unicode space variants, like no-break space, are also ac-
|
|
cepted). So these are all valid amounts in a journal file:
|
|
|
|
$1,000,000.00
|
|
EUR 2.000.000,00
|
|
INR 9,99,99,999.00
|
|
1 000 000.00 ; <- ordinary space
|
|
1 000 000.00 ; <- no-break space
|
|
|
|
Commodity
|
|
Amounts in hledger have both a "quantity", which is a signed decimal
|
|
number, and a "commodity", which is a currency symbol, stock ticker, or
|
|
any word or phrase describing something you are tracking.
|
|
|
|
If the commodity name contains non-letters (spaces, numbers, or punctu-
|
|
ation), you must always write it inside double quotes ("green apples",
|
|
"ABC123").
|
|
|
|
If you write just a bare number, that too will have a commodity, with
|
|
name ""; we call that the "no-symbol commodity".
|
|
|
|
Actually, hledger combines these single-commodity amounts into more
|
|
powerful multi-commodity amounts, which are what it works with most of
|
|
the time. A multi-commodity amount could be, eg: 1 USD, 2 EUR, 3.456
|
|
TSLA. In practice, you will only see multi-commodity amounts in
|
|
hledger's output; you can't write them directly in the journal file.
|
|
|
|
By default, the format of amounts in the journal influences how hledger
|
|
displays them in output. This is explained in Commodity display style
|
|
below.
|
|
|
|
Costs
|
|
After a posting amount, you can note its cost (when buying) or selling
|
|
price (when selling) in another commodity, by writing either @ UNIT-
|
|
PRICE or @@ TOTALPRICE after it. This indicates a conversion transac-
|
|
tion, where one commodity is exchanged for another.
|
|
|
|
(You might also see this called "transaction price" in hledger docs,
|
|
discussions, or code; that term was directionally neutral and reminded
|
|
that it is a price specific to a transaction, but we now just call it
|
|
"cost", with the understanding that the transaction could be a purchase
|
|
or a sale.)
|
|
|
|
Costs are usually written explicitly with @ or @@, but can also be in-
|
|
ferred automatically for simple multi-commodity transactions. Note, if
|
|
costs are inferred, the order of postings is significant; the first
|
|
posting will have a cost attached, in the commodity of the second.
|
|
|
|
As an example, here are several ways to record purchases of a foreign
|
|
currency in hledger, using the cost notation either explicitly or im-
|
|
plicitly:
|
|
|
|
1. Write the price per unit, as @ UNITPRICE after the amount:
|
|
|
|
2009/1/1
|
|
assets:euros 100 @ $1.35 ; one hundred euros purchased at $1.35 each
|
|
assets:dollars ; balancing amount is -$135.00
|
|
|
|
2. Write the total price, as @@ TOTALPRICE after the amount:
|
|
|
|
2009/1/1
|
|
assets:euros 100 @@ $135 ; one hundred euros purchased at $135 for the lot
|
|
assets:dollars
|
|
|
|
3. Specify amounts for all postings, using exactly two commodities, and
|
|
let hledger infer the price that balances the transaction. Note the
|
|
effect of posting order: the price is added to first posting, making
|
|
it 100 @@ $135, as in example 2:
|
|
|
|
2009/1/1
|
|
assets:euros 100 ; one hundred euros purchased
|
|
assets:dollars $-135 ; for $135
|
|
|
|
Amounts can be converted to cost at report time using the -B/--cost
|
|
flag; this is discussed more in the Cost reporting section.
|
|
|
|
Note that the cost normally should be a positive amount, though it's
|
|
not required to be. This can be a little confusing, see discussion at
|
|
--infer-market-prices: market prices from transactions.
|
|
|
|
Balance assertions
|
|
hledger supports Ledger-style balance assertions in journal files.
|
|
These look like, for example, = EXPECTEDBALANCE following a posting's
|
|
amount. Eg here we assert the expected dollar balance in accounts a
|
|
and b after each posting:
|
|
|
|
2013/1/1
|
|
a $1 = $1
|
|
b = $-1
|
|
|
|
2013/1/2
|
|
a $1 = $2
|
|
b $-1 = $-2
|
|
|
|
After reading a journal file, hledger will check all balance assertions
|
|
and report an error if any of them fail. Balance assertions can pro-
|
|
tect you from, eg, inadvertently disrupting reconciled balances while
|
|
cleaning up old entries. You can disable them temporarily with the
|
|
-I/--ignore-assertions flag, which can be useful for troubleshooting or
|
|
for reading Ledger files. (Note: this flag currently does not disable
|
|
balance assignments, described below).
|
|
|
|
Assertions and ordering
|
|
hledger calculates and checks an account's balance assertions in date
|
|
order (and when there are multiple assertions on the same day, in parse
|
|
order). Note this is different from Ledger, which checks assertions
|
|
always in parse order, ignoring dates.
|
|
|
|
This means in hledger you can freely reorder transactions, postings, or
|
|
files, and balance assertions will usually keep working. The exception
|
|
is when you reorder multiple postings on the same day, to the same ac-
|
|
count, which have balance assertions; those will likely need updating.
|
|
|
|
Assertions and multiple files
|
|
If an account has transactions appearing in multiple files, balance as-
|
|
sertions can still work - but only if those files are part of a hierar-
|
|
chy made by include directives.
|
|
|
|
If the same files are specified with two -f options on the command
|
|
line, the assertions in the second will not see the balances from the
|
|
first.
|
|
|
|
To work around this, arrange your files in a hierarchy with include.
|
|
Or, you could concatenate the files temporarily, and process them like
|
|
one big file.
|
|
|
|
Why does it work this way ? It might be related to hledger's goal of
|
|
stable predictable reports. File hierarchy is considered "permanent",
|
|
part of your data, while the order of command line options/arguments is
|
|
not. We don't want transient changes to be able to change the meaning
|
|
of the data. Eg it would be frustrating if tomorrow all your balance
|
|
assertions broke because you wrote command line arguments in a differ-
|
|
ent order. (Discussion welcome.)
|
|
|
|
Assertions and costs
|
|
Balance assertions ignore costs, and should normally be written without
|
|
one:
|
|
|
|
2019/1/1
|
|
(a) $1 @ 1 = $1
|
|
|
|
We do allow costs to be written in balance assertion amounts, however,
|
|
and print shows them, but they don't affect whether the assertion
|
|
passes or fails. This is for backward compatibility (hledger's close
|
|
command used to generate balance assertions with costs), and because
|
|
balance assignments do use costs (see below).
|
|
|
|
Assertions and commodities
|
|
The balance assertions described so far are "single commodity balance
|
|
assertions": they assert and check the balance in one commodity, ignor-
|
|
ing any others that may be present. This is how balance assertions
|
|
work in Ledger also.
|
|
|
|
If an account contains multiple commodities, you can assert their bal-
|
|
ances by writing multiple postings with balance assertions, one for
|
|
each commodity:
|
|
|
|
2013/1/1
|
|
usd $-1
|
|
eur -1
|
|
both
|
|
|
|
2013/1/2
|
|
both 0 = $1
|
|
both 0 = 1
|
|
|
|
In hledger you can make a stronger "sole commodity balance assertion"
|
|
by writing two equals signs (== EXPECTEDBALANCE). This also asserts
|
|
that there are no other commodities in the account besides the asserted
|
|
one (or at least, that their current balance is zero):
|
|
|
|
2013/1/1
|
|
usd $-1 == $-1 ; these sole commodity assertions succeed
|
|
eur -1 == -1
|
|
both ;== $1 ; this one would fail because 'both' contains $ and
|
|
|
|
It's less easy to make a "sole commodities balance assertion" (note the
|
|
plural) - ie, asserting that an account contains two or more specified
|
|
commodities and no others. It can be done by
|
|
|
|
1. isolating each commodity in a subaccount, and asserting those
|
|
|
|
2. and also asserting there are no commodities in the parent account
|
|
itself:
|
|
|
|
2013/1/1
|
|
usd $-1
|
|
eur -1
|
|
both 0 == 0 ; nothing up my sleeve
|
|
both:usd $1 == $1 ; a dollar here
|
|
both:eur 1 == 1 ; a euro there
|
|
|
|
Assertions and subaccounts
|
|
All of the balance assertions above (both = and ==) are "subaccount-ex-
|
|
clusive balance assertions"; they ignore any balances that exist in
|
|
deeper subaccounts.
|
|
|
|
In hledger you can make "subaccount-inclusive balance assertions" by
|
|
adding a star after the equals (=* or ==*):
|
|
|
|
2019/1/1
|
|
equity:start
|
|
assets:checking $10
|
|
assets:savings $10
|
|
assets $0 ==* $20 ; assets + subaccounts contains $20 and nothing else
|
|
|
|
Assertions and status
|
|
Balance assertions always consider postings of all statuses (unmarked,
|
|
pending, or cleared); they are not affected by the -U/--unmarked /
|
|
-P/--pending / -C/--cleared flags or the status: query.
|
|
|
|
Assertions and virtual postings
|
|
Balance assertions always consider both real and virtual postings; they
|
|
are not affected by the --real/-R flag or real: query.
|
|
|
|
Assertions and auto postings
|
|
Balance assertions are affected by the --auto flag, which generates
|
|
auto postings, which can alter account balances. Because auto postings
|
|
are optional in hledger, accounts affected by them effectively have two
|
|
balances. But balance assertions can only test one or the other of
|
|
these. So to avoid making fragile assertions, either:
|
|
|
|
o assert the balance calculated with --auto, and always use --auto with
|
|
that file
|
|
|
|
o or assert the balance calculated without --auto, and never use --auto
|
|
with that file
|
|
|
|
o or avoid balance assertions on accounts affected by auto postings (or
|
|
avoid auto postings entirely).
|
|
|
|
Assertions and precision
|
|
Balance assertions compare the exactly calculated amounts, which are
|
|
not always what is shown by reports. Eg a commodity directive may
|
|
limit the display precision, but this will not affect balance asser-
|
|
tions. Balance assertion failure messages show exact amounts.
|
|
|
|
Assertions and hledger add
|
|
Balance assertions can be included in the amounts given in add. All
|
|
types of assertions are supported, and assertions can be used as in a
|
|
normal journal file.
|
|
|
|
All transactions, not just those that have an explicit assertion, are
|
|
validated against the existing assertions in the journal. This means
|
|
it is possible for an added transaction to fail even if its assertions
|
|
are correct as of the transaction date.
|
|
|
|
If this assertion checking is not desired, then it can be disabled with
|
|
-I.
|
|
|
|
However, balance assignments are currently not supported.
|
|
|
|
Posting comments
|
|
Text following ;, at the end of a posting line, and/or on indented
|
|
lines immediately below it, form comments for that posting. They are
|
|
reproduced by print but otherwise ignored, except they may contain
|
|
tags, which are not ignored.
|
|
|
|
2012-01-01
|
|
expenses 1 ; a comment for posting 1
|
|
assets
|
|
; a comment for posting 2
|
|
; a second comment line for posting 2
|
|
|
|
Transaction balancing
|
|
How exactly does hledger decide when a transaction is balanced ? Espe-
|
|
cially when it involves costs, which often are not exact, because of
|
|
repeating decimals, or imperfect data from financial institutions ? In
|
|
each commodity, hledger sums the transaction's posting amounts, after
|
|
converting any with costs; then it checks if that sum is zero, when
|
|
rounded to a suitable number of decimal digits - which we call the bal-
|
|
ancing precision.
|
|
|
|
Since version 1.50, hledger infers balancing precision in each transac-
|
|
tion from the amounts in that transaction's journal entry (like
|
|
Ledger). Ie, when checking the balance of commodity A, it uses the
|
|
highest decimal precision seen for A in the journal entry (excluding
|
|
cost amounts). This makes transaction balancing robust; any imbalances
|
|
must be visibly accounted for in the journal entry, display precision
|
|
can be freely increased with -c, and compatibility with Ledger and
|
|
Beancount journals is good.
|
|
|
|
Note that hledger versions before 1.50 worked differently: they allowed
|
|
display precision to override the balancing precision. This masked
|
|
small imbalances and caused fragility (see issue #2402). As a result,
|
|
some journal entries (or CSV rules) that worked with hledger <1.50, are
|
|
now rejected with an "unbalanced transaction" error. If you hit this
|
|
problem, it's easy to fix:
|
|
|
|
o You can restore the old behaviour, by adding --txn-balancing=old to
|
|
the command or to your ~/.hledger.conf file. This lets you keep us-
|
|
ing old journals unchanged, though without the above benefits.
|
|
|
|
o Or you can fix the problem entries (recommended). There are three
|
|
ways, use whichever seems best:
|
|
|
|
1. make cost amounts more precise (add more/better decimal digits)
|
|
|
|
2. or make non-cost amounts less precise (remove unnecessary decimal
|
|
digits that are raising the precision)
|
|
|
|
3. or add a posting to absorb the imbalance (eg "expenses:rounding".
|
|
Remember that one posting may omit the amount; that's convenient
|
|
here.)
|
|
|
|
Tags
|
|
Tags are a way to add extra labels or data fields to transactions,
|
|
postings, or accounts, which you can match with a tag: query in re-
|
|
ports. (See queries below.)
|
|
|
|
Tags are a single word or hyphenated word, immediately followed by a
|
|
full colon, written within a comment. (Yes, storing data in comments
|
|
is slightly weird.) Here's a transaction with a tag:
|
|
|
|
2025-01-01 groceries ; some-tag:
|
|
assets:checking
|
|
expenses:food $1
|
|
|
|
A tag can have a value, a single line of text written after the colon.
|
|
Tag values can't contain newlines.:
|
|
|
|
2025-01-01 groceries ; tag1: this is tag1's value
|
|
|
|
Multiple tags can be separated by comma. Tag values can't contain com-
|
|
mas.:
|
|
|
|
2025-01-01 groceries ; tag1:value 1, tag2:value 2, comment text
|
|
|
|
A tag can have multiple values:
|
|
|
|
2025-01-01 groceries ; tag1:value 1, tag1:value 2
|
|
|
|
You can write each tag on its own line of you prefer (but they still
|
|
can't contain commas):
|
|
|
|
2025-01-01 groceries
|
|
; tag1: value 1
|
|
; tag2: value 2
|
|
|
|
Tags can be attached to individual postings, rather than the overall
|
|
transaction:
|
|
|
|
2025-01-01 rent
|
|
assets:checking
|
|
expenses:rent $1000 ; postingtag:
|
|
|
|
Tags can be attached to accounts, in their account directive:
|
|
|
|
account assets:checking ; acct-number: 123-45-6789
|
|
|
|
Tag propagation
|
|
In addition to what they are attached to, tags also affect related data
|
|
in a few ways, allowing more powerful queries:
|
|
|
|
1. Accounts -> postings. Postings inherit tags from their account.
|
|
|
|
2. Transactions -> postings. Postings inherit tags from their transac-
|
|
tion.
|
|
|
|
3. Postings -> transactions. Transactions also acquire the tags of
|
|
their postings.
|
|
|
|
So when you use a tag: query to match whole transactions, individual
|
|
postings, or accounts, it's good to understand how tags behave. Here's
|
|
an example showing all three kinds of propagation:
|
|
|
|
account assets:checking
|
|
account expenses:food ; atag:
|
|
|
|
2025-01-01 groceries ; ttag:
|
|
assets:checking ; p1tag:
|
|
expenses:food $1 ; p2tag:
|
|
|
|
data part has tags explanation
|
|
-----------------------------------------------------------------------------
|
|
assets:check- no tags attached
|
|
ing account
|
|
expenses:food atag atag: in comment
|
|
account
|
|
assets:check- p1tag, ttag p1tag: in comment, ttag acquired from
|
|
ing posting transaction
|
|
expenses:food p2tag, atag, p2tag: in comment, atag from account, ttag
|
|
posting ttag from transaction
|
|
groceries ttag, p1tag, ttag: in comment, p1tag from first posting,
|
|
transaction p2tag, atag p2tag and atag from second posting
|
|
|
|
Displaying tags
|
|
You can use the tags command to list tag names or values.
|
|
|
|
The print command also shows tags.
|
|
|
|
You can use --pivot to display tag values in other reports, in various
|
|
ways (eg appended to account names, like pseudo subaccounts).
|
|
|
|
When to use tags ?
|
|
Tags provide more dimensions of categorisation, complementing accounts
|
|
and transaction descriptions. When to use each of these is somewhat a
|
|
matter of taste. Accounts have the most built-in support, and regex
|
|
queries on descriptions are also quite powerful. So you may not need
|
|
tags at all. But if you want to track multiple cross-cutting cate-
|
|
gories, they can be a good fit. For example, you could tag trip-re-
|
|
lated transactions with trip: YEAR:PLACE, without disturbing your usual
|
|
account categories.
|
|
|
|
Tag names
|
|
What is allowed in a tag name ? Most non-whitespace characters. Eg :
|
|
is a valid tag.
|
|
|
|
For extra error checking, you can declare valid tag names with the tag
|
|
directive, and then enforce these with the check command. But note
|
|
that tags are detected quite loosely at present, sometimes where you
|
|
didn't intend them. Eg a comment like ; see https://foo.com adds a
|
|
https tag.
|
|
|
|
There are several tag names which have special significance to hledger.
|
|
They are explained elsewhere, but here's a quick reference:
|
|
|
|
type -- declares an account's type
|
|
date -- overrides a posting's date
|
|
date2 -- overrides a posting's secondary date
|
|
assert -- appears on txns generated by close --assert
|
|
retain -- appears on txns generated by close --retain
|
|
start -- appears on txns generated by close --migrate/--close/--open/--assign
|
|
t -- appears on postings generated from timedot letters
|
|
|
|
generated-transaction -- appears on txns generated by a periodic rule
|
|
modified-transaction -- appears on txns which have had auto postings added
|
|
generated-posting -- appears on generated postings
|
|
cost-posting -- appears on postings which have (or could have) a cost,
|
|
and which have equivalent conversion postings in the transaction
|
|
conversion-posting -- appears on postings which are to a V/Conversion account
|
|
and which have an equivalent cost posting in the transaction
|
|
|
|
The second group above (generated-transaction, etc.) are normally hid-
|
|
den, with a _ prefix added. This means print doesn't show them by de-
|
|
fault; but you can still use them in queries. You can add the --ver-
|
|
bose-tags flag to make them visible, which can be useful for trou-
|
|
bleshooting.
|
|
|
|
Directives
|
|
Besides transactions, there is something else you can put in a journal
|
|
file: directives. These are declarations, beginning with a keyword,
|
|
that modify hledger's behaviour. Some directives can have more spe-
|
|
cific subdirectives, indented below them. hledger's directives are
|
|
similar to Ledger's in many cases, but there are also many differences.
|
|
Directives are not required, but can be useful. Here are the main di-
|
|
rectives:
|
|
|
|
purpose directive
|
|
--------------------------------------------------------------------------
|
|
READING DATA:
|
|
Rewrite account names alias
|
|
Comment out sections of the file comment
|
|
Declare file's decimal mark, to help decimal-mark
|
|
parse amounts accurately
|
|
Include other data files include
|
|
GENERATING DATA:
|
|
Generate recurring transactions or bud- ~
|
|
get goals
|
|
Generate extra postings on existing =
|
|
transactions
|
|
CHECKING FOR ERRORS:
|
|
Define valid entities to provide more account, commodity, payee, tag
|
|
error checking
|
|
REPORTING:
|
|
Declare accounts' type and display order account
|
|
Declare commodity display styles commodity
|
|
Declare market prices P
|
|
|
|
Directives and multiple files
|
|
Directives vary in their scope, ie which journal entries and which in-
|
|
put files they affect. Most often, a directive will affect the follow-
|
|
ing entries and included files if any, until the end of the current
|
|
file - and no further. You might find this inconvenient! For example,
|
|
alias directives do not affect parent or sibling files. But there are
|
|
usually workarounds; for example, put alias directives in your top-most
|
|
file, before including other files.
|
|
|
|
The restriction, though it may be annoying at first, is in a good
|
|
cause; it allows reports to be stable and deterministic, independent of
|
|
the order of input. Without it, reports could show different numbers
|
|
depending on the order of -f options, or the positions of include di-
|
|
rectives in your files.
|
|
|
|
Directive effects
|
|
Here are all hledger's directives, with their effects and scope sum-
|
|
marised - nine main directives, plus four others which we consider
|
|
non-essential:
|
|
|
|
di- what it does ends
|
|
rec- at
|
|
tive file
|
|
end?
|
|
--------------------------------------------------------------------------------------
|
|
ac- Declares an account, for checking all entries in all files; and N
|
|
count its display order and type. Subdirectives: any text, ignored.
|
|
alias Rewrites account names, in following entries until end of cur- Y
|
|
rent file or end aliases. Command line equivalent: --alias
|
|
com- Ignores part of the journal file, until end of current file or Y
|
|
ment end comment.
|
|
com- Declares up to four things: 1. a commodity symbol, for checking N,N,Y,Y
|
|
mod- all amounts in all files 2. the display style for all amounts
|
|
ity of this commodity 3. the decimal mark for parsing amounts of
|
|
this commodity, in the rest of this file and its children, if
|
|
there is no decimal-mark directive 4. the precision to use for
|
|
balanced-transaction checking in this commodity, in this file
|
|
and its children. Takes precedence over D. Subdirectives:
|
|
format (ignored). Command line equivalent: -c/--commodity-style
|
|
deci- Declares the decimal mark, for parsing amounts of all commodi- Y
|
|
mal-mark ties in following entries until next decimal-mark or end of cur-
|
|
rent file. Included files can override. Takes precedence over
|
|
commodity and D.
|
|
include Includes entries and directives from another file, as if they N
|
|
were written inline. Command line alternative: multiple
|
|
-f/--file
|
|
payee Declares a payee name, for checking all entries in all files. N
|
|
P Declares the market price of a commodity on some date, for value N
|
|
reports.
|
|
~ Declares a periodic transaction rule that generates future N
|
|
(tilde) transactions with --forecast and budget goals with balance
|
|
--budget.
|
|
Other
|
|
syntax:
|
|
apply Prepends a common parent account to all account names, in fol- Y
|
|
account lowing entries until end of current file or end apply account.
|
|
D Sets a default commodity to use for no-symbol amounts;and, if Y,Y,N,N
|
|
there is no commodity directive for this commodity: its decimal
|
|
mark, balancing precision, and display style, as above.
|
|
Y Sets a default year to use for any yearless dates, in following Y
|
|
entries until end of current file.
|
|
= Declares an auto posting rule that generates extra postings on partly
|
|
(equals) matched transactions with --auto, in current, parent, and child
|
|
files (but not sibling files, see #1212).
|
|
Other Other directives from Ledger's file format are accepted but ig-
|
|
Ledger nored.
|
|
direc-
|
|
tives
|
|
|
|
account directive
|
|
account directives can be used to declare accounts (ie, the places that
|
|
amounts are transferred from and to). Though not required, these dec-
|
|
larations can provide several benefits:
|
|
|
|
o They can document your intended chart of accounts, providing a refer-
|
|
ence.
|
|
|
|
o They can store additional account information as comments, or as tags
|
|
which can be used to filter or pivot reports.
|
|
|
|
o They can restrict which accounts may be posted to by transactions, eg
|
|
in strict mode, which helps prevent errors.
|
|
|
|
o They influence account display order in reports, allowing non-alpha-
|
|
betic sorting (eg Revenues to appear above Expenses).
|
|
|
|
o They can help hledger know your accounts' types (asset, liability,
|
|
equity, revenue, expense), enabling reports like balancesheet and in-
|
|
comestatement.
|
|
|
|
o They help with account name completion (in hledger add, hledger-web,
|
|
hledger-iadd, ledger-mode, etc.)
|
|
|
|
They are written as the word account followed by a hledger-style ac-
|
|
count name. Eg:
|
|
|
|
account assets:bank:checking
|
|
|
|
Ledger-style indented subdirectives are also accepted, but ignored:
|
|
|
|
account assets:bank:checking
|
|
format subdirective ; currently ignored
|
|
|
|
Account comments
|
|
Text following two or more spaces and ; at the end of an account direc-
|
|
tive line, and/or following ; on indented lines immediately below it,
|
|
form comments for that account. They are ignored except they may con-
|
|
tain tags, which are not ignored.
|
|
|
|
The two-space requirement for same-line account comments is because ;
|
|
is allowed in account names.
|
|
|
|
account assets:bank:checking ; same-line comment, at least 2 spaces before the semicolon
|
|
; next-line comment
|
|
; some tags - type:A, acctnum:12345
|
|
|
|
Account error checking
|
|
By default, accounts need not be declared; they come into existence
|
|
when a posting references them. This is convenient, but it means
|
|
hledger can't warn you when you mis-spell an account name in the jour-
|
|
nal. Usually you'll find that error later, as an extra account in bal-
|
|
ance reports, or an incorrect balance when reconciling.
|
|
|
|
In strict mode, enabled with the -s/--strict flag, or when you run
|
|
hledger check accounts, hledger will report an error if any transaction
|
|
uses an account name that has not been declared by an account direc-
|
|
tive. Some notes:
|
|
|
|
o The declaration is case-sensitive; transactions must use the correct
|
|
account name capitalisation.
|
|
|
|
o The account directive's scope is "whole file and below" (see direc-
|
|
tives). This means it affects all of the current file, and any files
|
|
it includes, but not parent or sibling files. The position of ac-
|
|
count directives within the file does not matter, though it's usual
|
|
to put them at the top.
|
|
|
|
o Accounts can only be declared in journal files, but will affect in-
|
|
cluded files of all types.
|
|
|
|
o It's currently not possible to declare "all possible subaccounts"
|
|
with a wildcard; every account posted to must be declared.
|
|
|
|
o If you use the --infer-equity flag, you will also need declarations
|
|
for the account names it generates.
|
|
|
|
Account display order
|
|
Account directives also cause hledger to display accounts in a particu-
|
|
lar order, not just alphabetically. Eg, here is a conventional order-
|
|
ing for the top-level accounts:
|
|
|
|
account assets
|
|
account liabilities
|
|
account equity
|
|
account revenues
|
|
account expenses
|
|
|
|
Now hledger displays them in that order:
|
|
|
|
$ hledger accounts
|
|
assets
|
|
liabilities
|
|
equity
|
|
revenues
|
|
expenses
|
|
|
|
If there are undeclared accounts, those will be displayed last, in al-
|
|
phabetical order.
|
|
|
|
Sorting is done within each group of sibling accounts, at each level of
|
|
the account tree. Eg, a declaration like account parent:child influ-
|
|
ences child's position among its siblings.
|
|
|
|
Note, it does not affect parent's position; for that, you need an ac-
|
|
count parent declaration.
|
|
|
|
Sibling accounts are always displayed together; hledger won't display
|
|
x:y in between a:b and a:c.
|
|
|
|
An account directive both declares an account as a valid posting tar-
|
|
get, and declares its display order; you can't easily do one without
|
|
the other.
|
|
|
|
Account types
|
|
hledger knows that in accounting there are three main account types:
|
|
|
|
Asset A things you own
|
|
Liability L things you owe
|
|
Equity E owner's investment,
|
|
balances the two
|
|
above
|
|
|
|
and two more representing changes in these:
|
|
|
|
Revenue R inflows (also known
|
|
as Income)
|
|
Expense X outflows
|
|
|
|
hledger also uses a couple of subtypes:
|
|
|
|
Cash C liquid assets
|
|
Conversion V commodity conver-
|
|
sions equity
|
|
|
|
As a convenience, hledger will detect these types automatically from
|
|
english account names. But it's better to declare them explicitly by
|
|
adding a type: tag in the account directives. The tag's value can be
|
|
any of the types or one-letter abbreviations above.
|
|
|
|
Here is a typical set of account type declarations. Subaccounts will
|
|
inherit their parent's type, or can override it:
|
|
|
|
account assets ; type: A
|
|
account liabilities ; type: L
|
|
account equity ; type: E
|
|
account revenues ; type: R
|
|
account expenses ; type: X
|
|
|
|
account assets:bank ; type: C
|
|
account assets:cash ; type: C
|
|
|
|
account equity:conversion ; type: V
|
|
|
|
This enables the easy balancesheet, balancesheetequity, cashflow and
|
|
incomestatement reports, and querying by type:.
|
|
|
|
Tips:
|
|
|
|
o You can list accounts and their types, for troubleshooting:
|
|
|
|
$ hledger accounts --types [ACCTPAT] [type:TYPECODES] [-DEPTH] [--locations]
|
|
|
|
o It's a good idea to declare at least one account for each account
|
|
type. Having some types declared and some inferred can disrupt cer-
|
|
tain reports.
|
|
|
|
o The rules for inferring types from account names are as follows (us-
|
|
ing Regular expressions).
|
|
If they don't work for you, just ignore them and declare your types
|
|
with type: tags.
|
|
|
|
If account's name contains this case insensitive regular expression | its type is
|
|
--------------------------------------------------------------------|-------------
|
|
^assets?(:.+)?:(cash|bank|che(ck|que?)(ing)?|savings?|current)(:|$) | Cash
|
|
^assets?(:|$) | Asset
|
|
^(debts?|liabilit(y|ies))(:|$) | Liability
|
|
^equity:(trad(e|ing)|conversion)s?(:|$) | Conversion
|
|
^equity(:|$) | Equity
|
|
^(income|revenue)s?(:|$) | Revenue
|
|
^expenses?(:|$) | Expense
|
|
|
|
o As mentioned above, subaccounts will inherit a type from their parent
|
|
account. To be precise, an account's type is decided by the first of
|
|
these that exists:
|
|
|
|
1. A type: declaration for this account.
|
|
|
|
2. A type: declaration in the parent accounts above it, preferring
|
|
the nearest.
|
|
|
|
3. An account type inferred from this account's name.
|
|
|
|
4. An account type inferred from a parent account's name, preferring
|
|
the nearest parent.
|
|
|
|
5. Otherwise, it will have no type.
|
|
|
|
o Account aliases can disrupt account types.
|
|
|
|
alias directive
|
|
You can define account alias rules which rewrite your account names, or
|
|
parts of them, before generating reports. This can be useful for:
|
|
|
|
o expanding shorthand account names to their full form, allowing easier
|
|
data entry and a less verbose journal
|
|
|
|
o adapting old journals to your current chart of accounts
|
|
|
|
o experimenting with new account organisations, like a new hierarchy
|
|
|
|
o combining two accounts into one, eg to see their sum or difference on
|
|
one line
|
|
|
|
o customising reports
|
|
|
|
Account aliases also rewrite account names in account directives. They
|
|
do not affect account names being entered via hledger add or
|
|
hledger-web.
|
|
|
|
Account aliases are very powerful. They are generally easy to use cor-
|
|
rectly, but you can also generate invalid account names with them; more
|
|
on this below.
|
|
|
|
See also Rewrite account names.
|
|
|
|
Basic aliases
|
|
To set an account alias, use the alias directive in your journal file.
|
|
This affects all subsequent journal entries in the current file or its
|
|
included files (but note: not sibling or parent files). The spaces
|
|
around the = are optional:
|
|
|
|
alias OLD = NEW
|
|
|
|
Or, you can use the --alias 'OLD=NEW' option on the command line. This
|
|
affects all entries. It's useful for trying out aliases interactively.
|
|
|
|
OLD and NEW are case sensitive full account names. hledger will re-
|
|
place any occurrence of the old account name with the new one. Subac-
|
|
counts are also affected. Eg:
|
|
|
|
alias checking = assets:bank:wells fargo:checking
|
|
; rewrites "checking" to "assets:bank:wells fargo:checking", or "checking:a" to "assets:bank:wells fargo:checking:a"
|
|
|
|
Regex aliases
|
|
There is also a more powerful variant that uses a regular expression,
|
|
indicated by wrapping the pattern in forward slashes. (This is the
|
|
only place where hledger requires forward slashes around a regular ex-
|
|
pression.)
|
|
|
|
Eg:
|
|
|
|
alias /REGEX/ = REPLACEMENT
|
|
|
|
or:
|
|
|
|
$ hledger --alias '/REGEX/=REPLACEMENT' ...
|
|
|
|
Any part of an account name matched by REGEX will be replaced by RE-
|
|
PLACEMENT. REGEX is case-insensitive as usual.
|
|
|
|
If you need to match a forward slash, escape it with a backslash, eg
|
|
/\/=:.
|
|
|
|
If REGEX contains parenthesised match groups, these can be referenced
|
|
by the usual backslash and number in REPLACEMENT:
|
|
|
|
alias /^(.+):bank:([^:]+):(.*)/ = \1:\2 \3
|
|
; rewrites "assets:bank:wells fargo:checking" to "assets:wells fargo checking"
|
|
|
|
REPLACEMENT continues to the end of line (or on command line, to end of
|
|
option argument), so it can contain trailing whitespace.
|
|
|
|
Combining aliases
|
|
You can define as many aliases as you like, using journal directives
|
|
and/or command line options.
|
|
|
|
Recursive aliases - where an account name is rewritten by one alias,
|
|
then by another alias, and so on - are allowed. Each alias sees the
|
|
effect of previously applied aliases.
|
|
|
|
In such cases it can be important to understand which aliases will be
|
|
applied and in which order. For (each account name in) each journal
|
|
entry, we apply:
|
|
|
|
1. alias directives preceding the journal entry, most recently parsed
|
|
first (ie, reading upward from the journal entry, bottom to top)
|
|
|
|
2. --alias options, in the order they appeared on the command line
|
|
(left to right).
|
|
|
|
In other words, for (an account name in) a given journal entry:
|
|
|
|
o the nearest alias declaration before/above the entry is applied first
|
|
|
|
o the next alias before/above that will be be applied next, and so on
|
|
|
|
o aliases defined after/below the entry do not affect it.
|
|
|
|
This gives nearby aliases precedence over distant ones, and helps pro-
|
|
vide semantic stability - aliases will keep working the same way inde-
|
|
pendent of which files are being read and in which order.
|
|
|
|
In case of trouble, adding --debug=6 to the command line will show
|
|
which aliases are being applied when.
|
|
|
|
Aliases and multiple files
|
|
As explained at Directives and multiple files, alias directives do not
|
|
affect parent or sibling files. Eg in this command,
|
|
|
|
hledger -f a.aliases -f b.journal
|
|
|
|
account aliases defined in a.aliases will not affect b.journal. In-
|
|
cluding the aliases doesn't work either:
|
|
|
|
include a.aliases
|
|
|
|
2023-01-01 ; not affected by a.aliases
|
|
foo 1
|
|
bar
|
|
|
|
This means that account aliases should usually be declared at the start
|
|
of your top-most file, like this:
|
|
|
|
alias foo=Foo
|
|
alias bar=Bar
|
|
|
|
2023-01-01 ; affected by aliases above
|
|
foo 1
|
|
bar
|
|
|
|
include c.journal ; also affected
|
|
|
|
end aliases directive
|
|
You can clear (forget) all currently defined aliases (seen in the jour-
|
|
nal so far, or defined on the command line) with this directive:
|
|
|
|
end aliases
|
|
|
|
Aliases can generate bad account names
|
|
Be aware that account aliases can produce malformed account names,
|
|
which could cause confusing reports or invalid print output. For exam-
|
|
ple, you could erase all account names:
|
|
|
|
2021-01-01
|
|
a:aa 1
|
|
b
|
|
|
|
$ hledger print --alias '/.*/='
|
|
2021-01-01
|
|
1
|
|
|
|
The above print output is not a valid journal. Or you could insert an
|
|
illegal double space, causing print output that would give a different
|
|
journal when reparsed:
|
|
|
|
2021-01-01
|
|
old 1
|
|
other
|
|
|
|
$ hledger print --alias old="new USD" | hledger -f- print
|
|
2021-01-01
|
|
new USD 1
|
|
other
|
|
|
|
Aliases and account types
|
|
If an account with a type declaration (see Declaring accounts > Account
|
|
types) is renamed by an alias, normally the account type remains in ef-
|
|
fect.
|
|
|
|
However, renaming in a way that reshapes the account tree (eg renaming
|
|
parent accounts but not their children, or vice versa) could prevent
|
|
child accounts from inheriting the account type of their parents.
|
|
|
|
Secondly, if an account's type is being inferred from its name, renam-
|
|
ing it by an alias could prevent or alter that.
|
|
|
|
If you are using account aliases and the type: query is not matching
|
|
accounts as you expect, try troubleshooting with the accounts command,
|
|
eg something like:
|
|
|
|
$ hledger accounts --types -1 --alias assets=bassetts
|
|
|
|
commodity directive
|
|
The commodity directive performs several functions:
|
|
|
|
1. It declares which commodity symbols may be used in the journal, en-
|
|
abling useful error checking with strict mode or the check command.
|
|
See Commodity error checking below.
|
|
|
|
2. It declares how all amounts in this commodity should be displayed,
|
|
eg how many decimals to show. See Commodity display style above.
|
|
|
|
3. (If no decimal-mark directive is in effect:) It sets the decimal
|
|
mark to expect (period or comma) when parsing amounts in this com-
|
|
modity, in this file and files it includes, from the directive until
|
|
end of current file. See Decimal marks above.
|
|
|
|
4. It declares the precision with which this commodity's amounts should
|
|
be compared when checking for balanced transactions, anywhere in
|
|
this file and files it includes, until end of current file.
|
|
|
|
Declaring commodities solves several common parsing/display problems,
|
|
so we recommend it.
|
|
|
|
Note that effects 3 and 4 above end at the end of the directive's file,
|
|
and will not affect sibling or parent files. So if you are relying on
|
|
them (especially 4) and using multiple files, placing your commodity
|
|
directives in a top-level parent file might be important. Or, keep
|
|
your decimal marks unambiguous and your entries well balanced and pre-
|
|
cise.
|
|
|
|
Omitting the commodity symbol will set the display style for just the
|
|
no-symbol commodity, not all commodities.
|
|
|
|
Commodity styles can be overridden by the -c/--commodity-style command
|
|
line option.
|
|
|
|
(Related: #793)
|
|
|
|
Commodity directive syntax
|
|
A commodity directive is normally the word commodity followed by a sam-
|
|
ple amount (and optionally a comment). Only the amount's symbol and
|
|
the number's format is significant. Eg:
|
|
|
|
commodity $1000.00
|
|
commodity 1.000,00 EUR
|
|
commodity 1 000 000.0000 ; the no-symbol commodity
|
|
|
|
Commodities do not have tags (tags in the comment will be ignored).
|
|
|
|
A commodity directive's sample amount must always include a period or
|
|
comma decimal mark (this rule helps disambiguate decimal marks and
|
|
digit group marks). If you don't want to show any decimal digits,
|
|
write the decimal mark at the end:
|
|
|
|
commodity 1000. AAAA ; show AAAA with no decimals
|
|
|
|
Commodity symbols containing spaces, numbers, or punctuation must be
|
|
enclosed in double quotes, as usual:
|
|
|
|
commodity 1.0000 "AAAA 2023"
|
|
|
|
Commodity directives normally include a sample amount, but can declare
|
|
only a symbol (ie, just function 1 above):
|
|
|
|
commodity $
|
|
commodity INR
|
|
commodity "AAAA 2023"
|
|
commodity "" ; the no-symbol commodity
|
|
|
|
Commodity directives may also be written with an indented format subdi-
|
|
rective, as in Ledger. The symbol is repeated and must be the same in
|
|
both places. Other subdirectives are currently ignored:
|
|
|
|
; display indian rupees with currency name on the left,
|
|
; thousands, lakhs and crores comma-separated,
|
|
; period as decimal point, and two decimal places.
|
|
commodity INR
|
|
format INR 1,00,00,000.00
|
|
an unsupported subdirective ; ignored by hledger
|
|
|
|
Commodity error checking
|
|
In strict mode (-s/--strict) (or when you run hledger check commodi-
|
|
ties), hledger will report an error if an undeclared commodity symbol
|
|
is used. (With one exception: zero amounts are always allowed to have
|
|
no commodity symbol.) It works like account error checking (described
|
|
above).
|
|
|
|
decimal-mark directive
|
|
You can use a decimal-mark directive - usually one per file, at the top
|
|
of the file - to declare which character represents a decimal mark when
|
|
parsing amounts in this file. It can look like
|
|
|
|
decimal-mark .
|
|
|
|
or
|
|
|
|
decimal-mark ,
|
|
|
|
This prevents any ambiguity when parsing numbers in the file, so we
|
|
recommend it, especially if the file contains digit group marks (eg
|
|
thousands separators).
|
|
|
|
include directive
|
|
You can pull in the content of additional files by writing an include
|
|
directive, like this:
|
|
|
|
include SOMEFILE
|
|
|
|
This has the same effect as if SOMEFILE's content was inlined at this
|
|
point. (With any include directives in SOMEFILE processed similarly,
|
|
recursively.)
|
|
|
|
Only journal files can include other files. They can include journal,
|
|
timeclock or timedot files, but not CSV files.
|
|
|
|
If the file path begins with a tilde, that means your home directory:
|
|
include ~/main.journal.
|
|
|
|
If it begins with a slash, it is an absolute path: include
|
|
/home/user/main.journal. Otherwise it is relative to the including
|
|
file's folder: include ../finances/main.journal.
|
|
|
|
Also, the path may have a file type prefix to force a specific file
|
|
format, overriding the file extension(s) (as described in Data for-
|
|
mats): include timedot:notes/2023.md.
|
|
|
|
The path may contain glob patterns to match multiple files. hledger's
|
|
globs are similar to zsh's: ? to match any character; [a-z] to match
|
|
any character in a range; * to match zero or more characters that
|
|
aren't a path separator (like /); ** to match zero or more subdirecto-
|
|
ries and/or zero or more characters at the start of a file name; etc.
|
|
For convenience, include always excludes the current file. So, you can
|
|
do
|
|
|
|
o include *.journal to include all other journal files in the current
|
|
directory (excluding dot files)
|
|
|
|
o include **.journal to include all other journal files in this direc-
|
|
tory and below (excluding dot files and top-level dot directories)
|
|
|
|
o include timelogs/2???.timedot to include all timedot files named like
|
|
a year number.
|
|
|
|
Note * and ** usually won't match dot files or dot directories, with
|
|
one exception: ** does search non-top-level dot directories. If this
|
|
causes problems, make your glob pattern more specific (eg **.journal
|
|
instead of **).
|
|
|
|
If you are using many, or deeply nested, include files, and have an er-
|
|
ror that's hard to pinpoint: a good troubleshooting command is hledger
|
|
files --debug=6 (or 7).
|
|
|
|
P directive
|
|
The P directive declares a market price, which is a conversion rate be-
|
|
tween two commodities on a certain date. This allows value reports to
|
|
convert amounts of one commodity to their value in another, on or after
|
|
that date. These prices are often obtained from a stock exchange,
|
|
cryptocurrency exchange, the or foreign exchange market.
|
|
|
|
The format is:
|
|
|
|
P DATE COMMODITY1SYMBOL COMMODITY2AMOUNT
|
|
|
|
DATE is a simple date, COMMODITY1SYMBOL is the symbol of the commodity
|
|
being priced, and COMMODITY2AMOUNT is the amount (symbol and quantity)
|
|
of commodity 2 that one unit of commodity 1 is worth on this date. Ex-
|
|
amples:
|
|
|
|
# one euro was worth $1.35 from 2009-01-01 onward:
|
|
P 2009-01-01 $1.35
|
|
|
|
# and $1.40 from 2010-01-01 onward:
|
|
P 2010-01-01 $1.40
|
|
|
|
The -V, -X and --value flags use these market prices to show amount
|
|
values in another commodity. See Value reporting.
|
|
|
|
payee directive
|
|
payee PAYEE NAME
|
|
|
|
This directive can be used to declare a limited set of payees which may
|
|
appear in transaction descriptions. The "payees" check will report an
|
|
error if any transaction refers to a payee that has not been declared.
|
|
Eg:
|
|
|
|
payee Whole Foods ; a comment
|
|
|
|
Payees do not have tags (tags in the comment will be ignored).
|
|
|
|
To declare the empty payee name, use "".
|
|
|
|
payee ""
|
|
|
|
Ledger-style indented subdirectives, if any, are currently ignored.
|
|
|
|
tag directive
|
|
tag TAGNAME
|
|
|
|
This directive can be used to declare a limited set of tag names al-
|
|
lowed in tags. TAGNAME should be a valid tag name (no spaces). Eg:
|
|
|
|
tag item-id
|
|
|
|
Any indented subdirectives are currently ignored.
|
|
|
|
The "tags" check will report an error if any undeclared tag name is
|
|
used. It is quite easy to accidentally create a tag through normal use
|
|
of colons in comments; if you want to prevent this, you can declare and
|
|
check your tags .
|
|
|
|
Periodic transactions
|
|
The ~ directive declares a "periodic rule" which generates temporary
|
|
extra transactions, usually recurring at some interval, when hledger is
|
|
run with the --forecast flag. These "forecast transactions" are useful
|
|
for forecasting future activity. They exist only for the duration of
|
|
the report, and only when --forecast is used; they are not saved in the
|
|
journal file by hledger.
|
|
|
|
Periodic rules also have a second use: with the --budget flag they set
|
|
budget goals for budgeting.
|
|
|
|
Periodic rules can be a little tricky, so before you use them, read
|
|
this whole section, or at least the following tips:
|
|
|
|
1. Two spaces accidentally added or omitted will cause you trouble -
|
|
read about this below.
|
|
|
|
2. For troubleshooting, show the generated transactions with hledger
|
|
print --forecast tag:generated or hledger register --forecast
|
|
tag:generated.
|
|
|
|
3. Forecasted transactions will begin only after the last non-fore-
|
|
casted transaction's date.
|
|
|
|
4. Forecasted transactions will end 6 months from today, by default.
|
|
See below for the exact start/end rules.
|
|
|
|
5. period expressions can be tricky. Their documentation needs im-
|
|
provement, but is worth studying.
|
|
|
|
6. Some period expressions with a repeating interval must begin on a
|
|
natural boundary of that interval. Eg in weekly from DATE, DATE
|
|
must be a monday. ~ weekly from 2019/10/1 (a tuesday) will give an
|
|
error.
|
|
|
|
7. Other period expressions with an interval are automatically expanded
|
|
to cover a whole number of that interval. (This is done to improve
|
|
reports, but it also affects periodic transactions. Yes, it's a bit
|
|
inconsistent with the above.) Eg: ~ every 10th day of month from
|
|
2023/01, which is equivalent to ~ every 10th day of month from
|
|
2023/01/01, will be adjusted to start on 2019/12/10.
|
|
|
|
Periodic rule syntax
|
|
A periodic transaction rule looks like a normal journal entry, with the
|
|
date replaced by a tilde (~) followed by a period expression (mnemonic:
|
|
~ looks like a recurring sine wave.):
|
|
|
|
# every first of month
|
|
~ monthly
|
|
expenses:rent $2000
|
|
assets:bank:checking
|
|
|
|
# every 15th of month in 2023's first quarter:
|
|
~ monthly from 2023-04-15 to 2023-06-16
|
|
expenses:utilities $400
|
|
assets:bank:checking
|
|
|
|
The period expression is the same syntax used for specifying multi-pe-
|
|
riod reports, just interpreted differently; there, it specifies report
|
|
periods; here it specifies recurrence dates (the periods' start dates).
|
|
|
|
Periodic rules and relative dates
|
|
Partial or relative dates (like 12/31, 25, tomorrow, last week, next
|
|
quarter) are usually not recommended in periodic rules, since the re-
|
|
sults will change as time passes. If used, they will be interpreted
|
|
relative to, in order of preference:
|
|
|
|
1. the first day of the default year specified by a recent Y directive
|
|
|
|
2. or the date specified with --today
|
|
|
|
3. or the date on which you are running the report.
|
|
|
|
They will not be affected at all by report period or forecast period
|
|
dates.
|
|
|
|
Two spaces between period expression and description!
|
|
If the period expression is followed by a transaction description,
|
|
these must be separated by two or more spaces. This helps hledger know
|
|
where the period expression ends, so that descriptions can not acciden-
|
|
tally alter their meaning, as in this example:
|
|
|
|
; 2 or more spaces needed here, so the period is not understood as "every 2 months in 2023"
|
|
; ||
|
|
; vv
|
|
~ every 2 months in 2023, we will review
|
|
assets:bank:checking $1500
|
|
income:acme inc
|
|
|
|
So,
|
|
|
|
o Do write two spaces between your period expression and your transac-
|
|
tion description, if any.
|
|
|
|
o Don't accidentally write two spaces in the middle of your period ex-
|
|
pression.
|
|
|
|
Auto postings
|
|
The = directive declares an "auto posting rule", which adds extra post-
|
|
ings to existing transactions. (Remember, postings are the account
|
|
name & amount lines below a transaction's date & description.)
|
|
|
|
In the journal, an auto posting rule looks quite like a transaction,
|
|
but instead of date and description it has = (mnemonic: "match") and a
|
|
query, like this:
|
|
|
|
= QUERY
|
|
ACCOUNT AMOUNT
|
|
...
|
|
|
|
Queries are just like command line queries; an account name substring
|
|
is most common. Query terms containing spaces should be enclosed in
|
|
single or double quotes.
|
|
|
|
Each = rule works like this: when hledger is run with the --auto flag,
|
|
wherever the QUERY matches a posting in the journal, the rule's post-
|
|
ings are added to that transaction, immediately below the matched post-
|
|
ing. Note these generated postings are temporary, existing only for
|
|
the duration of the report, and only when --auto is used; they are not
|
|
saved in the journal file by hledger.
|
|
|
|
The postings can contain the special string %account which will be ex-
|
|
panded to the account name of the matched account.
|
|
|
|
Generated postings' amounts can depend on the matched posting's amount.
|
|
So auto postings can be useful for, eg, adding tax postings with a
|
|
standard percentage. AMOUNT can be:
|
|
|
|
o a number with no commodity symbol, like 2. The matched posting's
|
|
commodity symbol will be added to this.
|
|
|
|
o a normal amount with a commodity symbol, like $2. This will be used
|
|
as-is.
|
|
|
|
o an asterisk followed by a number, like *2. This will multiply the
|
|
matched posting's amount (and total price, if any) by the number.
|
|
|
|
o an asterisk followed by an amount with commodity symbol, like *$2.
|
|
This multiplies and also replaces the commodity symbol with this new
|
|
one.
|
|
|
|
Some examples:
|
|
|
|
; every time I buy food, schedule a dollar donation
|
|
= expenses:food
|
|
(liabilities:charity) $-1
|
|
|
|
; when I buy a gift, also deduct that amount from a budget envelope subaccount
|
|
= expenses:gifts
|
|
assets:checking:gifts *-1
|
|
assets:checking *1
|
|
|
|
2017/12/1
|
|
expenses:food $10
|
|
assets:checking
|
|
|
|
2017/12/14
|
|
expenses:gifts $20
|
|
assets:checking
|
|
|
|
$ hledger print --auto
|
|
2017-12-01
|
|
expenses:food $10
|
|
assets:checking
|
|
(liabilities:charity) $-1
|
|
|
|
2017-12-14
|
|
expenses:gifts $20
|
|
assets:checking
|
|
assets:checking:gifts -$20
|
|
assets:checking $20
|
|
|
|
Note that depending fully on generated data such as this has some draw-
|
|
backs - it's less portable, less future-proof, less auditable by oth-
|
|
ers, and less robust (eg your balance assertions will depend on whether
|
|
you use or don't use --auto). An alternative is to use auto postings
|
|
in "one time" fashion - use them to help build a complex journal entry,
|
|
view it with hledger print --auto, and then copy that output into the
|
|
journal file to make it permanent.
|
|
|
|
Auto postings and multiple files
|
|
An auto posting rule can affect any transaction in the current file, or
|
|
in any parent file or child file. Note, currently it will not affect
|
|
sibling files (when multiple -f/--file are used - see #1212).
|
|
|
|
Auto postings and dates
|
|
A posting date (or secondary date) in the matched posting, or (taking
|
|
precedence) a posting date in the auto posting rule itself, will also
|
|
be used in the generated posting.
|
|
|
|
Auto postings and transaction balancing / inferred amounts / balance asser-
|
|
tions
|
|
Currently, auto postings are added:
|
|
|
|
o after missing amounts are inferred, and transactions are checked for
|
|
balancedness,
|
|
|
|
o but before balance assertions are checked.
|
|
|
|
Note this means that journal entries must be balanced both before and
|
|
after auto postings are added. This changed in hledger 1.12+; see #893
|
|
for background.
|
|
|
|
This also means that you cannot have more than one auto-posting with a
|
|
missing amount applied to a given transaction, as it will be unable to
|
|
infer amounts.
|
|
|
|
Auto posting tags
|
|
Automated postings will have some extra tags:
|
|
|
|
o generated-posting:= QUERY - shows this was generated by an auto post-
|
|
ing rule, and the query
|
|
|
|
o _generated-posting:= QUERY - a hidden tag, which does not appear in
|
|
hledger's output. This can be used to match postings generated "just
|
|
now", rather than generated in the past and saved to the journal.
|
|
|
|
Also, any transaction that has been changed by auto posting rules will
|
|
have these tags added:
|
|
|
|
o modified: - this transaction was modified
|
|
|
|
o _modified: - a hidden tag not appearing in the comment; this transac-
|
|
tion was modified "just now".
|
|
|
|
Auto postings on forecast transactions only
|
|
Tip: you can can make auto postings that will apply to forecast trans-
|
|
actions but not recorded transactions, by adding tag:_generated-trans-
|
|
action to their QUERY. This can be useful when generating new journal
|
|
entries to be saved in the journal.
|
|
|
|
Other syntax
|
|
hledger journal format supports quite a few other features, mainly to
|
|
make interoperating with or converting from Ledger easier. Note some
|
|
of the features below are powerful and can be useful in special cases,
|
|
but in general, features in this section are considered less important
|
|
or even not recommended for most users. Downsides are mentioned to
|
|
help you decide if you want to use them.
|
|
|
|
Balance assignments
|
|
Ledger-style balance assignments are also supported. These are like
|
|
balance assertions, but with no posting amount on the left side of the
|
|
equals sign; instead it is calculated automatically so as to satisfy
|
|
the assertion. This can be a convenience during data entry, eg when
|
|
setting opening balances:
|
|
|
|
; starting a new journal, set asset account balances
|
|
2016/1/1 opening balances
|
|
assets:checking = $409.32
|
|
assets:savings = $735.24
|
|
assets:cash = $42
|
|
equity:opening balances
|
|
|
|
or when adjusting a balance to reality:
|
|
|
|
; no cash left; update balance, record any untracked spending as a generic expense
|
|
2016/1/15
|
|
assets:cash = $0
|
|
expenses:misc
|
|
|
|
The calculated amount depends on the account's balance in the commodity
|
|
at that point (which depends on the previously-dated postings of the
|
|
commodity to that account since the last balance assertion or assign-
|
|
ment).
|
|
|
|
Downsides: using balance assignments makes your journal less explicit;
|
|
to know the exact amount posted, you have to run hledger or do the cal-
|
|
culations yourself, instead of just reading it. Also balance assign-
|
|
ments' forcing of balances can hide errors. These things make your fi-
|
|
nancial data less portable, less future-proof, and less trustworthy in
|
|
an audit.
|
|
|
|
Balance assignments and costs
|
|
A cost in a balance assignment will cause the calculated amount to have
|
|
that cost attached:
|
|
|
|
2019/1/1
|
|
(a) = $1 @ 2
|
|
|
|
$ hledger print --explicit
|
|
2019-01-01
|
|
(a) $1 @ 2 = $1 @ 2
|
|
|
|
Balance assignments and multiple files
|
|
Balance assignments handle multiple files like balance assertions.
|
|
They see balance from other files previously included from the current
|
|
file, but not from previous sibling or parent files.
|
|
|
|
Bracketed posting dates
|
|
For setting posting dates and secondary posting dates, Ledger's brack-
|
|
eted date syntax is also supported: [DATE], [DATE=DATE2] or [=DATE2] in
|
|
posting comments. hledger will attempt to parse any square-bracketed
|
|
sequence of the 0123456789/-.= characters in this way. With this syn-
|
|
tax, DATE infers its year from the transaction and DATE2 infers its
|
|
year from DATE.
|
|
|
|
Downsides: another syntax to learn, redundant with hledger's
|
|
date:/date2: tags, and confusingly similar to Ledger's lot date syntax.
|
|
|
|
D directive
|
|
D AMOUNT
|
|
|
|
This directive sets a default commodity, to be used for any subsequent
|
|
commodityless amounts (ie, plain numbers) seen while parsing the jour-
|
|
nal. This effect lasts until the next D directive, or the end of the
|
|
current file.
|
|
|
|
For compatibility/historical reasons, D also acts like a commodity di-
|
|
rective (setting the commodity's decimal mark for parsing and display
|
|
style for output). So its argument is not just a commodity symbol, but
|
|
a full amount demonstrating the style. The amount must include a deci-
|
|
mal mark (either period or comma). Eg:
|
|
|
|
; commodity-less amounts should be treated as dollars
|
|
; (and displayed with the dollar sign on the left, thousands separators and two decimal places)
|
|
D $1,000.00
|
|
|
|
1/1
|
|
a 5 ; <- commodity-less amount, parsed as $5 and displayed as $5.00
|
|
b
|
|
|
|
Interactions with other directives:
|
|
|
|
For setting a commodity's display style, a commodity directive has
|
|
highest priority, then a D directive.
|
|
|
|
For detecting a commodity's decimal mark during parsing, decimal-mark
|
|
has highest priority, then commodity, then D.
|
|
|
|
For checking commodity symbols with the check command, a commodity di-
|
|
rective is required (hledger check commodities ignores D directives).
|
|
|
|
Downsides: omitting commodity symbols makes your financial data less
|
|
explicit, less portable, and less trustworthy in an audit. It is usu-
|
|
ally an unsustainable shortcut; sooner or later you will want to track
|
|
multiple commodities. D is overloaded with functions redundant with
|
|
commodity and decimal-mark. And it works differently from Ledger's D.
|
|
|
|
apply account directive
|
|
This directive sets a default parent account, which will be prepended
|
|
to all accounts in following entries, until an end apply account direc-
|
|
tive or end of current file. Eg:
|
|
|
|
apply account home
|
|
|
|
2010/1/1
|
|
food $10
|
|
cash
|
|
|
|
end apply account
|
|
|
|
is equivalent to:
|
|
|
|
2010/01/01
|
|
home:food $10
|
|
home:cash $-10
|
|
|
|
account directives are also affected, and so is any included content.
|
|
|
|
Account names entered via hledger add or hledger-web are not affected.
|
|
|
|
Account aliases, if any, are applied after the parent account is
|
|
prepended.
|
|
|
|
Downsides: this can make your financial data less explicit, less
|
|
portable, and less trustworthy in an audit.
|
|
|
|
Y directive
|
|
Y YEAR
|
|
|
|
or (deprecated backward-compatible forms):
|
|
|
|
year YEAR apply year YEAR
|
|
|
|
The space is optional. This sets a default year to be used for subse-
|
|
quent dates which don't specify a year. Eg:
|
|
|
|
Y2009 ; set default year to 2009
|
|
|
|
12/15 ; equivalent to 2009/12/15
|
|
expenses 1
|
|
assets
|
|
|
|
year 2010 ; change default year to 2010
|
|
|
|
2009/1/30 ; specifies the year, not affected
|
|
expenses 1
|
|
assets
|
|
|
|
1/31 ; equivalent to 2010/1/31
|
|
expenses 1
|
|
assets
|
|
|
|
Downsides: omitting the year (from primary transaction dates, at least)
|
|
makes your financial data less explicit, less portable, and less trust-
|
|
worthy in an audit. Such dates can get separated from their corre-
|
|
sponding Y directive, eg when evaluating a region of the journal in
|
|
your editor. A missing Y directive makes reports dependent on today's
|
|
date.
|
|
|
|
Secondary dates
|
|
A secondary date is written after the primary date, following an equals
|
|
sign: DATE1=DATE2. If the year is omitted, the primary date's year is
|
|
assumed. When running reports, the primary (left side) date is used by
|
|
default, but with the --date2 flag (--aux-date or--effective also work,
|
|
for Ledger users), the secondary (right side) date will be used in-
|
|
stead.
|
|
|
|
The meaning of secondary dates is up to you. Eg it could be "primary
|
|
is the bank's clearing date, secondary is the date the transaction was
|
|
initiated, if different".
|
|
|
|
In practice, this feature usually adds confusion:
|
|
|
|
o You have to remember the primary and secondary dates' meaning, and
|
|
follow that consistently.
|
|
|
|
o It splits your bookkeeping into two modes, and you have to remember
|
|
which mode is appropriate for a given report.
|
|
|
|
o Usually your balance assertions will work with only one of these
|
|
modes.
|
|
|
|
o It makes your financial data more complicated, less portable, and
|
|
less clear in an audit.
|
|
|
|
o It interacts with every feature, creating an ongoing cost for imple-
|
|
mentors.
|
|
|
|
o It distracts new users and supporters.
|
|
|
|
o Posting dates are simpler and work better.
|
|
|
|
So secondary dates are officially deprecated in hledger, remaining only
|
|
as a Ledger compatibility aid; we recommend using posting dates in-
|
|
stead.
|
|
|
|
Star comments
|
|
Lines beginning with * (star/asterisk) are also comment lines. This
|
|
feature allows Emacs users to insert org headings in their journal, al-
|
|
lowing them to fold/unfold/navigate it like an outline when viewed with
|
|
org mode.
|
|
|
|
Downsides: another, unconventional comment syntax to learn. Decreases
|
|
your journal's portability. And switching to Emacs org mode just for
|
|
folding/unfolding meant losing the benefits of ledger mode; nowadays
|
|
you can add outshine mode to ledger mode to get folding without losing
|
|
ledger mode's features.
|
|
|
|
Valuation expressions
|
|
Ledger allows a valuation function or value to be written in double
|
|
parentheses after an amount. hledger ignores these.
|
|
|
|
Virtual postings
|
|
A posting with parentheses around the account name, like (some:account)
|
|
10, is called an unbalanced virtual posting. These postings do not
|
|
participate in transaction balancing. (And if you write them without
|
|
an amount, a zero amount is always inferred.) These can occasionally
|
|
be convenient for special circumstances, but they violate double entry
|
|
bookkeeping and make your data less portable across applications, so
|
|
many people avoid using them at all.
|
|
|
|
A posting with brackets around the account name ([some:account]) is
|
|
called a balanced virtual posting. The balanced virtual postings in a
|
|
transaction must add up to zero, just like ordinary postings, but sepa-
|
|
rately from them. These are not part of double entry bookkeeping ei-
|
|
ther, but they are at least balanced. An example:
|
|
|
|
2022-01-01 buy food with cash, update budget envelope subaccounts, & something else
|
|
assets:cash $-10 ; <- these balance each other
|
|
expenses:food $7 ; <-
|
|
expenses:food $3 ; <-
|
|
[assets:checking:budget:food] $-10 ; <- and these balance each other
|
|
[assets:checking:available] $10 ; <-
|
|
(something:else) $5 ; <- this is not required to balance
|
|
|
|
Ordinary postings, whose account names are neither parenthesised nor
|
|
bracketed, are called real postings. You can exclude virtual postings
|
|
from reports with the -R/--real flag or a real:1 query.
|
|
|
|
Other Ledger directives
|
|
These other Ledger directives are currently accepted but ignored. This
|
|
allows hledger to read more Ledger files, but be aware that hledger's
|
|
reports may differ from Ledger's if you use these.
|
|
|
|
apply fixed COMM AMT
|
|
apply tag TAG
|
|
assert EXPR
|
|
bucket / A ACCT
|
|
capture ACCT REGEX
|
|
check EXPR
|
|
define VAR=EXPR
|
|
end apply fixed
|
|
end apply tag
|
|
end apply year
|
|
end tag
|
|
eval / expr EXPR
|
|
python
|
|
PYTHONCODE
|
|
tag NAME
|
|
value EXPR
|
|
--command-line-flags
|
|
|
|
See also https://hledger.org/ledger.html for a detailed hledger/Ledger
|
|
syntax comparison.
|
|
|
|
Other cost/lot notations
|
|
A slight digression for Ledger and Beancount users.
|
|
|
|
Ledger has a number of cost/lot-related notations:
|
|
|
|
o @ UNITCOST and @@ TOTALCOST
|
|
|
|
o expresses a conversion rate, as in hledger
|
|
|
|
o when buying, also creates a lot that can be selected at selling
|
|
time
|
|
|
|
o (@) UNITCOST and (@@) TOTALCOST (virtual cost)
|
|
|
|
o like the above, but also means "this cost was exceptional, don't
|
|
use it when inferring market prices".
|
|
|
|
o {=UNITCOST} and {{=TOTALCOST}} (fixed price)
|
|
|
|
o when buying, means "this cost is also the fixed value, don't let it
|
|
fluctuate in value reports"
|
|
|
|
o {UNITCOST} and {{TOTALCOST}} (lot price)
|
|
|
|
o can be used identically to @ UNITCOST and @@ TOTALCOST, also cre-
|
|
ates a lot
|
|
|
|
o when selling, combined with @ ..., selects an existing lot by its
|
|
cost basis. Does not check if that lot is present.
|
|
|
|
o [YYYY/MM/DD] (lot date)
|
|
|
|
o when buying, attaches this acquisition date to the lot
|
|
|
|
o when selling, selects a lot by its acquisition date
|
|
|
|
o (SOME TEXT) (lot note)
|
|
|
|
o when buying, attaches this note to the lot
|
|
|
|
o when selling, selects a lot by its note
|
|
|
|
Currently, hledger
|
|
|
|
o accepts any or all of the above in any order after the posting amount
|
|
|
|
o supports @ and @@
|
|
|
|
o treats (@) and (@@) as synonyms for @ and @@
|
|
|
|
o and ignores the rest. (This can break transaction balancing.)
|
|
|
|
Beancount has simpler notation and different behaviour:
|
|
|
|
o @ UNITCOST and @@ TOTALCOST
|
|
|
|
o expresses a cost without creating a lot, as in hledger
|
|
|
|
o when buying (acquiring) or selling (disposing of) a lot, and com-
|
|
bined with {...}: is not used except to document the cost/selling
|
|
price
|
|
|
|
o {UNITCOST} and {{TOTALCOST}}
|
|
|
|
o when buying, expresses the cost for transaction balancing, and also
|
|
creates a lot with this cost basis attached
|
|
|
|
o when selling,
|
|
|
|
o selects a lot by its cost basis
|
|
|
|
o raises an error if that lot is not present or can not be selected
|
|
unambiguously (depending on booking method configured)
|
|
|
|
o expresses the selling price for transaction balancing
|
|
|
|
o {}, {YYYY-MM-DD}, {"LABEL"}, {UNITCOST, "LABEL"}, {UNITCOST,
|
|
YYYY-MM-DD, "LABEL"}
|
|
|
|
o when selling, other combinations of date/cost/label, like the
|
|
above, are accepted for selecting the lot.
|
|
|
|
Currently, hledger
|
|
|
|
o supports @ and @@
|
|
|
|
o accepts the {UNITCOST}/{{TOTALCOST}} notation, but ignores it
|
|
|
|
o and rejects the rest.
|
|
|
|
CSV
|
|
hledger can read transactions from CSV (comma-separated values) files.
|
|
More precisely, it can read DSV (delimiter-separated values), from a
|
|
file or standard input. Comma-separated, semicolon-separated and
|
|
tab-separated are the most common variants, and hledger will recognise
|
|
these three automatically based on a .csv, .ssv or .tsv file name ex-
|
|
tension or a csv:, ssv: or tsv: file path prefix.
|
|
|
|
(To learn about producing CSV or TSV output, see Output format.)
|
|
|
|
Each CSV file must be described by a corresponding rules file. This
|
|
contains rules describing the CSV data (header line, fields layout,
|
|
date format etc.), how to construct hledger transactions from it, and
|
|
how to categorise transactions based on description or other attrib-
|
|
utes.
|
|
|
|
By default, hledger expects this rules file to be named like the CSV
|
|
file, with an extra .rules extension added, in the same directory. Eg
|
|
when asked to read foo/FILE.csv, hledger looks for foo/FILE.csv.rules.
|
|
You can specify a different rules file with the --rules option.
|
|
|
|
At minimum, the rules file must identify the date and amount fields,
|
|
and often it also specifies the date format and how many header lines
|
|
there are. Here's a simple CSV file and a rules file for it:
|
|
|
|
Date, Description, Id, Amount
|
|
12/11/2019, Foo, 123, 10.23
|
|
|
|
# basic.csv.rules
|
|
skip 1
|
|
fields date, description, , amount
|
|
date-format %d/%m/%Y
|
|
|
|
$ hledger print -f basic.csv
|
|
2019-11-12 Foo
|
|
expenses:unknown 10.23
|
|
income:unknown -10.23
|
|
|
|
There's an introductory Tutorial: Import CSV data on hledger.org, and
|
|
more CSV rules examples below, and a larger collection at
|
|
https://github.com/simonmichael/hledger/tree/master/examples/csv.
|
|
|
|
CSV rules cheatsheet
|
|
The following kinds of rule can appear in the rules file, in any order.
|
|
(Blank lines and lines beginning with # or ; or * are ignored.)
|
|
|
|
source optionally declare which file to read data
|
|
from
|
|
archive optionally enable an archive of imported files
|
|
encoding optionally declare which text encoding the
|
|
data has
|
|
separator declare the field separator, instead of rely-
|
|
ing on file extension
|
|
decimal-mark declare the decimal mark used in CSV amounts,
|
|
when ambiguous
|
|
date-format declare how to parse CSV dates/date-times
|
|
timezone declare the time zone of ambiguous CSV
|
|
date-times
|
|
newest-first improve txn order when: there are multiple
|
|
records, newest first, all with the same date
|
|
intra-day-reversed improve txn order when: same-day txns are in
|
|
opposite order to the overall file
|
|
skip (at top level) skip header line(s) at start of
|
|
file
|
|
fields list name CSV fields for easy reference, and op-
|
|
tionally assign their values to hledger fields
|
|
Field assignment assign a CSV value or interpolated text value
|
|
to a hledger field
|
|
if block conditionally assign values to hledger fields,
|
|
or skip a record or end (skip rest of file)
|
|
if table conditionally assign values to hledger fields,
|
|
using compact syntax
|
|
skip (inside an if rule) skip current record(s)
|
|
end (inside an if rule) skip all remaining records
|
|
balance-type select which type of balance assertions/as-
|
|
signments to generate
|
|
include inline another CSV rules file
|
|
|
|
Working with CSV tips can be found below, including How CSV rules are
|
|
evaluated.
|
|
|
|
source
|
|
If you tell hledger to read a csv file with -f foo.csv, it will look
|
|
for rules in foo.csv.rules. Or, you can tell it to read the rules
|
|
file, with -f foo.csv.rules, and it will look for data in foo.csv
|
|
(since 1.30). These are mostly equivalent, but the second method pro-
|
|
vides some extra features. For one, the data file can be missing,
|
|
without causing an error; it is just considered empty.
|
|
|
|
For more flexibility, add a source rule, which lets you specify a dif-
|
|
ferent data file:
|
|
|
|
source ./Checking1.csv
|
|
|
|
If the file does not exist, it is just considered empty, without rais-
|
|
ing an error.
|
|
|
|
If you specify just a file name with no path, hledger will look for it
|
|
in the ~/Downloads folder:
|
|
|
|
source Checking1.csv
|
|
|
|
You can use a glob pattern, to avoid specifying the file name exactly:
|
|
|
|
source Checking1*.csv
|
|
|
|
This has another benefit: if the pattern matches multiple files,
|
|
hledger will read the newest (most recently modified) one. This avoids
|
|
problems if you have downloaded a file multiple times without cleaning
|
|
up.
|
|
|
|
All this enables a convenient workflow where can you just download CSV
|
|
files, then run hledger import rules/*.
|
|
|
|
See also "Working with CSV > Reading files specified by rule".
|
|
|
|
Data cleaning / data generating commands
|
|
After source's file pattern, you can write | (pipe) and a data cleaning
|
|
command (or command pipeline). If hledger's CSV rules aren't enough,
|
|
you can pre-process the downloaded data here with a shell command or
|
|
script, to make it more suitable for conversion. The command will be
|
|
executed by your default shell, in the directory of the rules file,
|
|
will receive the data file's content as standard input, and should out-
|
|
put zero or more lines of character-separated-values, suitable for con-
|
|
version by the CSV rules.
|
|
|
|
Examples:
|
|
|
|
source ./paypal.json | paypalcsv
|
|
source data/simplefin.json | simplefincsv - 'chase.*card'
|
|
source OfxDownload*.csv | grep -vE '^(([^,]*,){6}[^,]*|)$' | sort -t, -n +2
|
|
source History_for_Account_Z20144832*.csv # | grep -E '^([^,]*,){12}[^,]*$' | sed -E -e 's/^ //' -e 's/\.([0-9]),/.\10,/g' -e 's/,([0-9]+),/,\1.00,/g'
|
|
|
|
Or, after source you can write | and a data generating command (with no
|
|
file pattern before the |). This command receives no input, and should
|
|
output zero or more lines of character-separated values, suitable for
|
|
conversion by the CSV rules.
|
|
|
|
Examples:
|
|
|
|
source | paypaljson | paypalcsv
|
|
source | paypalcsv data/paypal.json
|
|
source | simplefinjson >data/simplefin.json && simplefincsv data/simplefin.json 'chase.*card'
|
|
source | simplefincsv data/simplefin.json 'unify.*checking'
|
|
|
|
(paypal* and simplefin* scripts are in bin/)
|
|
|
|
Whenever hledger runs one of these commands, it will echo the command
|
|
on stderr. If the command produces error output, but exits success-
|
|
fully, hledger will show the error output as a warning. If the command
|
|
fails, hledger will fail and show the error output in the error mes-
|
|
sage.
|
|
|
|
Added in 1.50; experimental.
|
|
|
|
archive
|
|
With archive added to a rules file, the import command will archive
|
|
each successfully processed data file or data command output in a
|
|
nearby data/ directory. The archive file name will be based on the
|
|
rules file and the data file's modification date and extension (or for
|
|
a data-generating command, the current date and the ".csv" extension).
|
|
The original data file, if any, will be removed.
|
|
|
|
Also, in this mode import will prefer the oldest file matched by the
|
|
source rule's glob pattern, not the newest. (So if there are multiple
|
|
downloads, they will be imported and archived oldest first.)
|
|
|
|
Archiving is optional, but it can be useful for troubleshooting your
|
|
CSV rules, regenerating entries with improved rules, checking for vari-
|
|
ations in your bank's CSV, etc.
|
|
|
|
Added in 1.50; experimental.
|
|
|
|
encoding
|
|
encoding ENCODING
|
|
|
|
hledger normally expects non-ascii text to be using the system locale's
|
|
text encoding. If you need to read CSV files which have some other en-
|
|
coding, you can do it by adding encoding ENCODING to your CSV rules.
|
|
Eg: encoding iso-8859-1.
|
|
|
|
The following encodings are supported:
|
|
|
|
ascii, utf-8, utf-16, utf-32, iso-8859-1, iso-8859-2, iso-8859-3,
|
|
iso-8859-4, iso-8859-5, iso-8859-6, iso-8859-7, iso-8859-8, iso-8859-9,
|
|
iso-8859-10, iso-8859-11, iso-8859-13, iso-8859-14, iso-8859-15,
|
|
iso-8859-16, cp1250, cp1251, cp1252, cp1253, cp1254, cp1255, cp1256,
|
|
cp1257, cp1258, koi8-r, koi8-u, gb18030, macintosh, jis-x-0201,
|
|
jis-x-0208, iso-2022-jp, shift-jis, cp437, cp737, cp775, cp850, cp852,
|
|
cp855, cp857, cp860, cp861, cp862, cp863, cp864, cp865, cp866, cp869,
|
|
cp874, cp932.
|
|
|
|
Added in 1.42.
|
|
|
|
separator
|
|
You can use the separator rule to read other kinds of character-sepa-
|
|
rated data. The argument is any single separator character, or the
|
|
words tab or space (case insensitive). Eg, for comma-separated values
|
|
(CSV):
|
|
|
|
separator ,
|
|
|
|
or for semicolon-separated values (SSV):
|
|
|
|
separator ;
|
|
|
|
or for tab-separated values (TSV):
|
|
|
|
separator TAB
|
|
|
|
If the input file has a .csv, .ssv or .tsv file extension (or a csv:,
|
|
ssv:, tsv: prefix), the appropriate separator will be inferred automat-
|
|
ically, and you won't need this rule.
|
|
|
|
skip
|
|
skip N
|
|
|
|
The word skip followed by a number (or no number, meaning 1) tells
|
|
hledger to ignore this many non-empty lines at the start of the input
|
|
data. You'll need this whenever your CSV data contains header lines.
|
|
Note, empty and blank lines are skipped automatically, so you don't
|
|
need to count those.
|
|
|
|
skip has a second meaning: it can be used inside if blocks (described
|
|
below), to skip one or more records whenever the condition is true.
|
|
Records skipped in this way are ignored, except they are still required
|
|
to be valid CSV.
|
|
|
|
date-format
|
|
date-format DATEFMT
|
|
|
|
This is a helper for the date (and date2) fields. If your CSV dates
|
|
are not formatted like YYYY-MM-DD, YYYY/MM/DD or YYYY.MM.DD, you'll
|
|
need to add a date-format rule describing them with a strptime-style
|
|
date parsing pattern - see https://hackage.haskell.org/pack-
|
|
age/time/docs/Data-Time-Format.html#v:formatTime. The pattern must
|
|
parse the CSV date value completely. Some examples:
|
|
|
|
# MM/DD/YY
|
|
date-format %m/%d/%y
|
|
|
|
# D/M/YYYY
|
|
# The - makes leading zeros optional.
|
|
date-format %-d/%-m/%Y
|
|
|
|
# YYYY-Mmm-DD
|
|
date-format %Y-%h-%d
|
|
|
|
# M/D/YYYY HH:MM AM some other junk
|
|
# Note the time and junk must be fully parsed, though only the date is used.
|
|
date-format %-m/%-d/%Y %l:%M %p some other junk
|
|
|
|
Note currently there is no locale awareness for things like %b, and
|
|
setting LC_TIME won't help.
|
|
|
|
timezone
|
|
timezone TIMEZONE
|
|
|
|
When CSV contains date-times that are implicitly in some time zone
|
|
other than yours, but containing no explicit time zone information, you
|
|
can use this rule to declare the CSV's native time zone, which helps
|
|
prevent off-by-one dates.
|
|
|
|
When the CSV date-times do contain time zone information, you don't
|
|
need this rule; instead, use %Z in date-format (or %z, %EZ, %Ez; see
|
|
the formatTime link above).
|
|
|
|
In either of these cases, hledger will do a time-zone-aware conversion,
|
|
localising the CSV date-times to your current system time zone. If you
|
|
prefer to localise to some other time zone, eg for reproducibility, you
|
|
can (on unix at least) set the output timezone with the TZ environment
|
|
variable, eg:
|
|
|
|
$ TZ=-1000 hledger print -f foo.csv # or TZ=-1000 hledger import foo.csv
|
|
|
|
timezone currently does not understand timezone names, except "UTC",
|
|
"GMT", "EST", "EDT", "CST", "CDT", "MST", "MDT", "PST", or "PDT". For
|
|
others, use numeric format: +HHMM or -HHMM.
|
|
|
|
newest-first
|
|
hledger tries to ensure that the generated transactions will be ordered
|
|
chronologically, including same-day transactions. Usually it can
|
|
auto-detect how the CSV records are ordered. But if it encounters CSV
|
|
where all records are on the same date, it assumes that the records are
|
|
oldest first. If in fact the CSV's records are normally newest first,
|
|
like:
|
|
|
|
2022-10-01, txn 3...
|
|
2022-10-01, txn 2...
|
|
2022-10-01, txn 1...
|
|
|
|
you can add the newest-first rule to help hledger generate the transac-
|
|
tions in correct order.
|
|
|
|
# same-day CSV records are newest first
|
|
newest-first
|
|
|
|
intra-day-reversed
|
|
If CSV records within a single day are ordered opposite to the overall
|
|
record order, you can add the intra-day-reversed rule to improve the
|
|
order of journal entries. Eg, here the overall record order is newest
|
|
first, but same-day records are oldest first:
|
|
|
|
2022-10-02, txn 3...
|
|
2022-10-02, txn 4...
|
|
2022-10-01, txn 1...
|
|
2022-10-01, txn 2...
|
|
|
|
# transactions within each day are reversed with respect to the overall date order
|
|
intra-day-reversed
|
|
|
|
decimal-mark
|
|
decimal-mark .
|
|
|
|
or:
|
|
|
|
decimal-mark ,
|
|
|
|
hledger automatically accepts either period or comma as a decimal mark
|
|
when parsing numbers (cf Amounts). However if any numbers in the CSV
|
|
contain digit group marks, such as thousand-separating commas, you
|
|
should declare the decimal mark explicitly with this rule, to avoid
|
|
misparsed numbers.
|
|
|
|
CSV fields and hledger fields
|
|
This can be confusing, so let's start with an overview:
|
|
|
|
o CSV fields are provided by your data file. They are named by their
|
|
position in the CSV record, starting with 1. You can also give them
|
|
a readable name.
|
|
|
|
o hledger fields are predefined; date, description, account1, amount1,
|
|
account2 are some of them. They correspond to parts of a transac-
|
|
tion's journal entry, mostly.
|
|
|
|
o The CSV fields and hledger fields are the only fields you'll be work-
|
|
ing with; you can't define new fields, or variables as in a program-
|
|
ming language. (But you could add extra CSV fields to the data in
|
|
preprocessing, before running the rules.)
|
|
|
|
o For each CSV record, you'll assign values to one or more of the
|
|
hledger fields to build up a transaction (journal entry). Values can
|
|
be static text, CSV field values from the current record, or a combi-
|
|
nation of these.
|
|
|
|
o For simple cases, you can give a CSV field the same name as one of
|
|
the hledger fields, then its value will be automatically assigned to
|
|
that hledger field.
|
|
|
|
o CSV fields can only be read, not written to. They'll be on the right
|
|
hand side, with a % prefix. Eg
|
|
|
|
o testing a CSV field's value: if %CSVFIELD ...
|
|
|
|
o interpolating its value: HLEDGERFIELD %CSVFIELD
|
|
|
|
o hledger fields can only be written to, not read. They'll be on the
|
|
left hand side (or in a fields list), with no prefix. Eg
|
|
|
|
o setting the transaction's description to a value: description VALUE
|
|
|
|
o setting the transaction's description to the second CSV field's
|
|
value:
|
|
fields date, description, amount
|
|
|
|
fields list
|
|
fields FIELDNAME1, FIELDNAME2, ...
|
|
|
|
A fields list (the word fields followed by comma-separated field names)
|
|
is optional, but convenient. It does two things:
|
|
|
|
1. It names the CSV field in each column. This can be convenient if
|
|
you are referencing them in other rules, so you can say %SomeField
|
|
instead of remembering %13.
|
|
|
|
2. Whenever you use one of the special hledger field names (described
|
|
below), it assigns the CSV value in this position to that hledger
|
|
field. This is the quickest way to populate hledger's fields and
|
|
build a transaction.
|
|
|
|
Here's an example that says "use the 1st, 2nd and 4th fields as the
|
|
transaction's date, description and amount; name the last two fields
|
|
for later reference; and ignore the others":
|
|
|
|
fields date, description, , amount, , , somefield, anotherfield
|
|
|
|
In a fields list, the separator is always comma; it is unrelated to the
|
|
CSV file's separator. Also:
|
|
|
|
o There must be least two items in the list (at least one comma).
|
|
|
|
o Field names may not contain spaces. Spaces before/after field names
|
|
are optional.
|
|
|
|
o Field names may contain _ (underscore) or - (hyphen).
|
|
|
|
o Fields you don't care about can be given a dummy name or an empty
|
|
name.
|
|
|
|
If the CSV contains column headings, it's convenient to use these for
|
|
your field names, suitably modified (eg lower-cased with spaces re-
|
|
placed by underscores).
|
|
|
|
Sometimes you may want to alter a CSV field name to avoid assigning to
|
|
a hledger field with the same name. Eg you could call the CSV's "bal-
|
|
ance" field balance_ to avoid directly setting hledger's balance field
|
|
(and generating a balance assertion).
|
|
|
|
Field assignment
|
|
HLEDGERFIELD FIELDVALUE
|
|
|
|
Field assignments are the more flexible way to assign CSV values to
|
|
hledger fields. They can be used instead of or in addition to a fields
|
|
list (see above).
|
|
|
|
To assign a value to a hledger field, write the field name (any of the
|
|
standard hledger field/pseudo-field names, defined below), a space,
|
|
followed by a text value on the same line. This text value may inter-
|
|
polate CSV fields, referenced either by their 1-based position in the
|
|
CSV record (%N) or by the name they were given in the fields list
|
|
(%CSVFIELD), and regular expression match groups (\N).
|
|
|
|
Some examples:
|
|
|
|
# set the amount to the 4th CSV field, with " USD" appended
|
|
amount %4 USD
|
|
|
|
# combine three fields to make a comment, containing note: and date: tags
|
|
comment note: %somefield - %anotherfield, date: %1
|
|
|
|
Tips:
|
|
|
|
o Interpolation strips outer whitespace (so a CSV value like " 1 " be-
|
|
comes 1 when interpolated) (#1051).
|
|
|
|
o Interpolations always refer to a CSV field - you can't interpolate a
|
|
hledger field. (See Referencing other fields below).
|
|
|
|
Field names
|
|
Note the two kinds of field names mentioned here, and used only in
|
|
hledger CSV rules files:
|
|
|
|
1. CSV field names (CSVFIELD in these docs): you can optionally name
|
|
the CSV columns for easy reference (since hledger doesn't yet auto-
|
|
matically recognise column headings in a CSV file), by writing arbi-
|
|
trary names in a fields list, eg:
|
|
|
|
fields When, What, Some_Id, Net, Total, Foo, Bar
|
|
|
|
2. Special hledger field names (HLEDGERFIELD in these docs): you must
|
|
set at least some of these to generate the hledger transaction from
|
|
a CSV record, by writing them as the left hand side of a field as-
|
|
signment, eg:
|
|
|
|
date %When
|
|
code %Some_Id
|
|
description %What
|
|
comment %Foo %Bar
|
|
amount1 $ %Total
|
|
|
|
or directly in a fields list:
|
|
|
|
fields date, description, code, , amount1, Foo, Bar
|
|
currency $
|
|
comment %Foo %Bar
|
|
|
|
Here are all the special hledger field names available, and what hap-
|
|
pens when you assign values to them:
|
|
|
|
date field
|
|
Assigning to date sets the transaction date.
|
|
|
|
date2 field
|
|
date2 sets the transaction's secondary date, if any.
|
|
|
|
status field
|
|
status sets the transaction's status, if any.
|
|
|
|
code field
|
|
code sets the transaction's code, if any.
|
|
|
|
description field
|
|
description sets the transaction's description, if any.
|
|
|
|
comment field
|
|
comment sets the transaction's comment, if any.
|
|
|
|
commentN, where N is a number, sets the Nth posting's comment.
|
|
|
|
You can assign multi-line comments by writing literal \n in the code.
|
|
A comment starting with \n will begin on a new line.
|
|
|
|
Comments can contain tags, as usual.
|
|
|
|
Posting comments can also contain a posting date. A secondary date, or
|
|
a year-less date, will be ignored.
|
|
|
|
account field
|
|
Assigning to accountN, where N is 1 to 99, sets the account name of the
|
|
Nth posting, and causes that posting to be generated.
|
|
|
|
Most often there are two postings, so you'll want to set account1 and
|
|
account2. Typically account1 is associated with the CSV file, and is
|
|
set once with a top-level assignment, while account2 is set based on
|
|
each transaction's description, in conditional rules.
|
|
|
|
If a posting's account name is left unset but its amount is set (see
|
|
below), a default account name will be chosen (like "expenses:unknown"
|
|
or "income:unknown").
|
|
|
|
amount field
|
|
There are several ways to set posting amounts from CSV, useful in dif-
|
|
ferent situations.
|
|
|
|
1. amount is the oldest and simplest. Assigning to this sets the
|
|
amount of the first and second postings. In the second posting, the
|
|
amount will be negated; also, if it has a cost attached, it will be
|
|
converted to cost.
|
|
|
|
2. amount-in and amount-out work exactly like the above, but should be
|
|
used when the CSV has two amount fields (such as "Debit" and
|
|
"Credit", or "Inflow" and "Outflow"). Whichever field has a
|
|
non-zero value will be used as the amount of the first and second
|
|
postings. Here are some tips to avoid confusion:
|
|
|
|
o It's not "amount-in for posting 1 and amount-out for posting 2",
|
|
it is "extract a single amount from the amount-in or amount-out
|
|
field, and use that for posting 1 and (negated) for posting 2".
|
|
|
|
o Don't use both amount and amount-in/amount-out in the same rules
|
|
file; choose based on whether the amount is in a single CSV field
|
|
or spread across two fields.
|
|
|
|
o In each record, at most one of the two CSV fields should contain
|
|
a non-zero amount; the other field must contain a zero or noth-
|
|
ing.
|
|
|
|
o hledger assumes both CSV fields contain unsigned numbers, and it
|
|
automatically negates the amount-out values.
|
|
|
|
o If the data doesn't fit these requirements, you'll probably need
|
|
an if rule (see below).
|
|
|
|
3. amountN (where N is a number from 1 to 99) sets the amount of only a
|
|
single posting: the Nth posting in the transaction. You'll usually
|
|
need at least two such assignments to make a balanced transaction.
|
|
You can also generate more than two postings, to represent more com-
|
|
plex transactions. The posting numbers don't have to be consecu-
|
|
tive; with if rules, higher posting numbers can be useful to ensure
|
|
a certain order of postings.
|
|
|
|
4. amountN-in and amountN-out work exactly like the above, but should
|
|
be used when the CSV has two amount fields. This is analogous to
|
|
amount-in and amount-out, and those tips also apply here.
|
|
|
|
5. Remember that a fields list can also do assignments. So in a fields
|
|
list if you name a CSV field "amount", that counts as assigning to
|
|
amount. (If you don't want that, call it something else in the
|
|
fields list, like "amount_".)
|
|
|
|
6. The above don't handle every situation; if you need more flexibil-
|
|
ity, use an if rule to set amounts conditionally. See "Working with
|
|
CSV > Setting amounts" below for more on this and on amount-setting
|
|
generally.
|
|
|
|
currency field
|
|
currency sets a currency symbol, to be prepended to all postings'
|
|
amounts. You can use this if the CSV amounts do not have a currency
|
|
symbol, eg if it is in a separate column.
|
|
|
|
currencyN prepends a currency symbol to just the Nth posting's amount.
|
|
|
|
balance field
|
|
balanceN sets a balance assertion amount (or if the posting amount is
|
|
left empty, a balance assignment) on posting N.
|
|
|
|
balance is a compatibility spelling for hledger <1.17; it is equivalent
|
|
to balance1.
|
|
|
|
You can adjust the type of assertion/assignment with the balance-type
|
|
rule (see below).
|
|
|
|
See the Working with CSV tips below for more about setting amounts and
|
|
currency.
|
|
|
|
if block
|
|
Rules can be applied conditionally, depending on patterns in the CSV
|
|
data. This allows flexibility; in particular, it is how you can cate-
|
|
gorise transactions, selecting an appropriate account name based on
|
|
their description (for example). There are two ways to write condi-
|
|
tional rules: "if blocks", described here, and "if tables", described
|
|
below.
|
|
|
|
An if block is the word if and one or more "matcher" expressions (can
|
|
be a word or phrase), one per line, starting either on the same or next
|
|
line; followed by one or more indented rules. Eg,
|
|
|
|
if MATCHER
|
|
RULE
|
|
|
|
or
|
|
|
|
if
|
|
MATCHER
|
|
MATCHER
|
|
MATCHER
|
|
RULE
|
|
RULE
|
|
|
|
If any of the matchers succeeds, all of the indented rules will be ap-
|
|
plied. They are usually field assignments, but the following special
|
|
rules may also be used within an if block:
|
|
|
|
o skip - skips the matched CSV record (generating no transaction from
|
|
it)
|
|
|
|
o end - skips the rest of the current CSV file.
|
|
|
|
Some examples:
|
|
|
|
# if the record contains "groceries", set account2 to "expenses:groceries"
|
|
if groceries
|
|
account2 expenses:groceries
|
|
|
|
# if the record contains any of these phrases, set account2 and a transaction comment as shown
|
|
if
|
|
monthly service fee
|
|
atm transaction fee
|
|
banking thru software
|
|
account2 expenses:business:banking
|
|
comment XXX deductible ? check it
|
|
|
|
# if an empty record is seen (assuming five fields), ignore the rest of the CSV file
|
|
if ,,,,
|
|
end
|
|
|
|
Matchers
|
|
There are two kinds of matcher:
|
|
|
|
1. A whole record matcher is simplest: it is just a word, single-line
|
|
text fragment, or other regular expression, which hledger will try
|
|
to match case-insensitively anywhere within the CSV record.
|
|
Eg: whole foods.
|
|
|
|
2. A field matcher has a percent-prefixed CSV field number or name be-
|
|
fore the pattern.
|
|
Eg: %3 whole foods or %description whole foods.
|
|
hledger will try to match the pattern just within the named CSV field.
|
|
|
|
When using these, there's two things to be aware of:
|
|
|
|
1. Whole record matchers don't see the exact original record; they see
|
|
a reconstruction of it, in which values are comma-separated, and
|
|
quotes enclosing values and whitespace outside those quotes are re-
|
|
moved.
|
|
Eg when reading an SSV record like: 2023-01-01 ; "Acme, Inc. " ; 1,000
|
|
the whole record matcher sees instead: 2023-01-01,Acme, Inc. ,1,000
|
|
|
|
2. Field matchers expect either a CSV field number, or a CSV field name
|
|
declared with fields. (Don't use a hledger field name here, unless
|
|
it is also a CSV field name.) A non-CSV field name will cause the
|
|
matcher to match against "" (the empty string), and does not raise
|
|
an error, allowing easier reuse of common rules with different CSV
|
|
files.
|
|
|
|
You can also prefix a matcher with ! (and optional space) to negate it.
|
|
Eg ! whole foods, ! %3 whole foods, !%description whole foods will
|
|
match if "whole foods" is NOT present. Added in 1.32.
|
|
|
|
The pattern is, as usual in hledger, a POSIX extended regular expres-
|
|
sion that also supports GNU word boundaries (\b, \B, \<, \>) and noth-
|
|
ing else. For more details and tips, see Regular expressions in CSV
|
|
rules below.
|
|
|
|
Multiple matchers
|
|
When an if block has multiple matchers, each on its own line,
|
|
|
|
o By default they are OR'd (any of them can match).
|
|
|
|
o Matcher lines beginning with & (or &&, since 1.42) are AND'ed with
|
|
the matcher above (all in the AND'ed group must match).
|
|
|
|
o Matcher lines beginning with & ! (since 1.41, or && !, since 1.42)
|
|
are first negated and then AND'ed with the matcher above.
|
|
|
|
You can also combine multiple matchers one the same line separated by
|
|
&& (AND) or && ! (AND NOT). Eg %description amazon && %date 2025-01-01
|
|
will match only when the description field contains "amazon" and the
|
|
date field contains "2025-01-01". Added in 1.42.
|
|
|
|
Match groups
|
|
Added in 1.32
|
|
|
|
Matchers can define match groups: parenthesised portions of the regular
|
|
expression which are available for reference in field assignments.
|
|
Groups are enclosed in regular parentheses (( and )) and can be nested.
|
|
Each group is available in field assignments using the token \N, where
|
|
N is an index into the match groups for this conditional block (e.g.
|
|
\1, \2, etc.).
|
|
|
|
Example: Warp credit card payment postings to the beginning of the
|
|
billing period (Month start), to match how they are presented in state-
|
|
ments, using posting dates:
|
|
|
|
if %date (....-..)-..
|
|
comment2 date:\1-01
|
|
|
|
Another example: Read the expense account from the CSV field, but throw
|
|
away a prefix:
|
|
|
|
if %account1 liabilities:family:(expenses:.*)
|
|
account1 \1
|
|
|
|
if table
|
|
"if tables" are an alternative to if blocks; they can express many
|
|
matchers and field assignments in a more compact tabular format, like
|
|
this:
|
|
|
|
if,HLEDGERFIELD1,HLEDGERFIELD2,...
|
|
MATCHERA,VALUE1,VALUE2,...
|
|
MATCHERB && MATCHERC,VALUE1,VALUE2,... (*since 1.42*)
|
|
; Comment line that explains MATCHERD
|
|
MATCHERD,VALUE1,VALUE2,...
|
|
<empty line>
|
|
|
|
The first character after if is taken to be this if table's field sepa-
|
|
rator. It is unrelated to the separator used in the CSV file. It
|
|
should be a non-alphanumeric character like , or | that does not appear
|
|
anywhere else in the table (it should not be used in field names or
|
|
matchers or values, and it cannot be escaped with a backslash).
|
|
|
|
Each line must contain the same number of separators; empty values are
|
|
allowed. Whitespace can be used in the matcher lines for readability
|
|
(but not in the if line, currently). You can use the comment lines in
|
|
the table body. The table must be terminated by an empty line (or end
|
|
of file).
|
|
|
|
An if table like the above is interpreted as follows: try all of the
|
|
lines with matchers; whenever a line with matchers succeeds, assign all
|
|
of the values on that line to the corresponding hledger fields; If mul-
|
|
tiple lines match, later lines will override fields assigned by the
|
|
earlier ones - just like the sequence of if blocks would behave.
|
|
|
|
If table presented above is equivalent to this sequence of if blocks:
|
|
|
|
if MATCHERA
|
|
HLEDGERFIELD1 VALUE1
|
|
HLEDGERFIELD2 VALUE2
|
|
...
|
|
|
|
if MATCHERB && MATCHERC
|
|
HLEDGERFIELD1 VALUE1
|
|
HLEDGERFIELD2 VALUE2
|
|
...
|
|
|
|
; Comment line which explains MATCHERD
|
|
if MATCHERD
|
|
HLEDGERFIELD1 VALUE1
|
|
HLEDGERFIELD2 VALUE2
|
|
...
|
|
|
|
Example:
|
|
|
|
if,account2,comment
|
|
atm transaction fee,expenses:business:banking,deductible? check it
|
|
%description groceries,expenses:groceries,
|
|
;; Comment line that desribes why this particular date is special
|
|
2023/01/12.*Plumbing LLC,expenses:house:upkeep,emergency plumbing call-out
|
|
|
|
balance-type
|
|
Balance assertions generated by assigning to balanceN are of the simple
|
|
= type by default, which is a single-commodity, subaccount-excluding
|
|
assertion. You may find the subaccount-including variants more useful,
|
|
eg if you have created some virtual subaccounts of checking to help
|
|
with budgeting. You can select a different type of assertion with the
|
|
balance-type rule:
|
|
|
|
# balance assertions will consider all commodities and all subaccounts
|
|
balance-type ==*
|
|
|
|
Here are the balance assertion types for quick reference:
|
|
|
|
= single commodity, exclude subaccounts
|
|
=* single commodity, include subaccounts
|
|
== multi commodity, exclude subaccounts
|
|
==* multi commodity, include subaccounts
|
|
|
|
include
|
|
include RULESFILE
|
|
|
|
This includes the contents of another CSV rules file at this point.
|
|
RULESFILE is an absolute file path or a path relative to the current
|
|
file's directory. This can be useful for sharing common rules between
|
|
several rules files, eg:
|
|
|
|
# someaccount.csv.rules
|
|
|
|
## someaccount-specific rules
|
|
fields date,description,amount
|
|
account1 assets:someaccount
|
|
account2 expenses:misc
|
|
|
|
## common rules
|
|
include categorisation.rules
|
|
|
|
Working with CSV
|
|
Some tips:
|
|
|
|
Rapid feedback
|
|
It's a good idea to get rapid feedback while creating/troubleshooting
|
|
CSV rules. Here's a good way, using entr from eradman.com/entrproject:
|
|
|
|
$ ls foo.csv* | entr bash -c 'echo ----; hledger -f foo.csv print desc:SOMEDESC'
|
|
|
|
A desc: query (eg) is used to select just one, or a few, transactions
|
|
of interest. "bash -c" is used to run multiple commands, so we can
|
|
echo a separator each time the command re-runs, making it easier to
|
|
read the output.
|
|
|
|
Valid CSV
|
|
Note that hledger will only accept valid CSV conforming to RFC 4180,
|
|
and equivalent SSV and TSV formats (like RFC 4180 but with semicolon or
|
|
tab as separators). This means, eg:
|
|
|
|
o Values may be enclosed in double quotes, or not. Enclosing in single
|
|
quotes is not allowed. (Eg 'A','B' is rejected.)
|
|
|
|
o When values are enclosed in double quotes, spaces outside the quotes
|
|
are not allowed. (Eg "A", "B" is rejected.)
|
|
|
|
o When values are not enclosed in quotes, they may not contain double
|
|
quotes. (Eg A"A, B is rejected.)
|
|
|
|
If your CSV/SSV/TSV is not valid in this sense, you'll need to trans-
|
|
form it before reading with hledger. Try using sed, or a more permis-
|
|
sive CSV parser like python's csv lib.
|
|
|
|
File Extension
|
|
To help hledger choose the CSV file reader and show the right error
|
|
messages (and choose the right field separator character by default),
|
|
it's best if CSV/SSV/TSV files are named with a .csv, .ssv or .tsv
|
|
filename extension. (More about this at Data formats.)
|
|
|
|
When reading files with the "wrong" extension, you can ensure the CSV
|
|
reader (and the default field separator) by prefixing the file path
|
|
with csv:, ssv: or tsv:: Eg:
|
|
|
|
$ hledger -f ssv:foo.dat print
|
|
|
|
You can also override the default field separator with a separator rule
|
|
if needed.
|
|
|
|
Reading CSV from standard input
|
|
You'll need the file format prefix when reading CSV from stdin also,
|
|
since hledger assumes journal format by default. Eg:
|
|
|
|
$ cat foo.dat | hledger -f ssv:- print
|
|
|
|
Reading multiple CSV files
|
|
If you use multiple -f options to read multiple CSV files at once,
|
|
hledger will look for a correspondingly-named rules file for each CSV
|
|
file. But if you specify a rules file with --rules, that rules file
|
|
will be used for all the CSV files.
|
|
|
|
Reading files specified by rule
|
|
Instead of specifying a CSV file in the command line, you can specify a
|
|
rules file, as in hledger -f foo.csv.rules CMD. By default this will
|
|
read data from foo.csv in the same directory, but you can add a source
|
|
rule to specify a different data file, perhaps located in your web
|
|
browser's download directory.
|
|
|
|
This feature was added in hledger 1.30, so you won't see it in most CSV
|
|
rules examples. But it helps remove some of the busywork of managing
|
|
CSV downloads. Most of your financial institutions's default CSV file-
|
|
names are different and can be recognised by a glob pattern. So you
|
|
can put a rule like source Checking1*.csv in foo-checking.csv.rules,
|
|
and then periodically follow a workflow like:
|
|
|
|
1. Download CSV from Foo's website, using your browser's defaults
|
|
|
|
2. Run hledger import foo-checking.csv.rules to import any new transac-
|
|
tions
|
|
|
|
After import, you can: discard the CSV, or leave it where it is for a
|
|
while, or move it into your archives, as you prefer. If you do noth-
|
|
ing, next time your browser will save something like Checking1-2.csv,
|
|
and hledger will use that because of the * wild card and because it is
|
|
the most recent.
|
|
|
|
Valid transactions
|
|
After reading a CSV file, hledger post-processes and validates the gen-
|
|
erated journal entries as it would for a journal file - balancing them,
|
|
applying balance assignments, and canonicalising amount styles. Any
|
|
errors at this stage will be reported in the usual way, displaying the
|
|
problem entry.
|
|
|
|
There is one exception: balance assertions, if you have generated them,
|
|
will not be checked, since normally these will work only when the CSV
|
|
data is part of the main journal. If you do need to check balance as-
|
|
sertions generated from CSV right away, pipe into another hledger:
|
|
|
|
$ hledger -f file.csv print | hledger -f- print
|
|
|
|
Deduplicating, importing
|
|
When you download a CSV file periodically, eg to get your latest bank
|
|
transactions, the new file may overlap with the old one, containing
|
|
some of the same records.
|
|
|
|
The import command will (a) detect the new transactions, and (b) append
|
|
just those transactions to your main journal. It is idempotent, so you
|
|
don't have to remember how many times you ran it or with which version
|
|
of the CSV. (It keeps state in a hidden .latest.FILE.csv file.) This
|
|
is the easiest way to import CSV data. Eg:
|
|
|
|
# download the latest CSV files, then run this command.
|
|
# Note, no -f flags needed here.
|
|
$ hledger import *.csv [--dry]
|
|
|
|
This method works for most CSV files. (Where records have a stable
|
|
chronological order, and new records appear only at the new end.)
|
|
|
|
A number of other tools and workflows, hledger-specific and otherwise,
|
|
exist for converting, deduplicating, classifying and managing CSV data.
|
|
See:
|
|
|
|
o https://hledger.org/cookbook.html#setups-and-workflows
|
|
|
|
o https://plaintextaccounting.org -> data import/conversion
|
|
|
|
Regular expressions in CSV rules
|
|
Regular expressions in if conditions (AKA matchers) are POSIX extended
|
|
regular expressions, that also support GNU word boundaries (\b, \B, \<,
|
|
\>), and nothing else. (For more detail, see Regular expressions.)
|
|
|
|
Here are some examples that might be useful in CSV rules:
|
|
|
|
o Is field "foo" truly empty ? if %foo ^$
|
|
|
|
o Is it empty or containing only whitespace ? if %foo ^ *$
|
|
|
|
o Is it non-empty ? if %foo .
|
|
|
|
o Does it contain non-whitespace ? if %foo [^ ]
|
|
|
|
Testing the value of numeric fields is a little harder. You can't use
|
|
hledger queries like amt:0 or amt:>10 in CSV rules. But you can often
|
|
achieve the same thing with a regular expression.
|
|
|
|
Note the content and layout of number fields in CSV varies, and can
|
|
change over time (eg if you switch data providers). So numeric regexps
|
|
are always somewhat specific to your particular CSV data; and it's a
|
|
good idea to make them defensive and robust if you can.
|
|
|
|
Here are some examples:
|
|
|
|
o Does foo contain a non-zero number ? if %foo [1-9]
|
|
|
|
o Is it negative ? if %foo -
|
|
|
|
o Is it non-negative ? if ! %foo -
|
|
|
|
o Is it >= 10 ? if %foo [1-9][0-9]+\. (assuming a decimal period and
|
|
no leading zeros)
|
|
|
|
o Is it >= 10 and < 20 ? if %foo \b1[0-9]\.
|
|
|
|
Setting amounts
|
|
Continuing from amount field above, here are more tips for amount-set-
|
|
ting:
|
|
|
|
1. If the amount is in a single CSV field:
|
|
a. If its sign indicates direction of flow:
|
|
Assign it to amountN, to set the Nth posting's amount. N is usu-
|
|
ally 1 or 2 but can go up to 99.
|
|
|
|
b. If another field indicates direction of flow:
|
|
Use one or more conditional rules to set the appropriate amount
|
|
sign. Eg:
|
|
|
|
# assume a withdrawal unless Type contains "deposit":
|
|
amount1 -%Amount
|
|
if %Type deposit
|
|
amount1 %Amount
|
|
|
|
2. If the amount is in two CSV fields (such as Debit and Credit, or In
|
|
and Out):
|
|
a. If both fields are unsigned:
|
|
Assign one field to amountN-in and the other to amountN-out.
|
|
hledger will automatically negate the "out" field, and will use
|
|
whichever field value is non-zero as posting N's amount.
|
|
|
|
b. If either field is signed:
|
|
You will probably need to override hledger's sign for one or the
|
|
other field, as in the following example:
|
|
|
|
# Negate the -out value, but only if it is not empty:
|
|
fields date, description, amount1-in, amount1-out
|
|
if %amount1-out [1-9]
|
|
amount1-out -%amount1-out
|
|
|
|
c. If both fields can contain a non-zero value (or both can be
|
|
empty):
|
|
The -in/-out rules normally choose the value which is
|
|
non-zero/non-empty. Some value pairs can be ambiguous, such as 1
|
|
and none. For such cases, use conditional rules to help select the
|
|
amount. Eg, to handle the above you could select the value con-
|
|
taining non-zero digits:
|
|
|
|
fields date, description, in, out
|
|
if %in [1-9]
|
|
amount1 %in
|
|
if %out [1-9]
|
|
amount1 %out
|
|
|
|
3. If you want posting 2's amount converted to cost:
|
|
Use the unnumbered amount (or amount-in and amount-out) syntax.
|
|
|
|
4. If the CSV has only balance amounts, not transaction amounts:
|
|
Assign to balanceN, to set a balance assignment on the Nth posting,
|
|
causing the posting's amount to be calculated automatically. balance
|
|
with no number is equivalent to balance1. In this situation hledger is
|
|
more likely to guess the wrong default account name, so you may need to
|
|
set that explicitly.
|
|
|
|
Amount signs
|
|
There is some special handling making it easier to parse and to reverse
|
|
amount signs. (This only works for whole amounts, not for cost amounts
|
|
such as COST in amount1 AMT @ COST):
|
|
|
|
o If an amount value begins with a plus sign:
|
|
that will be removed: +AMT becomes AMT
|
|
|
|
o If an amount value is parenthesised:
|
|
it will be de-parenthesised and sign-flipped: (AMT) becomes -AMT
|
|
|
|
o If an amount value has two minus signs (or two sets of parentheses,
|
|
or a minus sign and parentheses):
|
|
they cancel out and will be removed: --AMT or -(AMT) becomes AMT
|
|
|
|
o If an amount value contains just a sign (or just a set of parenthe-
|
|
ses):
|
|
that is removed, making it an empty value. "+" or "-" or "()" becomes
|
|
"".
|
|
|
|
It's not possible (without preprocessing the CSV) to set an amount to
|
|
its absolute value, ie discard its sign.
|
|
|
|
Setting currency/commodity
|
|
If the currency/commodity symbol is included in the CSV's amount
|
|
field(s):
|
|
|
|
2023-01-01,foo,$123.00
|
|
|
|
you don't have to do anything special for the commodity symbol, it will
|
|
be assigned as part of the amount. Eg:
|
|
|
|
fields date,description,amount
|
|
|
|
2023-01-01 foo
|
|
expenses:unknown $123.00
|
|
income:unknown $-123.00
|
|
|
|
If the currency is provided as a separate CSV field:
|
|
|
|
2023-01-01,foo,USD,123.00
|
|
|
|
You can assign that to the currency pseudo-field, which has the special
|
|
effect of prepending itself to every amount in the transaction (on the
|
|
left, with no separating space):
|
|
|
|
fields date,description,currency,amount
|
|
|
|
2023-01-01 foo
|
|
expenses:unknown USD123.00
|
|
income:unknown USD-123.00
|
|
|
|
Or, you can use a field assignment to construct the amount yourself,
|
|
with more control. Eg to put the symbol on the right, and separated by
|
|
a space:
|
|
|
|
fields date,description,cur,amt
|
|
amount %amt %cur
|
|
|
|
2023-01-01 foo
|
|
expenses:unknown 123.00 USD
|
|
income:unknown -123.00 USD
|
|
|
|
Note we used a temporary field name (cur) that is not currency - that
|
|
would trigger the prepending effect, which we don't want here.
|
|
|
|
Amount decimal places
|
|
When you are reading CSV data, eg with a command like hledger -f
|
|
foo.csv print, hledger will infer each commodity's decimal precision
|
|
(and other commodity display styles) from the amounts - much as when
|
|
reading a journal file without commodity directives (see the link).
|
|
|
|
Note, the commodity styles are not inferred from the numbers in the
|
|
original CSV data; rather, they are inferred from the amounts generated
|
|
by the CSV rules.
|
|
|
|
When you are importing CSV data with the import command, eg hledger im-
|
|
port foo.csv, there's another step: import tries to make the new en-
|
|
tries conform to the journal's existing styles. So for each commodity
|
|
- let's say it's EUR - import will choose:
|
|
|
|
1. the style declared for EUR by a commodity directive in the journal
|
|
|
|
2. otherwise, the style inferred from EUR amounts in the journal
|
|
|
|
3. otherwise, the style inferred from EUR amounts generated by the CSV
|
|
rules.
|
|
|
|
TLDR: if import is not generating the precisions or styles you want,
|
|
add a commodity directive to specify them.
|
|
|
|
Referencing other fields
|
|
In field assignments, you can interpolate only CSV fields, not hledger
|
|
fields. In the example below, there's both a CSV field and a hledger
|
|
field named amount1, but %amount1 always means the CSV field, not the
|
|
hledger field:
|
|
|
|
# Name the third CSV field "amount1"
|
|
fields date,description,amount1
|
|
|
|
# Set hledger's amount1 to the CSV amount1 field followed by USD
|
|
amount1 %amount1 USD
|
|
|
|
# Set comment to the CSV amount1 (not the amount1 assigned above)
|
|
comment %amount1
|
|
|
|
Here, since there's no CSV amount1 field, %amount1 will produce a lit-
|
|
eral "amount1":
|
|
|
|
fields date,description,csvamount
|
|
amount1 %csvamount USD
|
|
# Can't interpolate amount1 here
|
|
comment %amount1
|
|
|
|
When there are multiple field assignments to the same hledger field,
|
|
only the last one takes effect. Here, comment's value will be be B, or
|
|
C if "something" is matched, but never A:
|
|
|
|
comment A
|
|
comment B
|
|
if something
|
|
comment C
|
|
|
|
How CSV rules are evaluated
|
|
Here's how to think of CSV rules being evaluated. If you get a confus-
|
|
ing error while reading a CSV file, it may help to try to understand
|
|
which of these steps is failing:
|
|
|
|
1. Any included rules files are inlined, from top to bottom, depth
|
|
first (scanning each included file for further includes, recur-
|
|
sively, before proceeding).
|
|
|
|
2. Top level rules (date-format, fields, newest-first, skip etc) are
|
|
read, top to bottom. "Top level rules" means non-conditional rules.
|
|
If a rule occurs more than once, the last one wins; except for
|
|
skip/end rules, where the first one wins.
|
|
|
|
3. The CSV file is read as text. Any non-ascii characters will be de-
|
|
coded using the text encoding specified by the encoding rule, other-
|
|
wise the system locale's text encoding.
|
|
|
|
4. Any top-level skip or end rule is applied. skip [N] immediately
|
|
skips the current or next N CSV records; end immediately skips all
|
|
remaining CSV records (not normally used at top level).
|
|
|
|
5. Now any remaining CSV records are processed. For each CSV record,
|
|
in file order:
|
|
|
|
o Is there a conditional skip/end rule that applies for this record
|
|
? Search the if blocks, from top to bottom, for a succeeding one
|
|
containing a skip or end rule. If found, skip the specified num-
|
|
ber of CSV records, then continue at 5.
|
|
Otherwise...
|
|
|
|
o Do some basic validation on this CSV record (eg, check that it
|
|
has at least two fields).
|
|
|
|
o For each hledger field (date, description, account1, etc.):
|
|
|
|
1. Get the field's assigned value, first searching top level as-
|
|
signments, made directly or by the fields rule, then assign-
|
|
ments made inside succeeding if blocks. If there are more
|
|
than one, the last one wins.
|
|
|
|
2. Compute the field's actual value (as text), by interpolating
|
|
any %CSVFIELD references within the assigned value; or by
|
|
choosing a default value if there was no assignment.
|
|
|
|
o Generate a hledger transaction from the hledger field values,
|
|
parsing them if needed (eg from text to an amount).
|
|
|
|
This is all done by the CSV reader, one of several readers hledger can
|
|
use to read transactions from an input file. When all input files have
|
|
been read successfully, their transactions are passed to whichever
|
|
hledger command the user specified.
|
|
|
|
Well factored rules
|
|
Some things than can help reduce duplication and complexity in rules
|
|
files:
|
|
|
|
o Extracting common rules usable with multiple CSV files into a com-
|
|
mon.rules, and adding include common.rules to each CSV's rules file.
|
|
|
|
o Splitting if blocks into smaller if blocks, extracting the frequently
|
|
used parts.
|
|
|
|
CSV rules examples
|
|
Bank of Ireland
|
|
Here's a CSV with two amount fields (Debit and Credit), and a balance
|
|
field, which we can use to add balance assertions, which is not neces-
|
|
sary but provides extra error checking:
|
|
|
|
Date,Details,Debit,Credit,Balance
|
|
07/12/2012,LODGMENT 529898,,10.0,131.21
|
|
07/12/2012,PAYMENT,5,,126
|
|
|
|
# bankofireland-checking.csv.rules
|
|
|
|
# skip the header line
|
|
skip
|
|
|
|
# name the csv fields, and assign some of them as journal entry fields
|
|
fields date, description, amount-out, amount-in, balance
|
|
|
|
# We generate balance assertions by assigning to "balance"
|
|
# above, but you may sometimes need to remove these because:
|
|
#
|
|
# - the CSV balance differs from the true balance,
|
|
# by up to 0.0000000000005 in my experience
|
|
#
|
|
# - it is sometimes calculated based on non-chronological ordering,
|
|
# eg when multiple transactions clear on the same day
|
|
|
|
# date is in UK/Ireland format
|
|
date-format %d/%m/%Y
|
|
|
|
# set the currency
|
|
currency EUR
|
|
|
|
# set the base account for all txns
|
|
account1 assets:bank:boi:checking
|
|
|
|
$ hledger -f bankofireland-checking.csv print
|
|
2012-12-07 LODGMENT 529898
|
|
assets:bank:boi:checking EUR10.0 = EUR131.2
|
|
income:unknown EUR-10.0
|
|
|
|
2012-12-07 PAYMENT
|
|
assets:bank:boi:checking EUR-5.0 = EUR126.0
|
|
expenses:unknown EUR5.0
|
|
|
|
The balance assertions don't raise an error above, because we're read-
|
|
ing directly from CSV, but they will be checked if these entries are
|
|
imported into a journal file.
|
|
|
|
Coinbase
|
|
A simple example with some CSV from Coinbase. The spot price is
|
|
recorded using cost notation. The legacy amount field name conve-
|
|
niently sets amount 2 (posting 2's amount) to the total cost.
|
|
|
|
# Timestamp,Transaction Type,Asset,Quantity Transacted,Spot Price Currency,Spot Price at Transaction,Subtotal,Total (inclusive of fees and/or spread),Fees and/or Spread,Notes
|
|
# 2021-12-30T06:57:59Z,Receive,USDC,100,GBP,0.740000,"","","","Received 100.00 USDC from an external account"
|
|
|
|
# coinbase.csv.rules
|
|
skip 1
|
|
fields Timestamp,Transaction_Type,Asset,Quantity_Transacted,Spot_Price_Currency,Spot_Price_at_Transaction,Subtotal,Total,Fees_Spread,Notes
|
|
date %Timestamp
|
|
date-format %Y-%m-%dT%T%Z
|
|
description %Notes
|
|
account1 assets:coinbase:cc
|
|
amount %Quantity_Transacted %Asset @ %Spot_Price_at_Transaction %Spot_Price_Currency
|
|
|
|
$ hledger print -f coinbase.csv
|
|
2021-12-30 Received 100.00 USDC from an external account
|
|
assets:coinbase:cc 100 USDC @ 0.740000 GBP
|
|
income:unknown -74.000000 GBP
|
|
|
|
Amazon
|
|
Here we convert amazon.com order history, and use an if block to gener-
|
|
ate a third posting if there's a fee. (In practice you'd probably get
|
|
this data from your bank instead, but it's an example.)
|
|
|
|
"Date","Type","To/From","Name","Status","Amount","Fees","Transaction ID"
|
|
"Jul 29, 2012","Payment","To","Foo.","Completed","$20.00","$0.00","16000000000000DGLNJPI1P9B8DKPVHL"
|
|
"Jul 30, 2012","Payment","To","Adapteva, Inc.","Completed","$25.00","$1.00","17LA58JSKRD4HDGLNJPI1P9B8DKPVHL"
|
|
|
|
# amazon-orders.csv.rules
|
|
|
|
# skip one header line
|
|
skip 1
|
|
|
|
# name the csv fields, and assign the transaction's date, amount and code.
|
|
# Avoided the "status" and "amount" hledger field names to prevent confusion.
|
|
fields date, _, toorfrom, name, amzstatus, amzamount, fees, code
|
|
|
|
# how to parse the date
|
|
date-format %b %-d, %Y
|
|
|
|
# combine two fields to make the description
|
|
description %toorfrom %name
|
|
|
|
# save the status as a tag
|
|
comment status:%amzstatus
|
|
|
|
# set the base account for all transactions
|
|
account1 assets:amazon
|
|
# leave amount1 blank so it can balance the other(s).
|
|
# I'm assuming amzamount excludes the fees, don't remember
|
|
|
|
# set a generic account2
|
|
account2 expenses:misc
|
|
amount2 %amzamount
|
|
# and maybe refine it further:
|
|
#include categorisation.rules
|
|
|
|
# add a third posting for fees, but only if they are non-zero.
|
|
if %fees [1-9]
|
|
account3 expenses:fees
|
|
amount3 %fees
|
|
|
|
$ hledger -f amazon-orders.csv print
|
|
2012-07-29 (16000000000000DGLNJPI1P9B8DKPVHL) To Foo. ; status:Completed
|
|
assets:amazon
|
|
expenses:misc $20.00
|
|
|
|
2012-07-30 (17LA58JSKRD4HDGLNJPI1P9B8DKPVHL) To Adapteva, Inc. ; status:Completed
|
|
assets:amazon
|
|
expenses:misc $25.00
|
|
expenses:fees $1.00
|
|
|
|
Paypal
|
|
Here's a real-world rules file for (customised) Paypal CSV, with some
|
|
Paypal-specific rules, and a second rules file included:
|
|
|
|
"Date","Time","TimeZone","Name","Type","Status","Currency","Gross","Fee","Net","From Email Address","To Email Address","Transaction ID","Item Title","Item ID","Reference Txn ID","Receipt ID","Balance","Note"
|
|
"10/01/2019","03:46:20","PDT","Calm Radio","Subscription Payment","Completed","USD","-6.99","0.00","-6.99","simon@joyful.com","memberships@calmradio.com","60P57143A8206782E","MONTHLY - $1 for the first 2 Months: Me - Order 99309. Item total: $1.00 USD first 2 months, then $6.99 / Month","","I-R8YLY094FJYR","","-6.99",""
|
|
"10/01/2019","03:46:20","PDT","","Bank Deposit to PP Account ","Pending","USD","6.99","0.00","6.99","","simon@joyful.com","0TU1544T080463733","","","60P57143A8206782E","","0.00",""
|
|
"10/01/2019","08:57:01","PDT","Patreon","PreApproved Payment Bill User Payment","Completed","USD","-7.00","0.00","-7.00","simon@joyful.com","support@patreon.com","2722394R5F586712G","Patreon* Membership","","B-0PG93074E7M86381M","","-7.00",""
|
|
"10/01/2019","08:57:01","PDT","","Bank Deposit to PP Account ","Pending","USD","7.00","0.00","7.00","","simon@joyful.com","71854087RG994194F","Patreon* Membership","","2722394R5F586712G","","0.00",""
|
|
"10/19/2019","03:02:12","PDT","Wikimedia Foundation, Inc.","Subscription Payment","Completed","USD","-2.00","0.00","-2.00","simon@joyful.com","tle@wikimedia.org","K9U43044RY432050M","Monthly donation to the Wikimedia Foundation","","I-R5C3YUS3285L","","-2.00",""
|
|
"10/19/2019","03:02:12","PDT","","Bank Deposit to PP Account ","Pending","USD","2.00","0.00","2.00","","simon@joyful.com","3XJ107139A851061F","","","K9U43044RY432050M","","0.00",""
|
|
"10/22/2019","05:07:06","PDT","Noble Benefactor","Subscription Payment","Completed","USD","10.00","-0.59","9.41","noble@bene.fac.tor","simon@joyful.com","6L8L1662YP1334033","Joyful Systems","","I-KC9VBGY2GWDB","","9.41",""
|
|
|
|
# paypal-custom.csv.rules
|
|
|
|
# Tips:
|
|
# Export from Activity -> Statements -> Custom -> Activity download
|
|
# Suggested transaction type: "Balance affecting"
|
|
# Paypal's default fields in 2018 were:
|
|
# "Date","Time","TimeZone","Name","Type","Status","Currency","Gross","Fee","Net","From Email Address","To Email Address","Transaction ID","Shipping Address","Address Status","Item Title","Item ID","Shipping and Handling Amount","Insurance Amount","Sales Tax","Option 1 Name","Option 1 Value","Option 2 Name","Option 2 Value","Reference Txn ID","Invoice Number","Custom Number","Quantity","Receipt ID","Balance","Address Line 1","Address Line 2/District/Neighborhood","Town/City","State/Province/Region/County/Territory/Prefecture/Republic","Zip/Postal Code","Country","Contact Phone Number","Subject","Note","Country Code","Balance Impact"
|
|
# This rules file assumes the following more detailed fields, configured in "Customize report fields":
|
|
# "Date","Time","TimeZone","Name","Type","Status","Currency","Gross","Fee","Net","From Email Address","To Email Address","Transaction ID","Item Title","Item ID","Reference Txn ID","Receipt ID","Balance","Note"
|
|
|
|
fields date, time, timezone, description_, type, status_, currency, grossamount, feeamount, netamount, fromemail, toemail, code, itemtitle, itemid, referencetxnid, receiptid, balance, note
|
|
|
|
skip 1
|
|
|
|
date-format %-m/%-d/%Y
|
|
|
|
# ignore some paypal events
|
|
if
|
|
In Progress
|
|
Temporary Hold
|
|
Update to
|
|
skip
|
|
|
|
# add more fields to the description
|
|
description %description_ %itemtitle
|
|
|
|
# save some other fields as tags
|
|
comment itemid:%itemid, fromemail:%fromemail, toemail:%toemail, time:%time, type:%type, status:%status_
|
|
|
|
# convert to short currency symbols
|
|
if %currency USD
|
|
currency $
|
|
if %currency EUR
|
|
currency E
|
|
if %currency GBP
|
|
currency P
|
|
|
|
# generate postings
|
|
|
|
# the first posting will be the money leaving/entering my paypal account
|
|
# (negative means leaving my account, in all amount fields)
|
|
account1 assets:online:paypal
|
|
amount1 %netamount
|
|
|
|
# the second posting will be money sent to/received from other party
|
|
# (account2 is set below)
|
|
amount2 -%grossamount
|
|
|
|
# if there's a fee, add a third posting for the money taken by paypal.
|
|
if %feeamount [1-9]
|
|
account3 expenses:banking:paypal
|
|
amount3 -%feeamount
|
|
comment3 business:
|
|
|
|
# choose an account for the second posting
|
|
|
|
# override the default account names:
|
|
# if the amount is positive, it's income (a debit)
|
|
if %grossamount ^[^-]
|
|
account2 income:unknown
|
|
# if negative, it's an expense (a credit)
|
|
if %grossamount ^-
|
|
account2 expenses:unknown
|
|
|
|
# apply common rules for setting account2 & other tweaks
|
|
include common.rules
|
|
|
|
# apply some overrides specific to this csv
|
|
|
|
# Transfers from/to bank. These are usually marked Pending,
|
|
# which can be disregarded in this case.
|
|
if
|
|
Bank Account
|
|
Bank Deposit to PP Account
|
|
description %type for %referencetxnid %itemtitle
|
|
account2 assets:bank:wf:pchecking
|
|
account1 assets:online:paypal
|
|
|
|
# Currency conversions
|
|
if Currency Conversion
|
|
account2 equity:currency conversion
|
|
|
|
# common.rules
|
|
|
|
if
|
|
darcs
|
|
noble benefactor
|
|
account2 revenues:foss donations:darcshub
|
|
comment2 business:
|
|
|
|
if
|
|
Calm Radio
|
|
account2 expenses:online:apps
|
|
|
|
if
|
|
electronic frontier foundation
|
|
Patreon
|
|
wikimedia
|
|
Advent of Code
|
|
account2 expenses:dues
|
|
|
|
if Google
|
|
account2 expenses:online:apps
|
|
description google | music
|
|
|
|
$ hledger -f paypal-custom.csv print
|
|
2019-10-01 (60P57143A8206782E) Calm Radio MONTHLY - $1 for the first 2 Months: Me - Order 99309. Item total: $1.00 USD first 2 months, then $6.99 / Month ; itemid:, fromemail:simon@joyful.com, toemail:memberships@calmradio.com, time:03:46:20, type:Subscription Payment, status:Completed
|
|
assets:online:paypal $-6.99 = $-6.99
|
|
expenses:online:apps $6.99
|
|
|
|
2019-10-01 (0TU1544T080463733) Bank Deposit to PP Account for 60P57143A8206782E ; itemid:, fromemail:, toemail:simon@joyful.com, time:03:46:20, type:Bank Deposit to PP Account, status:Pending
|
|
assets:online:paypal $6.99 = $0.00
|
|
assets:bank:wf:pchecking $-6.99
|
|
|
|
2019-10-01 (2722394R5F586712G) Patreon Patreon* Membership ; itemid:, fromemail:simon@joyful.com, toemail:support@patreon.com, time:08:57:01, type:PreApproved Payment Bill User Payment, status:Completed
|
|
assets:online:paypal $-7.00 = $-7.00
|
|
expenses:dues $7.00
|
|
|
|
2019-10-01 (71854087RG994194F) Bank Deposit to PP Account for 2722394R5F586712G Patreon* Membership ; itemid:, fromemail:, toemail:simon@joyful.com, time:08:57:01, type:Bank Deposit to PP Account, status:Pending
|
|
assets:online:paypal $7.00 = $0.00
|
|
assets:bank:wf:pchecking $-7.00
|
|
|
|
2019-10-19 (K9U43044RY432050M) Wikimedia Foundation, Inc. Monthly donation to the Wikimedia Foundation ; itemid:, fromemail:simon@joyful.com, toemail:tle@wikimedia.org, time:03:02:12, type:Subscription Payment, status:Completed
|
|
assets:online:paypal $-2.00 = $-2.00
|
|
expenses:dues $2.00
|
|
expenses:banking:paypal ; business:
|
|
|
|
2019-10-19 (3XJ107139A851061F) Bank Deposit to PP Account for K9U43044RY432050M ; itemid:, fromemail:, toemail:simon@joyful.com, time:03:02:12, type:Bank Deposit to PP Account, status:Pending
|
|
assets:online:paypal $2.00 = $0.00
|
|
assets:bank:wf:pchecking $-2.00
|
|
|
|
2019-10-22 (6L8L1662YP1334033) Noble Benefactor Joyful Systems ; itemid:, fromemail:noble@bene.fac.tor, toemail:simon@joyful.com, time:05:07:06, type:Subscription Payment, status:Completed
|
|
assets:online:paypal $9.41 = $9.41
|
|
revenues:foss donations:darcshub $-10.00 ; business:
|
|
expenses:banking:paypal $0.59 ; business:
|
|
|
|
Timeclock
|
|
hledger can read time logs in the timeclock time logging format of
|
|
timeclock.el. As with Ledger, hledger's timeclock format is a sub-
|
|
set/variant of timeclock.el's.
|
|
|
|
hledger's timeclock format was updated in hledger 1.43 and 1.50. If
|
|
your old time logs are rejected, you should adapt them to modern
|
|
hledger; for now, you can restore the pre-1.43 behaviour with the
|
|
--old-timeclock flag.
|
|
|
|
Here the timeclock format in hledger 1.50+:
|
|
|
|
# Comment lines like these, and blank lines, are ignored:
|
|
# comment line
|
|
; comment line
|
|
* comment line
|
|
|
|
# Lines beginning with b, h, or capital O are also ignored, for compatibility:
|
|
b SIMPLEDATE HH:MM[:SS][+-ZZZZ][ TEXT]
|
|
h SIMPLEDATE HH:MM[:SS][+-ZZZZ][ TEXT]
|
|
O SIMPLEDATE HH:MM[:SS][+-ZZZZ][ TEXT]
|
|
|
|
# Lines beginning with i or o are are clock-in / clock-out entries:
|
|
i SIMPLEDATE HH:MM[:SS][+-ZZZZ] ACCOUNT[ DESCRIPTION][;COMMENT]]
|
|
o SIMPLEDATE HH:MM[:SS][+-ZZZZ][ ACCOUNT][;COMMENT]
|
|
|
|
The date is a hledger simple date (YYYY-MM-DD or similar). The time
|
|
parts must use two digits. The seconds are optional. A + or -
|
|
four-digit time zone is accepted for compatibility, but currently ig-
|
|
nored; times are always interpreted as a local time.
|
|
|
|
In clock-in entries (i), the account name is required. A transaction
|
|
description, separated from the account name by 2+ spaces, is optional.
|
|
A transaction comment, beginning with ;, is also optional. (Indented
|
|
following comment lines are also allowed, as in journal format.)
|
|
|
|
In clock-out entries (o) have no description, but can have a comment if
|
|
you wish. A clock-in and clock-out pair form a "transaction" posting
|
|
some number of hours to an account - also known as a session. Eg:
|
|
|
|
i 2015/03/30 09:00:00 session1
|
|
o 2015/03/30 10:00:00
|
|
|
|
$ hledger -f a.timeclock print
|
|
2015-03-30 * 09:00-10:00
|
|
(session1) 1.00h
|
|
|
|
Clock-ins and clock-outs are matched by their account/session name. If
|
|
a clock-out does not specify a name, the most recent unclosed clock-in
|
|
is closed. You can have multiple sessions active simultaneously. En-
|
|
tries are processed in the order they are parsed. Sessions spanning
|
|
more than one day are automatically split at day boundaries.
|
|
|
|
Eg, the following time log:
|
|
|
|
i 2015/03/30 09:00:00 some account optional description after 2 spaces ; optional comment, tags:
|
|
o 2015/03/30 09:20:00
|
|
i 2015/03/31 22:21:45 another:account
|
|
o 2015/04/01 02:00:34
|
|
i 2015/04/02 12:00:00 another:account ; this demonstrates multple sessions being clocked in
|
|
i 2015/04/02 13:00:00 some account
|
|
o 2015/04/02 14:00:00
|
|
o 2015/04/02 15:00:00 another:account
|
|
|
|
generates these transactions:
|
|
|
|
$ hledger -f t.timeclock print
|
|
2015-03-30 * optional description after 2 spaces ; optional comment, tags:
|
|
(some account) 0.33h
|
|
|
|
2015-03-31 * 22:21-23:59
|
|
(another:account) 1.64h
|
|
|
|
2015-04-01 * 00:00-02:00
|
|
(another:account) 2.01h
|
|
|
|
2015-04-02 * 12:00-15:00 ; this demonstrates multiple sessions being clocked in
|
|
(another:account) 3.00h
|
|
|
|
2015-04-02 * 13:00-14:00
|
|
(some account) 1.00h
|
|
|
|
Here is a sample.timeclock to download and some queries to try:
|
|
|
|
$ hledger -f sample.timeclock balance # current time balances
|
|
$ hledger -f sample.timeclock register -p 2009/3 # sessions in march 2009
|
|
$ hledger -f sample.timeclock register -p weekly --depth 1 --empty # time summary by week
|
|
|
|
To generate time logs, ie to clock in and clock out, you could:
|
|
|
|
o use these shell aliases at the command line:
|
|
|
|
alias ti='echo i `date "+%Y-%m-%d %H:%M:%S"` $* >>$TIMELOG'
|
|
alias to='echo o `date "+%Y-%m-%d %H:%M:%S"` >>$TIMELOG'
|
|
|
|
o or Emacs's built-in timeclock.el, or the extended timeclock-x.el, and
|
|
perhaps the extras in ledgerutils.el
|
|
|
|
o or use the old ti and to scripts in the ledger 2.x repository. These
|
|
rely on a "timeclock" executable which I think is just the ledger 2
|
|
executable renamed.
|
|
|
|
Timedot
|
|
timedot format is hledger's human-friendly time logging format. Com-
|
|
pared to timeclock format, it is more convenient for quick, approxi-
|
|
mate, and retroactive time logging, and more human-readable (you can
|
|
see at a glance where time was spent). A quick example:
|
|
|
|
2023-05-01
|
|
hom:errands .... .... ; two hours; the space is ignored
|
|
fos:hledger:timedot .. ; half an hour
|
|
per:admin:finance ; no time spent yet
|
|
|
|
hledger reads this as a transaction on this day with three (unbalanced)
|
|
postings, where each dot represents "0.25". No commodity symbol is as-
|
|
sumed, but we typically interpret it as hours.
|
|
|
|
$ hledger -f a.timedot print # .timedot file extension (or timedot: prefix) is required
|
|
2023-05-01 *
|
|
(hom:errands) 2.00 ; two hours
|
|
(fos:hledger:timedot) 0.50 ; half an hour
|
|
(per:admin:finance) 0
|
|
|
|
A timedot file contains a series of transactions (usually one per day).
|
|
Each begins with a simple date (Y-M-D, Y/M/D, or Y.M.D), optionally be
|
|
followed on the same line by a transaction description, and/or a trans-
|
|
action comment following a semicolon.
|
|
|
|
After the date line are zero or more time postings, consisting of:
|
|
|
|
o An account name - any hledger-style account name, optionally in-
|
|
dented.
|
|
|
|
o Two or more spaces - required if there is an amount (as in journal
|
|
format).
|
|
|
|
o A timedot amount, which can be
|
|
|
|
o empty (representing zero)
|
|
|
|
o a number, optionally followed by a unit s, m, h, d, w, mo, or y,
|
|
representing a precise number of seconds, minutes, hours, days
|
|
weeks, months or years (hours is assumed by default), which will be
|
|
converted to hours according to 60s = 1m, 60m = 1h, 24h = 1d, 7d =
|
|
1w, 30d = 1mo, 365d = 1y.
|
|
|
|
o one or more dots (period characters), each representing 0.25.
|
|
These are the dots in "timedot". Spaces are ignored and can be
|
|
used for grouping/alignment.
|
|
|
|
o Added in 1.32 one or more letters. These are like dots but they
|
|
also generate a tag t: (short for "type") with the letter as its
|
|
value, and a separate posting for each of the values. This pro-
|
|
vides a second dimension of categorisation, viewable in reports
|
|
with --pivot t.
|
|
|
|
o An optional comment following a semicolon (a hledger-style posting
|
|
comment).
|
|
|
|
There is some flexibility to help with keeping time log data and notes
|
|
in the same file:
|
|
|
|
o Blank lines and lines beginning with # or ; are ignored.
|
|
|
|
o After the first date line, lines which do not contain a double space
|
|
are parsed as postings with zero amount. (hledger's register reports
|
|
will show these if you add -E).
|
|
|
|
o Before the first date line, lines beginning with * (eg org headings)
|
|
are ignored. And from the first date line onward, Emacs org mode
|
|
heading prefixes at the start of lines (one or more *'s followed by a
|
|
space) will be ignored. This means the time log can also be a org
|
|
outline.
|
|
|
|
Timedot files don't support directives like journal files. So a common
|
|
pattern is to have a main journal file (eg time.journal) that contains
|
|
any needed directives, and then includes the timedot file (include
|
|
time.timedot).
|
|
|
|
Timedot examples
|
|
Numbers:
|
|
|
|
2016/2/3
|
|
inc:client1 4
|
|
fos:hledger 3h
|
|
biz:research 60m
|
|
|
|
Dots:
|
|
|
|
# on this day, 6h was spent on client work, 1.5h on haskell FOSS work, etc.
|
|
2016/2/1
|
|
inc:client1 .... .... .... .... .... ....
|
|
fos:haskell .... ..
|
|
biz:research .
|
|
|
|
2016/2/2
|
|
inc:client1 .... ....
|
|
biz:research .
|
|
|
|
$ hledger -f a.timedot print date:2016/2/2
|
|
2016-02-02 *
|
|
(inc:client1) 2.00
|
|
|
|
2016-02-02 *
|
|
(biz:research) 0.25
|
|
|
|
$ hledger -f a.timedot bal --daily --tree
|
|
Balance changes in 2016-02-01-2016-02-03:
|
|
|
|
|| 2016-02-01d 2016-02-02d 2016-02-03d
|
|
============++========================================
|
|
biz || 0.25 0.25 1.00
|
|
research || 0.25 0.25 1.00
|
|
fos || 1.50 0 3.00
|
|
haskell || 1.50 0 0
|
|
hledger || 0 0 3.00
|
|
inc || 6.00 2.00 4.00
|
|
client1 || 6.00 2.00 4.00
|
|
------------++----------------------------------------
|
|
|| 7.75 2.25 8.00
|
|
|
|
Letters:
|
|
|
|
# Activity types:
|
|
# c cleanup/catchup/repair
|
|
# e enhancement
|
|
# s support
|
|
# l learning/research
|
|
|
|
2023-11-01
|
|
work:adm ccecces
|
|
|
|
$ hledger -f a.timedot print
|
|
2023-11-01
|
|
(work:adm) 1 ; t:c
|
|
(work:adm) 0.5 ; t:e
|
|
(work:adm) 0.25 ; t:s
|
|
|
|
$ hledger -f a.timedot bal
|
|
1.75 work:adm
|
|
--------------------
|
|
1.75
|
|
|
|
$ hledger -f a.timedot bal --pivot t
|
|
1.00 c
|
|
0.50 e
|
|
0.25 s
|
|
--------------------
|
|
1.75
|
|
|
|
Org:
|
|
|
|
* 2023 Work Diary
|
|
** Q1
|
|
*** 2023-02-29
|
|
**** DONE
|
|
0700 yoga
|
|
**** UNPLANNED
|
|
**** BEGUN
|
|
hom:chores
|
|
cleaning ...
|
|
water plants
|
|
outdoor - one full watering can
|
|
indoor - light watering
|
|
**** TODO
|
|
adm:planning: trip
|
|
*** LATER
|
|
|
|
Using . as account name separator:
|
|
|
|
2016/2/4
|
|
fos.hledger.timedot 4h
|
|
fos.ledger ..
|
|
|
|
$ hledger -f a.timedot --alias '/\./=:' bal -t
|
|
4.50 fos
|
|
4.00 hledger:timedot
|
|
0.50 ledger
|
|
--------------------
|
|
4.50
|
|
|
|
PART 3: REPORTING CONCEPTS
|
|
Time periods
|
|
Report start & end date
|
|
Most hledger reports will by default show the full time period repre-
|
|
sented by the journal. The report start date will be the earliest
|
|
transaction or posting date, and the report end date will be the latest
|
|
transaction, posting, or market price date.
|
|
|
|
Often you will want to see a shorter period, such as the current month.
|
|
You can specify a start and/or end date with the -b/--begin, -e/--end,
|
|
or -p/--period options, or a date: query argument, described below.
|
|
All of these accept the smart date syntax, also described below.
|
|
|
|
End dates are exclusive; specify the day after the last day you want to
|
|
see in the report.
|
|
|
|
When dates are specified by multiple options, the last (right-most) op-
|
|
tion wins. And when date: queries and date options are combined, the
|
|
report period will be their intersection.
|
|
|
|
Examples:
|
|
|
|
-b 2016/3/17
|
|
beginning on St. Patrick's day 2016
|
|
|
|
-e 12/1
|
|
ending at the start of December 1st in the current year
|
|
|
|
-p 'this month'
|
|
during the current month
|
|
|
|
-p thismonth
|
|
same as above, spaces are optional
|
|
|
|
-b 2023
|
|
beginning on the first day of 2023
|
|
|
|
date:2023.. or date:2023-
|
|
same as above
|
|
|
|
-b 2024 -e 2025 -p '2000 to 2030' date:2020-01 date:2020 :
|
|
during January 2020 (the smallest common period, with the -p overriding
|
|
-b and -e)
|
|
|
|
Smart dates
|
|
In hledger's user interfaces (though not in the journal file), you can
|
|
optionally use "smart date" syntax. Smart dates can be written with
|
|
english words, can be relative, and can have parts omitted. Missing
|
|
parts are inferred as 1, when needed. Smart dates can be interpreted
|
|
as dates or periods depending on the context.
|
|
|
|
Examples:
|
|
|
|
2004-01-01, 2004/10/1, 2004.9.1, 20240504, 2024Q1 :
|
|
Exact dates. The year must have at least four digits, the month must
|
|
be 1-12, the day must be 1-31, the separator can be - or / or . or
|
|
nothing. The q can be upper or lower case and the quarter number must
|
|
be 1-4.
|
|
|
|
2004-10
|
|
start of month
|
|
|
|
2004q3 start of third quarter of 2004
|
|
|
|
q3 start of third quarter of current year
|
|
|
|
2004 start of year
|
|
|
|
10/1 or oct or october
|
|
October 1st in current year
|
|
|
|
21 21st day in current month
|
|
|
|
yesterday, today, tomorrow
|
|
-1, 0, 1 days from today
|
|
|
|
last/this/next day/week/month/quarter/year
|
|
-1, 0, 1 periods from the current period
|
|
|
|
in n days/weeks/months/quarters/years
|
|
n periods from the current period
|
|
|
|
n days/weeks/months/quarters/years ahead
|
|
n periods from the current period
|
|
|
|
n days/weeks/months/quarters/years ago
|
|
-n periods from the current period
|
|
|
|
20181201
|
|
8 digit YYYYMMDD with valid year month and day
|
|
|
|
201812 6 digit YYYYMM with valid year and month
|
|
|
|
Dates with no separators are allowed but might give surprising results
|
|
if mistyped:
|
|
|
|
o 20181301 (YYYYMMDD with an invalid month) is parsed as an eight-digit
|
|
year
|
|
|
|
o 20181232 (YYYYMMDD with an invalid day) gives a parse error
|
|
|
|
o 201801012 (a valid YYYYMMDD followed by additional digits) gives a
|
|
parse error
|
|
|
|
The meaning of relative dates depends on today's date. If you need to
|
|
test or reproduce old reports, you can use the --today option to over-
|
|
ride that. (Except for periodic transaction rules, which are not af-
|
|
fected by --today.)
|
|
|
|
Report intervals
|
|
A report interval can be specified so that reports like register, bal-
|
|
ance or activity become multi-period, showing each subperiod as a sepa-
|
|
rate row or column.
|
|
|
|
The following standard intervals can be enabled with command-line
|
|
flags:
|
|
|
|
o -D/--daily
|
|
|
|
o -W/--weekly
|
|
|
|
o -M/--monthly
|
|
|
|
o -Q/--quarterly
|
|
|
|
o -Y/--yearly
|
|
|
|
More complex intervals can be specified using -p/--period, described
|
|
below.
|
|
|
|
Date adjustments
|
|
Start date adjustment
|
|
If you let hledger infer a report's start date, it will adjust the date
|
|
to the previous natural boundary of the report interval, for convenient
|
|
periodic reports. (If you don't want that, specify a start date.)
|
|
|
|
For example, if the journal's first transaction is on january 10th,
|
|
|
|
o hledger register (no report interval) will start the report on janu-
|
|
ary 10th.
|
|
|
|
o hledger register --monthly will start the report on the previous
|
|
month boundary, january 1st.
|
|
|
|
o hledger register --monthly --begin 1/5 will start the report on janu-
|
|
ary 5th [1].
|
|
|
|
Also if you are generating transactions or budget goals with periodic
|
|
transaction rules, their start date may be adjusted in a similar way
|
|
(in certain situations).
|
|
|
|
End date adjustment
|
|
A report's end date is always adjusted to include a whole number of in-
|
|
tervals, so that the last subperiod has the same length as the others.
|
|
|
|
For example, if the journal's last transaction is on february 20th,
|
|
|
|
o hledger register will end the report on february 20th.
|
|
|
|
o hledger register --monthly will end the report at the end of febru-
|
|
ary.
|
|
|
|
o hledger register --monthly --end 2/14 also will end the report at the
|
|
end of february (overriding the requested end date).
|
|
|
|
o hledger register --monthly --begin 1/5 --end 2/14 will end the report
|
|
on march 4th [1].
|
|
|
|
[1] Since hledger 1.29.
|
|
|
|
Period headings
|
|
With non-standard subperiods, hledger will show "STARTDATE..ENDDATE"
|
|
headings. With standard subperiods (ie, starting on a natural interval
|
|
boundary), you'll see more compact headings, which are usually prefer-
|
|
able. (Though month names will be in english, currently.)
|
|
|
|
So if you are specifying a start date and you want compact headings:
|
|
choose a start of year for yearly reports, a start of quarter for quar-
|
|
terly reports, a start of month for monthly reports, etc. (Remember,
|
|
you can write eg -b 2024 or 1/1 as a shortcut for a start of year, or
|
|
2024-04 or 202404 or Apr for a start of month or quarter.)
|
|
|
|
For weekly reports, choose a date that's a Monday. (You can try dif-
|
|
ferent dates until you see the short headings, or write eg -b '3 weeks
|
|
ago'.)
|
|
|
|
Period expressions
|
|
The -p/--period option specifies a period expression, which is a com-
|
|
pact way of expressing a start date, end date, and/or report interval.
|
|
|
|
Here's a period expression with a start and end date (specifying the
|
|
first quarter of 2009):
|
|
|
|
-p "from 2009/1/1 to 2009/4/1"
|
|
|
|
Several keywords like "from" and "to" are supported for readability;
|
|
these are optional. "to" can also be written as ".." or "-". The
|
|
spaces are also optional, as long as you don't run two dates together.
|
|
So the following are equivalent to the above:
|
|
|
|
-p "2009/1/1 2009/4/1"
|
|
-p2009/1/1to2009/4/1
|
|
-p2009/1/1..2009/4/1
|
|
|
|
Dates are smart dates, so if the current year is 2009, these are also
|
|
equivalent to the above:
|
|
|
|
-p "1/1 4/1"
|
|
-p "jan-apr"
|
|
-p "this year to 4/1"
|
|
|
|
If you specify only one date, the missing start or end date will be the
|
|
earliest or latest transaction date in the journal:
|
|
|
|
-p "from 2009/1/1" everything after january
|
|
1, 2009
|
|
-p "since 2009/1" the same, since is a syn-
|
|
onym
|
|
-p "from 2009" the same
|
|
-p "to 2009" everything before january
|
|
1, 2009
|
|
|
|
You can also specify a period by writing a single partial or full date:
|
|
|
|
-p "2009" the year 2009; equivalent to "2009/1/1 to 2010/1/1"
|
|
-p "2009/1" the month of january 2009; equivalent to "2009/1/1 to
|
|
2009/2/1"
|
|
-p "2009/1/1" the first day of 2009; equivalent to "2009/1/1 to
|
|
2009/1/2"
|
|
|
|
or by using the "Q" quarter-year syntax (case insensitive):
|
|
|
|
-p "2009Q1" first quarter of 2009, equivalent to "2009/1/1 to
|
|
2009/4/1"
|
|
-p "q4" fourth quarter of the current year
|
|
|
|
Period expressions with a report interval
|
|
A period expression can also begin with a report interval, separated
|
|
from the start/end dates (if any) by a space or the word in:
|
|
|
|
-p "weekly from 2009/1/1 to 2009/4/1"
|
|
-p "monthly in 2008"
|
|
-p "quarterly"
|
|
|
|
More complex report intervals
|
|
Some more complex intervals can be specified within period expressions,
|
|
such as:
|
|
|
|
o biweekly (every two weeks)
|
|
|
|
o fortnightly
|
|
|
|
o bimonthly (every two months)
|
|
|
|
o every day|week|month|quarter|year
|
|
|
|
o every N days|weeks|months|quarters|years
|
|
|
|
Weekly on a custom day:
|
|
|
|
o every Nth day of week (th, nd, rd, or st are all accepted after the
|
|
number)
|
|
|
|
o every WEEKDAYNAME (full or three-letter english weekday name, case
|
|
insensitive)
|
|
|
|
Monthly on a custom day:
|
|
|
|
o every Nth day [of month] (31st day will be adjusted to each month's
|
|
last day)
|
|
|
|
o every Nth WEEKDAYNAME [of month]
|
|
|
|
Yearly on a custom month and day:
|
|
|
|
o every MM/DD [of year] (month number and day of month number)
|
|
|
|
o every MONTHNAME DDth [of year] (full or three-letter english month
|
|
name, case insensitive, and day of month number)
|
|
|
|
o every DDth MONTHNAME [of year] (equivalent to the above)
|
|
|
|
Examples:
|
|
|
|
-p "bimonthly from 2008"
|
|
-p "every 2 weeks"
|
|
-p "every 5 months from
|
|
2009/03"
|
|
-p "every 2nd day of week" periods will go from Tue to Tue
|
|
-p "every Tue" same
|
|
-p "every 15th day" period boundaries will be on 15th of each
|
|
month
|
|
-p "every 2nd Monday" period boundaries will be on second Monday
|
|
of each month
|
|
-p "every 11/05" yearly periods with boundaries on 5th of
|
|
November
|
|
-p "every 5th November" same
|
|
-p "every Nov 5th" same
|
|
|
|
Show historical balances at end of the 15th day of each month (N is an
|
|
end date, exclusive as always):
|
|
|
|
$ hledger balance -H -p "every 16th day"
|
|
|
|
Group postings from the start of wednesday to end of the following
|
|
tuesday (N is both (inclusive) start date and (exclusive) end date):
|
|
|
|
$ hledger register checking -p "every 3rd day of week"
|
|
|
|
Multiple weekday intervals
|
|
This special form is also supported:
|
|
|
|
o every WEEKDAYNAME,WEEKDAYNAME,... (full or three-letter english week-
|
|
day names, case insensitive)
|
|
|
|
Also, weekday and weekendday are shorthand for mon,tue,wed,thu,fri and
|
|
sat,sun.
|
|
|
|
This is mainly intended for use with --forecast, to generate periodic
|
|
transactions on arbitrary days of the week. It may be less useful with
|
|
-p, since it divides each week into subperiods of unequal length, which
|
|
is unusual. (Related: #1632)
|
|
|
|
Examples:
|
|
|
|
-p "every dates will be Mon, Wed, Fri; periods will be
|
|
mon,wed,fri" Mon-Tue, Wed-Thu, Fri-Sun
|
|
-p "every weekday" dates will be Mon, Tue, Wed, Thu, Fri; periods will
|
|
be Mon, Tue, Wed, Thu, Fri-Sun
|
|
-p "every weekend- dates will be Sat, Sun; periods will be Sat, Sun-Fri
|
|
day"
|
|
|
|
Depth
|
|
With the --depth NUM option (short form, usually preferred: -NUM), re-
|
|
ports will show accounts only to the specified depth, hiding deeper
|
|
subaccounts. Use this when you want a summary with less detail. This
|
|
flag has the same effect as a depth: query argument. So all of these
|
|
are equivalent: depth:2, --depth=2, -2.
|
|
|
|
You can also provide custom depths for specific accounts, by providing
|
|
a REGEX=NUM argument instead of just NUM (since 1.41). For example,
|
|
--depth assets=2 (or depth:assets=2) will collapse accounts matching
|
|
the regular expression "assets" to depth 2. So assets:bank:savings
|
|
would be collapsed to assets:bank, but liabilities:bank:credit card
|
|
would not be affected.
|
|
|
|
If REGEX contains spaces or other special characters, enclose it in
|
|
quotes in the usual way. Eg: --depth 'credit card=2'
|
|
|
|
Combining depth options
|
|
If a command line contains multiple general depth options, the last one
|
|
wins. (Useful for overriding a depth specified by scripts.)
|
|
|
|
Or a command may contain a combination of general and custom depth op-
|
|
tions. In this case, the most specifically (deepest) matching option
|
|
wins. Some examples:
|
|
|
|
o --depth assets=3 --depth expenses=2 --depth 1 would collapse accounts
|
|
containing "assets" to depth 3, accounts containing "expenses" to
|
|
depth 2, and all other accounts to depth 1.
|
|
|
|
o --depth assets=1 --depth savings=2 would collapse assets:bank:savings
|
|
to depth 2 (not depth 1; because "savings" matches a deeper part of
|
|
the account name than "assets").
|
|
|
|
Note currently, to override a custom depth option --depth REGEX=NUM
|
|
with a later option, the later option must use the same REGEX.
|
|
|
|
Queries
|
|
Many hledger commands accept query arguments, which restrict their
|
|
scope and let you report on a precise subset of your data. Here's a
|
|
quick overview of hledger's queries:
|
|
|
|
o By default, a query argument is treated as a case-insensitive sub-
|
|
string pattern for matching account names. Eg:
|
|
|
|
dining groceries
|
|
car:fuel
|
|
o Patterns containing spaces or other special characters must be en-
|
|
closed in single or double quotes:
|
|
|
|
'personal care'
|
|
o Patterns are actually regular expressions, so you can add regexp
|
|
metacharacters for more precision (or you may need to backslash-es-
|
|
cape certain characters; see "Regular expressions" above):
|
|
|
|
'^expenses\b'
|
|
'food$'
|
|
'fuel|repair'
|
|
'accounts (payable|receivable)'
|
|
o To match something other than the account name, you can add a query
|
|
type prefix, such as:
|
|
|
|
date:202312-
|
|
status:
|
|
desc:amazon
|
|
cur:USD
|
|
cur:\\$
|
|
amt:'>0'
|
|
acct:groceries (but acct: is the default, so we usually don't bother
|
|
writing it)
|
|
o To negate a query, add a not: prefix:
|
|
|
|
not:status:'*'
|
|
not:desc:'opening|closing'
|
|
not:cur:USD
|
|
o Multiple query terms can be combined, as space-separated queries Eg:
|
|
hledger print date:2022 desc:amazon desc:amzn (show transactions
|
|
dated in 2022 whose description contains "amazon" or "amzn").
|
|
o Or more flexibly as boolean queries. Eg: hledger print
|
|
expr:'date:2022 and (desc:amazon or desc:amzn) and not date:202210'
|
|
All hledger commands use the same query language, but different com-
|
|
mands may interpret the query in different ways. We haven't described
|
|
the commands yet (that's coming in PART 4: COMMANDS below) but here's
|
|
the gist of it:
|
|
|
|
o Transaction-oriented commands (print, aregister, close, import, de-
|
|
scriptions..) try to match transactions (including the transaction's
|
|
postings).
|
|
|
|
o Posting-oriented commands (register, balance, balancesheet, incomes-
|
|
tatement, accounts..) try to match postings. Postings inherit their
|
|
transaction's attributes for querying purposes, so transaction fields
|
|
like date or description can still be referenced in a posting query.
|
|
|
|
o A few commands match in more specific ways. (Eg aregister, which has
|
|
a special first argument.)
|
|
|
|
Query types
|
|
Here are the query types available:
|
|
|
|
acct: query
|
|
acct:REGEX, or just REGEX
|
|
Match account names containing this case insensitive regular expres-
|
|
sion.
|
|
This is the default query type, so we usually don't bother writing the
|
|
"acct:" prefix.
|
|
|
|
amt: query
|
|
amt:N, amt:'<N', amt:'<=N', amt:'>N', amt:'>=N'
|
|
Match postings with a single-commodity amount equal to, less than, or
|
|
greater than N. (Postings with multi-commodity amounts are not tested
|
|
and will always match.) amt: needs quotes to hide the less
|
|
than/greater than sign from the command line shell.
|
|
|
|
The comparison has two modes: if N is preceded by a + or - sign (or is
|
|
0), the two signed numbers are compared. Otherwise, the absolute mag-
|
|
nitudes are compared, ignoring sign.
|
|
|
|
Keep in mind that amt: matches posting amounts, not account balances.
|
|
|
|
code: query
|
|
code:REGEX
|
|
Match by transaction code (eg check number).
|
|
|
|
cur: query
|
|
cur:REGEX
|
|
Match postings or transactions including any amounts whose cur-
|
|
rency/commodity symbol is fully matched by REGEX. (Contrary to
|
|
hledger's usual infix matching. To do infix matching, write
|
|
.*REGEX.*.) Note, to match special characters which are regex-signifi-
|
|
cant, you need to escape them with \. And for characters which are
|
|
significant to your shell you will usually need one more level of es-
|
|
caping. Eg to match the dollar sign: cur:\\$ or cur:'\$'
|
|
|
|
desc: query
|
|
desc:REGEX
|
|
Match transaction descriptions.
|
|
|
|
date: query
|
|
date:PERIODEXPR
|
|
Match dates (or with the --date2 flag, secondary dates) within the
|
|
specified period. PERIODEXPR is a period expression with no report in-
|
|
terval. Examples:
|
|
date:2016, date:thismonth, date:2/1-2/15, date:2021-07-27..nextquarter.
|
|
|
|
date2: query
|
|
date2:PERIODEXPR
|
|
If you use secondary dates: this matches secondary dates within the
|
|
specified period. It is not affected by the --date2 flag.
|
|
|
|
depth: query
|
|
depth:[REGEXP=]N
|
|
Match (or display, depending on command) accounts at or above this
|
|
depth, optionally only for accounts matching a provided regular expres-
|
|
sion. See Depth for detailed rules.
|
|
|
|
note: query
|
|
note:REGEX
|
|
Match transaction notes (the part of the description right of |, or the
|
|
whole description if there's no |).
|
|
|
|
payee: query
|
|
payee:REGEX
|
|
Match transaction payee/payer names (the part of the description left
|
|
of |, or the whole description if there's no |).
|
|
|
|
real: query
|
|
real:, real:0
|
|
Match real or virtual postings respectively.
|
|
|
|
status: query
|
|
status:, status:!, status:*
|
|
Match unmarked, pending, or cleared transactions respectively.
|
|
|
|
type: query
|
|
type:TYPECODES
|
|
Match by account type (see Declaring accounts > Account types). TYPE-
|
|
CODES is one or more of the single-letter account type codes ALERXCV,
|
|
case insensitive. Note type:A and type:E will also match their respec-
|
|
tive subtypes C (Cash) and V (Conversion). Certain kinds of account
|
|
alias can disrupt account types, see Rewriting accounts > Aliases and
|
|
account types.
|
|
|
|
tag: query
|
|
tag:NAMEREGEX[=VALREGEX]
|
|
Match by tag name, and optionally also by tag value. Note:
|
|
|
|
o Both regular expressions do infix matching. If you need a complete
|
|
match, use ^ and $.
|
|
Eg: tag:'^fullname$', tag:'^fullname$=^fullvalue$
|
|
|
|
o To match values, ignoring names, do tag:.=VALREGEX
|
|
|
|
o Accounts also inherit the tags of their parent accounts.
|
|
|
|
o Postings also inherit the tags of their account and their transaction
|
|
.
|
|
|
|
o Transactions also acquire the tags of their postings.
|
|
|
|
Negative queries
|
|
not: query
|
|
not:QUERY
|
|
You can prepend not: to a query to negate the match.
|
|
Eg: not:equity, not:desc:apple
|
|
(Also, a trick: not:not:... can sometimes solve query problems conve-
|
|
niently.)
|
|
|
|
Space-separated queries
|
|
When given multiple space-separated query terms, most commands select
|
|
things which match:
|
|
|
|
o any of the description terms AND
|
|
|
|
o any of the account terms AND
|
|
|
|
o any of the status terms AND
|
|
|
|
o all the other terms.
|
|
|
|
The print command is a little different, showing transactions which:
|
|
|
|
o match any of the description terms AND
|
|
|
|
o have any postings matching any of the positive account terms AND
|
|
|
|
o have no postings matching any of the negative account terms AND
|
|
|
|
o match all the other terms.
|
|
|
|
Boolean queries
|
|
You can write more complicated "boolean" query expressions, enclosed in
|
|
quotes and prefixed with expr:. These can combine subqueries with NOT,
|
|
AND, OR operators (case insensitive), and parentheses for grouping.
|
|
Eg, to show transactions involving both cash and expense accounts:
|
|
|
|
hledger print expr:'cash AND expenses'
|
|
|
|
The prefix and enclosing quotes are required, so don't write hledger
|
|
print cash AND expenses. That would be a space-separated query showing
|
|
transactions involving accounts with any of "cash", "and", "expenses"
|
|
in their names.
|
|
|
|
You can write space-separated queries inside a boolean query, and they
|
|
will combine as described above, but it might be confusing and best
|
|
avoided. Eg these are equivalent, showing transactions involving cash
|
|
or expenses accounts:
|
|
|
|
hledger print expr:'cash expenses'
|
|
hledger print cash expenses
|
|
|
|
There is a restriction with date: queries: they may not be used inside
|
|
OR expressions.
|
|
|
|
Actually, there are three types of boolean query: expr: for general
|
|
use, and any: and all: variants which can be useful with print.
|
|
|
|
expr: query
|
|
expr:'QUERYEXPR'
|
|
For example, expr:'date:lastmonth AND NOT (food OR rent)' means "match
|
|
things which are dated in the last month and do not have food or rent
|
|
in the account name".
|
|
|
|
When using expr: with transaction-oriented commands like print, post-
|
|
ing-oriented query terms like acct: and amt: are considered to match
|
|
the transaction if they match any of its postings.
|
|
So, hledger print expr:'cash and amt:>0' means "show transactions with
|
|
(at least one posting involving a cash account) and (at least one post-
|
|
ing with a positive amount)".
|
|
|
|
any: query
|
|
any:'QUERYEXPR'
|
|
Like expr:, but when used with transaction-oriented commands like
|
|
print, it matches the transaction only if a posting can be matched by
|
|
all of QUERYEXPR.
|
|
So, hledger print any:'cash and amt:>0' means "show transactions where
|
|
at least one posting posts a positive amount to a cash account".
|
|
|
|
all: query
|
|
all:'QUERYEXPR'
|
|
Like expr:, but when used with transaction-oriented commands like
|
|
print, it matches the transaction only if all postings are matched by
|
|
all of QUERYEXPR (and there is at least one posting).
|
|
So, hledger print all:'cash and amt:0' means "show transactions where
|
|
all postings involve a cash account and have a zero amount".
|
|
Or, hledger print all:'cash or checking' means "show transactions which
|
|
touch only cash and/or checking accounts".
|
|
|
|
Queries and command options
|
|
Some queries can also be expressed as command-line options: depth:2 is
|
|
equivalent to --depth 2, date:2023 is equivalent to -p 2023, etc. When
|
|
you mix command options and query arguments, generally the resulting
|
|
query is their intersection.
|
|
|
|
Queries and account aliases
|
|
When account names are rewritten with --alias or alias, acct: will
|
|
match either the old or the new account name.
|
|
|
|
Queries and valuation
|
|
When amounts are converted to other commodities in cost or value re-
|
|
ports, cur: and amt: match the old commodity symbol and the old amount
|
|
quantity, not the new ones. (Except in hledger 1.22, #1625.)
|
|
|
|
Pivoting
|
|
Normally, hledger groups amounts and displays their totals by account
|
|
(name). With --pivot PIVOTEXPR, some other field's (or multiple
|
|
fields') value is used as a synthetic account name, causing different
|
|
grouping and display. PIVOTEXPR can be
|
|
|
|
o any of these standard transaction or posting fields (their value is
|
|
substituted): status, code, desc, payee, note, acct, comm/cur, amt,
|
|
cost
|
|
|
|
o or a tag name
|
|
|
|
o or any combination of these, colon-separated.
|
|
|
|
Some special cases:
|
|
|
|
o Colons appearing in PIVOTEXPR or in a pivoted tag value will generate
|
|
account hierarchy.
|
|
|
|
o When pivoting a posting that has multiple values for a tag, the tag's
|
|
first value will be used as the pivoted value.
|
|
|
|
o When a posting has multiple commodities, the pivoted value of
|
|
"comm"/"cur" will be "". Also when an unrecognised tag name or field
|
|
is provided, its pivoted value will be "". (If this causes confusing
|
|
output, consider excluding those postings from the report.)
|
|
|
|
Examples:
|
|
|
|
2016/02/16 Yearly Dues Payment
|
|
assets:bank account 2 EUR
|
|
income:dues -2 EUR ; member: John Doe, kind: Lifetime
|
|
|
|
Normal balance report showing account names:
|
|
|
|
$ hledger balance
|
|
2 EUR assets:bank account
|
|
-2 EUR income:dues
|
|
--------------------
|
|
0
|
|
|
|
Pivoted balance report, using member: tag values instead:
|
|
|
|
$ hledger balance --pivot member
|
|
2 EUR
|
|
-2 EUR John Doe
|
|
--------------------
|
|
0
|
|
|
|
One way to show only amounts with a member: value (using a query):
|
|
|
|
$ hledger balance --pivot member tag:member=.
|
|
-2 EUR John Doe
|
|
--------------------
|
|
-2 EUR
|
|
|
|
Another way (the acct: query matches against the pivoted "account
|
|
name"):
|
|
|
|
$ hledger balance --pivot member acct:.
|
|
-2 EUR John Doe
|
|
--------------------
|
|
-2 EUR
|
|
|
|
Hierarchical reports can be generated with multiple pivot values:
|
|
|
|
$ hledger balance Income:Dues --pivot kind:member
|
|
-2 EUR Lifetime:John Doe
|
|
--------------------
|
|
-2 EUR
|
|
|
|
Generating data
|
|
hledger can enrich the data provided to it, or generate new data, in a
|
|
number of ways. Mostly, this is done only if you request it:
|
|
|
|
o Missing amounts or missing costs in transactions are inferred auto-
|
|
matically when possible.
|
|
|
|
o The --infer-equity flag infers missing conversion equity postings
|
|
from @/@@ costs.
|
|
|
|
o The --infer-costs flag infers missing costs from conversion equity
|
|
postings.
|
|
|
|
o The --infer-market-prices flag infers P price directives from costs.
|
|
|
|
o The --auto flag adds extra postings to transactions matched by auto
|
|
posting rules.
|
|
|
|
o The --forecast option generates transactions from periodic transac-
|
|
tion rules.
|
|
|
|
o The balance --budget report infers budget goals from periodic trans-
|
|
action rules.
|
|
|
|
o Commands like close, rewrite, and hledger-interest generate transac-
|
|
tions or postings.
|
|
|
|
o CSV data is converted to transactions by applying CSV conversion
|
|
rules.. etc.
|
|
|
|
Such generated data is temporary, existing only at report time. You
|
|
can convert it to permanent recorded data by, eg, capturing the output
|
|
of hledger print and saving it in your journal file. This can some-
|
|
times be useful as a data entry aid.
|
|
|
|
If you are curious what data is being generated and why, run hledger
|
|
print -x --verbose-tags. -x/--explicit shows inferred amounts and
|
|
--verbose-tags adds tags like generated-transaction (from periodic
|
|
rules) and generated-posting, modified (from auto posting rules). Sim-
|
|
ilar hidden tags (with an underscore prefix) are always present, also,
|
|
so you can always match such data with queries like tag:generated or
|
|
tag:modified.
|
|
|
|
Forecasting
|
|
Forecasting, or speculative future reporting, can be useful for esti-
|
|
mating future balances, or for exploring different future scenarios.
|
|
|
|
The simplest and most flexible way to do it with hledger is to manually
|
|
record a bunch of future-dated transactions. You could keep these in a
|
|
separate future.journal and include that with -f only when you want to
|
|
see them.
|
|
|
|
--forecast
|
|
There is another way: with the --forecast option, hledger can generate
|
|
temporary "forecast transactions" for reporting purposes, according to
|
|
periodic transaction rules defined in the journal. Each rule can gen-
|
|
erate multiple recurring transactions, so by changing one rule you can
|
|
change many forecasted transactions.
|
|
|
|
Forecast transactions usually start after ordinary transactions end.
|
|
By default, they begin after your latest-dated ordinary transaction, or
|
|
today, whichever is later, and they end six months from today. (The
|
|
exact rules are a little more complicated, and are given below.)
|
|
|
|
This is the "forecast period", which need not be the same as the report
|
|
period. You can override it - eg to forecast farther into the future,
|
|
or to force forecast transactions to overlap your ordinary transactions
|
|
- by giving the --forecast option a period expression argument, like
|
|
--forecast=..2099 or --forecast=2023-02-15... Note that the = is re-
|
|
quired.
|
|
|
|
Inspecting forecast transactions
|
|
print is the best command for inspecting and troubleshooting forecast
|
|
transactions. Eg:
|
|
|
|
~ monthly from 2022-12-20 rent
|
|
assets:bank:checking
|
|
expenses:rent $1000
|
|
|
|
$ hledger print --forecast --today=2023/4/21
|
|
2023-05-20 rent
|
|
; generated-transaction: ~ monthly from 2022-12-20
|
|
assets:bank:checking
|
|
expenses:rent $1000
|
|
|
|
2023-06-20 rent
|
|
; generated-transaction: ~ monthly from 2022-12-20
|
|
assets:bank:checking
|
|
expenses:rent $1000
|
|
|
|
2023-07-20 rent
|
|
; generated-transaction: ~ monthly from 2022-12-20
|
|
assets:bank:checking
|
|
expenses:rent $1000
|
|
|
|
2023-08-20 rent
|
|
; generated-transaction: ~ monthly from 2022-12-20
|
|
assets:bank:checking
|
|
expenses:rent $1000
|
|
|
|
2023-09-20 rent
|
|
; generated-transaction: ~ monthly from 2022-12-20
|
|
assets:bank:checking
|
|
expenses:rent $1000
|
|
|
|
Here there are no ordinary transactions, so the forecasted transactions
|
|
begin on the first occurrence after today's date. (You won't normally
|
|
use --today; it's just to make these examples reproducible.)
|
|
|
|
Forecast reports
|
|
Forecast transactions affect all reports, as you would expect. Eg:
|
|
|
|
$ hledger areg rent --forecast --today=2023/4/21
|
|
Transactions in expenses:rent and subaccounts:
|
|
2023-05-20 rent as:ba:checking $1000 $1000
|
|
2023-06-20 rent as:ba:checking $1000 $2000
|
|
2023-07-20 rent as:ba:checking $1000 $3000
|
|
2023-08-20 rent as:ba:checking $1000 $4000
|
|
2023-09-20 rent as:ba:checking $1000 $5000
|
|
|
|
$ hledger bal -M expenses --forecast --today=2023/4/21
|
|
Balance changes in 2023-05-01..2023-09-30:
|
|
|
|
|| May Jun Jul Aug Sep
|
|
===============++===================================
|
|
expenses:rent || $1000 $1000 $1000 $1000 $1000
|
|
---------------++-----------------------------------
|
|
|| $1000 $1000 $1000 $1000 $1000
|
|
|
|
Forecast tags
|
|
Forecast transactions generated by --forecast have a hidden tag, _gen-
|
|
erated-transaction. So if you ever need to match forecast transac-
|
|
tions, you could use tag:_generated-transaction (or just tag:generated)
|
|
in a query.
|
|
|
|
For troubleshooting, you can add the --verbose-tags flag. Then, visi-
|
|
ble generated-transaction tags will be added also, so you can view them
|
|
with the print command. Their value indicates which periodic rule was
|
|
responsible.
|
|
|
|
Forecast period, in detail
|
|
Forecast start/end dates are chosen so as to do something useful by de-
|
|
fault in almost all situations, while also being flexible. Here are
|
|
(with luck) the exact rules, to help with troubleshooting:
|
|
|
|
The forecast period starts on:
|
|
|
|
o the later of
|
|
|
|
o the start date in the periodic transaction rule
|
|
|
|
o the start date in --forecast's argument
|
|
|
|
o otherwise (if those are not available): the later of
|
|
|
|
o the report start date specified with -b/-p/date:
|
|
|
|
o the day after the latest ordinary transaction in the journal
|
|
|
|
o otherwise (if none of these are available): today.
|
|
|
|
The forecast period ends on:
|
|
|
|
o the earlier of
|
|
|
|
o the end date in the periodic transaction rule
|
|
|
|
o the end date in --forecast's argument
|
|
|
|
o otherwise: the report end date specified with -e/-p/date:
|
|
|
|
o otherwise: 180 days (~6 months) from today.
|
|
|
|
Forecast troubleshooting
|
|
When --forecast is not doing what you expect, one of these tips should
|
|
help:
|
|
|
|
o Remember to use the --forecast option.
|
|
|
|
o Remember to have at least one periodic transaction rule in your jour-
|
|
nal.
|
|
|
|
o Test with print --forecast.
|
|
|
|
o Check for typos or too-restrictive start/end dates in your periodic
|
|
transaction rule.
|
|
|
|
o Leave at least 2 spaces between the rule's period expression and de-
|
|
scription fields.
|
|
|
|
o Check for future-dated ordinary transactions suppressing forecasted
|
|
transactions.
|
|
|
|
o Try setting explicit report start and/or end dates with -b, -e, -p or
|
|
date:
|
|
|
|
o Try adding the -E flag to encourage display of empty periods/zero
|
|
transactions.
|
|
|
|
o Try setting explicit forecast start and/or end dates with --fore-
|
|
cast=START..END
|
|
|
|
o Consult Forecast period, in detail, above.
|
|
|
|
o Check inside the engine: add --debug=2 (eg).
|
|
|
|
Budgeting
|
|
With the balance command's --budget report, each periodic transaction
|
|
rule generates recurring budget goals in specified accounts, and goals
|
|
and actual performance can be compared. See the balance command's doc
|
|
below.
|
|
|
|
You can generate budget goals and forecast transactions at the same
|
|
time, from the same or different periodic transaction rules: hledger
|
|
bal -M --budget --forecast ...
|
|
|
|
See also: Budgeting and Forecasting.
|
|
|
|
Amount formatting
|
|
Commodity display style
|
|
For the amounts in each commodity, hledger chooses a consistent display
|
|
style (symbol placement, decimal mark and digit group marks, number of
|
|
decimal digits) to use in most reports. This is inferred as follows:
|
|
|
|
First, if there's a D directive declaring a default commodity, that
|
|
commodity symbol and amount format is applied to all no-symbol amounts
|
|
in the journal.
|
|
|
|
Then each commodity's display style is determined from its commodity
|
|
directive. We recommend always declaring commodities with commodity
|
|
directives, since they help ensure consistent display styles and preci-
|
|
sions, and bring other benefits such as error checking for commodity
|
|
symbols. Here's an example:
|
|
|
|
# Set display styles (and decimal marks, for parsing, if there is no decimal-mark directive)
|
|
# for the $, EUR, INR and no-symbol commodities:
|
|
commodity $1,000.00
|
|
commodity EUR 1.000,00
|
|
commodity INR 9,99,99,999.00
|
|
commodity 1 000 000.9455
|
|
|
|
But for convenience, if a commodity directive is not present, hledger
|
|
infers a commodity's display styles from its amounts as they are writ-
|
|
ten in the journal (excluding cost amounts and amounts in periodic
|
|
transaction rules or auto posting rules). It uses
|
|
|
|
o the symbol placement and decimal mark of the first amount seen
|
|
|
|
o the digit group marks of the first amount with digit group marks
|
|
|
|
o and the maximum number of decimal digits seen across all amounts.
|
|
|
|
And as fallback if no applicable amounts are found, it would use a de-
|
|
fault style, like $1000.00 (symbol on the left with no space, period as
|
|
decimal mark, and two decimal digits).
|
|
|
|
Finally, commodity styles can be overridden by the -c/--commodity-style
|
|
command line option.
|
|
|
|
Rounding
|
|
Amounts are stored internally as decimal numbers with up to 255 decimal
|
|
places. They are displayed with their original journal precisions by
|
|
print and print-like reports, and rounded to their display precision
|
|
(the number of decimal digits specified by the commodity display style)
|
|
by other reports. When rounding, hledger uses banker's rounding (it
|
|
rounds to the nearest even digit). So eg 0.5 displayed with zero deci-
|
|
mal digits appears as "0".
|
|
|
|
Trailing decimal marks
|
|
If you're wondering why your print report sometimes shows trailing dec-
|
|
imal marks, with no decimal digits; it does this when showing amounts
|
|
that have digit group marks but no decimal digits, to disambiguate them
|
|
and allow them to be re-parsed reliably (see Decimal marks). Eg:
|
|
|
|
commodity $1,000.00
|
|
|
|
2023-01-02
|
|
(a) $1000
|
|
|
|
$ hledger print
|
|
2023-01-02
|
|
(a) $1,000.
|
|
|
|
If this is a problem (eg when exporting to Ledger), you can avoid it by
|
|
disabling digit group marks, eg with -c/--commodity (for each affected
|
|
commodity):
|
|
|
|
$ hledger print -c '$1000.00'
|
|
2023-01-02
|
|
(a) $1000
|
|
|
|
or by forcing print to always show decimal digits, with --round:
|
|
|
|
$ hledger print -c '$1,000.00' --round=soft
|
|
2023-01-02
|
|
(a) $1,000.00
|
|
|
|
Amount parseability
|
|
More generally, hledger output falls into three rough categories, which
|
|
format amounts a little bit differently to suit different consumers:
|
|
|
|
1. "hledger-readable output" - should be readable by hledger (and by
|
|
humans)
|
|
|
|
o This is produced by reports that show full journal entries: print,
|
|
import, close, rewrite etc.
|
|
|
|
o It shows amounts with their original journal precisions, which may
|
|
not be consistent from one amount to the next.
|
|
|
|
o It adds a trailing decimal mark when needed to avoid showing ambigu-
|
|
ous amounts.
|
|
|
|
o It can be parsed reliably (by hledger and ledger2beancount at least,
|
|
but perhaps not by Ledger..)
|
|
|
|
2. "human-readable output" - usually for humans
|
|
|
|
o This is produced by all other reports.
|
|
|
|
o It shows amounts with standard display precisions, which will be con-
|
|
sistent within each commodity.
|
|
|
|
o It shows ambiguous amounts unmodified.
|
|
|
|
o It can be parsed reliably in the context of a known report (when you
|
|
know decimals are consistently not being shown, you can assume a sin-
|
|
gle mark is a digit group mark).
|
|
|
|
3. "machine-readable output" - usually for other software
|
|
|
|
o This is produced by all reports when an output format like csv, tsv,
|
|
json, or sql is selected.
|
|
|
|
o It shows amounts as 1 or 2 do, but without digit group marks.
|
|
|
|
o It can be parsed reliably (if needed, the decimal mark can be changed
|
|
with -c/--commodity-style).
|
|
|
|
Cost reporting
|
|
In some transactions - for example a currency conversion, or a purchase
|
|
or sale of stock - one commodity is exchanged for another. In these
|
|
transactions there is a conversion rate, also called the cost (when
|
|
buying) or selling price (when selling). (In hledger docs we just say
|
|
"cost" generically for convenience.) With the -B/--cost flag, hledger
|
|
can show amounts "at cost", converted to the cost's commodity.
|
|
|
|
Recording costs
|
|
We'll explore several ways of recording transactions involving costs.
|
|
These are also summarised at hledger Cookbook > Cost notation.
|
|
|
|
Costs can be recorded explicitly in the journal, using the @ UNITCOST
|
|
or @@ TOTALCOST notation described in Journal > Costs:
|
|
|
|
Variant 1
|
|
|
|
2022-01-01
|
|
assets:dollars $-135
|
|
assets:euros 100 @ $1.35 ; $1.35 per euro (unit cost)
|
|
|
|
Variant 2
|
|
|
|
2022-01-01
|
|
assets:dollars $-135
|
|
assets:euros 100 @@ $135 ; $135 total cost
|
|
|
|
Typically, writing the unit cost (variant 1) is preferable; it can be
|
|
more effort, requiring more attention to decimal digits; but it reveals
|
|
the per-unit cost basis, and makes stock sales easier.
|
|
|
|
Costs can also be left implicit, and hledger will infer the cost that
|
|
is consistent with a balanced transaction:
|
|
|
|
Variant 3
|
|
|
|
2022-01-01
|
|
assets:dollars $-135
|
|
assets:euros 100
|
|
|
|
Here, hledger will attach a @@ 100 cost to the first amount (you can
|
|
see it with hledger print -x). This form looks convenient, but there
|
|
are downsides:
|
|
|
|
o It sacrifices some error checking. For example, if you accidentally
|
|
wrote 10 instead of 100, hledger would not be able to detect the mis-
|
|
take.
|
|
|
|
o It is sensitive to the order of postings - if they were reversed, a
|
|
different entry would be inferred and reports would be different.
|
|
|
|
o The per-unit cost basis is not easy to read.
|
|
|
|
So generally this kind of entry is not recommended. You can make sure
|
|
you have none of these by using -s (strict mode), or by running hledger
|
|
check balanced.
|
|
|
|
Reporting at cost
|
|
Now when you add the -B/--cost flag to reports ("B" is from Ledger's
|
|
-B/--basis/--cost flag), any amounts which have been annotated with
|
|
costs will be converted to their cost's commodity (in the report out-
|
|
put). Ie they will be displayed "at cost" or "at sale price".
|
|
|
|
Some things to note:
|
|
|
|
o Costs are attached to specific posting amounts in specific transac-
|
|
tions, and once recorded they do not change. This contrasts with
|
|
market prices, which are ambient and fluctuating.
|
|
|
|
o Conversion to cost is performed before conversion to market value
|
|
(described below).
|
|
|
|
Equity conversion postings
|
|
There is a problem with the entries above - they are not conventional
|
|
Double Entry Bookkeeping (DEB) notation, and because of the "magical"
|
|
transformation of one commodity into another, they cause an imbalance
|
|
in the Accounting Equation. This shows up as a non-zero grand total in
|
|
balance reports like hledger bse.
|
|
|
|
For most hledger users, this doesn't matter in practice and can safely
|
|
be ignored ! But if you'd like to learn more, keep reading.
|
|
|
|
Conventional DEB uses an extra pair of equity postings to balance the
|
|
transaction. Of course you can do this in hledger as well:
|
|
|
|
Variant 4
|
|
|
|
2022-01-01
|
|
assets:dollars $-135
|
|
assets:euros 100
|
|
equity:conversion $135
|
|
equity:conversion -100
|
|
|
|
Now the transaction is perfectly balanced according to standard DEB,
|
|
and hledger bse's total will not be disrupted.
|
|
|
|
And, hledger can still infer the cost for cost reporting, but it's not
|
|
done by default - you must add the --infer-costs flag like so:
|
|
|
|
$ hledger print --infer-costs
|
|
2022-01-01 one hundred euros purchased at $1.35 each
|
|
assets:dollars $-135 @@ 100
|
|
assets:euros 100
|
|
equity:conversion $135
|
|
equity:conversion -100
|
|
|
|
$ hledger bal --infer-costs -B
|
|
-100 assets:dollars
|
|
100 assets:euros
|
|
--------------------
|
|
0
|
|
|
|
Here are some downsides of this kind of entry:
|
|
|
|
o The per-unit cost basis is not easy to read.
|
|
|
|
o Instead of -B you must remember to type -B --infer-costs.
|
|
|
|
o --infer-costs works only where hledger can identify the two eq-
|
|
uity:conversion postings and match them up with the two non-equity
|
|
postings. So writing the journal entry in a particular format be-
|
|
comes more important. More on this below.
|
|
|
|
Inferring equity conversion postings
|
|
Can we go in the other direction ? Yes, if you have transactions writ-
|
|
ten with the @/@@ cost notation, hledger can infer the missing equity
|
|
postings, if you add the --infer-equity flag. Eg:
|
|
|
|
2022-01-01
|
|
assets:dollars -$135
|
|
assets:euros 100 @ $1.35
|
|
|
|
$ hledger print --infer-equity
|
|
2022-01-01
|
|
assets:dollars $-135
|
|
assets:euros 100 @ $1.35
|
|
equity:conversion:$-: -100
|
|
equity:conversion:$-:$ $135.00
|
|
|
|
The equity account names will be "equity:conversion:A-B:A" and "eq-
|
|
uity:conversion:A-B:B" where A is the alphabetically first commodity
|
|
symbol. You can customise the "equity:conversion" part by declaring an
|
|
account with the V/Conversion account type.
|
|
|
|
Note you will need to add account declarations for these to your jour-
|
|
nal, if you use check accounts or check --strict.
|
|
|
|
Combining costs and equity conversion postings
|
|
Finally, you can use both the @/@@ cost notation and equity postings at
|
|
the same time. This in theory gives the best of all worlds - preserv-
|
|
ing the accounting equation, revealing the per-unit cost basis, and
|
|
providing more flexibility in how you write the entry:
|
|
|
|
Variant 5
|
|
|
|
2022-01-01 one hundred euros purchased at $1.35 each
|
|
assets:dollars $-135
|
|
equity:conversion $135
|
|
equity:conversion -100
|
|
assets:euros 100 @ $1.35
|
|
|
|
All the other variants above can (usually) be rewritten to this final
|
|
form with:
|
|
|
|
$ hledger print -x --infer-costs --infer-equity
|
|
|
|
Downsides:
|
|
|
|
o The precise format of the journal entry becomes more important. If
|
|
hledger can't detect and match up the cost and equity postings, it
|
|
will give a transaction balancing error.
|
|
|
|
o The add command does not yet accept this kind of entry (#2056).
|
|
|
|
o This is the most verbose form.
|
|
|
|
Requirements for detecting equity conversion postings
|
|
--infer-costs has certain requirements (unlike --infer-equity, which
|
|
always works). It will infer costs only in transactions with:
|
|
|
|
o Two non-equity postings, in different commodities. Their order is
|
|
significant: the cost will be added to the first of them.
|
|
|
|
o Two postings to equity conversion accounts, next to one another,
|
|
which balance the two non-equity postings. This balancing is checked
|
|
to the same precision (number of decimal places) used in the conver-
|
|
sion posting's amount. Equity conversion accounts are:
|
|
|
|
o any accounts declared with account type V/Conversion, or their sub-
|
|
accounts
|
|
|
|
o otherwise, accounts named equity:conversion, equity:trade, or eq-
|
|
uity:trading, or their subaccounts.
|
|
|
|
And multiple such four-posting groups can coexist within a single
|
|
transaction. When --infer-costs fails, it does not infer a cost in
|
|
that transaction, and does not raise an error (ie, it infers costs
|
|
where it can).
|
|
|
|
Reading variant 5 journal entries, combining cost notation and equity
|
|
postings, has all the same requirements. When reading such an entry
|
|
fails, hledger raises an "unbalanced transaction" error.
|
|
|
|
Infer cost and equity by default ?
|
|
Should --infer-costs and --infer-equity be enabled by default ? Try
|
|
using them always, eg with a shell alias:
|
|
|
|
alias h="hledger --infer-equity --infer-costs"
|
|
|
|
and let us know what problems you find.
|
|
|
|
Value reporting
|
|
hledger can also show amounts "at market value", converted to some
|
|
other commodity using the market price or conversion rate on a certain
|
|
date.
|
|
|
|
This is controlled by the --value=TYPE[,COMMODITY] option. We also
|
|
provide simpler -V and -X COMMODITY aliases for this, which are often
|
|
sufficient. The market prices are declared with a special P directive,
|
|
and/or they can be inferred from the costs recorded in transactions, by
|
|
using the --infer-market-prices flag.
|
|
|
|
-X: Value in specified commodity
|
|
The -X COMM (or --exchange=COMM) option converts amounts to their mar-
|
|
ket value in the specified commodity, using the market prices in effect
|
|
on the valuation date(s), if any. (More on these in a minute.)
|
|
|
|
Use this when you want to (eg) show everything in your base currency as
|
|
far as possible. (Commodities for which no conversion rate can be
|
|
found, will not be converted.)
|
|
|
|
COMM should be the full commodity symbol or name. Remember to quote
|
|
special shell characters, if needed. Some examples:
|
|
|
|
o -X
|
|
|
|
o -X$ (nothing after $, no quoting needed)
|
|
|
|
o -X CNY (the space after -X is optional)
|
|
|
|
o -X 'red apples'
|
|
|
|
o -X 'r&r'
|
|
|
|
-V: Value in default commodity(s)
|
|
The -V/--market flag is a variant of -X where you don't have to specify
|
|
COMM. Instead it tries to guess a default valuation commodity for each
|
|
original commodity, based on the market prices in effect on the valua-
|
|
tion date(s).
|
|
|
|
-V can often be a convenient shortcut for -X MYCURRENCY, but not al-
|
|
ways; depending on your data it could guess multiple valuation commodi-
|
|
ties. Usually you want to convert to a single commodity, so it's bet-
|
|
ter to use -X, unless you're sure -V is doing what you want.
|
|
|
|
Valuation date
|
|
Market prices can change from day to day. hledger will use the prices
|
|
on a particular valuation date (or on more than one date). By default
|
|
hledger uses "end" dates for valuation. More specifically:
|
|
|
|
o For single period reports (including normal print and register re-
|
|
ports):
|
|
|
|
o If an explicit report end date is specified, that is used.
|
|
|
|
o Otherwise the latest transaction date or non-future P directive
|
|
date is used.
|
|
|
|
o For multiperiod reports, each period is valued on its last day.
|
|
|
|
This can be customised with the --value option described below, which
|
|
can select either "then", "end", "now", or "custom" dates.
|
|
|
|
Finding market price
|
|
To convert a commodity A to its market value in another commodity B,
|
|
hledger looks for a suitable market price (exchange rate) as follows,
|
|
in this order of preference:
|
|
|
|
1. A declared market price or inferred market price: A's latest market
|
|
price in B on or before the valuation date as declared by a P direc-
|
|
tive, or (with the --infer-market-prices flag) inferred from costs.
|
|
|
|
2. A reverse market price: the inverse of a declared or inferred market
|
|
price from B to A.
|
|
|
|
3. A forward chain of market prices: a synthetic price formed by com-
|
|
bining the shortest chain of "forward" (only 1 above) market prices,
|
|
leading from A to B.
|
|
|
|
4. Any chain of market prices: a chain of any market prices, including
|
|
both forward and reverse prices (1 and 2 above), leading from A to
|
|
B.
|
|
|
|
There is a limit to the length of these price chains; if hledger
|
|
reaches that length without finding a complete chain or exhausting all
|
|
possibilities, it will give up (with a "gave up" message visible in
|
|
--debug=2 output). That limit is currently 1000.
|
|
|
|
Amounts for which no suitable market price can be found, are not con-
|
|
verted.
|
|
|
|
--infer-market-prices: market prices from transactions
|
|
Normally, market value in hledger is fully controlled by, and requires,
|
|
P directives in your journal. Since adding and updating those can be a
|
|
chore, and since transactions usually take place at close to market
|
|
value, why not use the recorded costs as additional market prices (as
|
|
Ledger does) ? Adding the --infer-market-prices flag to -V, -X or
|
|
--value enables this.
|
|
|
|
So for example, hledger bs -V --infer-market-prices will get market
|
|
prices both from P directives and from transactions. If both occur on
|
|
the same day, the P directive takes precedence.
|
|
|
|
There is a downside: value reports can sometimes be affected in confus-
|
|
ing/undesired ways by your journal entries. If this happens to you,
|
|
read all of this Value reporting section carefully, and try adding
|
|
--debug or --debug=2 to troubleshoot.
|
|
|
|
--infer-market-prices can infer market prices from:
|
|
|
|
o multicommodity transactions with explicit prices (@/@@)
|
|
|
|
o multicommodity transactions with implicit prices (no @, two commodi-
|
|
ties, unbalanced). (With these, the order of postings matters.
|
|
hledger print -x can be useful for troubleshooting.)
|
|
|
|
o multicommodity transactions with equity postings, if cost is inferred
|
|
with --infer-costs.
|
|
|
|
There is a limitation (bug) currently: when a valuation commodity is
|
|
not specified, prices inferred with --infer-market-prices do not help
|
|
select a default valuation commodity, as P prices would. So conversion
|
|
might not happen because no valuation commodity was detected (--debug=2
|
|
will show this). To be safe, specify the valuation commmodity, eg:
|
|
|
|
o -X EUR --infer-market-prices, not -V --infer-market-prices
|
|
|
|
o --value=then,EUR --infer-market-prices, not --value=then --infer-mar-
|
|
ket-prices
|
|
|
|
Signed costs and market prices can be confusing. For reference, here
|
|
is the current behaviour, since hledger 1.25. (If you think it should
|
|
work differently, see #1870.)
|
|
|
|
2022-01-01 Positive Unit prices
|
|
a A 1
|
|
b B -1 @ A 1
|
|
|
|
2022-01-01 Positive Total prices
|
|
a A 1
|
|
b B -1 @@ A 1
|
|
|
|
|
|
2022-01-02 Negative unit prices
|
|
a A 1
|
|
b B 1 @ A -1
|
|
|
|
2022-01-02 Negative total prices
|
|
a A 1
|
|
b B 1 @@ A -1
|
|
|
|
|
|
2022-01-03 Double Negative unit prices
|
|
a A -1
|
|
b B -1 @ A -1
|
|
|
|
2022-01-03 Double Negative total prices
|
|
a A -1
|
|
b B -1 @@ A -1
|
|
|
|
All of the transactions above are considered balanced (and on each day,
|
|
the two transactions are considered equivalent). Here are the market
|
|
prices inferred for B:
|
|
|
|
$ hledger -f- --infer-market-prices prices
|
|
P 2022-01-01 B A 1
|
|
P 2022-01-01 B A 1.0
|
|
P 2022-01-02 B A -1
|
|
P 2022-01-02 B A -1.0
|
|
P 2022-01-03 B A -1
|
|
P 2022-01-03 B A -1.0
|
|
|
|
Valuation commodity
|
|
When you specify a valuation commodity (-X COMM or --value TYPE,COMM):
|
|
hledger will convert all amounts to COMM, wherever it can find a suit-
|
|
able market price (including by reversing or chaining prices).
|
|
|
|
When you leave the valuation commodity unspecified (-V or --value
|
|
TYPE):
|
|
For each commodity A, hledger picks a default valuation commodity as
|
|
follows, in this order of preference:
|
|
|
|
1. The price commodity from the latest P-declared market price for A on
|
|
or before valuation date.
|
|
|
|
2. The price commodity from the latest P-declared market price for A on
|
|
any date. (Allows conversion to proceed when there are inferred
|
|
prices before the valuation date.)
|
|
|
|
3. If there are no P directives at all (any commodity or date) and the
|
|
--infer-market-prices flag is used: the price commodity from the
|
|
latest transaction-inferred price for A on or before valuation date.
|
|
|
|
This means:
|
|
|
|
o If you have P directives, they determine which commodities -V will
|
|
convert, and to what.
|
|
|
|
o If you have no P directives, and use the --infer-market-prices flag,
|
|
costs determine it.
|
|
|
|
Amounts for which no valuation commodity can be found are not con-
|
|
verted.
|
|
|
|
--value: Flexible valuation
|
|
-V and -X are special cases of the more general --value option:
|
|
|
|
--value=TYPE[,COMM] TYPE is then, end, now or YYYY-MM-DD.
|
|
COMM is an optional commodity symbol.
|
|
Shows amounts converted to:
|
|
- default valuation commodity (or COMM) using market prices at posting dates
|
|
- default valuation commodity (or COMM) using market prices at period end(s)
|
|
- default valuation commodity (or COMM) using current market prices
|
|
- default valuation commodity (or COMM) using market prices at some date
|
|
|
|
The TYPE part selects cost or value and valuation date:
|
|
|
|
--value=then
|
|
Convert amounts to their value in the default valuation commod-
|
|
ity, using market prices on each posting's date.
|
|
|
|
--value=end
|
|
Convert amounts to their value in the default valuation commod-
|
|
ity, using market prices on the last day of the report period
|
|
(or if unspecified, the journal's end date); or in multiperiod
|
|
reports, market prices on the last day of each subperiod.
|
|
|
|
--value=now
|
|
Convert amounts to their value in the default valuation commod-
|
|
ity using current market prices (as of when report is gener-
|
|
ated).
|
|
|
|
--value=YYYY-MM-DD
|
|
Convert amounts to their value in the default valuation commod-
|
|
ity using market prices on this date.
|
|
|
|
To select a different valuation commodity, add the optional ,COMM part:
|
|
a comma, then the target commodity's symbol. Eg: --value=now,EUR.
|
|
hledger will do its best to convert amounts to this commodity, deducing
|
|
market prices as described above.
|
|
|
|
Valuation examples
|
|
Here are some quick examples of -V:
|
|
|
|
; one euro is worth this many dollars from nov 1
|
|
P 2016/11/01 $1.10
|
|
|
|
; purchase some euros on nov 3
|
|
2016/11/3
|
|
assets:euros 100
|
|
assets:checking
|
|
|
|
; the euro is worth fewer dollars by dec 21
|
|
P 2016/12/21 $1.03
|
|
|
|
How many euros do I have ?
|
|
|
|
$ hledger -f t.j bal -N euros
|
|
100 assets:euros
|
|
|
|
What are they worth at end of nov 3 ?
|
|
|
|
$ hledger -f t.j bal -N euros -V -e 2016/11/4
|
|
$110.00 assets:euros
|
|
|
|
What are they worth after 2016/12/21 ? (no report end date specified,
|
|
defaults to today)
|
|
|
|
$ hledger -f t.j bal -N euros -V
|
|
$103.00 assets:euros
|
|
|
|
Here are some examples showing the effect of --value, as seen with
|
|
print:
|
|
|
|
P 2000-01-01 A 1 B
|
|
P 2000-02-01 A 2 B
|
|
P 2000-03-01 A 3 B
|
|
P 2000-04-01 A 4 B
|
|
|
|
2000-01-01
|
|
(a) 1 A @ 5 B
|
|
|
|
2000-02-01
|
|
(a) 1 A @ 6 B
|
|
|
|
2000-03-01
|
|
(a) 1 A @ 7 B
|
|
|
|
Show the cost of each posting:
|
|
|
|
$ hledger -f- print --cost
|
|
2000-01-01
|
|
(a) 5 B
|
|
|
|
2000-02-01
|
|
(a) 6 B
|
|
|
|
2000-03-01
|
|
(a) 7 B
|
|
|
|
Show the value as of the last day of the report period (2000-02-29):
|
|
|
|
$ hledger -f- print --value=end date:2000/01-2000/03
|
|
2000-01-01
|
|
(a) 2 B
|
|
|
|
2000-02-01
|
|
(a) 2 B
|
|
|
|
With no report period specified, the latest transaction date or price
|
|
date is used as valuation date (2000-04-01):
|
|
|
|
$ hledger -f- print --value=end
|
|
2000-01-01
|
|
(a) 3 B
|
|
|
|
2000-02-01
|
|
(a) 3 B
|
|
|
|
2000-03-01
|
|
(a) 3 B
|
|
|
|
The value today is the same (the 2000-04-01 price is still in effect):
|
|
|
|
$ hledger -f- print --value=now
|
|
2000-01-01
|
|
(a) 4 B
|
|
|
|
2000-02-01
|
|
(a) 4 B
|
|
|
|
2000-03-01
|
|
(a) 4 B
|
|
|
|
Show the value on 2000/01/15:
|
|
|
|
$ hledger -f- print --value=2000-01-15
|
|
2000-01-01
|
|
(a) 1 B
|
|
|
|
2000-02-01
|
|
(a) 1 B
|
|
|
|
2000-03-01
|
|
(a) 1 B
|
|
|
|
Interaction of valuation and queries
|
|
When matching postings based on queries in the presence of valuation,
|
|
the following happens:
|
|
|
|
1. The query is separated into two parts:
|
|
|
|
1. the currency (cur:) or amount (amt:).
|
|
|
|
2. all other parts.
|
|
|
|
2. The postings are matched to the currency and amount queries based on
|
|
pre-valued amounts.
|
|
|
|
3. Valuation is applied to the postings.
|
|
|
|
4. The postings are matched to the other parts of the query based on
|
|
post-valued amounts.
|
|
|
|
Related: #1625
|
|
|
|
Effect of valuation on reports
|
|
Here is a reference for how valuation is supposed to affect each part
|
|
of hledger's reports. It may be useful when troubleshooting. If you
|
|
find problems, please report them, ideally with a reproducible example.
|
|
Related: #329, #1083.
|
|
|
|
First, a quick glossary:
|
|
|
|
cost calculated using price(s) recorded in the transaction(s).
|
|
|
|
value market value using available market price declarations, or the
|
|
unchanged amount if no conversion rate can be found.
|
|
|
|
report start
|
|
the first day of the report period specified with -b or -p or
|
|
date:, otherwise today.
|
|
|
|
report or journal start
|
|
the first day of the report period specified with -b or -p or
|
|
date:, otherwise the earliest transaction date in the journal,
|
|
otherwise today.
|
|
|
|
report end
|
|
the last day of the report period specified with -e or -p or
|
|
date:, otherwise today.
|
|
|
|
report or journal end
|
|
the last day of the report period specified with -e or -p or
|
|
date:, otherwise the latest transaction date in the journal,
|
|
otherwise today.
|
|
|
|
report interval
|
|
a flag (-D/-W/-M/-Q/-Y) or period expression that activates the
|
|
report's multi-period mode (whether showing one or many subperi-
|
|
ods).
|
|
|
|
Report -B, --cost -V, -X --value=then --value=end --value=DATE,
|
|
type --value=now
|
|
--------------------------------------------------------------------------------------------
|
|
print
|
|
posting cost value at re- value at posting value at re- value at
|
|
amounts port end or date port or DATE/today
|
|
today journal end
|
|
balance unchanged unchanged unchanged unchanged unchanged
|
|
asser-
|
|
tions/as-
|
|
signments
|
|
|
|
register
|
|
starting cost value at re- valued at day value at re- value at
|
|
balance port or each historical port or DATE/today
|
|
(-H) journal end posting was made journal end
|
|
starting cost value at day valued at day value at day value at
|
|
balance before re- each historical before re- DATE/today
|
|
(-H) with port or posting was made port or
|
|
report journal journal
|
|
interval start start
|
|
posting cost value at re- value at posting value at re- value at
|
|
amounts port or date port or DATE/today
|
|
journal end journal end
|
|
summary summarised value at pe- sum of postings value at pe- value at
|
|
posting cost riod ends in interval, val- riod ends DATE/today
|
|
amounts ued at interval
|
|
with re- start
|
|
port in-
|
|
terval
|
|
running sum/average sum/average sum/average of sum/average sum/average
|
|
total/av- of displayed of displayed displayed values of displayed of displayed
|
|
erage values values values values
|
|
|
|
balance
|
|
(bs, bse,
|
|
cf, is)
|
|
balance sums of value at re- value at posting value at re- value at
|
|
changes costs port end or date port or DATE/today of
|
|
today of journal end sums of post-
|
|
sums of of sums of ings
|
|
postings postings
|
|
budget like balance like balance like balance like bal- like balance
|
|
amounts changes changes changes ances changes
|
|
(--bud-
|
|
get)
|
|
grand to- sum of dis- sum of dis- sum of displayed sum of dis- sum of dis-
|
|
tal played val- played val- valued played val- played values
|
|
ues ues ues
|
|
|
|
balance
|
|
(bs, bse,
|
|
cf, is)
|
|
with re-
|
|
port in-
|
|
terval
|
|
starting sums of value at re- sums of values of value at re- sums of post-
|
|
balances costs of port start postings before port start ings before
|
|
(-H) postings be- of sums of report start at of sums of report start
|
|
fore report all postings respective post- all postings
|
|
start before re- ing dates before re-
|
|
port start port start
|
|
balance sums of same as sums of values of balance value at
|
|
changes costs of --value=end postings in pe- change in DATE/today of
|
|
(bal, is, postings in riod at respec- each period, sums of post-
|
|
bs period tive posting valued at ings
|
|
--change, dates period ends
|
|
cf
|
|
--change)
|
|
end bal- sums of same as sums of values of period end value at
|
|
ances costs of --value=end postings from be- balances, DATE/today of
|
|
(bal -H, postings fore period start valued at sums of post-
|
|
is --H, from before to period end at period ends ings
|
|
bs, cf) report start respective post-
|
|
to period ing dates
|
|
end
|
|
budget like balance like balance like balance like bal- like balance
|
|
amounts changes/end changes/end changes/end bal- ances changes/end
|
|
(--bud- balances balances ances balances
|
|
get)
|
|
row to- sums, aver- sums, aver- sums, averages of sums, aver- sums, aver-
|
|
tals, row ages of dis- ages of dis- displayed values ages of dis- ages of dis-
|
|
averages played val- played val- played val- played values
|
|
(-T, -A) ues ues ues
|
|
column sums of dis- sums of dis- sums of displayed sums of dis- sums of dis-
|
|
totals played val- played val- values played val- played values
|
|
ues ues ues
|
|
grand to- sum, average sum, average sum, average of sum, average sum, average
|
|
tal, of column of column column totals of column of column to-
|
|
grand av- totals totals totals tals
|
|
erage
|
|
|
|
|
|
--cumulative is omitted to save space, it works like -H but with a zero
|
|
starting balance.
|
|
|
|
PART 4: COMMANDS
|
|
Here are hledger's standard subcommands. You can list these by running
|
|
hledger. If you have installed more add-on commands, they also will be
|
|
listed.
|
|
|
|
In the following command docs, each command's specific options are
|
|
shown. Most commands also support the general options described above,
|
|
though some of them might have no effect. (Usually if there's a sensi-
|
|
ble way for a general option to affect a command, it will.) You can
|
|
list all of a command's options by running hledger CMD -h.
|
|
|
|
Help commands
|
|
|
|
o commands - show the hledger commands list (default)
|
|
|
|
o demo - show small hledger demos in the terminal
|
|
|
|
o help - show the hledger manual with info, man, or pager
|
|
|
|
User interface commands
|
|
|
|
o repl - run commands from an interactive prompt
|
|
|
|
o run - run commands from a script
|
|
|
|
o ui - (if installed) run hledger's terminal UI
|
|
|
|
o web - (if installed) run hledger's web UI
|
|
|
|
Data entry commands
|
|
|
|
o add - add transactions using terminal prompts
|
|
|
|
o import - add new transactions from other files, eg CSV files
|
|
|
|
Basic report commands
|
|
|
|
o accounts - show account names
|
|
|
|
o codes - show transaction codes
|
|
|
|
o commodities - show commodity/currency symbols
|
|
|
|
o descriptions - show transaction descriptions
|
|
|
|
o files - show input file paths
|
|
|
|
o notes - show note parts of transaction descriptions
|
|
|
|
o payees - show payee parts of transaction descriptions
|
|
|
|
o prices - show market prices
|
|
|
|
o stats - show journal statistics
|
|
|
|
o tags - show tag names
|
|
|
|
Standard report commands
|
|
|
|
o print - show transactions or export journal data
|
|
|
|
o aregister (areg) - show transactions in a particular account
|
|
|
|
o register (reg) - show postings in one or more accounts & running to-
|
|
tal
|
|
|
|
o balancesheet (bs) - show assets, liabilities and net worth
|
|
|
|
o balancesheetequity (bse) - show assets, liabilities and equity
|
|
|
|
o cashflow (cf) - show changes in liquid assets
|
|
|
|
o incomestatement (is) - show revenues and expenses
|
|
|
|
Advanced report commands
|
|
|
|
o balance (bal) - show balance changes, end balances, budgets, gains..
|
|
|
|
o roi - show return on investments
|
|
|
|
Chart commands
|
|
|
|
o activity - show bar charts of posting counts per period
|
|
|
|
Data generation commands
|
|
|
|
o close - generate balance-zeroing/restoring transactions
|
|
|
|
o rewrite - generate auto postings, like print --auto
|
|
|
|
Maintenance commands
|
|
|
|
o check - check for various kinds of error in the data
|
|
|
|
o diff - compare account transactions in two journal files
|
|
|
|
o setup - check and show the status of the hledger installation
|
|
|
|
o test - run self tests
|
|
|
|
Next, these commands are described in detail.
|
|
|
|
Help commands
|
|
commands
|
|
Show the hledger commands list.
|
|
|
|
Flags:
|
|
--builtin show only builtin commands, not addons
|
|
|
|
demo
|
|
Play demos of hledger usage in the terminal, if asciinema is installed.
|
|
|
|
Flags:
|
|
-s --speed=SPEED playback speed (1 is original speed, .5 is half, 2
|
|
is double, etc (default: 2))
|
|
|
|
Run this command with no argument to list the demos. To play a demo,
|
|
write its number or a prefix or substring of its title. Tips:
|
|
|
|
Make your terminal window large enough to see the demo clearly.
|
|
|
|
Use the -s/--speed SPEED option to set your preferred playback speed,
|
|
eg -s4 to play at 4x original speed or -s.5 to play at half speed. The
|
|
default speed is 2x.
|
|
|
|
During playback, several keys are available: SPACE to pause/unpause, .
|
|
to step forward (while paused), CTRL-c quit.
|
|
|
|
Examples:
|
|
|
|
$ hledger demo # list available demos
|
|
$ hledger demo 1 # play the first demo at default speed (2x)
|
|
$ hledger demo install -s4 # play the "install" demo at 4x speed
|
|
|
|
This command is experimental: there aren't many useful demos yet.
|
|
|
|
help
|
|
Show the hledger user manual with info, man, or a pager. With a (case
|
|
insensitive) TOPIC argument, try to open it at that section heading.
|
|
|
|
Flags:
|
|
-i show the manual with info
|
|
-m show the manual with man
|
|
-p show the manual with $PAGER or less
|
|
(less is always used if TOPIC is specified)
|
|
|
|
This command shows the hledger manual built in to your hledger exe-
|
|
cutable. It can be useful when offline, or when you prefer the termi-
|
|
nal to a web browser, or when the appropriate hledger manual or viewers
|
|
are not installed properly on your system.
|
|
|
|
By default it chooses the best viewer found in $PATH, trying in this
|
|
order: info, man, $PAGER, less, more, stdout. (If a TOPIC is speci-
|
|
fied, $PAGER and more are not tried.) You can force the use of info,
|
|
man, or a pager with the -i, -m, or -p flags. If no viewer can be
|
|
found, or if running non-interactively, it just prints the manual to
|
|
stdout.
|
|
|
|
When using info, TOPIC can match either the full heading or a prefix.
|
|
If your info --version is < 6, you'll need to upgrade it, eg with 'brew
|
|
install texinfo' on mac.
|
|
|
|
When using man or less, TOPIC must match the full heading. For a pre-
|
|
fix match, you can write 'TOPIC.*'.
|
|
|
|
Examples
|
|
|
|
$ hledger help -h # show the help command's usage
|
|
$ hledger help # show the manual with info, man or $PAGER
|
|
$ hledger help 'time periods' # show the manual's "Time periods" topic
|
|
$ hledger help 'time periods' -m # use man, even if info is installed
|
|
|
|
User interface commands
|
|
repl
|
|
Start an interactive prompt, where you can run any of hledger's com-
|
|
mands. Data files are parsed just once, so the commands run faster.
|
|
|
|
Flags:
|
|
no command-specific flags
|
|
|
|
This command is experimental and could change in the future.
|
|
|
|
hledger repl starts a read-eval-print loop (REPL) where you can enter
|
|
commands interactively. As with the run command, each input file (or
|
|
each input file/input options combination) is parsed just once, so com-
|
|
mands will run more quickly than if you ran them individually at the
|
|
command line.
|
|
|
|
Also like run, the input file(s) specified for the repl command will be
|
|
the default input for all interactive commands. You can override this
|
|
temporarily by specifying an -f option in particular commands. But
|
|
note that commands will not see any changes made to input files (eg by
|
|
add) until you exit and restart the REPL.
|
|
|
|
The command syntax is the same as with run:
|
|
|
|
o enter one hledger command at a time, without the usual hledger first
|
|
word
|
|
|
|
o empty lines and comment text from # to end of line are ignored
|
|
|
|
o use single or double quotes to quote arguments when needed
|
|
|
|
o type exit or quit or control-D to exit the REPL.
|
|
|
|
While it is running, the REPL remembers your command history, and you
|
|
can navigate in the usual ways:
|
|
|
|
o Keypad or Emacs navigation keys to edit the current command line
|
|
|
|
o UP/DOWN or control-P/control-N to step back/forward through history
|
|
|
|
o control-R to search for a past command
|
|
|
|
o TAB to complete file paths.
|
|
|
|
Generally repl command lines should feel much like the normal hledger
|
|
CLI, but you may find differences. repl is a little stricter; eg it
|
|
requires full command names or official abbreviations (as seen in the
|
|
commands list).
|
|
|
|
The commands and help commands, and the command help flags (CMD --tldr,
|
|
CMD -h/--help, CMD --info, CMD --man), can be useful.
|
|
|
|
You can type control-C to cancel a long-running command (but only once;
|
|
typing it a second time will exit the REPL).
|
|
|
|
And in most shells you can type control-Z to temporarily exit to the
|
|
shell (and then fg to return to the REPL).
|
|
|
|
Examples
|
|
Start the REPL and enter some commands:
|
|
|
|
$ hledger repl
|
|
Enter hledger commands. To exit, enter 'quit' or 'exit', or send EOF.
|
|
% stats
|
|
Main file : .../2025.journal
|
|
...
|
|
% stats -f 2024/2024.journal
|
|
Main file : .../2024.journal
|
|
...
|
|
% stats
|
|
Main file : .../2025.journal
|
|
...
|
|
|
|
or:
|
|
|
|
$ hledger repl -f some.journal
|
|
Enter hledger commands. To exit, enter 'quit' or 'exit', or send EOF.
|
|
% bs
|
|
...
|
|
% print -b 'last week'
|
|
...
|
|
% bs -f other.journal
|
|
...
|
|
|
|
run
|
|
Run a sequence of hledger commands, provided as files or command line
|
|
arguments. Data files are parsed just once, so the commands run
|
|
faster.
|
|
|
|
Flags:
|
|
no command-specific flags
|
|
|
|
This command is experimental and could change in the future.
|
|
|
|
You can use run in three ways:
|
|
|
|
o hledger run -- CMD1 -- CMD2 -- CMD3 - read commands from the command
|
|
line, separated by --
|
|
|
|
o hledger run SCRIPTFILE1 SCRIPTFILE2 - read commands from one or more
|
|
files
|
|
|
|
o cat SCRIPTFILE1 | hledger run - read commands from standard input.
|
|
|
|
run first loads the input file(s) specified by LEDGER_FILE or by -f op-
|
|
tions, in the usual way. Then it runs each command in turn, each using
|
|
the same input data. But if you want a particular command to use dif-
|
|
ferent input, you can specify an -f option within that command. This
|
|
will override (not add to) the default input, just for that command.
|
|
|
|
Each input file (more precisely, each combination of input file and in-
|
|
put options) is parsed only once. This means that commands will not
|
|
see any changes made to these files, until the next run. But the com-
|
|
mands will run more quickly than if run individually (typically about
|
|
twice as fast).
|
|
|
|
Command scripts, whether in a file or written on the command line, have
|
|
a simple syntax:
|
|
|
|
o each line may contain a single hledger command and its arguments,
|
|
without the usual hledger first word
|
|
|
|
o empty lines are ignored
|
|
|
|
o text from # to end of line is a comment, and ignored
|
|
|
|
o you can use single or double quotes to quote arguments when needed,
|
|
as on the command line
|
|
|
|
o these extra commands are available: echo TEXT prints some text, and
|
|
exit or quit ends the run.
|
|
|
|
On unix systems you can use #!/usr/bin/env hledger run in the first
|
|
line of a command file to make it a runnable script. If that gives an
|
|
error, use #!/usr/bin/env -S hledger run.
|
|
|
|
It's ok to use the run command recursively within a command script.
|
|
|
|
You may find some differences in behaviour between run command lines
|
|
and normal hledger command lines. run is a little stricter; eg it re-
|
|
quires full command names or official abbreviations (as seen in the
|
|
commands list), and command options must be written after the command
|
|
name.
|
|
|
|
Examples
|
|
Run commands from the command line:
|
|
|
|
hledger -f some.journal run -- balance assets --depth 2 -- balance liabilities -f /some/other.journal --depth 3 --transpose -- stats
|
|
|
|
This would load some.journal, run balance assets --depth 2 on it, then
|
|
run balance liabilities --depth 3 --transpose on /some/other.journal,
|
|
and finally run stats on some.journal
|
|
|
|
Run commands from standard input:
|
|
|
|
(echo "files"; echo "stats") | hledger -f some.journal run
|
|
|
|
Run commands as a script:
|
|
|
|
$ cat report
|
|
#!/usr/bin/env -S hledger run -f some.journal
|
|
|
|
echo "List of accounts in some.journal"
|
|
accounts
|
|
|
|
echo "Assets of some.journal"
|
|
balance assets --depth 2
|
|
|
|
echo "Liabilities from /some/other.journal"
|
|
balance liabilities -f /some/other.journal --depth 3 --transpose
|
|
|
|
echo "Commands from another.script, applied to another.journal"
|
|
run -f another.journal another.script
|
|
|
|
$ chmod +x report
|
|
$ ./report
|
|
List of accounts in some.journal
|
|
...
|
|
|
|
ui
|
|
Runs hledger-ui (if installed).
|
|
|
|
web
|
|
Runs hledger-web (if installed).
|
|
|
|
Data entry commands
|
|
add
|
|
Add new transactions to a journal file, with interactive prompting.
|
|
|
|
Flags:
|
|
--no-new-accounts don't allow creating new accounts
|
|
|
|
Many hledger users edit their journals directly with a text editor, or
|
|
generate them from CSV. For more interactive data entry, there is the
|
|
add command, which prompts interactively on the console for new trans-
|
|
actions, and appends them to the main journal file (which should be in
|
|
journal format). Existing transactions are not changed. This is one
|
|
of the few hledger commands that writes to the journal file (see also
|
|
import).
|
|
|
|
To use it, just run hledger add and follow the prompts. You can add as
|
|
many transactions as you like; when you are finished, enter . or press
|
|
control-d or control-c to exit.
|
|
|
|
Features:
|
|
|
|
o add tries to provide useful defaults, using the most similar (by de-
|
|
scription) recent transaction (filtered by the query, if any) as a
|
|
template.
|
|
|
|
o You can also set the initial defaults with command line arguments.
|
|
|
|
o Readline-style edit keys can be used during data entry.
|
|
|
|
o The tab key will auto-complete whenever possible - accounts, pay-
|
|
ees/descriptions, dates (yesterday, today, tomorrow). If the input
|
|
area is empty, it will insert the default value.
|
|
|
|
o A parenthesised transaction code may be entered following a date.
|
|
|
|
o Comments and tags may be entered following a description or amount.
|
|
|
|
o If you make a mistake, enter < at any prompt to go one step backward.
|
|
|
|
o Input prompts are displayed in a different colour when the terminal
|
|
supports it.
|
|
|
|
Notes:
|
|
|
|
o If you enter a number with no commodity symbol, and you have declared
|
|
a default commodity with a D directive, you might expect add to add
|
|
this symbol for you. It does not do this; we assume that if you are
|
|
using a D directive you prefer not to see the commodity symbol re-
|
|
peated on amounts in the journal.
|
|
|
|
o add creates entries in journal format; it won't work with timeclock
|
|
or timedot files.
|
|
|
|
Examples:
|
|
|
|
o Record new transactions, saving to the default journal file:
|
|
|
|
hledger add
|
|
|
|
o Add transactions to 2024.journal, but also load 2023.journal for com-
|
|
pletions:
|
|
|
|
hledger add --file 2024.journal --file 2023.journal
|
|
|
|
o Provide answers for the first four prompts:
|
|
|
|
hledger add today 'best buy' expenses:supplies '$20'
|
|
|
|
There is a detailed tutorial at https://hledger.org/add.html.
|
|
|
|
add and balance assertions
|
|
Since hledger 1.43, you can add a balance assertion by writing AMOUNT =
|
|
BALANCE when asked for an amount. Eg 100 = 500.
|
|
|
|
Also, each time you enter a new amount, hledger re-checks all balance
|
|
assertions in the journal and rejects the new amount if it would make
|
|
any of them fail. You can run add with -I/--ignore-assertions to dis-
|
|
able balance assertion checking.
|
|
|
|
add and balance assignments
|
|
Since hledger 1.51, you can add a balance assignment by writing = BAL-
|
|
ANCE (or ==, =* etc) when asked for an amount. The missing amount will
|
|
be calculated automatically.
|
|
|
|
add normally won't let you add a new posting which is dated earlier
|
|
than an existing balance assignment. (Because when add runs, existing
|
|
balance assignments have already been calculated and converted to
|
|
amounts and balance assertions.) You can allow it by disabling balance
|
|
assertion checking with -I.
|
|
|
|
import
|
|
Import new transactions from one or more data files to the main jour-
|
|
nal.
|
|
|
|
Flags:
|
|
--catchup just mark all transactions as already imported
|
|
--dry-run just show the transactions to be imported
|
|
|
|
This command detects new transactions in one or more data files speci-
|
|
fied as arguments, and appends them to the main journal.
|
|
|
|
You can import from any input file format hledger supports, but
|
|
CSV/SSV/TSV files, downloaded from financial institutions, are the most
|
|
common import source.
|
|
|
|
The import destination is the default journal file, or another speci-
|
|
fied in the usual way with $LEDGER_FILE or -f/--file. It should be in
|
|
journal format.
|
|
|
|
Examples:
|
|
|
|
$ hledger import bank1-checking.csv bank1-savings.csv
|
|
|
|
$ hledger import *.csv
|
|
|
|
Import dry run
|
|
It's useful to preview the import by running first with --dry-run, to
|
|
sanity check the range of dates being imported, and to check the effect
|
|
of your conversion rules if converting from CSV. Eg:
|
|
|
|
$ hledger import bank.csv --dry-run
|
|
|
|
The dry run output is valid journal format, so hledger can re-parse it.
|
|
If the output is large, you could show just the uncategorised transac-
|
|
tions like so:
|
|
|
|
$ hledger import --dry-run bank.csv | hledger -f- -I print unknown
|
|
|
|
You could also run this repeatedly to see the effect of edits to your
|
|
conversion rules:
|
|
|
|
$ watchexec -- "hledger import --dry-run bank.csv | hledger -f- -I print unknown"
|
|
|
|
Once the conversion and dates look good enough to import to your jour-
|
|
nal, perhaps with some manual fixups to follow, you would do the actual
|
|
import:
|
|
|
|
$ hledger import bank.csv
|
|
|
|
Overlap detection
|
|
Reading CSV files is built in to hledger, and not specific to import;
|
|
so you could also import by doing hledger -f bank.csv print
|
|
>>$LEDGER_FILE.
|
|
|
|
But import is easier and provides some advantages. The main one is
|
|
that it avoids re-importing transactions it has seen on previous runs.
|
|
This means you don't have to worry about overlapping data in successive
|
|
downloads of your bank CSV; just download and import as often as you
|
|
like, and only the new transactions will be imported each time.
|
|
|
|
We don't call this "deduplication", as it's generally not possible to
|
|
reliably detect duplicates in bank CSV. Instead, import remembers the
|
|
latest date processed previously in each CSV file (saving it in a hid-
|
|
den file), and skips any records prior to that date. This works well
|
|
for most real-world CSV, where:
|
|
|
|
1. the data file name is stable (does not change) across imports
|
|
|
|
2. the item dates are stable across imports
|
|
|
|
3. the order of same-date items is stable across imports
|
|
|
|
4. the newest items have the newest dates
|
|
|
|
(Occasional violations of 2-4 are often harmless; you can reduce the
|
|
chance of disruption by downloading and importing more often.)
|
|
|
|
Overlap detection is automatic, and shouldn't require much attention
|
|
from you, except perhaps at first import (see below). But here's how
|
|
it works:
|
|
|
|
o For each FILE being imported from:
|
|
|
|
1. hledger reads a file named .latest.FILE file in the same direc-
|
|
tory, if any. This file contains the latest record date previ-
|
|
ously imported from FILE, in YYYY-MM-DD format. If multiple
|
|
records with that date were imported, the date is repeated on N
|
|
lines.
|
|
|
|
2. hledger reads records from FILE. If a latest date was found in
|
|
step 1, any records before that date, and the first N records on
|
|
that date, are skipped.
|
|
|
|
o After a successful import from all FILEs, without error and without
|
|
--dry-run, hledger updates each FILE's .latest.FILE for next time.
|
|
|
|
If this goes wrong, it's relatively easy to repair:
|
|
|
|
o You'll notice it before import when you preview with import
|
|
--dry-run.
|
|
|
|
o Or after import when you try to reconcile your hledger account bal-
|
|
ances with your bank.
|
|
|
|
o hledger print -f FILE.csv will show all recently downloaded transac-
|
|
tions. Compare these with your journal. Copy/paste if needed.
|
|
|
|
o Update your conversion rules and print again, if needed.
|
|
|
|
o You can manually update or remove the .latest file, or use import
|
|
--catchup FILE.
|
|
|
|
o Download and import more often, eg twice a week, at least while you
|
|
are learning. It's easier to review and troubleshoot when there are
|
|
fewer transactions.
|
|
|
|
First import
|
|
The first time you import from a file, when no corresponding .latest
|
|
file has been created yet, all of the records will be imported.
|
|
|
|
But perhaps you have been entering the data manually, so you know that
|
|
all of these transactions are already recorded in the journal. In this
|
|
case you can run hledger import --catchup once. This will create a
|
|
.latest file containing the latest CSV record date, so that none of
|
|
those records will be re-imported.
|
|
|
|
Or, if you know that some but not all of the transactions are in the
|
|
journal, you can create the .latest file yourself. Eg, let's say you
|
|
previously recorded foobank transactions up to 2024-10-31 in the jour-
|
|
nal. Then in the directory where you'll be saving foobank.csv, you
|
|
would create a .latest.foobank.csv file containing
|
|
|
|
2024-10-31
|
|
|
|
Or if you had three foobank transactions recorded with that date, you
|
|
would repeat the date that many times:
|
|
|
|
2024-10-31
|
|
2024-10-31
|
|
2024-10-31
|
|
|
|
Then hledger import foobank.csv [--dry-run] will import only the newer
|
|
records.
|
|
|
|
Importing balance assignments
|
|
Journal entries added by import will have all posting amounts made ex-
|
|
plicit (like print -x).
|
|
|
|
This means that any balance assignments in the imported entries would
|
|
need to be evaluated. But this generally isn't possible, as the main
|
|
file's account balances are not visible during import. So try to avoid
|
|
generating balance assignments with your CSV rules, or importing from a
|
|
journal that contains balance assignments. (Balance assignments are
|
|
best avoided anyway.)
|
|
|
|
But if you must use them, eg because your CSV includes only balances:
|
|
you can import with print, which leaves implicit amounts implicit.
|
|
(print can also do overlap detection like import, with the --new flag):
|
|
|
|
$ hledger print --new -f bank.csv >> $LEDGER_FILE
|
|
|
|
(If you think import should preserve implicit balances, please test
|
|
that and send a pull request.)
|
|
|
|
Import and commodity styles
|
|
Amounts in entries added by import will be formatted according to the
|
|
journal's canonical commodity styles, as declared by commodity direc-
|
|
tives or inferred from the journal's amounts.
|
|
|
|
Related: CSV > Amount decimal places.
|
|
|
|
Import archiving
|
|
When importing from a CSV rules file (hledger import bank.rules), you
|
|
can use the archive rule to enable automatic archiving of the data
|
|
file. After a successful import, the data file (specified by source)
|
|
will be moved to an archive folder (data/, next to the rules file,
|
|
auto-created), and renamed similar to the rules file, with a date.
|
|
This can be useful for troubleshooting, detecting variations in your
|
|
banks' CSV data, regenerating entries with improved rules, etc.
|
|
|
|
The archive rule also causes import to handle source glob patterns dif-
|
|
ferently: when there are multiple matched files, it will pick the old-
|
|
est, not the newest.
|
|
|
|
Import special cases
|
|
Deduplication
|
|
Here are two kinds of "deduplication" which import does not handle (and
|
|
should not, because these can happen legitimately in financial data):
|
|
|
|
o Two or more of the new CSV records are identical, and generate iden-
|
|
tical new journal entries.
|
|
|
|
o A new CSV record generates a journal entry identical to one(s) al-
|
|
ready in the journal.
|
|
|
|
Varying file name
|
|
If you have a download whose file name varies, you could rename it to a
|
|
fixed name after each download. Or you could use a CSV source rule
|
|
with a suitable glob pattern, and import from the .rules file.
|
|
|
|
Multiple versions
|
|
Say you download bank.csv, import it, but forget to delete it from your
|
|
downloads folder. The next time you download it, your web browser will
|
|
save it as (eg) bank (2).csv. The source rule's glob patterns are for
|
|
just this situation: instead of specifying source bank.csv, specify
|
|
source bank*.csv. Then hledger -f bank.rules CMD or hledger import
|
|
bank.rules will automatically pick the newest matched file (bank
|
|
(2).csv).
|
|
|
|
Alternately, what if you download, but forget to import or delete, then
|
|
download again ? Now each of bank.csv and bank (2).csv might contain
|
|
data that's not in the other, and not in your journal. In this case,
|
|
it's best to import each of them in turn, oldest first (otherwise,
|
|
overlap detection could cause new records to be skipped). Enabling im-
|
|
port archiving ensures this. Then hledger import bank.rules; hledger
|
|
import bank.rules will import and archive first bank.csv, then bank
|
|
(2).csv.
|
|
|
|
Basic report commands
|
|
accounts
|
|
List the account names used or declared in the journal.
|
|
|
|
Flags:
|
|
-u --used list accounts used
|
|
-d --declared list accounts declared
|
|
--undeclared list accounts used but not declared
|
|
--unused list accounts declared but not used
|
|
--find list the first account matched by the first
|
|
argument (a case-insensitive infix regexp)
|
|
--directives show as account directives, for use in journals
|
|
--locations also show where accounts were declared
|
|
--types also show account types when known
|
|
-l --flat list/tree mode: show accounts as a flat list
|
|
(default)
|
|
-t --tree list/tree mode: show accounts as a tree
|
|
--drop=N flat mode: omit N leading account name parts
|
|
|
|
This command lists account names - all of them by default, or just the
|
|
ones which have been used in transactions (-u/--used), or declared with
|
|
account directives (-d/--declared), or used but not declared (--unde-
|
|
clared), or declared but not used (--unused), or just the first one
|
|
matched by a pattern (--find, returning a non-zero exit code if it
|
|
fails).
|
|
|
|
You can add query arguments to select a subset of transactions or ac-
|
|
counts.
|
|
|
|
With --directives, it shows valid account directives which could be
|
|
pasted into a journal file. This is useful together with --undeclared
|
|
when updating your account declarations to satisfy hledger check ac-
|
|
counts.
|
|
|
|
With --locations, it also shows the file and line number of each ac-
|
|
count's declaration, if any, and the account's overall declaration or-
|
|
der; these may be useful when troubleshooting account display order.
|
|
|
|
With --types, it also shows each account's type, if it's known. (See
|
|
Declaring accounts > Account types.)
|
|
|
|
It shows a flat list by default. With --tree, it uses indentation to
|
|
show the account hierarchy. In flat mode you can add --drop N to omit
|
|
the first few account name components. Account names can be
|
|
depth-clipped with depth:N or --depth N or -N.
|
|
|
|
Examples:
|
|
|
|
$ hledger accounts
|
|
assets:bank:checking
|
|
assets:bank:saving
|
|
assets:cash
|
|
expenses:food
|
|
expenses:supplies
|
|
income:gifts
|
|
income:salary
|
|
liabilities:debts
|
|
|
|
$ hledger accounts --undeclared --directives >> $LEDGER_FILE
|
|
$ hledger check accounts
|
|
|
|
codes
|
|
List the codes seen in transactions, in the order parsed.
|
|
|
|
Flags:
|
|
no command-specific flags
|
|
|
|
This command prints the value of each transaction's code field, in the
|
|
order transactions were parsed. The transaction code is an optional
|
|
value written in parentheses between the date and description, often
|
|
used to store a cheque number, order number or similar.
|
|
|
|
Transactions aren't required to have a code, and missing or empty codes
|
|
will not be shown by default. With the -E/--empty flag, they will be
|
|
printed as blank lines.
|
|
|
|
You can add a query to select a subset of transactions.
|
|
|
|
Examples:
|
|
|
|
2022/1/1 (123) Supermarket
|
|
Food $5.00
|
|
Checking
|
|
|
|
2022/1/2 (124) Post Office
|
|
Postage $8.32
|
|
Checking
|
|
|
|
2022/1/3 Supermarket
|
|
Food $11.23
|
|
Checking
|
|
|
|
2022/1/4 (126) Post Office
|
|
Postage $3.21
|
|
Checking
|
|
|
|
$ hledger codes
|
|
123
|
|
124
|
|
126
|
|
|
|
$ hledger codes -E
|
|
123
|
|
124
|
|
|
|
126
|
|
|
|
commodities
|
|
List the commodity symbols used or declared in the journal.
|
|
|
|
Flags:
|
|
--used list commodities used
|
|
--declared list commodities declared
|
|
--undeclared list commodities used but not declared
|
|
--unused list commodities declared but not used
|
|
--find list the first commodity matched by the first
|
|
argument (a case-insensitive infix regexp)
|
|
|
|
This command lists commodity symbols/names - all of them by default, or
|
|
just the ones which have been used in transactions or P directives, or
|
|
declared with commodity directives, or used but not declared, or de-
|
|
clared but not used, or just the first one matched by a pattern (with
|
|
--find, returning a non-zero exit code if it fails).
|
|
|
|
You can add cur: query arguments to further limit the commodities.
|
|
|
|
descriptions
|
|
List the unique descriptions used in transactions.
|
|
|
|
Flags:
|
|
no command-specific flags
|
|
|
|
This command lists the unique descriptions that appear in transactions,
|
|
in alphabetic order. You can add a query to select a subset of trans-
|
|
actions.
|
|
|
|
Example:
|
|
|
|
$ hledger descriptions
|
|
Store Name
|
|
Gas Station | Petrol
|
|
Person A
|
|
|
|
files
|
|
List all files included in the journal. With a REGEX argument, only
|
|
file names matching the regular expression (case sensitive) are shown.
|
|
|
|
Flags:
|
|
no command-specific flags
|
|
|
|
notes
|
|
List the unique notes that appear in transactions.
|
|
|
|
Flags:
|
|
no command-specific flags
|
|
|
|
This command lists the unique notes that appear in transactions, in al-
|
|
phabetic order. You can add a query to select a subset of transac-
|
|
tions. The note is the part of the transaction description after a |
|
|
character (or if there is no |, the whole description).
|
|
|
|
Example:
|
|
|
|
$ hledger notes
|
|
Petrol
|
|
Snacks
|
|
|
|
payees
|
|
List the payee/payer names used or declared in the journal.
|
|
|
|
Flags:
|
|
--used list payees used
|
|
--declared list payees declared
|
|
--undeclared list payees used but not declared
|
|
--unused list payees declared but not used
|
|
--find list the first payee matched by the first
|
|
argument (a case-insensitive infix regexp)
|
|
|
|
This command lists unique payee/payer names - all of them by default,
|
|
or just the ones which have been used in transaction descriptions, or
|
|
declared with payee directives, or used but not declared, or declared
|
|
but not used, or just the first one matched by a pattern (with --find,
|
|
returning a non-zero exit code if it fails).
|
|
|
|
The payee/payer name is the part of the transaction description before
|
|
a | character (or if there is no |, the whole description).
|
|
|
|
You can add query arguments to select a subset of transactions or pay-
|
|
ees.
|
|
|
|
Example:
|
|
|
|
$ hledger payees
|
|
Store Name
|
|
Gas Station
|
|
Person A
|
|
|
|
prices
|
|
Print the market prices declared with P directives. With --infer-mar-
|
|
ket-prices, also show any additional prices inferred from costs. With
|
|
--show-reverse, also show additional prices inferred by reversing known
|
|
prices.
|
|
|
|
Flags:
|
|
--show-reverse also show the prices inferred by reversing known
|
|
prices
|
|
|
|
Price amounts are always displayed with their full precision, except
|
|
for reverse prices which are limited to 8 decimal digits.
|
|
|
|
Prices can be filtered by a date:, cur: or amt: query.
|
|
|
|
Generally if you run this command with --infer-market-prices --show-re-
|
|
verse, it will show the same prices used internally to calculate value
|
|
reports. But if in doubt, you can inspect those directly by running
|
|
the value report with --debug=2.
|
|
|
|
stats
|
|
Show journal and performance statistics.
|
|
|
|
Flags:
|
|
-1 show a single line of output
|
|
-v --verbose show more detailed output
|
|
-o --output-file=FILE write output to FILE.
|
|
|
|
The stats command shows summary information for the whole journal, or a
|
|
matched part of it. With a reporting interval, it shows a report for
|
|
each report period.
|
|
|
|
It also shows some performance statistics:
|
|
|
|
o how long the program ran for
|
|
|
|
o the number of transactions processed per second
|
|
|
|
o the peak live memory in use by the program to do its work
|
|
|
|
o the peak allocated memory as seen by the program
|
|
|
|
By default, the output is reasonably discreet; it reveals the main file
|
|
name, your activity level, and the speed of your machine.
|
|
|
|
With -v/--verbose, more details are shown: the full paths of all files,
|
|
and the names of the commodities you work with.
|
|
|
|
With -1, only one line of output is shown, in a machine-friendly
|
|
tab-separated format: the program version, the main journal file name,
|
|
and the performance stats,
|
|
|
|
The run time of stats is similar to that of a balance report.
|
|
|
|
Example:
|
|
|
|
$ hledger stats -f examples/1ktxns-1kaccts.journal
|
|
Main file : .../1ktxns-1kaccts.journal
|
|
Included files : 0
|
|
Txns span : 2000-01-01 to 2002-09-27 (1000 days)
|
|
Last txn : 2002-09-26 (7827 days ago)
|
|
Txns : 1000 (1.0 per day)
|
|
Txns last 30 days : 0 (0.0 per day)
|
|
Txns last 7 days : 0 (0.0 per day)
|
|
Payees/descriptions : 1000
|
|
Accounts : 1000 (depth 10)
|
|
Commodities : 26
|
|
Market prices : 1000
|
|
Runtime stats : 0.12 s elapsed, 8266 txns/s, 4 MB live, 16 MB alloc
|
|
|
|
$ hledger stats -1 -f examples/10ktxns-1kaccts.journal
|
|
1.50.99-g0835a2485-20251119, mac-aarch64 10ktxns-1kaccts.journal 0.66 s elapsed 15244 txns/s 28 MB live 86 MB alloc
|
|
|
|
This command supports the -o/--output-file option (but not -O/--out-
|
|
put-format).
|
|
|
|
tags
|
|
List the tag names used or declared in the journal, or their values.
|
|
|
|
Flags:
|
|
--used list tags used
|
|
--declared list tags declared
|
|
--undeclared list tags used but not declared
|
|
--unused list tags declared but not used
|
|
--find list the first tag whose name is matched by the
|
|
first argument (a case-insensitive infix regexp)
|
|
--values list tag values instead of tag names
|
|
--parsed show them in the order they were parsed (mostly),
|
|
including duplicates
|
|
|
|
This command lists tag names - all of them by default, or just the ones
|
|
which have been used on transactions/postings/accounts, or declared
|
|
with tag directives, or used but not declared, or declared but not
|
|
used, or just the first one matched by a pattern (with --find, return-
|
|
ing a non-zero exit code if it fails).
|
|
|
|
Note this command's non-standard first argument: it is a case-insensi-
|
|
tive infix regular expression for matching tag names, which limits the
|
|
tags shown. Any additional arguments are standard query arguments,
|
|
which limit the transactions, postings, or accounts providing tags.
|
|
|
|
With --values, the tags' unique non-empty values are listed instead.
|
|
|
|
With -E/--empty, blank/empty values are also shown.
|
|
|
|
With --parsed, tags or values are shown in the order they were parsed,
|
|
with duplicates included. (Except, tags from account declarations are
|
|
always shown first.)
|
|
|
|
Remember that accounts also acquire tags from their parents; postings
|
|
also acquire tags from their account and transaction; and transactions
|
|
also acquire tags from their postings.
|
|
|
|
Standard report commands
|
|
print
|
|
Show full journal entries, representing transactions.
|
|
|
|
Flags:
|
|
-x --explicit show all amounts explicitly
|
|
--invert display all amounts with reversed sign
|
|
--locations add tags showing file paths and line numbers
|
|
-m --match=DESC fuzzy search for one recent transaction with
|
|
description closest to DESC
|
|
--new show only newer-dated transactions added in each
|
|
file since last run
|
|
--round=TYPE how much rounding or padding should be done when
|
|
displaying amounts ?
|
|
none - show original decimal digits,
|
|
as in journal (default)
|
|
soft - just add or remove decimal zeros
|
|
to match precision
|
|
hard - round posting amounts to precision
|
|
(can unbalance transactions)
|
|
all - also round cost amounts to precision
|
|
(can unbalance transactions)
|
|
--base-url=URLPREFIX in html output, generate links to hledger-web,
|
|
with this prefix. (Usually the base url shown by
|
|
hledger-web; can also be relative.)
|
|
-O --output-format=FMT select the output format. Supported formats:
|
|
txt, beancount, csv, tsv, html, fods, json, sql.
|
|
-o --output-file=FILE write output to FILE. A file extension matching
|
|
one of the above formats selects that format.
|
|
|
|
The print command displays full journal entries (transactions) from the
|
|
journal file, sorted by date (or with --date2, by secondary date).
|
|
|
|
Directives and inter-transaction comments are not shown, currently.
|
|
This means the print command is somewhat lossy, and if you are using it
|
|
to reformat/regenerate your journal you should take care to also copy
|
|
over the directives and inter-transaction comments.
|
|
|
|
Eg:
|
|
|
|
$ hledger print -f examples/sample.journal date:200806
|
|
2008/06/01 gift
|
|
assets:bank:checking $1
|
|
income:gifts $-1
|
|
|
|
2008/06/02 save
|
|
assets:bank:saving $1
|
|
assets:bank:checking $-1
|
|
|
|
2008/06/03 * eat & shop
|
|
expenses:food $1
|
|
expenses:supplies $1
|
|
assets:cash $-2
|
|
|
|
print amount explicitness
|
|
Normally, whether posting amounts are implicit or explicit is pre-
|
|
served. For example, when an amount is omitted in the journal, it will
|
|
not appear in the output. Similarly, if a conversion cost is implied
|
|
but not written, it will not appear in the output.
|
|
|
|
You can use the -x/--explicit flag to force explicit display of all
|
|
amounts and costs. This can be useful for troubleshooting or for mak-
|
|
ing your journal more readable and robust against data entry errors.
|
|
-x is also implied by using any of -B,-V,-X,--value.
|
|
|
|
The -x/--explicit flag will cause any postings with a multi-commodity
|
|
amount (which can arise when a multi-commodity transaction has an im-
|
|
plicit amount) to be split into multiple single-commodity postings,
|
|
keeping the output parseable.
|
|
|
|
print alignment
|
|
Amounts are shown right-aligned within each transaction (but not
|
|
aligned across all transactions; you can achieve that with ledger-mode
|
|
in Emacs).
|
|
|
|
print amount style
|
|
Amounts will be displayed mostly in their commodity's display style,
|
|
with standardised symbol placement, decimal mark, and digit group
|
|
marks. This does not apply to their decimal digits; print normally
|
|
shows the same decimal digits that are recorded in each journal entry.
|
|
|
|
You can override the decimal precisions with print's special --round
|
|
option (since 1.32). --round tries to show amounts with their commodi-
|
|
ties' standard decimal precisions, increasingly strongly:
|
|
|
|
o --round=none show amounts with original precisions (default)
|
|
|
|
o --round=soft add/remove decimal zeros in amounts (except costs)
|
|
|
|
o --round=hard round amounts (except costs), possibly hiding signifi-
|
|
cant digits
|
|
|
|
o --round=all round all amounts and costs
|
|
|
|
soft is good for non-lossy cleanup, displaying more consistent decimals
|
|
where possible, without making entries unbalanced.
|
|
|
|
hard or all can be good for stronger cleanup, when decimal rounding is
|
|
wanted. Note rounding can produce unbalanced journal entries, perhaps
|
|
requiring manual fixup.
|
|
|
|
print parseability
|
|
Normally, print's output is a valid hledger journal, which you can
|
|
"pipe" to a second hledger command for further processing. This is
|
|
sometimes convenient for achieving certain kinds of query (though less
|
|
needed now that queries have become more powerful):
|
|
|
|
# Show running total of food expenses paid from cash.
|
|
# -f- reads from stdin. -I/--ignore-assertions is sometimes needed.
|
|
$ hledger print assets:cash | hledger -f- -I reg expenses:food
|
|
|
|
But here are some things which can cause print's output to become un-
|
|
parseable:
|
|
|
|
o --round (see above) can disrupt transaction balancing.
|
|
|
|
o Account aliases or pivoting can disrupt account names, balance asser-
|
|
tions, or balance assignments.
|
|
|
|
o Value reporting also can disrupt balance assertions or balance as-
|
|
signments.
|
|
|
|
o Auto postings can generate too many amountless postings.
|
|
|
|
o --infer-costs or --infer-equity can generate too-complex redundant
|
|
costs.
|
|
|
|
o Because print always shows transactions in date order, balance asser-
|
|
tions involving non-date-ordered transactions (and same-day postings)
|
|
could be disrupted.
|
|
|
|
print, other features
|
|
With -B/--cost, amounts with costs are shown converted to cost.
|
|
|
|
With --invert, posting amounts are shown with their sign flipped. It
|
|
could be useful if you have accidentally recorded some transactions
|
|
with the wrong signs.
|
|
|
|
With --new, print shows only transactions it has not seen on a previous
|
|
run. This uses the same deduplication system as the import command.
|
|
(See import's docs for details.)
|
|
|
|
With -m DESC/--match=DESC, print shows one recent transaction whose de-
|
|
scription is most similar to DESC. DESC should contain at least two
|
|
characters. If there is no similar-enough match, no transaction will
|
|
be shown and the program exit code will be non-zero.
|
|
|
|
With --locations, print adds the source file and line number to every
|
|
transaction, as a tag.
|
|
|
|
print output format
|
|
This command also supports the output destination and output format op-
|
|
tions The output formats supported are txt, beancount (Added in 1.32),
|
|
csv, tsv (Added in 1.32), json and sql.
|
|
|
|
The beancount format tries to produce Beancount-compatible output, as
|
|
follows:
|
|
|
|
o Transaction and postings with unmarked status are converted to
|
|
cleared (*) status.
|
|
|
|
o Transactions' payee and note are backslash-escaped and dou-
|
|
ble-quote-escaped and wrapped in double quotes.
|
|
|
|
o Transaction tags are copied to Beancount #tag format.
|
|
|
|
o Commodity symbols are converted to upper case, and a small number of
|
|
currency symbols like $ are converted to the corresponding currency
|
|
names.
|
|
|
|
o Account name parts are capitalised and unsupported characters are re-
|
|
placed with -. If an account name part does not begin with a letter,
|
|
or if the first part is not Assets, Liabilities, Equity, Income, or
|
|
Expenses, an error is raised. (Use --alias options to bring your ac-
|
|
counts into compliance.)
|
|
|
|
o An open directive is generated for each account used, on the earliest
|
|
transaction date.
|
|
|
|
Some limitations:
|
|
|
|
o Balance assertions are removed.
|
|
|
|
o Balance assignments become missing amounts.
|
|
|
|
o Virtual and balanced virtual postings become regular postings.
|
|
|
|
o Directives are not converted.
|
|
|
|
Here's an example of print's CSV output:
|
|
|
|
$ hledger print -Ocsv
|
|
"txnidx","date","date2","status","code","description","comment","account","amount","commodity","credit","debit","posting-status","posting-comment"
|
|
"1","2008/01/01","","","","income","","assets:bank:checking","1","$","","1","",""
|
|
"1","2008/01/01","","","","income","","income:salary","-1","$","1","","",""
|
|
"2","2008/06/01","","","","gift","","assets:bank:checking","1","$","","1","",""
|
|
"2","2008/06/01","","","","gift","","income:gifts","-1","$","1","","",""
|
|
"3","2008/06/02","","","","save","","assets:bank:saving","1","$","","1","",""
|
|
"3","2008/06/02","","","","save","","assets:bank:checking","-1","$","1","","",""
|
|
"4","2008/06/03","","*","","eat & shop","","expenses:food","1","$","","1","",""
|
|
"4","2008/06/03","","*","","eat & shop","","expenses:supplies","1","$","","1","",""
|
|
"4","2008/06/03","","*","","eat & shop","","assets:cash","-2","$","2","","",""
|
|
"5","2008/12/31","","*","","pay off","","liabilities:debts","1","$","","1","",""
|
|
"5","2008/12/31","","*","","pay off","","assets:bank:checking","-1","$","1","","",""
|
|
|
|
o There is one CSV record per posting, with the parent transaction's
|
|
fields repeated.
|
|
|
|
o The "txnidx" (transaction index) field shows which postings belong to
|
|
the same transaction. (This number might change if transactions are
|
|
reordered within the file, files are parsed/included in a different
|
|
order, etc.)
|
|
|
|
o The amount is separated into "commodity" (the symbol) and "amount"
|
|
(numeric quantity) fields.
|
|
|
|
o The numeric amount is repeated in either the "credit" or "debit" col-
|
|
umn, for convenience. (Those names are not accurate in the account-
|
|
ing sense; it just puts negative amounts under credit and zero or
|
|
greater amounts under debit.)
|
|
|
|
aregister
|
|
(areg)
|
|
|
|
Show the transactions and running balances in one account, with each
|
|
transaction on one line.
|
|
|
|
Flags:
|
|
--txn-dates filter strictly by transaction date, not posting
|
|
date. Warning: this can show a wrong running
|
|
balance.
|
|
--no-elide don't show only 2 commodities per amount
|
|
--cumulative accumulation mode: show running total from report
|
|
start date
|
|
-H --historical accumulation mode: show historical running
|
|
total/balance (includes postings before report
|
|
start date) (default)
|
|
--invert display all amounts with reversed sign
|
|
--heading=YN show heading row above table: yes (default) or no
|
|
-w --width=N set output width (default: terminal width). -wN,M
|
|
sets description width as well.
|
|
--align-all guarantee alignment across all lines (slower)
|
|
-O --output-format=FMT select the output format. Supported formats:
|
|
txt, html, csv, tsv, json.
|
|
-o --output-file=FILE write output to FILE. A file extension matching
|
|
one of the above formats selects that format.
|
|
|
|
aregister shows the overall transactions affecting a particular account
|
|
(and any subaccounts). Each report line represents one transaction in
|
|
this account. Transactions before the report start date are included
|
|
in the running balance (--historical mode is the default). You can
|
|
suppress this behaviour using the --cumulative option.
|
|
|
|
This is a more "real world", bank-like view than the register command
|
|
(which shows individual postings, possibly from multiple accounts, not
|
|
necessarily in historical mode). As a quick rule of thumb:
|
|
|
|
o aregister is best when reconciling real-world asset/liability ac-
|
|
counts
|
|
|
|
o register is best when reviewing individual revenues/expenses.
|
|
|
|
Note this command's non-standard, and required, first argument; it
|
|
specifies the account whose register will be shown. You can write the
|
|
account's name, or (to save typing) a case-insensitive infix regular
|
|
expression matching the name, which selects the alphabetically first
|
|
matched account. (For example, if you have assets:personal checking
|
|
and assets:business checking, hledger areg checking would select as-
|
|
sets:business checking.)
|
|
|
|
Transactions involving subaccounts of this account will also be shown.
|
|
aregister ignores depth limits, so its final total will always match a
|
|
historical balance report with similar arguments.
|
|
|
|
Any additional arguments are standard query arguments, which will limit
|
|
the transactions shown. Note some queries will disturb the running
|
|
balance, causing it to be different from the account's real-world run-
|
|
ning balance.
|
|
|
|
An example: this shows the transactions and historical running balance
|
|
during july, in the first account whose name contains "checking":
|
|
|
|
$ hledger areg checking date:jul
|
|
|
|
Each aregister line item shows:
|
|
|
|
o the transaction's date (or the relevant posting's date if different,
|
|
see below)
|
|
|
|
o the names of all the other account(s) involved in this transaction
|
|
(probably abbreviated)
|
|
|
|
o the total change to this account's balance from this transaction
|
|
|
|
o the account's historical running balance after this transaction.
|
|
|
|
Transactions making a net change of zero are not shown by default; add
|
|
the -E/--empty flag to show them.
|
|
|
|
For performance reasons, column widths are chosen based on the first
|
|
1000 lines; this means unusually wide values in later lines can cause
|
|
visual discontinuities as column widths are adjusted. If you want to
|
|
ensure perfect alignment, at the cost of more time and memory, use the
|
|
--align-all flag.
|
|
|
|
By default, aregister shows a heading above the data. However, when
|
|
reporting in a language different from English, it is easier to omit
|
|
this heading and prepend your own one. For this purpose, use the
|
|
--heading=no option.
|
|
|
|
This command also supports the output destination and output format op-
|
|
tions. The output formats supported are txt, csv, tsv (Added in 1.32),
|
|
html, fods (Added in 1.41) and json.
|
|
|
|
aregister and posting dates
|
|
aregister always shows one line (and date and amount) per transaction.
|
|
But sometimes transactions have postings with different dates. Also,
|
|
not all of a transaction's postings may be within the report period.
|
|
To resolve this, aregister shows the earliest of the transaction's date
|
|
and posting dates that is in-period, and the sum of the in-period post-
|
|
ings. In other words it will show a combined line item with just the
|
|
earliest date, and the running balance will (temporarily, until the
|
|
transaction's last posting) be inaccurate. Use register -H if you need
|
|
to see the individual postings.
|
|
|
|
There is also a --txn-dates flag, which filters strictly by transaction
|
|
date, ignoring posting dates. This too can cause an inaccurate running
|
|
balance.
|
|
|
|
register
|
|
(reg)
|
|
|
|
Show postings and their running total.
|
|
|
|
Flags:
|
|
--cumulative accumulation mode: show running total from report
|
|
start date (default)
|
|
-H --historical accumulation mode: show historical running
|
|
total/balance (includes postings before report
|
|
start date)
|
|
-A --average show running average of posting amounts instead
|
|
of total (implies --empty)
|
|
-m --match=DESC fuzzy search for one recent posting with
|
|
description closest to DESC
|
|
-r --related show postings' siblings instead
|
|
--invert display all amounts with reversed sign
|
|
--sort=FIELDS sort by: date, desc, account, amount, absamount,
|
|
or a comma-separated combination of these. For a
|
|
descending sort, prefix with -. (Default: date)
|
|
-w --width=N set output width (default: terminal width). -wN,M
|
|
sets description width as well.
|
|
--align-all guarantee alignment across all lines (slower)
|
|
--base-url=URLPREFIX in html output, generate links to hledger-web,
|
|
with this prefix. (Usually the base url shown by
|
|
hledger-web; can also be relative.)
|
|
-O --output-format=FMT select the output format. Supported formats:
|
|
txt, csv, tsv, html, fods, json.
|
|
-o --output-file=FILE write output to FILE. A file extension matching
|
|
one of the above formats selects that format.
|
|
|
|
The register command displays matched postings, across all accounts, in
|
|
date order, with their running total or running historical balance.
|
|
(See also the aregister command, which shows matched transactions in a
|
|
specific account.)
|
|
|
|
register normally shows line per posting, but note that multi-commodity
|
|
amounts will occupy multiple lines (one line per commodity).
|
|
|
|
It is typically used with a query selecting a particular account, to
|
|
see that account's activity:
|
|
|
|
$ hledger register checking
|
|
2008/01/01 income assets:bank:checking $1 $1
|
|
2008/06/01 gift assets:bank:checking $1 $2
|
|
2008/06/02 save assets:bank:checking $-1 $1
|
|
2008/12/31 pay off assets:bank:checking $-1 0
|
|
|
|
With --date2, it shows and sorts by secondary date instead.
|
|
|
|
For performance reasons, column widths are chosen based on the first
|
|
1000 lines; this means unusually wide values in later lines can cause
|
|
visual discontinuities as column widths are adjusted. If you want to
|
|
ensure perfect alignment, at the cost of more time and memory, use the
|
|
--align-all flag.
|
|
|
|
The --historical/-H flag adds the balance from any undisplayed prior
|
|
postings to the running total. This is useful when you want to see
|
|
only recent activity, with a historically accurate running balance:
|
|
|
|
$ hledger register checking -b 2008/6 --historical
|
|
2008/06/01 gift assets:bank:checking $1 $2
|
|
2008/06/02 save assets:bank:checking $-1 $1
|
|
2008/12/31 pay off assets:bank:checking $-1 0
|
|
|
|
The --depth option limits the amount of sub-account detail displayed.
|
|
|
|
The --average/-A flag shows the running average posting amount instead
|
|
of the running total (so, the final number displayed is the average for
|
|
the whole report period). This flag implies --empty (see below). It
|
|
is affected by --historical. It works best when showing just one ac-
|
|
count and one commodity.
|
|
|
|
The --related/-r flag shows the other postings in the transactions of
|
|
the postings which would normally be shown.
|
|
|
|
The --invert flag negates all amounts. For example, it can be used on
|
|
an income account where amounts are normally displayed as negative num-
|
|
bers. It's also useful to show postings on the checking account to-
|
|
gether with the related account:
|
|
|
|
The --sort=FIELDS flag sorts by the fields given, which can be any of
|
|
account, amount, absamount, date, or desc/description, optionally sepa-
|
|
rated by commas. For example, --sort account,amount will group all
|
|
transactions in each account, sorted by transaction amount. Each field
|
|
can be negated by a preceding -, so --sort -amount will show transac-
|
|
tions ordered from smallest amount to largest amount.
|
|
|
|
$ hledger register --related --invert assets:checking
|
|
|
|
With a reporting interval, register shows summary postings, one per in-
|
|
terval, aggregating the postings to each account:
|
|
|
|
$ hledger register --monthly income
|
|
2008/01 income:salary $-1 $-1
|
|
2008/06 income:gifts $-1 $-2
|
|
|
|
Periods with no activity, and summary postings with a zero amount, are
|
|
not shown by default; use the --empty/-E flag to see them:
|
|
|
|
$ hledger register --monthly income -E
|
|
2008/01 income:salary $-1 $-1
|
|
2008/02 0 $-1
|
|
2008/03 0 $-1
|
|
2008/04 0 $-1
|
|
2008/05 0 $-1
|
|
2008/06 income:gifts $-1 $-2
|
|
2008/07 0 $-2
|
|
2008/08 0 $-2
|
|
2008/09 0 $-2
|
|
2008/10 0 $-2
|
|
2008/11 0 $-2
|
|
2008/12 0 $-2
|
|
|
|
Often, you'll want to see just one line per interval. The --depth op-
|
|
tion helps with this, causing subaccounts to be aggregated:
|
|
|
|
$ hledger register --monthly assets --depth 1
|
|
2008/01 assets $1 $1
|
|
2008/06 assets $-1 0
|
|
2008/12 assets $-1 $-1
|
|
|
|
Note when using report intervals, if you specify start/end dates these
|
|
will be adjusted outward if necessary to contain a whole number of in-
|
|
tervals. This ensures that the first and last intervals are full
|
|
length and comparable to the others in the report.
|
|
|
|
With -m DESC/--match=DESC, register does a fuzzy search for one recent
|
|
posting whose description is most similar to DESC. DESC should contain
|
|
at least two characters. If there is no similar-enough match, no post-
|
|
ing will be shown and the program exit code will be non-zero.
|
|
|
|
Custom register output
|
|
register normally uses the full terminal width (or 80 columns if it
|
|
can't detect that). You can override this with the --width/-w option.
|
|
|
|
The description and account columns normally share the space equally
|
|
(about half of (width - 40) each). You can adjust this by adding a de-
|
|
scription width as part of --width's argument, comma-separated: --width
|
|
W,D . Here's a diagram (won't display correctly in --help):
|
|
|
|
<--------------------------------- width (W) ---------------------------------->
|
|
date (10) description (D) account (W-41-D) amount (12) balance (12)
|
|
DDDDDDDDDD dddddddddddddddddddd aaaaaaaaaaaaaaaaaaa AAAAAAAAAAAA AAAAAAAAAAAA
|
|
|
|
and some examples:
|
|
|
|
$ hledger reg # use terminal width (or 80 on windows)
|
|
$ hledger reg -w 100 # use width 100
|
|
$ hledger reg -w 100,40 # set overall width 100, description width 40
|
|
|
|
This command also supports the output destination and output format op-
|
|
tions The output formats supported are txt, csv, tsv (Added in 1.32),
|
|
and json.
|
|
|
|
balancesheet
|
|
(bs)
|
|
|
|
Show the end balances in asset and liability accounts. Amounts are
|
|
shown with normal positive sign, as in conventional financial state-
|
|
ments.
|
|
|
|
Flags:
|
|
--sum calculation mode: show sum of posting amounts
|
|
(default)
|
|
--valuechange calculation mode: show total change of value of
|
|
period-end historical balances (caused by deposits,
|
|
withdrawals, market price fluctuations)
|
|
--gain calculation mode: show unrealised capital
|
|
gain/loss (historical balance value minus cost
|
|
basis)
|
|
--count calculation mode: show the count of postings
|
|
--change accumulation mode: accumulate amounts from column
|
|
start to column end (in multicolumn reports)
|
|
--cumulative accumulation mode: accumulate amounts from report
|
|
start (specified by e.g. -b/--begin) to column end
|
|
-H --historical accumulation mode: accumulate amounts from
|
|
journal start to column end (includes postings
|
|
before report start date) (default)
|
|
-l --flat list/tree mode: show accounts as a flat list
|
|
(default). Amounts exclude subaccount amounts,
|
|
except where the account is depth-clipped.
|
|
-t --tree list/tree mode: show accounts as a tree. Amounts
|
|
include subaccount amounts.
|
|
--drop=N in list mode, omit N leading account name parts
|
|
--declared include non-parent declared accounts (best used
|
|
with -E)
|
|
-A --average show a row average column (in multicolumn
|
|
reports)
|
|
-T --row-total show a row total column (in multicolumn reports)
|
|
--summary-only display only row summaries (e.g. row total,
|
|
average) (in multicolumn reports)
|
|
-N --no-total omit the final total row
|
|
--no-elide in tree mode, don't squash boring parent accounts
|
|
--format=FORMATSTR use this custom line format (in simple reports)
|
|
-S --sort-amount sort by amount instead of account code/name
|
|
-% --percent express values in percentage of each column's
|
|
total
|
|
--layout=ARG how to show multi-commodity amounts:
|
|
'wide[,WIDTH]': all commodities on one line
|
|
'tall' : each commodity on a new line
|
|
'bare' : bare numbers, symbols in a column
|
|
--base-url=URLPREFIX in html output, generate hyperlinks to
|
|
hledger-web, with this prefix. (Usually the base
|
|
url shown by hledger-web; can also be relative.)
|
|
-O --output-format=FMT select the output format. Supported formats:
|
|
txt, html, csv, tsv, json.
|
|
-o --output-file=FILE write output to FILE. A file extension matching
|
|
one of the above formats selects that format.
|
|
|
|
This command displays a balance sheet, showing historical ending bal-
|
|
ances of asset and liability accounts. (To see equity as well, use the
|
|
balancesheetequity command.)
|
|
|
|
Accounts declared with the Asset, Cash or Liability type are shown (see
|
|
account types). Or if no such accounts are declared, it shows
|
|
top-level accounts named asset or liability (case insensitive, plurals
|
|
allowed) and their subaccounts.
|
|
|
|
Example:
|
|
|
|
$ hledger balancesheet
|
|
Balance Sheet 2008-12-31
|
|
|
|
|| 2008-12-31
|
|
====================++============
|
|
Assets ||
|
|
--------------------++------------
|
|
assets:bank:saving || $1
|
|
assets:cash || $-2
|
|
--------------------++------------
|
|
|| $-1
|
|
====================++============
|
|
Liabilities ||
|
|
--------------------++------------
|
|
liabilities:debts || $-1
|
|
--------------------++------------
|
|
|| $-1
|
|
====================++============
|
|
Net: || 0
|
|
|
|
This command is a higher-level variant of the balance command, and sup-
|
|
ports many of that command's features, such as multi-period reports.
|
|
It is similar to hledger balance -H assets liabilities, but with
|
|
smarter account detection, and liabilities displayed with their sign
|
|
flipped.
|
|
|
|
This command also supports the output destination and output format op-
|
|
tions The output formats supported are txt, csv, tsv (Added in 1.32),
|
|
html, and json.
|
|
|
|
balancesheetequity
|
|
(bse)
|
|
|
|
This command displays a balance sheet, showing historical ending bal-
|
|
ances of asset, liability and equity accounts. Amounts are shown with
|
|
normal positive sign, as in conventional financial statements.
|
|
|
|
Flags:
|
|
--sum calculation mode: show sum of posting amounts
|
|
(default)
|
|
--valuechange calculation mode: show total change of value of
|
|
period-end historical balances (caused by deposits,
|
|
withdrawals, market price fluctuations)
|
|
--gain calculation mode: show unrealised capital
|
|
gain/loss (historical balance value minus cost
|
|
basis)
|
|
--count calculation mode: show the count of postings
|
|
--change accumulation mode: accumulate amounts from column
|
|
start to column end (in multicolumn reports)
|
|
--cumulative accumulation mode: accumulate amounts from report
|
|
start (specified by e.g. -b/--begin) to column end
|
|
-H --historical accumulation mode: accumulate amounts from
|
|
journal start to column end (includes postings
|
|
before report start date) (default)
|
|
-l --flat list/tree mode: show accounts as a flat list
|
|
(default). Amounts exclude subaccount amounts,
|
|
except where the account is depth-clipped.
|
|
-t --tree list/tree mode: show accounts as a tree. Amounts
|
|
include subaccount amounts.
|
|
--drop=N in list mode, omit N leading account name parts
|
|
--declared include non-parent declared accounts (best used
|
|
with -E)
|
|
-A --average show a row average column (in multicolumn
|
|
reports)
|
|
-T --row-total show a row total column (in multicolumn reports)
|
|
--summary-only display only row summaries (e.g. row total,
|
|
average) (in multicolumn reports)
|
|
-N --no-total omit the final total row
|
|
--no-elide in tree mode, don't squash boring parent accounts
|
|
--format=FORMATSTR use this custom line format (in simple reports)
|
|
-S --sort-amount sort by amount instead of account code/name
|
|
-% --percent express values in percentage of each column's
|
|
total
|
|
--layout=ARG how to show multi-commodity amounts:
|
|
'wide[,WIDTH]': all commodities on one line
|
|
'tall' : each commodity on a new line
|
|
'bare' : bare numbers, symbols in a column
|
|
--base-url=URLPREFIX in html output, generate hyperlinks to
|
|
hledger-web, with this prefix. (Usually the base
|
|
url shown by hledger-web; can also be relative.)
|
|
-O --output-format=FMT select the output format. Supported formats:
|
|
txt, html, csv, tsv, json.
|
|
-o --output-file=FILE write output to FILE. A file extension matching
|
|
one of the above formats selects that format.
|
|
|
|
This report shows accounts declared with the Asset, Cash, Liability or
|
|
Equity type (see account types). Or if no such accounts are declared,
|
|
it shows top-level accounts named asset, liability or equity (case in-
|
|
sensitive, plurals allowed) and their subaccounts.
|
|
|
|
Example:
|
|
|
|
$ hledger balancesheetequity
|
|
Balance Sheet With Equity 2008-12-31
|
|
|
|
|| 2008-12-31
|
|
====================++============
|
|
Assets ||
|
|
--------------------++------------
|
|
assets:bank:saving || $1
|
|
assets:cash || $-2
|
|
--------------------++------------
|
|
|| $-1
|
|
====================++============
|
|
Liabilities ||
|
|
--------------------++------------
|
|
liabilities:debts || $-1
|
|
--------------------++------------
|
|
|| $-1
|
|
====================++============
|
|
Equity ||
|
|
--------------------++------------
|
|
--------------------++------------
|
|
|| 0
|
|
====================++============
|
|
Net: || 0
|
|
|
|
This command is a higher-level variant of the balance command, and sup-
|
|
ports many of that command's features, such as multi-period reports.
|
|
It is similar to hledger balance -H assets liabilities equity, but with
|
|
smarter account detection, and liabilities/equity displayed with their
|
|
sign flipped.
|
|
|
|
This report is the easiest way to see if the accounting equation (A+L+E
|
|
= 0) is satisfied (after you have done a close --retain to merge rev-
|
|
enues and expenses with equity, and perhaps added --infer-equity to
|
|
balance your commodity conversions).
|
|
|
|
This command also supports the output destination and output format op-
|
|
tions The output formats supported are txt, csv, tsv, html, and json.
|
|
|
|
cashflow
|
|
(cf)
|
|
|
|
This command displays a (simple) cashflow statement, showing the in-
|
|
flows and outflows affecting "cash" (ie, liquid, easily convertible)
|
|
assets. Amounts are shown with normal positive sign, as in conven-
|
|
tional financial statements.
|
|
|
|
Flags:
|
|
--sum calculation mode: show sum of posting amounts
|
|
(default)
|
|
--valuechange calculation mode: show total change of value of
|
|
period-end historical balances (caused by deposits,
|
|
withdrawals, market price fluctuations)
|
|
--gain calculation mode: show unrealised capital
|
|
gain/loss (historical balance value minus cost
|
|
basis)
|
|
--count calculation mode: show the count of postings
|
|
--change accumulation mode: accumulate amounts from column
|
|
start to column end (in multicolumn reports)
|
|
(default)
|
|
--cumulative accumulation mode: accumulate amounts from report
|
|
start (specified by e.g. -b/--begin) to column end
|
|
-H --historical accumulation mode: accumulate amounts from
|
|
journal start to column end (includes postings
|
|
before report start date)
|
|
-l --flat list/tree mode: show accounts as a flat list
|
|
(default). Amounts exclude subaccount amounts,
|
|
except where the account is depth-clipped.
|
|
-t --tree list/tree mode: show accounts as a tree. Amounts
|
|
include subaccount amounts.
|
|
--drop=N in list mode, omit N leading account name parts
|
|
--declared include non-parent declared accounts (best used
|
|
with -E)
|
|
-A --average show a row average column (in multicolumn
|
|
reports)
|
|
-T --row-total show a row total column (in multicolumn reports)
|
|
--summary-only display only row summaries (e.g. row total,
|
|
average) (in multicolumn reports)
|
|
-N --no-total omit the final total row
|
|
--no-elide in tree mode, don't squash boring parent accounts
|
|
--format=FORMATSTR use this custom line format (in simple reports)
|
|
-S --sort-amount sort by amount instead of account code/name
|
|
-% --percent express values in percentage of each column's
|
|
total
|
|
--layout=ARG how to show multi-commodity amounts:
|
|
'wide[,WIDTH]': all commodities on one line
|
|
'tall' : each commodity on a new line
|
|
'bare' : bare numbers, symbols in a column
|
|
--base-url=URLPREFIX in html output, generate hyperlinks to
|
|
hledger-web, with this prefix. (Usually the base
|
|
url shown by hledger-web; can also be relative.)
|
|
-O --output-format=FMT select the output format. Supported formats:
|
|
txt, html, csv, tsv, json.
|
|
-o --output-file=FILE write output to FILE. A file extension matching
|
|
one of the above formats selects that format.
|
|
|
|
This report shows accounts declared with the Cash type (see account
|
|
types). Or if no such accounts are declared, it shows accounts
|
|
|
|
o under a top-level account named asset (case insensitive, plural al-
|
|
lowed)
|
|
|
|
o whose name contains some variation of cash, bank, checking or saving.
|
|
|
|
More precisely: all accounts matching this case insensitive regular ex-
|
|
pression:
|
|
|
|
^assets?(:.+)?:(cash|bank|che(ck|que?)(ing)?|savings?|currentcash)(:|$)
|
|
|
|
and their subaccounts.
|
|
|
|
An example cashflow report:
|
|
|
|
$ hledger cashflow
|
|
Cashflow Statement 2008
|
|
|
|
|| 2008
|
|
====================++======
|
|
Cash flows ||
|
|
--------------------++------
|
|
assets:bank:saving || $1
|
|
assets:cash || $-2
|
|
--------------------++------
|
|
|| $-1
|
|
|
|
This command is a higher-level variant of the balance command, and sup-
|
|
ports many of that command's features, such as multi-period reports.
|
|
It is similar to hledger balance assets not:fixed not:investment
|
|
not:receivable, but with smarter account detection.
|
|
|
|
This command also supports the output destination and output format op-
|
|
tions The output formats supported are txt, csv, tsv (Added in 1.32),
|
|
html, and json.
|
|
|
|
incomestatement
|
|
(is)
|
|
|
|
Show revenue inflows and expense outflows during the report period.
|
|
Amounts are shown with normal positive sign, as in conventional finan-
|
|
cial statements.
|
|
|
|
Flags:
|
|
--sum calculation mode: show sum of posting amounts
|
|
(default)
|
|
--valuechange calculation mode: show total change of value of
|
|
period-end historical balances (caused by deposits,
|
|
withdrawals, market price fluctuations)
|
|
--gain calculation mode: show unrealised capital
|
|
gain/loss (historical balance value minus cost
|
|
basis)
|
|
--count calculation mode: show the count of postings
|
|
--change accumulation mode: accumulate amounts from column
|
|
start to column end (in multicolumn reports)
|
|
(default)
|
|
--cumulative accumulation mode: accumulate amounts from report
|
|
start (specified by e.g. -b/--begin) to column end
|
|
-H --historical accumulation mode: accumulate amounts from
|
|
journal start to column end (includes postings
|
|
before report start date)
|
|
-l --flat list/tree mode: show accounts as a flat list
|
|
(default). Amounts exclude subaccount amounts,
|
|
except where the account is depth-clipped.
|
|
-t --tree list/tree mode: show accounts as a tree. Amounts
|
|
include subaccount amounts.
|
|
--drop=N in list mode, omit N leading account name parts
|
|
--declared include non-parent declared accounts (best used
|
|
with -E)
|
|
-A --average show a row average column (in multicolumn
|
|
reports)
|
|
-T --row-total show a row total column (in multicolumn reports)
|
|
--summary-only display only row summaries (e.g. row total,
|
|
average) (in multicolumn reports)
|
|
-N --no-total omit the final total row
|
|
--no-elide in tree mode, don't squash boring parent accounts
|
|
--format=FORMATSTR use this custom line format (in simple reports)
|
|
-S --sort-amount sort by amount instead of account code/name
|
|
-% --percent express values in percentage of each column's
|
|
total
|
|
--layout=ARG how to show multi-commodity amounts:
|
|
'wide[,WIDTH]': all commodities on one line
|
|
'tall' : each commodity on a new line
|
|
'bare' : bare numbers, symbols in a column
|
|
--base-url=URLPREFIX in html output, generate hyperlinks to
|
|
hledger-web, with this prefix. (Usually the base
|
|
url shown by hledger-web; can also be relative.)
|
|
-O --output-format=FMT select the output format. Supported formats:
|
|
txt, html, csv, tsv, json.
|
|
-o --output-file=FILE write output to FILE. A file extension matching
|
|
one of the above formats selects that format.
|
|
|
|
This command displays an income statement, showing revenues and ex-
|
|
penses during one or more periods.
|
|
|
|
It shows accounts declared with the Revenue or Expense type (see ac-
|
|
count types). Or if no such accounts are declared, it shows top-level
|
|
accounts named revenue or income or expense (case insensitive, plurals
|
|
allowed) and their subaccounts.
|
|
|
|
Example:
|
|
|
|
$ hledger incomestatement
|
|
Income Statement 2008
|
|
|
|
|| 2008
|
|
===================++======
|
|
Revenues ||
|
|
-------------------++------
|
|
income:gifts || $1
|
|
income:salary || $1
|
|
-------------------++------
|
|
|| $2
|
|
===================++======
|
|
Expenses ||
|
|
-------------------++------
|
|
expenses:food || $1
|
|
expenses:supplies || $1
|
|
-------------------++------
|
|
|| $2
|
|
===================++======
|
|
Net: || 0
|
|
|
|
This command is a higher-level variant of the balance command, and sup-
|
|
ports many of that command's features, such as multi-period reports.
|
|
It is similar to hledger balance '(revenues|income)' expenses, but with
|
|
smarter account detection, and revenues/income displayed with their
|
|
sign flipped.
|
|
|
|
This command also supports the output destination and output format op-
|
|
tions The output formats supported are txt, csv, tsv (Added in 1.32),
|
|
html, and json.
|
|
|
|
Advanced report commands
|
|
balance
|
|
(bal)
|
|
|
|
A flexible, general purpose "summing" report that shows accounts with
|
|
some kind of numeric data. This can be balance changes per period, end
|
|
balances, budget performance, unrealised capital gains, etc.
|
|
|
|
Flags:
|
|
--sum calculation mode: show sum of posting amounts
|
|
(default)
|
|
--valuechange calculation mode: show total change of value of
|
|
period-end historical balances (caused by deposits,
|
|
withdrawals, market price fluctuations)
|
|
--gain calculation mode: show unrealised capital
|
|
gain/loss (historical balance value minus cost
|
|
basis)
|
|
--budget[=DESCPAT] calculation mode: show sum of posting amounts
|
|
together with budget goals defined by periodic
|
|
transactions. With a DESCPAT argument (must be
|
|
separated by = not space),
|
|
use only periodic transactions with matching
|
|
description
|
|
(case insensitive substring match).
|
|
--count calculation mode: show the count of postings
|
|
--change accumulation mode: accumulate amounts from column
|
|
start to column end (in multicolumn reports,
|
|
default)
|
|
--cumulative accumulation mode: accumulate amounts from report
|
|
start (specified by e.g. -b/--begin) to column end
|
|
-H --historical accumulation mode: accumulate amounts from
|
|
journal start to column end (includes postings
|
|
before report start date)
|
|
-l --flat list/tree mode: show accounts as a flat list
|
|
(default). Amounts exclude subaccount amounts,
|
|
except where the account is depth-clipped.
|
|
-t --tree list/tree mode: show accounts as a tree. Amounts
|
|
include subaccount amounts.
|
|
--drop=N in list mode, omit N leading account name parts
|
|
--declared include non-parent declared accounts (best used
|
|
with -E)
|
|
-A --average show a row average column (in multicolumn
|
|
reports)
|
|
-T --row-total show a row total column (in multicolumn reports)
|
|
--summary-only display only row summaries (e.g. row total,
|
|
average) (in multicolumn reports)
|
|
-N --no-total omit the final total row
|
|
--no-elide in tree mode, don't squash boring parent accounts
|
|
--format=FORMATSTR use this custom line format (in simple reports)
|
|
-S --sort-amount sort by amount instead of account code/name (in
|
|
flat mode). With multiple columns, sorts by the row
|
|
total, or by row average if that is displayed.
|
|
-% --percent express values in percentage of each column's
|
|
total
|
|
-r --related show the other accounts transacted with, instead
|
|
--invert display all amounts with reversed sign
|
|
--transpose switch rows and columns (use vertical time axis)
|
|
--layout=ARG how to lay out multi-commodity amounts and the
|
|
overall table:
|
|
'wide[,W]': commodities on same line, up to W wide
|
|
'tall' : commodities on separate lines
|
|
'bare' : commodity symbols in a separate column
|
|
'tidy' : each data field in its own column
|
|
--base-url=URLPREFIX in html output, generate links to hledger-web,
|
|
with this prefix. (Usually the base url shown by
|
|
hledger-web; can also be relative.)
|
|
-O --output-format=FMT select the output format. Supported formats:
|
|
txt, html, csv, tsv, json, fods.
|
|
-o --output-file=FILE write output to FILE. A file extension matching
|
|
one of the above formats selects that format.
|
|
|
|
balance is one of hledger's oldest and most versatile commands, for
|
|
listing account balances, balance changes, values, value changes and
|
|
more, during one time period or many. Generally it shows a table, with
|
|
rows representing accounts, and columns representing periods.
|
|
|
|
Note there are some variants of the balance command with convenient de-
|
|
faults, which are simpler to use: balancesheet, balancesheetequity,
|
|
cashflow and incomestatement. When you need more control, then use
|
|
balance.
|
|
|
|
balance features
|
|
Here's a quick overview of the balance command's features, followed by
|
|
more detailed descriptions and examples. Many of these work with the
|
|
other balance-like commands as well (bs, cf, is..).
|
|
|
|
balance can show..
|
|
|
|
o accounts as a list (-l) or a tree (-t)
|
|
|
|
o optionally depth-limited (-[1-9])
|
|
|
|
o sorted by declaration order and name, or by amount
|
|
|
|
..and their..
|
|
|
|
o balance changes (the default)
|
|
|
|
o or actual and planned balance changes (--budget)
|
|
|
|
o or value of balance changes (-V)
|
|
|
|
o or change of balance values (--valuechange)
|
|
|
|
o or unrealised capital gain/loss (--gain)
|
|
|
|
o or balance changes from sibling postings (--related/-r)
|
|
|
|
o or postings count (--count)
|
|
|
|
..in..
|
|
|
|
o one time period (the whole journal period by default)
|
|
|
|
o or multiple periods (-D, -W, -M, -Q, -Y, -p INTERVAL)
|
|
|
|
..either..
|
|
|
|
o per period (the default)
|
|
|
|
o or accumulated since report start date (--cumulative)
|
|
|
|
o or accumulated since account creation (--historical/-H)
|
|
|
|
..possibly converted to..
|
|
|
|
o cost (--value=cost[,COMM]/--cost/-B)
|
|
|
|
o or market value, as of transaction dates (--value=then[,COMM])
|
|
|
|
o or at period ends (--value=end[,COMM])
|
|
|
|
o or now (--value=now)
|
|
|
|
o or at some other date (--value=YYYY-MM-DD)
|
|
|
|
..with..
|
|
|
|
o totals (-T), averages (-A), percentages (-%), inverted sign (--in-
|
|
vert)
|
|
|
|
o rows and columns swapped (--transpose)
|
|
|
|
o another field used as account name (--pivot)
|
|
|
|
o custom-formatted line items (single-period reports only) (--format)
|
|
|
|
o commodities displayed on the same line or multiple lines (--layout)
|
|
|
|
This command supports the output destination and output format options,
|
|
with output formats txt, csv, tsv (Added in 1.32), json, and (multi-pe-
|
|
riod reports only:) html, fods (Added in 1.40). In txt output in a
|
|
colour-supporting terminal, negative amounts are shown in red.
|
|
|
|
Simple balance report
|
|
With no arguments, balance shows a list of all accounts and their
|
|
change of balance - ie, the sum of posting amounts, both inflows and
|
|
outflows - during the entire period of the journal. ("Simple" here
|
|
means just one column of numbers, covering a single period. You can
|
|
also have multi-period reports, described later.)
|
|
|
|
For real-world accounts, these numbers will normally be their end bal-
|
|
ance at the end of the journal period; more on this below.
|
|
|
|
Accounts are sorted by declaration order if any, and then alphabeti-
|
|
cally by account name. For instance (using examples/sample.journal):
|
|
|
|
$ hledger -f examples/sample.journal bal
|
|
$1 assets:bank:saving
|
|
$-2 assets:cash
|
|
$1 expenses:food
|
|
$1 expenses:supplies
|
|
$-1 income:gifts
|
|
$-1 income:salary
|
|
$1 liabilities:debts
|
|
--------------------
|
|
0
|
|
|
|
Accounts with a zero balance (and no non-zero subaccounts, in tree mode
|
|
- see below) are hidden by default. Use -E/--empty to show them (re-
|
|
vealing assets:bank:checking here):
|
|
|
|
$ hledger -f examples/sample.journal bal -E
|
|
0 assets:bank:checking
|
|
$1 assets:bank:saving
|
|
$-2 assets:cash
|
|
$1 expenses:food
|
|
$1 expenses:supplies
|
|
$-1 income:gifts
|
|
$-1 income:salary
|
|
$1 liabilities:debts
|
|
--------------------
|
|
0
|
|
|
|
The total of the amounts displayed is shown as the last line, unless
|
|
-N/--no-total is used.
|
|
|
|
Balance report line format
|
|
For single-period balance reports displayed in the terminal (only), you
|
|
can use --format FMT to customise the format and content of each line.
|
|
Eg:
|
|
|
|
$ hledger -f examples/sample.journal balance --format "%20(account) %12(total)"
|
|
assets $-1
|
|
bank:saving $1
|
|
cash $-2
|
|
expenses $2
|
|
food $1
|
|
supplies $1
|
|
income $-2
|
|
gifts $-1
|
|
salary $-1
|
|
liabilities:debts $1
|
|
---------------------------------
|
|
0
|
|
|
|
The FMT format string specifies the formatting applied to each ac-
|
|
count/balance pair. It may contain any suitable text, with data fields
|
|
interpolated like so:
|
|
|
|
%[MIN][.MAX](FIELDNAME)
|
|
|
|
o MIN pads with spaces to at least this width (optional)
|
|
|
|
o MAX truncates at this width (optional)
|
|
|
|
o FIELDNAME must be enclosed in parentheses, and can be one of:
|
|
|
|
o depth_spacer - a number of spaces equal to the account's depth, or
|
|
if MIN is specified, MIN * depth spaces.
|
|
|
|
o account - the account's name
|
|
|
|
o total - the account's balance/posted total, right justified
|
|
|
|
Also, FMT can begin with an optional prefix to control how multi-com-
|
|
modity amounts are rendered:
|
|
|
|
o %_ - render on multiple lines, bottom-aligned (the default)
|
|
|
|
o %^ - render on multiple lines, top-aligned
|
|
|
|
o %, - render on one line, comma-separated
|
|
|
|
There are some quirks. Eg in one-line mode, %(depth_spacer) has no ef-
|
|
fect, instead %(account) has indentation built in. Experimentation
|
|
may be needed to get pleasing results.
|
|
|
|
Some example formats:
|
|
|
|
o %(total) - the account's total
|
|
|
|
o %-20.20(account) - the account's name, left justified, padded to 20
|
|
characters and clipped at 20 characters
|
|
|
|
o %,%-50(account) %25(total) - account name padded to 50 characters,
|
|
total padded to 20 characters, with multiple commodities rendered on
|
|
one line
|
|
|
|
o %20(total) %2(depth_spacer)%-(account) - the default format for the
|
|
single-column balance report
|
|
|
|
Filtered balance report
|
|
You can show fewer accounts, a different time period, totals from
|
|
cleared transactions only, etc. by using query arguments or options to
|
|
limit the postings being matched. Eg:
|
|
|
|
$ hledger -f examples/sample.journal bal --cleared assets date:200806
|
|
$-2 assets:cash
|
|
--------------------
|
|
$-2
|
|
|
|
List or tree mode
|
|
By default, or with -l/--flat, accounts are shown as a flat list with
|
|
their full names visible, as in the examples above.
|
|
|
|
With -t/--tree, the account hierarchy is shown, with subaccounts'
|
|
"leaf" names indented below their parent:
|
|
|
|
$ hledger -f examples/sample.journal balance
|
|
$-1 assets
|
|
$1 bank:saving
|
|
$-2 cash
|
|
$2 expenses
|
|
$1 food
|
|
$1 supplies
|
|
$-2 income
|
|
$-1 gifts
|
|
$-1 salary
|
|
$1 liabilities:debts
|
|
--------------------
|
|
0
|
|
|
|
Notes:
|
|
|
|
o "Boring" accounts are combined with their subaccount for more compact
|
|
output, unless --no-elide is used. Boring accounts have no balance
|
|
of their own and just one subaccount (eg assets:bank and liabilities
|
|
above).
|
|
|
|
o All balances shown are "inclusive", ie including the balances from
|
|
all subaccounts. Note this means some repetition in the output,
|
|
which requires explanation when sharing reports with non-plaintextac-
|
|
counting-users. A tree mode report's final total is the sum of the
|
|
top-level balances shown, not of all the balances shown.
|
|
|
|
o Each group of sibling accounts (ie, under a common parent) is sorted
|
|
separately.
|
|
|
|
Depth limiting
|
|
With a depth:NUM query, or --depth NUM option, or just -NUM (eg: -3)
|
|
balance reports will show accounts only to the specified depth, hiding
|
|
the deeper subaccounts. This can be useful for getting an overview
|
|
without too much detail.
|
|
|
|
Account balances at the depth limit always include the balances from
|
|
any deeper subaccounts (even in list mode). Eg, limiting to depth 1:
|
|
|
|
$ hledger -f examples/sample.journal balance -1
|
|
$-1 assets
|
|
$2 expenses
|
|
$-2 income
|
|
$1 liabilities
|
|
--------------------
|
|
0
|
|
|
|
Dropping top-level accounts
|
|
You can also hide one or more top-level account name parts, using
|
|
--drop NUM. This can be useful for hiding repetitive top-level account
|
|
names:
|
|
|
|
$ hledger -f examples/sample.journal bal expenses --drop 1
|
|
$1 food
|
|
$1 supplies
|
|
--------------------
|
|
$2
|
|
|
|
Showing declared accounts
|
|
With --declared, accounts which have been declared with an account di-
|
|
rective will be included in the balance report, even if they have no
|
|
transactions. (Since they will have a zero balance, you will also need
|
|
-E/--empty to see them.)
|
|
|
|
More precisely, leaf declared accounts (with no subaccounts) will be
|
|
included, since those are usually the more useful in reports.
|
|
|
|
The idea of this is to be able to see a useful "complete" balance re-
|
|
port, even when you don't have transactions in all of your declared ac-
|
|
counts yet.
|
|
|
|
Sorting by amount
|
|
With -S/--sort-amount, accounts with the largest (most positive) bal-
|
|
ances are shown first. Eg: hledger bal expenses -MAS shows your
|
|
biggest averaged monthly expenses first. When more than one commodity
|
|
is present, they will be sorted by the alphabetically earliest commod-
|
|
ity first, and then by subsequent commodities (if an amount is missing
|
|
a commodity, it is treated as 0).
|
|
|
|
Revenues and liability balances are typically negative, however, so -S
|
|
shows these in reverse order. To work around this, you can add --in-
|
|
vert to flip the signs. Or you could use one of the higher-level bal-
|
|
ance reports (bs, is..), which flip the sign automatically (eg: hledger
|
|
is -MAS).
|
|
|
|
Percentages
|
|
With -%/--percent, balance reports show each account's value expressed
|
|
as a percentage of the (column) total.
|
|
|
|
Note it is not useful to calculate percentages if the amounts in a col-
|
|
umn have mixed signs. In this case, make a separate report for each
|
|
sign, eg:
|
|
|
|
$ hledger bal -% amt:`>0`
|
|
$ hledger bal -% amt:`<0`
|
|
|
|
Similarly, if the amounts in a column have mixed commodities, convert
|
|
them to one commodity with -B, -V, -X or --value, or make a separate
|
|
report for each commodity:
|
|
|
|
$ hledger bal -% cur:\\$
|
|
$ hledger bal -% cur:
|
|
|
|
Multi-period balance report
|
|
With a report interval (set by the -D/--daily, -W/--weekly,
|
|
-M/--monthly, -Q/--quarterly, -Y/--yearly, or -p/--period flag), bal-
|
|
ance shows a tabular report, with columns representing successive time
|
|
periods (and a title):
|
|
|
|
$ hledger -f examples/sample.journal bal --quarterly income expenses -E
|
|
Balance changes in 2008:
|
|
|
|
|| 2008q1 2008q2 2008q3 2008q4
|
|
===================++=================================
|
|
expenses:food || 0 $1 0 0
|
|
expenses:supplies || 0 $1 0 0
|
|
income:gifts || 0 $-1 0 0
|
|
income:salary || $-1 0 0 0
|
|
-------------------++---------------------------------
|
|
|| $-1 $1 0 0
|
|
|
|
Notes:
|
|
|
|
o The report's start/end dates will be expanded, if necessary, to fully
|
|
encompass the displayed subperiods (so that the first and last subpe-
|
|
riods have the same duration as the others).
|
|
|
|
o Leading and trailing periods (columns) containing all zeroes are not
|
|
shown, unless -E/--empty is used.
|
|
|
|
o Accounts (rows) containing all zeroes are not shown, unless
|
|
-E/--empty is used.
|
|
|
|
o Amounts with many commodities are shown in abbreviated form, unless
|
|
--no-elide is used.
|
|
|
|
o Average and/or total columns can be added with the -A/--average and
|
|
-T/--row-total flags.
|
|
|
|
o The --transpose flag can be used to exchange rows and columns.
|
|
|
|
o The --pivot FIELD option causes a different transaction field to be
|
|
used as "account name". See PIVOTING.
|
|
|
|
o The --summary-only flag (--summary also works) hides all but the To-
|
|
tal and Average columns (those should be enabled with --row-total and
|
|
-A/--average).
|
|
|
|
Multi-period reports with many periods can be too wide for easy viewing
|
|
in the terminal. Here are some ways to handle that:
|
|
|
|
o Hide the totals row with -N/--no-total
|
|
|
|
o Filter to a single currency with cur:
|
|
|
|
o Convert to a single currency with -V [--infer-market-price]
|
|
|
|
o Use a more compact layout like --layout=bare
|
|
|
|
o Maximize the terminal window
|
|
|
|
o Reduce the terminal's font size
|
|
|
|
o View with a pager like less, eg: hledger bal -D --color=yes | less
|
|
-RS
|
|
|
|
o Output as CSV and use a CSV viewer like visidata (hledger bal -D -O
|
|
csv | vd -f csv), Emacs' csv-mode (M-x csv-mode, C-c C-a), or a
|
|
spreadsheet (hledger bal -D -o a.csv && open a.csv)
|
|
|
|
o Output as HTML and view with a browser: hledger bal -D -o a.html &&
|
|
open a.html
|
|
|
|
Balance change, end balance
|
|
It's important to be clear on the meaning of the numbers shown in bal-
|
|
ance reports. Here is some terminology we use:
|
|
|
|
A balance change is the net amount added to, or removed from, an ac-
|
|
count during some period.
|
|
|
|
An end balance is the amount accumulated in an account as of some date
|
|
(and some time, but hledger doesn't store that; assume end of day in
|
|
your timezone). It is the sum of previous balance changes.
|
|
|
|
We call it a historical end balance if it includes all balance changes
|
|
since the account was created. For a real world account, this means it
|
|
will match the "historical record", eg the balances reported in your
|
|
bank statements or bank web UI. (If they are correct!)
|
|
|
|
In general, balance changes are what you want to see when reviewing
|
|
revenues and expenses, and historical end balances are what you want to
|
|
see when reviewing or reconciling asset, liability and equity accounts.
|
|
|
|
balance shows balance changes by default. To see accurate historical
|
|
end balances:
|
|
|
|
1. Initialise account starting balances with an "opening balances"
|
|
transaction (a transfer from equity to the account), unless the
|
|
journal covers the account's full lifetime.
|
|
|
|
2. Include all of of the account's prior postings in the report, by not
|
|
specifying a report start date, or by using the -H/--historical
|
|
flag. (-H causes report start date to be ignored when summing post-
|
|
ings.)
|
|
|
|
Balance report modes
|
|
The balance command is quite flexible; here is the full detail on how
|
|
to control what it reports. If the following seems complicated, don't
|
|
worry - this is for advanced reporting, and it does take time and ex-
|
|
perimentation to get familiar with all the report modes.
|
|
|
|
There are three important option groups:
|
|
|
|
hledger balance [CALCULATIONMODE] [ACCUMULATIONMODE] [VALUATIONMODE]
|
|
...
|
|
|
|
Calculation mode
|
|
The basic calculation to perform for each table cell. It is one of:
|
|
|
|
o --sum : sum the posting amounts (default)
|
|
|
|
o --budget : sum the amounts, but also show the budget goal amount (for
|
|
each account/period)
|
|
|
|
o --valuechange : show the change in period-end historical balance val-
|
|
ues (caused by deposits, withdrawals, and/or market price fluctua-
|
|
tions)
|
|
|
|
o --gain : show the unrealised capital gain/loss, (the current valued
|
|
balance minus each amount's original cost)
|
|
|
|
o --count : show the count of postings
|
|
|
|
Accumulation mode
|
|
How amounts should accumulate across a report's subperiods/columns.
|
|
Another way to say it: which time period's postings should contribute
|
|
to each cell's calculation. It is one of:
|
|
|
|
o --change : calculate with postings from column start to column end,
|
|
ie "just this column". Typically used to see revenues/expenses.
|
|
(default for balance, cashflow, incomestatement)
|
|
|
|
o --cumulative : calculate with postings from report start to column
|
|
end, ie "previous columns plus this column". Typically used to show
|
|
changes accumulated since the report's start date. Not often used.
|
|
|
|
o --historical/-H : calculate with postings from journal start to col-
|
|
umn end, ie "all postings from before report start date until this
|
|
column's end". Typically used to see historical end balances of as-
|
|
sets/liabilities/equity. (default for balancesheet, balancesheete-
|
|
quity)
|
|
|
|
Valuation mode
|
|
Which kind of value or cost conversion should be applied, if any, be-
|
|
fore displaying the report. See Cost reporting and Value reporting for
|
|
more about conversions.
|
|
|
|
A valuation (or cost) mode can be selected with the --value option:
|
|
|
|
o no conversion : don't convert to cost or value (default)
|
|
|
|
o --value=cost[,COMM] : convert amounts to cost (then optionally to
|
|
some other commodity)
|
|
|
|
o --value=then[,COMM] : convert amounts to market value on transaction
|
|
dates
|
|
|
|
o --value=end[,COMM] : convert amounts to market value on period end
|
|
date(s)
|
|
(default with --valuechange, --gain)
|
|
|
|
o --value=now[,COMM] : convert amounts to market value on today's date
|
|
|
|
o --value=YYYY-MM-DD[,COMM] : convert amounts to market value on an-
|
|
other date
|
|
|
|
or with the legacy -B/-V/-X options, which are equivalent and easier to
|
|
type:
|
|
|
|
o -B/--cost : like --value=cost
|
|
|
|
o -V/--market : like --value=end
|
|
|
|
o -X COMM/--exchange COMM : like --value=end,COMM
|
|
|
|
Note that --value can also convert to cost, as a convenience; but actu-
|
|
ally --cost and --value are independent options, and could be used to-
|
|
gether.
|
|
|
|
Combining balance report modes
|
|
Most combinations of these modes should produce reasonable reports, but
|
|
if you find any that seem wrong or misleading, let us know. The fol-
|
|
lowing restrictions are applied:
|
|
|
|
o --valuechange implies --value=end
|
|
|
|
o --valuechange makes --change the default when used with the bal-
|
|
ancesheet/balancesheetequity commands
|
|
|
|
o --cumulative or --historical disables --row-total/-T
|
|
|
|
For reference, here is what the combinations of accumulation and valua-
|
|
tion show:
|
|
|
|
Valua- no valuation --value= then --value= end --value=
|
|
tion:> YYYY-MM-DD
|
|
Accumu- /now
|
|
lation:v
|
|
-----------------------------------------------------------------------------------
|
|
--change change in period sum of post- period-end DATE-value of
|
|
ing-date market value of change change in pe-
|
|
values in period in period riod
|
|
--cumu- change from re- sum of post- period-end DATE-value of
|
|
lative port start to ing-date market value of change change from
|
|
period end values from re- from report report start
|
|
port start to pe- start to period to period end
|
|
riod end end
|
|
--his- change from sum of post- period-end DATE-value of
|
|
torical journal start to ing-date market value of change change from
|
|
/-H period end (his- values from jour- from journal journal start
|
|
torical end bal- nal start to pe- start to period to period end
|
|
ance) riod end end
|
|
|
|
Budget report
|
|
The --budget report is like a regular balance report, but with two main
|
|
differences:
|
|
|
|
o Budget goals and performance percentages are also shown, in brackets
|
|
|
|
o Accounts which don't have budget goals are hidden by default.
|
|
|
|
This is useful for comparing planned and actual income, expenses, time
|
|
usage, etc.
|
|
|
|
Periodic transaction rules are used to define budget goals. For exam-
|
|
ple, here's a periodic rule defining monthly goals for bus travel and
|
|
food expenses:
|
|
|
|
;; Budget
|
|
~ monthly
|
|
(expenses:bus) $30
|
|
(expenses:food) $400
|
|
|
|
After recording some actual expenses,
|
|
|
|
;; Two months worth of expenses
|
|
2017-11-01
|
|
income $-1950
|
|
expenses:bus $35
|
|
expenses:food:groceries $310
|
|
expenses:food:dining $42
|
|
expenses:movies $38
|
|
assets:bank:checking
|
|
|
|
2017-12-01
|
|
income $-2100
|
|
expenses:bus $53
|
|
expenses:food:groceries $380
|
|
expenses:food:dining $32
|
|
expenses:gifts $100
|
|
assets:bank:checking
|
|
|
|
we can see a budget report like this:
|
|
|
|
$ hledger bal -M --budget
|
|
Budget performance in 2017-11-01..2017-12-31:
|
|
|
|
|| Nov Dec
|
|
===============++============================================
|
|
<unbudgeted> || $-425 $-565
|
|
expenses || $425 [ 99% of $430] $565 [131% of $430]
|
|
expenses:bus || $35 [117% of $30] $53 [177% of $30]
|
|
expenses:food || $352 [ 88% of $400] $412 [103% of $400]
|
|
---------------++--------------------------------------------
|
|
|| 0 [ 0% of $430] 0 [ 0% of $430]
|
|
|
|
This is "goal-based budgeting"; you define goals for accounts and peri-
|
|
ods, often recurring, and hledger shows performance relative to the
|
|
goals. This contrasts with "envelope budgeting", which is more de-
|
|
tailed and strict - useful when cash is tight, but also quite a bit
|
|
more work. https://plaintextaccounting.org/Budgeting has more on this
|
|
topic.
|
|
|
|
Using the budget report
|
|
Historically this report has been confusing and fragile. hledger's
|
|
version should be relatively robust and intuitive, but you may still
|
|
find surprises. Here are more notes to help with learning and trou-
|
|
bleshooting.
|
|
|
|
o In the above example, expenses:bus and expenses:food are shown be-
|
|
cause they have budget goals during the report period.
|
|
|
|
o Their parent expenses is also shown, with budget goals aggregated
|
|
from the children.
|
|
|
|
o The subaccounts expenses:food:groceries and expenses:food:dining are
|
|
not shown since they have no budget goal of their own, but they con-
|
|
tribute to expenses:food's actual amount.
|
|
|
|
o Unbudgeted accounts expenses:movies and expenses:gifts are also not
|
|
shown, but they contribute to expenses's actual amount.
|
|
|
|
o The other unbudgeted accounts income and assets:bank:checking are
|
|
grouped as <unbudgeted>.
|
|
|
|
o --depth or depth: can be used to limit report depth in the usual way
|
|
(but will not reveal unbudgeted subaccounts).
|
|
|
|
o Amounts are always inclusive of subaccounts (even in -l/--list mode).
|
|
|
|
o Numbers displayed in a --budget report will not always agree with the
|
|
totals, because of hidden unbudgeted accounts; this is normal.
|
|
-E/--empty can be used to reveal the hidden accounts.
|
|
|
|
o In the periodic rules used for setting budget goals, unbalanced post-
|
|
ings are convenient.
|
|
|
|
o You can filter budget reports with the usual queries, eg to focus on
|
|
particular accounts. It's common to restrict them to just expenses.
|
|
(The <unbudgeted> account is occasionally hard to exclude; this is
|
|
because of date surprises, discussed below.)
|
|
|
|
o When you have multiple currencies, you may want to convert them to
|
|
one (-X COMM --infer-market-prices) and/or show just one at a time
|
|
(cur:COMM). If you do need to show multiple currencies at once,
|
|
--layout bare can be helpful.
|
|
|
|
o You can "roll over" amounts (actual and budgeted) to the next period
|
|
with --cumulative.
|
|
|
|
See also: https://hledger.org/budgeting.html.
|
|
|
|
Budget date surprises
|
|
With small data, or when starting out, some of the generated budget
|
|
goal transaction dates might fall outside the report periods. Eg with
|
|
the following journal and report, the first period appears to have no
|
|
expenses:food budget. (Also the <unbudgeted> account should be ex-
|
|
cluded by the expenses query, but isn't.):
|
|
|
|
~ monthly in 2020
|
|
(expenses:food) $500
|
|
|
|
2020-01-15
|
|
expenses:food $400
|
|
assets:checking
|
|
|
|
$ hledger bal --budget expenses
|
|
Budget performance in 2020-01-15:
|
|
|
|
|| 2020-01-15
|
|
===============++====================
|
|
<unbudgeted> || $400
|
|
expenses:food || 0 [ 0% of $500]
|
|
---------------++--------------------
|
|
|| $400 [80% of $500]
|
|
|
|
In this case, the budget goal transactions are generated on first days
|
|
of of month (this can be seen with hledger print --forecast tag:gener-
|
|
ated expenses). Whereas the report period defaults to just the 15th
|
|
day of january (this can be seen from the report table's column head-
|
|
ings).
|
|
|
|
To fix this kind of thing, be more explicit about the report period
|
|
(and/or the periodic rules' dates). In this case, adding -b 2020 does
|
|
the trick.
|
|
|
|
Selecting budget goals
|
|
By default, the budget report uses all available periodic transaction
|
|
rules to generate goals. This includes rules with a different report
|
|
interval from your report. Eg if you have daily, weekly and monthly
|
|
periodic rules, all of these will contribute to the goals in a monthly
|
|
budget report.
|
|
|
|
You can select a subset of periodic rules by providing an argument to
|
|
the --budget flag. --budget=DESCPAT will match all periodic rules
|
|
whose description contains DESCPAT, a case-insensitive substring (not a
|
|
regular expression or query). This means you can give your periodic
|
|
rules descriptions (remember that two spaces are needed between period
|
|
expression and description), and then select from multiple budgets de-
|
|
fined in your journal.
|
|
|
|
Budgeting vs forecasting
|
|
--forecast and --budget both use the periodic transaction rules in the
|
|
journal to generate temporary transactions for reporting purposes.
|
|
However they are separate features - though you can use both at the
|
|
same time if you want. Here are some differences between them:
|
|
|
|
--forecast --budget
|
|
--------------------------------------------------------------------------
|
|
is a general option; it enables fore- is a balance command option; it
|
|
casting with all reports selects the balance report's
|
|
budget mode
|
|
generates visible transactions which generates invisible transactions
|
|
appear in reports which produce goal amounts
|
|
generates forecast transactions from generates budget goal transac-
|
|
after the last regular transaction, to tions throughout the report pe-
|
|
the end of the report period; or with riod, optionally restricted by
|
|
an argument --forecast=PERIODEXPR gen- periods specified in the peri-
|
|
erates them throughout the specified odic transaction rules
|
|
period, both optionally restricted by
|
|
periods specified in the periodic
|
|
transaction rules
|
|
uses all periodic rules uses all periodic rules; or with
|
|
an argument --budget=DESCPAT
|
|
uses just the rules matched by
|
|
DESCPAT
|
|
|
|
Balance report layout
|
|
The --layout option affects how balance and the other balance-like com-
|
|
mands show multi-commodity amounts and commodity symbols. It can im-
|
|
prove readability, for humans and/or machines (other software). It has
|
|
four possible values:
|
|
|
|
o --layout=wide[,WIDTH]: commodities are shown on a single line, op-
|
|
tionally elided to WIDTH
|
|
|
|
o --layout=tall: each commodity is shown on a separate line
|
|
|
|
o --layout=bare: commodity symbols are in their own column, amounts are
|
|
bare numbers
|
|
|
|
o --layout=tidy: data is normalised to easily-consumed "tidy" form,
|
|
with one row per data value. (This one is currently supported only
|
|
by the balance command.)
|
|
|
|
Here are the --layout modes supported by each output format Only CSV
|
|
output supports all of them:
|
|
|
|
- txt csv html json sql
|
|
-------------------------------------
|
|
wide Y Y Y
|
|
tall Y Y Y
|
|
bare Y Y Y
|
|
tidy Y
|
|
|
|
Examples:
|
|
|
|
Wide layout
|
|
With many commodities, reports can be very wide:
|
|
|
|
$ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -T -Y --layout=wide
|
|
Balance changes in 2012-01-01..2014-12-31:
|
|
|
|
|| 2012 2013 2014 Total
|
|
==================++====================================================================================================================================================================================================================
|
|
Assets:US:ETrade || 10.00 ITOT, 337.18 USD, 12.00 VEA, 106.00 VHT 70.00 GLD, 18.00 ITOT, -98.12 USD, 10.00 VEA, 18.00 VHT -11.00 ITOT, 4881.44 USD, 14.00 VEA, 170.00 VHT 70.00 GLD, 17.00 ITOT, 5120.50 USD, 36.00 VEA, 294.00 VHT
|
|
------------------++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|| 10.00 ITOT, 337.18 USD, 12.00 VEA, 106.00 VHT 70.00 GLD, 18.00 ITOT, -98.12 USD, 10.00 VEA, 18.00 VHT -11.00 ITOT, 4881.44 USD, 14.00 VEA, 170.00 VHT 70.00 GLD, 17.00 ITOT, 5120.50 USD, 36.00 VEA, 294.00 VHT
|
|
|
|
A width limit reduces the width, but some commodities will be hidden:
|
|
|
|
$ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -T -Y --layout=wide,32
|
|
Balance changes in 2012-01-01..2014-12-31:
|
|
|
|
|| 2012 2013 2014 Total
|
|
==================++===========================================================================================================================
|
|
Assets:US:ETrade || 10.00 ITOT, 337.18 USD, 2 more.. 70.00 GLD, 18.00 ITOT, 3 more.. -11.00 ITOT, 3 more.. 70.00 GLD, 17.00 ITOT, 3 more..
|
|
------------------++---------------------------------------------------------------------------------------------------------------------------
|
|
|| 10.00 ITOT, 337.18 USD, 2 more.. 70.00 GLD, 18.00 ITOT, 3 more.. -11.00 ITOT, 3 more.. 70.00 GLD, 17.00 ITOT, 3 more..
|
|
|
|
Tall layout
|
|
Each commodity gets a new line (may be different in each column), and
|
|
account names are repeated:
|
|
|
|
$ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -T -Y --layout=tall
|
|
Balance changes in 2012-01-01..2014-12-31:
|
|
|
|
|| 2012 2013 2014 Total
|
|
==================++==================================================
|
|
Assets:US:ETrade || 10.00 ITOT 70.00 GLD -11.00 ITOT 70.00 GLD
|
|
Assets:US:ETrade || 337.18 USD 18.00 ITOT 4881.44 USD 17.00 ITOT
|
|
Assets:US:ETrade || 12.00 VEA -98.12 USD 14.00 VEA 5120.50 USD
|
|
Assets:US:ETrade || 106.00 VHT 10.00 VEA 170.00 VHT 36.00 VEA
|
|
Assets:US:ETrade || 18.00 VHT 294.00 VHT
|
|
------------------++--------------------------------------------------
|
|
|| 10.00 ITOT 70.00 GLD -11.00 ITOT 70.00 GLD
|
|
|| 337.18 USD 18.00 ITOT 4881.44 USD 17.00 ITOT
|
|
|| 12.00 VEA -98.12 USD 14.00 VEA 5120.50 USD
|
|
|| 106.00 VHT 10.00 VEA 170.00 VHT 36.00 VEA
|
|
|| 18.00 VHT 294.00 VHT
|
|
|
|
Bare layout
|
|
Commodity symbols are kept in one column, each commodity has its own
|
|
row, amounts are bare numbers, account names are repeated:
|
|
|
|
$ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -T -Y --layout=bare
|
|
Balance changes in 2012-01-01..2014-12-31:
|
|
|
|
|| Commodity 2012 2013 2014 Total
|
|
==================++=============================================
|
|
Assets:US:ETrade || GLD 0 70.00 0 70.00
|
|
Assets:US:ETrade || ITOT 10.00 18.00 -11.00 17.00
|
|
Assets:US:ETrade || USD 337.18 -98.12 4881.44 5120.50
|
|
Assets:US:ETrade || VEA 12.00 10.00 14.00 36.00
|
|
Assets:US:ETrade || VHT 106.00 18.00 170.00 294.00
|
|
------------------++---------------------------------------------
|
|
|| GLD 0 70.00 0 70.00
|
|
|| ITOT 10.00 18.00 -11.00 17.00
|
|
|| USD 337.18 -98.12 4881.44 5120.50
|
|
|| VEA 12.00 10.00 14.00 36.00
|
|
|| VHT 106.00 18.00 170.00 294.00
|
|
|
|
Bare layout also affects CSV output, which is useful for producing data
|
|
that is easier to consume, eg for making charts:
|
|
|
|
$ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -O csv --layout=bare
|
|
"account","commodity","balance"
|
|
"Assets:US:ETrade","GLD","70.00"
|
|
"Assets:US:ETrade","ITOT","17.00"
|
|
"Assets:US:ETrade","USD","5120.50"
|
|
"Assets:US:ETrade","VEA","36.00"
|
|
"Assets:US:ETrade","VHT","294.00"
|
|
"Total:","GLD","70.00"
|
|
"Total:","ITOT","17.00"
|
|
"Total:","USD","5120.50"
|
|
"Total:","VEA","36.00"
|
|
"Total:","VHT","294.00"
|
|
|
|
Bare layout will sometimes display an extra row for the no-symbol com-
|
|
modity, because of zero amounts (hledger treats zeroes as commod-
|
|
ity-less, usually). This can break hledger-bar confusingly
|
|
(workaround: add a cur: query to exclude the no-symbol row).
|
|
|
|
Tidy layout
|
|
This produces normalised "tidy data" (see
|
|
https://cran.r-project.org/web/packages/tidyr/vignettes/tidy-data.html)
|
|
where every variable has its own column and each row represents a sin-
|
|
gle data point. This is the easiest kind of data for other software to
|
|
consume:
|
|
|
|
$ hledger -f examples/bcexample.hledger bal assets:us:etrade -3 -Y -O csv --layout=tidy
|
|
"account","period","start_date","end_date","commodity","value"
|
|
"Assets:US:ETrade","2012","2012-01-01","2012-12-31","GLD","0"
|
|
"Assets:US:ETrade","2012","2012-01-01","2012-12-31","ITOT","10.00"
|
|
"Assets:US:ETrade","2012","2012-01-01","2012-12-31","USD","337.18"
|
|
"Assets:US:ETrade","2012","2012-01-01","2012-12-31","VEA","12.00"
|
|
"Assets:US:ETrade","2012","2012-01-01","2012-12-31","VHT","106.00"
|
|
"Assets:US:ETrade","2013","2013-01-01","2013-12-31","GLD","70.00"
|
|
"Assets:US:ETrade","2013","2013-01-01","2013-12-31","ITOT","18.00"
|
|
"Assets:US:ETrade","2013","2013-01-01","2013-12-31","USD","-98.12"
|
|
"Assets:US:ETrade","2013","2013-01-01","2013-12-31","VEA","10.00"
|
|
"Assets:US:ETrade","2013","2013-01-01","2013-12-31","VHT","18.00"
|
|
"Assets:US:ETrade","2014","2014-01-01","2014-12-31","GLD","0"
|
|
"Assets:US:ETrade","2014","2014-01-01","2014-12-31","ITOT","-11.00"
|
|
"Assets:US:ETrade","2014","2014-01-01","2014-12-31","USD","4881.44"
|
|
"Assets:US:ETrade","2014","2014-01-01","2014-12-31","VEA","14.00"
|
|
"Assets:US:ETrade","2014","2014-01-01","2014-12-31","VHT","170.00"
|
|
|
|
Balance report output
|
|
As noted in Output format, if you choose HTML output (by using -O html
|
|
or -o somefile.html), you can create a hledger.css file in the same di-
|
|
rectory to customise the report's appearance.
|
|
|
|
The HTML and FODS output formats can generate hyperlinks to a
|
|
hledger-web register view for each account and period. E.g. if your
|
|
hledger-web server is reachable at http://localhost:5000 then you might
|
|
run the balance command with the extra option --base-url=http://local-
|
|
host:5000. You can also produce relative links, like
|
|
--base-url="some/path" or --base-url="".)
|
|
|
|
Some useful balance reports
|
|
Some frequently used balance options/reports are:
|
|
|
|
o bal -M revenues expenses
|
|
Show revenues/expenses in each month. Also available as the incomes-
|
|
tatement command.
|
|
|
|
o bal -M -H assets liabilities
|
|
Show historical asset/liability balances at each month end. Also
|
|
available as the balancesheet command.
|
|
|
|
o bal -M -H assets liabilities equity
|
|
Show historical asset/liability/equity balances at each month end.
|
|
Also available as the balancesheetequity command.
|
|
|
|
o bal -M assets not:receivable
|
|
Show changes to liquid assets in each month. Also available as the
|
|
cashflow command.
|
|
|
|
Also:
|
|
|
|
o bal -M expenses -2 -SA
|
|
Show monthly expenses summarised to depth 2 and sorted by average
|
|
amount.
|
|
|
|
o bal -M --budget expenses
|
|
Show monthly expenses and budget goals.
|
|
|
|
o bal -M --valuechange investments
|
|
Show monthly change in market value of investment assets.
|
|
|
|
o bal investments --valuechange -D date:lastweek amt:'>1000' -STA
|
|
[--invert]
|
|
Show top gainers [or losers] last week
|
|
|
|
roi
|
|
Shows the time-weighted (TWR) and money-weighted (IRR) rate of return
|
|
on your investments.
|
|
|
|
Flags:
|
|
--cashflow show all amounts that were used to compute
|
|
returns
|
|
--investment=QUERY query to select your investment transactions
|
|
--profit-loss=QUERY --pnl query to select profit-and-loss or
|
|
appreciation/valuation transactions
|
|
|
|
At a minimum, you need to supply a query (which could be just an ac-
|
|
count name) to select your investment(s) with --inv, and another query
|
|
to identify your profit and loss transactions with --pnl.
|
|
|
|
If you do not record changes in the value of your investment manually,
|
|
or do not require computation of time-weighted return (TWR), --pnl
|
|
could be an empty query (--pnl "" or --pnl STR where STR does not match
|
|
any of your accounts).
|
|
|
|
This command will compute and display the internalized rate of return
|
|
(IRR, also known as money-weighted rate of return) and time-weighted
|
|
rate of return (TWR) for your investments for the time period re-
|
|
quested. IRR is always annualized due to the way it is computed, but
|
|
TWR is reported both as a rate over the chosen reporting period and as
|
|
an annual rate.
|
|
|
|
Price directives will be taken into account if you supply appropriate
|
|
--cost or --value flags (see VALUATION).
|
|
|
|
Note, in some cases this report can fail, for these reasons:
|
|
|
|
o Error (NotBracketed): No solution for Internal Rate of Return (IRR).
|
|
Possible causes: IRR is huge (>1000000%), balance of investment be-
|
|
comes negative at some point in time.
|
|
|
|
o Error (SearchFailed): Failed to find solution for Internal Rate of
|
|
Return (IRR). Either search does not converge to a solution, or con-
|
|
verges too slowly.
|
|
|
|
Examples:
|
|
|
|
o Using roi to compute total return of investment in stocks:
|
|
https://github.com/simonmichael/hledger/blob/master/examples/invest-
|
|
ing/roi-unrealised.ledger
|
|
|
|
o Cookbook > Return on Investment: https://hledger.org/roi.html
|
|
|
|
Spaces and special characters in --inv and --pnl
|
|
Note that --inv and --pnl's argument is a query, and queries could have
|
|
several space-separated terms (see QUERIES).
|
|
|
|
To indicate that all search terms form single command-line argument,
|
|
you will need to put them in quotes (see Special characters):
|
|
|
|
$ hledger roi --inv 'term1 term2 term3 ...'
|
|
|
|
If any query terms contain spaces themselves, you will need an extra
|
|
level of nested quoting, eg:
|
|
|
|
$ hledger roi --inv="'Assets:Test 1'" --pnl="'Equity:Unrealized Profit and Loss'"
|
|
|
|
Semantics of --inv and --pnl
|
|
Query supplied to --inv has to match all transactions that are related
|
|
to your investment. Transactions not matching --inv will be ignored.
|
|
|
|
In these transactions, ROI will conside postings that match --inv to be
|
|
"investment postings" and other postings (not matching --inv) will be
|
|
sorted into two categories: "cash flow" and "profit and loss", as ROI
|
|
needs to know which part of the investment value is your contributions
|
|
and which is due to the return on investment.
|
|
|
|
o "Cash flow" is depositing or withdrawing money, buying or selling as-
|
|
sets, or otherwise converting between your investment commodity and
|
|
any other commodity. Example:
|
|
|
|
2019-01-01 Investing in Snake Oil
|
|
assets:cash -$100
|
|
investment:snake oil
|
|
|
|
2020-01-01 Selling my Snake Oil
|
|
assets:cash $10
|
|
investment:snake oil = 0
|
|
|
|
o "Profit and loss" is change in the value of your investment:
|
|
|
|
2019-06-01 Snake Oil falls in value
|
|
investment:snake oil = $57
|
|
equity:unrealized profit or loss
|
|
|
|
All non-investment postings are assumed to be "cash flow", unless they
|
|
match --pnl query. Changes in value of your investment due to "profit
|
|
and loss" postings will be considered as part of your investment re-
|
|
turn.
|
|
|
|
Example: if you use --inv snake --pnl equity:unrealized, then postings
|
|
in the example below would be classifed as:
|
|
|
|
2019-01-01 Snake Oil #1
|
|
assets:cash -$100 ; cash flow posting
|
|
investment:snake oil ; investment posting
|
|
|
|
2019-03-01 Snake Oil #2
|
|
equity:unrealized pnl -$100 ; profit and loss posting
|
|
snake oil ; investment posting
|
|
|
|
2019-07-01 Snake Oil #3
|
|
equity:unrealized pnl ; profit and loss posting
|
|
cash -$100 ; cash flow posting
|
|
snake oil $50 ; investment posting
|
|
|
|
IRR and TWR explained
|
|
"ROI" stands for "return on investment". Traditionally this was com-
|
|
puted as a difference between current value of investment and its ini-
|
|
tial value, expressed in percentage of the initial value.
|
|
|
|
However, this approach is only practical in simple cases, where invest-
|
|
ments receives no in-flows or out-flows of money, and where rate of
|
|
growth is fixed over time. For more complex scenarios you need differ-
|
|
ent ways to compute rate of return, and this command implements two of
|
|
them: IRR and TWR.
|
|
|
|
Internal rate of return, or "IRR" (also called "money-weighted rate of
|
|
return") takes into account effects of in-flows and out-flows, and the
|
|
time between them. Investment at a particular fixed interest rate is
|
|
going to give you more interest than the same amount invested at the
|
|
same interest rate, but made later in time. If you are withdrawing
|
|
from your investment, your future gains would be smaller (in absolute
|
|
numbers), and will be a smaller percentage of your initial investment,
|
|
so your IRR will be smaller. And if you are adding to your investment,
|
|
you will receive bigger absolute gains, which will be a bigger percent-
|
|
age of your initial investment, so your IRR will be larger.
|
|
|
|
As mentioned before, in-flows and out-flows would be any cash that you
|
|
personally put in or withdraw, and for the "roi" command, these are the
|
|
postings that match the query in the--inv argument and NOT match the
|
|
query in the--pnl argument.
|
|
|
|
If you manually record changes in the value of your investment as
|
|
transactions that balance them against "profit and loss" (or "unreal-
|
|
ized gains") account or use price directives, then in order for IRR to
|
|
compute the precise effect of your in-flows and out-flows on the rate
|
|
of return, you will need to record the value of your investement on or
|
|
close to the days when in- or out-flows occur.
|
|
|
|
In technical terms, IRR uses the same approach as computation of net
|
|
present value, and tries to find a discount rate that makes net present
|
|
value of all the cash flows of your investment to add up to zero. This
|
|
could be hard to wrap your head around, especially if you haven't done
|
|
discounted cash flow analysis before. Implementation of IRR in hledger
|
|
should produce results that match the =XIRR formula in Excel.
|
|
|
|
Second way to compute rate of return that roi command implements is
|
|
called "time-weighted rate of return" or "TWR". Like IRR, it will ac-
|
|
count for the effect of your in-flows and out-flows, but unlike IRR it
|
|
will try to compute the true rate of return of the underlying asset,
|
|
compensating for the effect that deposits and withdrawas have on the
|
|
apparent rate of growth of your investment.
|
|
|
|
TWR represents your investment as an imaginary "unit fund" where
|
|
in-flows/ out-flows lead to buying or selling "units" of your invest-
|
|
ment and changes in its value change the value of "investment unit".
|
|
Change in "unit price" over the reporting period gives you rate of re-
|
|
turn of your investment, and make TWR less sensitive than IRR to the
|
|
effects of cash in-flows and out-flows.
|
|
|
|
References:
|
|
|
|
o Explanation of rate of return
|
|
|
|
o Explanation of IRR
|
|
|
|
o Explanation of TWR
|
|
|
|
o IRR vs TWR
|
|
|
|
o Examples of computing IRR and TWR and discussion of the limitations
|
|
of both metrics
|
|
|
|
Chart commands
|
|
activity
|
|
Show an ascii barchart of posting counts per interval.
|
|
|
|
Flags:
|
|
no command-specific flags
|
|
|
|
The activity command displays an ascii histogram showing transaction
|
|
counts by day, week, month or other reporting interval (by day is the
|
|
default). With query arguments, it counts only matched transactions.
|
|
|
|
Examples:
|
|
|
|
$ hledger activity --quarterly
|
|
2008-01-01 **
|
|
2008-04-01 *******
|
|
2008-07-01
|
|
2008-10-01 **
|
|
|
|
Data generation commands
|
|
close
|
|
(equity)
|
|
|
|
close prints several kinds of "closing" and/or "opening" transactions,
|
|
useful in various situations: migrating balances to a new journal file,
|
|
retaining earnings into equity, consolidating balances, viewing lot
|
|
costs.. Like print, it prints valid journal entries. You can copy
|
|
these into your journal file(s) when you are happy with how they look.
|
|
|
|
Flags:
|
|
--clopen[=TAGVAL] show closing and opening balances transactions,
|
|
for AL accounts by default
|
|
--close[=TAGVAL] show just a closing balances transaction
|
|
--open[=TAGVAL] show just an opening balances transaction
|
|
--assert[=TAGVAL] show a balance assertions transaction
|
|
--assign[=TAGVAL] show a balance assignments transaction
|
|
--retain[=TAGVAL] show a retain earnings transaction, for RX
|
|
accounts by default
|
|
-x --explicit show all amounts explicitly
|
|
--show-costs show amounts with different costs separately
|
|
--interleaved show source and destination postings together
|
|
--assertion-type=TYPE =, ==, =* or ==*
|
|
--close-desc=DESC set closing transaction's description
|
|
--close-acct=ACCT set closing transaction's destination account
|
|
--open-desc=DESC set opening transaction's description
|
|
--open-acct=ACCT set opening transaction's source account
|
|
--round=TYPE how much rounding or padding should be done when
|
|
displaying amounts ?
|
|
none - show original decimal digits,
|
|
as in journal (default)
|
|
soft - just add or remove decimal zeros
|
|
to match precision
|
|
hard - round posting amounts to precision
|
|
(can unbalance transactions)
|
|
all - also round cost amounts to precision
|
|
(can unbalance transactions)
|
|
|
|
close has six modes, selected by choosing one of the mode flags:
|
|
--clopen, --close (default), --open, --assert, --assign, or --retain.
|
|
They are all doing the same kind of operation, but with different de-
|
|
faults for different situations.
|
|
|
|
The journal entries generated by close will have a clopen: tag, which
|
|
is helpful when you want to exclude them from reports. If the main
|
|
journal file name contains a number, the tag's value will be that base
|
|
file name with the number incremented. Eg if the journal file is
|
|
2025.journal, the tag will be clopen:2026. Or you can set the tag
|
|
value by providing an argument to the mode flag. Eg --close=foo or
|
|
--clopen=2025-main.
|
|
|
|
close --clopen
|
|
This is useful if migrating balances to a new journal file at the start
|
|
of a new year. It prints a "closing balances" transaction that zeroes
|
|
out account balances (Asset and Liability accounts, by default), and an
|
|
opposite "opening balances" transaction that restores them again. Typ-
|
|
ically, you would run
|
|
|
|
hledger close --clopen -e NEWYEAR >> $LEDGER_FILE
|
|
|
|
and then move the opening transaction from the old file to the new file
|
|
(and probably also update your LEDGER_FILE environment variable).
|
|
|
|
Why might you do this ? If your reports are fast, you may not need it.
|
|
But at some point you will probably want to partition your data by
|
|
time, for performance or data integrity or regulatory reasons. A new
|
|
file or set of files per year is common. Then, having each file/file-
|
|
set "bookended" with opening and closing balance transactions will al-
|
|
low you to freely pick and choose which files to read - just the cur-
|
|
rent year, any past year, any sequence of years, or all of them - while
|
|
showing correct account balances in each case. The earliest opening
|
|
balances transaction sets correct starting balances, and any later
|
|
closing/opening pairs will harmlessly cancel each other out.
|
|
|
|
The balances will be transferred to and from equity:opening/closing
|
|
balances by default. You can override this by using --close-acct
|
|
and/or --open-acct.
|
|
|
|
You can select a different set of accounts to close/open by providing
|
|
an account query. Eg to add Equity accounts, provide arguments like
|
|
assets liabilities equity or type:ALE. When migrating to a new file,
|
|
you'll usually want to bring along the AL or ALE accounts, but not the
|
|
RX accounts (Revenue, Expense).
|
|
|
|
Assertions will be added indicating and checking the new balances of
|
|
the closed/opened accounts.
|
|
|
|
close --close
|
|
This prints just the closing balances transaction of --clopen. It is
|
|
the default if you don't specify a mode.
|
|
|
|
More customisation options are described below. Among other things,
|
|
you can use close --close to generate a transaction moving the balances
|
|
from any set of accounts, to a different account. (If you need to move
|
|
just a portion of the balance, see hledger-move.)
|
|
|
|
close --open
|
|
This prints just the opening balances transaction of --clopen. (It is
|
|
similar to Ledger's equity command.)
|
|
|
|
close --assert
|
|
This prints a transaction that asserts the account balances as they are
|
|
on the end date (and adds an assert: tag). It could be useful as docu-
|
|
mention and to guard against changes.
|
|
|
|
close --assign
|
|
This prints a transaction that assigns the account balances as they are
|
|
on the end date (and adds an "assign:" tag). Unlike balance asser-
|
|
tions, assignments will post changes to balances as needed to reach the
|
|
specified amounts.
|
|
|
|
This is another way to set starting balances when migrating to a new
|
|
file, and it will set them correctly even in the presence of earlier
|
|
files which do not have a closing balances transaction. However, it
|
|
can hide errors, and disturb the accounting equation, so --clopen is
|
|
usually recommended.
|
|
|
|
close --retain
|
|
This is like --close, but it closes Revenue and Expense account bal-
|
|
ances by default. They will be transferred to equity:retained earn-
|
|
ings, or another account specified with --close-acct.
|
|
|
|
Revenues and expenses correspond to changes in equity. They are cate-
|
|
gorised separately for reporting purposes, but traditionally at the end
|
|
of each accounting period, businesses consolidate them into equity,
|
|
This is called "retaining earnings", or "closing the books".
|
|
|
|
In personal accounting, there's not much reason to do this, and most
|
|
people don't. (One reason to do it is to help the balancesheetequity
|
|
report show a zero total, demonstrating that the accounting equation
|
|
(A-L=E) is satisfied.)
|
|
|
|
close customisation
|
|
In all modes, the following things can be overridden:
|
|
|
|
o the accounts to be closed/opened, with account query arguments
|
|
|
|
o the closing/opening dates, with -e OPENDATE
|
|
|
|
o the balancing account, with --close-acct=ACCT and/or --open-acct=ACCT
|
|
|
|
o the transaction descriptions, with --close-desc=DESC and
|
|
--open-desc=DESC
|
|
|
|
o the transactions' clopen tag value, with a TAGVAL argument for the
|
|
mode flag (see above).
|
|
|
|
By default, the closing date is yesterday, or the journal's end date,
|
|
whichever is later; and the opening date is always one day after the
|
|
closing date. You can change these by specifying a report end date;
|
|
the closing date will be the last day of the report period. Eg -e 2024
|
|
means "close on 2023-12-31, open on 2024-01-01".
|
|
|
|
With --x/--explicit, the balancing amount will be shown explicitly, and
|
|
if it involves multiple commodities, a separate posting will be gener-
|
|
ated for each of them (similar to print -x).
|
|
|
|
With --interleaved, each individual transfer is shown with source and
|
|
destination postings next to each other (perhaps useful for trou-
|
|
bleshooting).
|
|
|
|
With --show-costs, balances' costs are also shown, with different costs
|
|
kept separate. This may generate very large journal entries, if you
|
|
have many currency conversions or investment transactions. close
|
|
--show-costs is currently the best way to view investment lots with
|
|
hledger. (To move or dispose of lots, see the more capable
|
|
hledger-move script.)
|
|
|
|
close and balance assertions
|
|
close adds balance assertions verifying that the accounts have been re-
|
|
set to zero in a closing transaction or restored to their previous bal-
|
|
ances in an opening transaction. These provide useful error checking,
|
|
but you can ignore them temporarily with -I, or remove them if you pre-
|
|
fer.
|
|
|
|
Single-commodity, subaccount-exclusive balance assertions (=) are gen-
|
|
erated by default. This can be changed with --assertion-type='==*'
|
|
(eg).
|
|
|
|
When running close you should probably avoid using -C, -R, status:
|
|
(filtering by status or realness) or --auto (generating postings),
|
|
since the generated balance assertions would then require these.
|
|
|
|
Transactions with multiple dates (eg posting dates) spanning the file
|
|
boundary also can disrupt the balance assertions:
|
|
|
|
2023-12-30 a purchase made in december, cleared in january
|
|
expenses:food 5
|
|
assets:bank:checking -5 ; date: 2023-01-02
|
|
|
|
To solve this you can transfer the money to and from a temporary ac-
|
|
count, splitting the multi-day transaction into two single-day transac-
|
|
tions:
|
|
|
|
; in 2022.journal:
|
|
2022-12-30 a purchase made in december, cleared in january
|
|
expenses:food 5
|
|
equity:pending -5
|
|
|
|
; in 2023.journal:
|
|
2023-01-02 last year's transaction cleared
|
|
equity:pending 5 = 0
|
|
assets:bank:checking -5
|
|
|
|
close examples
|
|
Retain earnings
|
|
Record 2022's revenues/expenses as retained earnings on 2022-12-31, ap-
|
|
pending the generated transaction to the journal:
|
|
|
|
$ hledger close --retain -f 2022.journal -p 2022 >> 2022.journal
|
|
|
|
After this, to see 2022's revenues and expenses you must exclude the
|
|
retain earnings transaction:
|
|
|
|
$ hledger -f 2022.journal is not:desc:'retain earnings'
|
|
|
|
Migrate balances to a new file
|
|
Close assets/liabilities on 2022-12-31 and re-open them on 2023-01-01:
|
|
|
|
$ hledger close --clopen -f 2022.journal -p 2022
|
|
# copy/paste the closing transaction to the end of 2022.journal
|
|
# copy/paste the opening transaction to the start of 2023.journal
|
|
|
|
After this, to see 2022's end-of-year balances you must exclude the
|
|
closing balances transaction:
|
|
|
|
$ hledger -f 2022.journal bs not:desc:'closing balances'
|
|
|
|
For more flexibility, it helps to tag closing and opening transactions
|
|
with eg clopen:NEWYEAR, then you can ensure correct balances by exclud-
|
|
ing all opening/closing transactions except the first, like so:
|
|
|
|
$ hledger bs -Y -f 2021.j -f 2022.j -f 2023.j expr:'tag:clopen=2021 or not tag:clopen'
|
|
$ hledger bs -Y -f 2021.j -f 2022.j expr:'tag:clopen=2021 or not tag:clopen'
|
|
$ hledger bs -Y -f 2022.j -f 2023.j expr:'tag:clopen=2022 or not tag:clopen'
|
|
$ hledger bs -Y -f 2021.j expr:'tag:clopen=2021 or not tag:clopen'
|
|
$ hledger bs -Y -f 2022.j expr:'tag:clopen=2022 or not tag:clopen'
|
|
$ hledger bs -Y -f 2023.j # unclosed file, no query needed
|
|
|
|
More detailed close examples
|
|
See examples/multi-year.
|
|
|
|
rewrite
|
|
Print all transactions, rewriting the postings of matched transactions.
|
|
For now the only rewrite available is adding new postings, like print
|
|
--auto.
|
|
|
|
Flags:
|
|
--add-posting='ACCT AMTEXPR' add a posting to ACCT, which may be
|
|
parenthesised. AMTEXPR is either a literal
|
|
amount, or *N which means the transaction's
|
|
first matched amount multiplied by N (a
|
|
decimal number). Two spaces separate ACCT
|
|
and AMTEXPR.
|
|
--diff generate diff suitable as an input for
|
|
patch tool
|
|
|
|
This is a start at a generic rewriter of transaction entries. It reads
|
|
the default journal and prints the transactions, like print, but adds
|
|
one or more specified postings to any transactions matching QUERY. The
|
|
posting amounts can be fixed, or a multiplier of the existing transac-
|
|
tion's first posting amount.
|
|
|
|
Examples:
|
|
|
|
$ hledger-rewrite.hs ^income --add-posting '(liabilities:tax) *.33 ; income tax' --add-posting '(reserve:gifts) $100'
|
|
$ hledger-rewrite.hs expenses:gifts --add-posting '(reserve:gifts) *-1"'
|
|
$ hledger-rewrite.hs -f rewrites.hledger
|
|
|
|
rewrites.hledger may consist of entries like:
|
|
|
|
= ^income amt:<0 date:2017
|
|
(liabilities:tax) *0.33 ; tax on income
|
|
(reserve:grocery) *0.25 ; reserve 25% for grocery
|
|
(reserve:) *0.25 ; reserve 25% for grocery
|
|
|
|
Note the single quotes to protect the dollar sign from bash, and the
|
|
two spaces between account and amount.
|
|
|
|
More:
|
|
|
|
$ hledger rewrite [QUERY] --add-posting "ACCT AMTEXPR" ...
|
|
$ hledger rewrite ^income --add-posting '(liabilities:tax) *.33'
|
|
$ hledger rewrite expenses:gifts --add-posting '(budget:gifts) *-1"'
|
|
$ hledger rewrite ^income --add-posting '(budget:foreign currency) *0.25 JPY; diversify'
|
|
|
|
Argument for --add-posting option is a usual posting of transaction
|
|
with an exception for amount specification. More precisely, you can
|
|
use '*' (star symbol) before the amount to indicate that that this is a
|
|
factor for an amount of original matched posting. If the amount in-
|
|
cludes a commodity name, the new posting amount will be in the new com-
|
|
modity; otherwise, it will be in the matched posting amount's commod-
|
|
ity.
|
|
|
|
Re-write rules in a file
|
|
During the run this tool will execute so called "Automated Transac-
|
|
tions" found in any journal it process. I.e instead of specifying this
|
|
operations in command line you can put them in a journal file.
|
|
|
|
$ rewrite-rules.journal
|
|
|
|
Make contents look like this:
|
|
|
|
= ^income
|
|
(liabilities:tax) *.33
|
|
|
|
= expenses:gifts
|
|
budget:gifts *-1
|
|
assets:budget *1
|
|
|
|
Note that '=' (equality symbol) that is used instead of date in trans-
|
|
actions you usually write. It indicates the query by which you want to
|
|
match the posting to add new ones.
|
|
|
|
$ hledger rewrite -f input.journal -f rewrite-rules.journal > rewritten-tidy-output.journal
|
|
|
|
This is something similar to the commands pipeline:
|
|
|
|
$ hledger rewrite -f input.journal '^income' --add-posting '(liabilities:tax) *.33' \
|
|
| hledger rewrite -f - expenses:gifts --add-posting 'budget:gifts *-1' \
|
|
--add-posting 'assets:budget *1' \
|
|
> rewritten-tidy-output.journal
|
|
|
|
It is important to understand that relative order of such entries in
|
|
journal is important. You can re-use result of previously added post-
|
|
ings.
|
|
|
|
Diff output format
|
|
To use this tool for batch modification of your journal files you may
|
|
find useful output in form of unified diff.
|
|
|
|
$ hledger rewrite --diff -f examples/sample.journal '^income' --add-posting '(liabilities:tax) *.33'
|
|
|
|
Output might look like:
|
|
|
|
--- /tmp/examples/sample.journal
|
|
+++ /tmp/examples/sample.journal
|
|
@@ -18,3 +18,4 @@
|
|
2008/01/01 income
|
|
- assets:bank:checking $1
|
|
+ assets:bank:checking $1
|
|
income:salary
|
|
+ (liabilities:tax) 0
|
|
@@ -22,3 +23,4 @@
|
|
2008/06/01 gift
|
|
- assets:bank:checking $1
|
|
+ assets:bank:checking $1
|
|
income:gifts
|
|
+ (liabilities:tax) 0
|
|
|
|
If you'll pass this through patch tool you'll get transactions contain-
|
|
ing the posting that matches your query be updated. Note that multiple
|
|
files might be update according to list of input files specified via
|
|
--file options and include directives inside of these files.
|
|
|
|
Be careful. Whole transaction being re-formatted in a style of output
|
|
from hledger print.
|
|
|
|
See also:
|
|
|
|
https://github.com/simonmichael/hledger/issues/99
|
|
|
|
rewrite vs. print --auto
|
|
This command predates print --auto, and currently does much the same
|
|
thing, but with these differences:
|
|
|
|
o with multiple files, rewrite lets rules in any file affect all other
|
|
files. print --auto uses standard directive scoping; rules affect
|
|
only child files.
|
|
|
|
o rewrite's query limits which transactions can be rewritten; all are
|
|
printed. print --auto's query limits which transactions are printed.
|
|
|
|
o rewrite applies rules specified on command line or in the journal.
|
|
print --auto applies rules specified in the journal.
|
|
|
|
Maintenance commands
|
|
check
|
|
Check for various kinds of errors in your data.
|
|
|
|
Flags:
|
|
no command-specific flags
|
|
|
|
hledger provides a number of built-in correctness checks to help vali-
|
|
date your data and prevent errors. Some are run automatically, some
|
|
when you enable --strict mode; or you can run any of them on demand by
|
|
providing them as arguments to the check command. check produces no
|
|
output and a zero exit code if all is well. Eg:
|
|
|
|
hledger check # run basic checks
|
|
hledger check -s # run basic and strict checks
|
|
hledger check ordereddates payees # run basic checks and two others
|
|
|
|
If you are an Emacs user, you can also configure flycheck-hledger to
|
|
run these checks, providing instant feedback as you edit the journal.
|
|
|
|
Here are the checks currently available. They are generally checked in
|
|
the order they are shown here, and only the first failure will be re-
|
|
ported.
|
|
|
|
Basic checks
|
|
These important checks are performed by default, by almost all hledger
|
|
commands:
|
|
|
|
o parseable - data files are in a supported format, with no syntax er-
|
|
rors and no invalid include directives. This ensures that all files
|
|
exist and are readable.
|
|
|
|
o autobalanced - all transactions are balanced, after automatically in-
|
|
ferring missing amounts and conversion rates and then converting
|
|
amounts to cost. This ensures that each transaction's journal entry
|
|
is well formed.
|
|
|
|
o assertions - all balance assertions in the journal are passing. Bal-
|
|
ance assertions are a strong defense against errors, catching many
|
|
problems. This check is on by default, but if it gets in your way,
|
|
you can disable it temporarily with -I/--ignore-assertions, or as a
|
|
default by adding that flag to your config file. (Then use
|
|
-s/--strict or hledger check assertions when you want to enable it).
|
|
|
|
Strict checks
|
|
When the -s/--strict flag is used (AKA strict mode), all commands will
|
|
perform the following additional checks (and assertions, above). These
|
|
provide extra error-catching power to help you keep your data clean and
|
|
correct:
|
|
|
|
o balanced - like autobalanced, but implicit conversions between com-
|
|
modities are not allowed; all conversion transactions must use cost
|
|
notation or equity postings. This prevents wrong conversions caused
|
|
by typos.
|
|
|
|
o commodities - all commodity symbols used must be declared. This
|
|
guards against mistyping or omitting commodity symbols.
|
|
|
|
o accounts - all account names used must be declared. This prevents
|
|
the use of mis-spelled or outdated account names.
|
|
|
|
Other checks
|
|
These are not wanted by everyone, but can be run using the check com-
|
|
mand:
|
|
|
|
o tags - all tags used must be declared. This prevents mis-spelled tag
|
|
names. Note hledger fairly often finds unintended tags in comments.
|
|
|
|
o payees - all payees used in transactions must be declared. This will
|
|
force you to declare any new payee name before using it. Most people
|
|
will probably find this a bit too strict.
|
|
|
|
o ordereddates - within each file, transactions must be ordered by
|
|
date. This is a simple and effective error catcher. It's not in-
|
|
cluded in strict mode, but you can add it by running hledger check -s
|
|
ordereddates. If enabled, this check is performed before balance as-
|
|
sertions.
|
|
|
|
o recentassertions - all accounts with balance assertions must have one
|
|
that's within the 7 days before their latest posting. This will en-
|
|
courage adding balance assertions for your active asset/liability ac-
|
|
counts, which in turn should encourage you to reconcile regularly
|
|
with those real world balances - another strong defense against er-
|
|
rors. (hledger close --assert >>$LEDGER_FILE is a convenient way to
|
|
add new balance assertions. Later these become quite redundant, and
|
|
you might choose to remove them to reduce clutter.)
|
|
|
|
o uniqueleafnames - no two accounts may have the same last account name
|
|
part (eg the checking in assets:bank:checking). This ensures each
|
|
account can be matched by a unique short name, easier to remember and
|
|
to type.
|
|
|
|
Custom checks
|
|
You can build your own custom checks with add-on command scripts. See
|
|
also Cookbook > Scripting. Here are some examples from hledger/bin/:
|
|
|
|
o hledger-check-tagfiles - all tag values containing / exist as file
|
|
paths
|
|
|
|
o hledger-check-fancyassertions - more complex balance assertions are
|
|
passing
|
|
|
|
diff
|
|
Compares a particular account's transactions in two input files. It
|
|
shows any transactions to this account which are in one file but not in
|
|
the other.
|
|
|
|
Flags:
|
|
no command-specific flags
|
|
|
|
More precisely: for each posting affecting this account in either file,
|
|
this command looks for a corresponding posting in the other file which
|
|
posts the same amount to the same account (ignoring date, description,
|
|
etc).
|
|
|
|
Since it compares postings, not transactions, this also works when mul-
|
|
tiple bank transactions have been combined into a single journal entry.
|
|
|
|
This command is useful eg if you have downloaded an account's transac-
|
|
tions from your bank (eg as CSV data): when hledger and your bank dis-
|
|
agree about the account balance, you can compare the bank data with
|
|
your journal to find out the cause.
|
|
|
|
Examples:
|
|
|
|
$ hledger diff -f $LEDGER_FILE -f bank.csv assets:bank:giro
|
|
These transactions are in the first file only:
|
|
|
|
2014/01/01 Opening Balances
|
|
assets:bank:giro EUR ...
|
|
...
|
|
equity:opening balances EUR -...
|
|
|
|
These transactions are in the second file only:
|
|
|
|
setup
|
|
Check the status of the hledger installation.
|
|
|
|
Flags:
|
|
no command-specific flags
|
|
|
|
setup tests your hledger installation and prints a list of results,
|
|
sometimes with helpful hints. This is a good first command to run af-
|
|
ter installing hledger. Also after upgrading, or when something's not
|
|
working, or just when you want a reminder of where things are.
|
|
|
|
It makes one network request to detect the latest hledger release ver-
|
|
sion. It's ok if this fails or times out. It will use ANSI color by
|
|
default, unless disabled by NO_COLOR or --color=n. It does not use a
|
|
pager or a config file.
|
|
|
|
It expects that the hledger version you are running is installed in
|
|
your PATH. If not, it will stop until you have done that (to keep
|
|
things simple).
|
|
|
|
Example:
|
|
|
|
$ hledger setup
|
|
Checking your hledger setup..
|
|
Legend: good, neutral, unknown, warning
|
|
|
|
hledger
|
|
* is a released version ? no hledger 1.42.99-gbca4b39c5-20250425, mac-aarch64
|
|
* is up to date ? yes 1.42.99 installed, latest is 1.42.1
|
|
* is a native binary for this machine ? yes aarch64
|
|
* is installed in PATH ? yes /Users/simon/.local/bin/hledger
|
|
* has a system text encoding configured ? yes UTF-8, data files should use this encoding
|
|
* has a user config file ? (optional) no
|
|
* current directory has a local config ? yes /Users/simon/src/hledger/hledger.conf
|
|
* the config file is readable ? yes /Users/simon/src/hledger/hledger.conf
|
|
|
|
terminal
|
|
* the NO_COLOR variable is defined ? no
|
|
* --color is configured by config file ? no
|
|
* hledger will use color by default ? yes
|
|
* the PAGER variable is defined ? yes less
|
|
* --pager is configured by config file ? no
|
|
* hledger will use a pager when needed ? yes /opt/homebrew/bin/less
|
|
* the LESS variable is defined ? yes
|
|
* the HLEDGER_LESS variable is defined ? no
|
|
* adjusting LESS variable for color etc. ? yes
|
|
* --pretty is enabled by config file ? no tables will use ASCII characters
|
|
* bash shell completions are installed ? ?
|
|
* zsh shell completions are installed ? ?
|
|
|
|
journal
|
|
* the LEDGER_FILE variable is defined ? yes /Users/simon/finance/2025/2025.journal
|
|
* a default journal file is readable ? yes /Users/simon/finance/2025/2025.journal
|
|
* it includes additional files ? yes 15
|
|
* all commodities are declared ? yes 10
|
|
* all accounts are declared ? yes 160
|
|
* all accounts have types ? no 14 untyped
|
|
* accounts of each type were detected ? yes ALERXCV
|
|
* commodities/accounts are checked ? no use -s to check commodities/accounts
|
|
* balance assertions are checked ? yes use -I to ignore assertions
|
|
|
|
test
|
|
Run built-in unit tests.
|
|
|
|
Flags:
|
|
no command-specific flags
|
|
|
|
This command runs the unit tests built in to hledger and hledger-lib,
|
|
printing the results on stdout. If any test fails, the exit code will
|
|
be non-zero.
|
|
|
|
This is mainly used by hledger developers, but you can also use it to
|
|
sanity-check the installed hledger executable on your platform. All
|
|
tests are expected to pass - if you ever see a failure, please report
|
|
as a bug!
|
|
|
|
Any arguments before a -- argument will be passed to the tasty test
|
|
runner as test-selecting -p patterns, and any arguments after -- will
|
|
be passed to tasty unchanged.
|
|
|
|
Examples:
|
|
|
|
$ hledger test # run all unit tests
|
|
$ hledger test balance # run tests with "balance" in their name
|
|
$ hledger test -- -h # show tasty's options
|
|
|
|
PART 5: COMMON TASKS
|
|
Here are some quick examples of how to do some basic tasks with
|
|
hledger.
|
|
|
|
Getting help
|
|
Here's how to list commands and view options and command docs:
|
|
|
|
$ hledger # show available commands
|
|
$ hledger --help # show common options
|
|
$ hledger CMD --help # show CMD's options, common options and CMD's documentation
|
|
|
|
You can also view your hledger version's manual in several formats by
|
|
using the help command. Eg:
|
|
|
|
$ hledger help # show the hledger manual with info, man or $PAGER (best available)
|
|
$ hledger help journal # show the journal topic in the hledger manual
|
|
$ hledger help --help # find out more about the help command
|
|
|
|
To view manuals and introductory docs on the web, visit
|
|
https://hledger.org. Chat and mail list support and discussion
|
|
archives can be found at https://hledger.org/support.
|
|
|
|
Constructing command lines
|
|
hledger has a flexible command line interface. We strive to keep it
|
|
simple and ergonomic, but if you run into one of the sharp edges de-
|
|
scribed in OPTIONS, here are some tips that might help:
|
|
|
|
o command-specific options must go after the command (it's fine to put
|
|
common options there too: hledger CMD OPTS ARGS)
|
|
|
|
o you can run addon commands via hledger (hledger ui [ARGS]) or di-
|
|
rectly (hledger-ui [ARGS])
|
|
|
|
o enclose "problematic" arguments in single quotes
|
|
|
|
o if needed, also add a backslash to hide regular expression metachar-
|
|
acters from the shell
|
|
|
|
o to see how a misbehaving command line is being parsed, add --debug=2.
|
|
|
|
Starting a journal file
|
|
hledger looks for your accounting data in a journal file,
|
|
$HOME/.hledger.journal by default:
|
|
|
|
$ hledger stats
|
|
The hledger journal file "/Users/simon/.hledger.journal" was not found.
|
|
Please create it first, eg with "hledger add" or a text editor.
|
|
Or, specify an existing journal file with -f or LEDGER_FILE.
|
|
|
|
You can override this by setting the LEDGER_FILE environment variable
|
|
(see below). It's a good practice to keep this important file under
|
|
version control, and to start a new file each year. So you could do
|
|
something like this:
|
|
|
|
$ mkdir ~/finance
|
|
$ cd ~/finance
|
|
$ git init
|
|
Initialized empty Git repository in /Users/simon/finance/.git/
|
|
$ touch 2023.journal
|
|
$ echo "export LEDGER_FILE=$HOME/finance/2023.journal" >> ~/.profile
|
|
$ source ~/.profile
|
|
$ hledger stats
|
|
Main file : /Users/simon/finance/2023.journal
|
|
Included files :
|
|
Transactions span : to (0 days)
|
|
Last transaction : none
|
|
Transactions : 0 (0.0 per day)
|
|
Transactions last 30 days: 0 (0.0 per day)
|
|
Transactions last 7 days : 0 (0.0 per day)
|
|
Payees/descriptions : 0
|
|
Accounts : 0 (depth 0)
|
|
Commodities : 0 ()
|
|
Market prices : 0 ()
|
|
|
|
Setting LEDGER_FILE
|
|
Set LEDGER_FILE on unix
|
|
It depends on your shell, but running these commands in the terminal
|
|
will work for many people; adapt if needed:
|
|
|
|
$ echo 'export LEDGER_FILE=~/finance/my.journal' >> ~/.profile
|
|
$ source ~/.profile
|
|
|
|
When correctly configured:
|
|
|
|
o env | grep LEDGER_FILE will show your new setting
|
|
|
|
o and so should hledger setup and hledger files.
|
|
|
|
Set LEDGER_FILE on mac
|
|
In a terminal window, follow the unix procedure above.
|
|
|
|
Also, this optional step may be helpful for GUI applications:
|
|
|
|
1. Add an entry to ~/.MacOSX/environment.plist like
|
|
|
|
{
|
|
"LEDGER_FILE" : "~/finance/my.journal"
|
|
}
|
|
|
|
2. Run killall Dock in a terminal window (or restart the machine), to
|
|
complete the change.
|
|
|
|
When correctly configured for GUI applications:
|
|
|
|
o apps started from the dock or a spotlight search, such as a GUI
|
|
Emacs, will be aware of the new LEDGER_FILE setting.
|
|
|
|
Set LEDGER_FILE on Windows
|
|
Using the gui is easiest:
|
|
|
|
1. In task bar, search for environment variables, and choose "Edit en-
|
|
vironment variables for your account".
|
|
|
|
2. Create or change a LEDGER_FILE setting in the User variables pane.
|
|
A typical value would be C:\Users\USERNAME\finance\my.journal.
|
|
|
|
3. Click OK to complete the change.
|
|
|
|
4. And open a new powershell window. (Existing windows won't see the
|
|
change.)
|
|
|
|
Or at the command line, you can do it this way:
|
|
|
|
1. In a powershell window, run [Environment]::SetEnvironmentVari-
|
|
able("LEDGER_FILE", "C:\User\USERNAME\finance\my.journal", [Sys-
|
|
tem.EnvironmentVariableTarget]::User)
|
|
|
|
2. And open a new powershell window. (Existing windows won't see the
|
|
change.)
|
|
|
|
Warning, doing this from the Windows command line can be tricky; other
|
|
methods you may find online:
|
|
|
|
o may not affect the current window
|
|
|
|
o may not be persistent
|
|
|
|
o may not work unless you are an administrator
|
|
|
|
o may limit values to 1024 characters
|
|
|
|
o may break dynamic references to other variables
|
|
|
|
o may require a new-enough version of powershell
|
|
|
|
o or may be intended for the older command window.
|
|
|
|
o If you still have trouble, see eg Setting Windows PowerShell environ-
|
|
ment variables or Adding path permanently to windows using powershell
|
|
doesn't appear to work.
|
|
|
|
When correctly configured:
|
|
|
|
o in a new powershell window, $env:LEDGER_FILE will show your new set-
|
|
ting
|
|
|
|
o and so should hledger setup and (once the file exists) hledger files.
|
|
|
|
Setting opening balances
|
|
Pick a starting date for which you can look up the balances of some
|
|
real-world assets (bank accounts, wallet..) and liabilities (credit
|
|
cards..).
|
|
|
|
To avoid a lot of data entry, you may want to start with just one or
|
|
two accounts, like your checking account or cash wallet; and pick a re-
|
|
cent starting date, like today or the start of the week. You can al-
|
|
ways come back later and add more accounts and older transactions, eg
|
|
going back to january 1st.
|
|
|
|
Add an opening balances transaction to the journal, declaring the bal-
|
|
ances on this date. Here are two ways to do it:
|
|
|
|
o The first way: open the journal in any text editor and save an entry
|
|
like this:
|
|
|
|
2023-01-01 * opening balances
|
|
assets:bank:checking $1000 = $1000
|
|
assets:bank:savings $2000 = $2000
|
|
assets:cash $100 = $100
|
|
liabilities:creditcard $-50 = $-50
|
|
equity:opening/closing balances
|
|
|
|
These are start-of-day balances, ie whatever was in the account at
|
|
the end of the previous day.
|
|
|
|
The * after the date is an optional status flag. Here it means
|
|
"cleared & confirmed".
|
|
|
|
The currency symbols are optional, but usually a good idea as you'll
|
|
be dealing with multiple currencies sooner or later.
|
|
|
|
The = amounts are optional balance assertions, providing extra error
|
|
checking.
|
|
|
|
o The second way: run hledger add and follow the prompts to record a
|
|
similar transaction:
|
|
|
|
$ hledger add
|
|
Adding transactions to journal file /Users/simon/finance/2023.journal
|
|
Any command line arguments will be used as defaults.
|
|
Use tab key to complete, readline keys to edit, enter to accept defaults.
|
|
An optional (CODE) may follow transaction dates.
|
|
An optional ; COMMENT may follow descriptions or amounts.
|
|
If you make a mistake, enter < at any prompt to go one step backward.
|
|
To end a transaction, enter . when prompted.
|
|
To quit, enter . at a date prompt or press control-d or control-c.
|
|
Date [2023-02-07]: 2023-01-01
|
|
Description: * opening balances
|
|
Account 1: assets:bank:checking
|
|
Amount 1: $1000
|
|
Account 2: assets:bank:savings
|
|
Amount 2 [$-1000]: $2000
|
|
Account 3: assets:cash
|
|
Amount 3 [$-3000]: $100
|
|
Account 4: liabilities:creditcard
|
|
Amount 4 [$-3100]: $-50
|
|
Account 5: equity:opening/closing balances
|
|
Amount 5 [$-3050]:
|
|
Account 6 (or . or enter to finish this transaction): .
|
|
2023-01-01 * opening balances
|
|
assets:bank:checking $1000
|
|
assets:bank:savings $2000
|
|
assets:cash $100
|
|
liabilities:creditcard $-50
|
|
equity:opening/closing balances $-3050
|
|
|
|
Save this transaction to the journal ? [y]:
|
|
Saved.
|
|
Starting the next transaction (. or ctrl-D/ctrl-C to quit)
|
|
Date [2023-01-01]: .
|
|
|
|
If you're using version control, this could be a good time to commit
|
|
the journal. Eg:
|
|
|
|
$ git commit -m 'initial balances' 2023.journal
|
|
|
|
Recording transactions
|
|
As you spend or receive money, you can record these transactions using
|
|
one of the methods above (text editor, hledger add) or by using the
|
|
hledger-iadd or hledger-web add-ons, or by using the import command to
|
|
convert CSV data downloaded from your bank.
|
|
|
|
Here are some simple transactions, see the hledger_journal(5) manual
|
|
and hledger.org for more ideas:
|
|
|
|
2023/1/10 * gift received
|
|
assets:cash $20
|
|
income:gifts
|
|
|
|
2023.1.12 * farmers market
|
|
expenses:food $13
|
|
assets:cash
|
|
|
|
2023-01-15 paycheck
|
|
income:salary
|
|
assets:bank:checking $1000
|
|
|
|
Reconciling
|
|
Periodically you should reconcile - compare your hledger-reported bal-
|
|
ances against external sources of truth, like bank statements or your
|
|
bank's website - to be sure that your ledger accurately represents the
|
|
real-world balances (and, that the real-world institutions have not
|
|
made a mistake!). This gets easy and fast with (1) practice and (2)
|
|
frequency. If you do it daily, it can take 2-10 minutes. If you let
|
|
it pile up, expect it to take longer as you hunt down errors and dis-
|
|
crepancies.
|
|
|
|
A typical workflow:
|
|
|
|
1. Reconcile cash. Count what's in your wallet. Compare with what
|
|
hledger reports (hledger bal cash). If they are different, try to
|
|
remember the missing transaction, or look for the error in the al-
|
|
ready-recorded transactions. A register report can be helpful
|
|
(hledger reg cash). If you can't find the error, add an adjustment
|
|
transaction. Eg if you have $105 after the above, and can't explain
|
|
the missing $2, it could be:
|
|
|
|
2023-01-16 * adjust cash
|
|
assets:cash $-2 = $105
|
|
expenses:misc
|
|
|
|
2. Reconcile checking. Log in to your bank's website. Compare today's
|
|
(cleared) balance with hledger's cleared balance (hledger bal check-
|
|
ing -C). If they are different, track down the error or record the
|
|
missing transaction(s) or add an adjustment transaction, similar to
|
|
the above. Unlike the cash case, you can usually compare the trans-
|
|
action history and running balance from your bank with the one re-
|
|
ported by hledger reg checking -C. This will be easier if you gen-
|
|
erally record transaction dates quite similar to your bank's clear-
|
|
ing dates.
|
|
|
|
3. Repeat for other asset/liability accounts.
|
|
|
|
Tip: instead of the register command, use hledger-ui to see a live-up-
|
|
dating register while you edit the journal: hledger-ui --watch --regis-
|
|
ter checking -C
|
|
|
|
After reconciling, it could be a good time to mark the reconciled
|
|
transactions' status as "cleared and confirmed", if you want to track
|
|
that, by adding the * marker. Eg in the paycheck transaction above,
|
|
insert * between 2023-01-15 and paycheck
|
|
|
|
If you're using version control, this can be another good time to com-
|
|
mit:
|
|
|
|
$ git commit -m 'txns' 2023.journal
|
|
|
|
Reporting
|
|
Here are some basic reports.
|
|
|
|
Show all transactions:
|
|
|
|
$ hledger print
|
|
2023-01-01 * opening balances
|
|
assets:bank:checking $1000
|
|
assets:bank:savings $2000
|
|
assets:cash $100
|
|
liabilities:creditcard $-50
|
|
equity:opening/closing balances $-3050
|
|
|
|
2023-01-10 * gift received
|
|
assets:cash $20
|
|
income:gifts
|
|
|
|
2023-01-12 * farmers market
|
|
expenses:food $13
|
|
assets:cash
|
|
|
|
2023-01-15 * paycheck
|
|
income:salary
|
|
assets:bank:checking $1000
|
|
|
|
2023-01-16 * adjust cash
|
|
assets:cash $-2 = $105
|
|
expenses:misc
|
|
|
|
Show account names, and their hierarchy:
|
|
|
|
$ hledger accounts --tree
|
|
assets
|
|
bank
|
|
checking
|
|
savings
|
|
cash
|
|
equity
|
|
opening/closing balances
|
|
expenses
|
|
food
|
|
misc
|
|
income
|
|
gifts
|
|
salary
|
|
liabilities
|
|
creditcard
|
|
|
|
Show all account totals:
|
|
|
|
$ hledger balance
|
|
$4105 assets
|
|
$4000 bank
|
|
$2000 checking
|
|
$2000 savings
|
|
$105 cash
|
|
$-3050 equity:opening/closing balances
|
|
$15 expenses
|
|
$13 food
|
|
$2 misc
|
|
$-1020 income
|
|
$-20 gifts
|
|
$-1000 salary
|
|
$-50 liabilities:creditcard
|
|
--------------------
|
|
0
|
|
|
|
Show only asset and liability balances, as a flat list, limited to
|
|
depth 2:
|
|
|
|
$ hledger bal assets liabilities -2
|
|
$4000 assets:bank
|
|
$105 assets:cash
|
|
$-50 liabilities:creditcard
|
|
--------------------
|
|
$4055
|
|
|
|
Show the same thing without negative numbers, formatted as a simple
|
|
balance sheet:
|
|
|
|
$ hledger bs -2
|
|
Balance Sheet 2023-01-16
|
|
|
|
|| 2023-01-16
|
|
========================++============
|
|
Assets ||
|
|
------------------------++------------
|
|
assets:bank || $4000
|
|
assets:cash || $105
|
|
------------------------++------------
|
|
|| $4105
|
|
========================++============
|
|
Liabilities ||
|
|
------------------------++------------
|
|
liabilities:creditcard || $50
|
|
------------------------++------------
|
|
|| $50
|
|
========================++============
|
|
Net: || $4055
|
|
|
|
The final total is your "net worth" on the end date. (Or use bse for a
|
|
full balance sheet with equity.)
|
|
|
|
Show income and expense totals, formatted as an income statement:
|
|
|
|
hledger is
|
|
Income Statement 2023-01-01-2023-01-16
|
|
|
|
|| 2023-01-01-2023-01-16
|
|
===============++=======================
|
|
Revenues ||
|
|
---------------++-----------------------
|
|
income:gifts || $20
|
|
income:salary || $1000
|
|
---------------++-----------------------
|
|
|| $1020
|
|
===============++=======================
|
|
Expenses ||
|
|
---------------++-----------------------
|
|
expenses:food || $13
|
|
expenses:misc || $2
|
|
---------------++-----------------------
|
|
|| $15
|
|
===============++=======================
|
|
Net: || $1005
|
|
|
|
The final total is your net income during this period.
|
|
|
|
Show transactions affecting your wallet, with running total:
|
|
|
|
$ hledger register cash
|
|
2023-01-01 opening balances assets:cash $100 $100
|
|
2023-01-10 gift received assets:cash $20 $120
|
|
2023-01-12 farmers market assets:cash $-13 $107
|
|
2023-01-16 adjust cash assets:cash $-2 $105
|
|
|
|
Show weekly posting counts as a bar chart:
|
|
|
|
$ hledger activity -W
|
|
2019-12-30 *****
|
|
2023-01-06 ****
|
|
2023-01-13 ****
|
|
|
|
Migrating to a new file
|
|
At the end of the year, you may want to continue your journal in a new
|
|
file, so that old transactions don't slow down or clutter your reports,
|
|
and to help ensure the integrity of your accounting history. See the
|
|
close command.
|
|
|
|
If using version control, don't forget to git add the new file.
|
|
|
|
BUGS
|
|
We welcome bug reports in the hledger issue tracker
|
|
(https://bugs.hledger.org), or on the hledger chat or mail list
|
|
(https://hledger.org/support).
|
|
|
|
Some known issues and limitations:
|
|
|
|
hledger uses the system's text encoding when reading non-ascii text.
|
|
If no system encoding is configured, or if the data's encoding is dif-
|
|
ferent, hledger will give an error. (See Text encoding, Troubleshoot-
|
|
ing.)
|
|
|
|
On Microsoft Windows, depending what kind of terminal window you use,
|
|
non-ascii characters, ANSI text formatting, and/or the add command's
|
|
TAB key, may not be fully supported. (For best results, try a power-
|
|
shell window.)
|
|
|
|
When processing large data files, hledger uses more memory than Ledger.
|
|
|
|
Troubleshooting
|
|
Here are some common issues you might encounter when you run hledger,
|
|
and how to resolve them (and remember also you can usually get quick
|
|
Support):
|
|
|
|
PATH issues: I get an error like "No command 'hledger' found"
|
|
Depending how you installed hledger, the executables may not be in your
|
|
shell's PATH. Eg on unix systems, stack installs hledger in ~/.lo-
|
|
cal/bin and cabal installs it in ~/.cabal/bin. You may need to add one
|
|
of these directories to your shell's PATH, and/or open a new terminal
|
|
window.
|
|
|
|
LEDGER_FILE issues: I configured LEDGER_FILE but hledger is not using
|
|
it
|
|
o LEDGER_FILE should be a real environment variable, not just a shell
|
|
variable. Eg on unix, the command env | grep LEDGER_FILE should show
|
|
it. You may need to use export (see https://stackover-
|
|
flow.com/a/7411509). On Windows, $env:LEDGER_FILE should show it.
|
|
|
|
o You may need to force your shell to see the new configuration. A
|
|
simple way is to close your terminal window and open a new one.
|
|
|
|
Text decoding issues: I get errors like "Illegal byte sequence" or "In-
|
|
valid or incomplete multibyte or wide character" or "commitAndRelease-
|
|
Buffer: invalid argument (invalid character)"
|
|
hledger usually needs its input to be decodable with the system lo-
|
|
cale's text encoding. See Text encoding and Install: Text encoding.
|
|
|
|
COMPATIBILITY ISSUES: hledger gives an error with my Ledger file
|
|
Not all of Ledger's journal file syntax or feature set is supported.
|
|
See hledger and Ledger for full details.
|
|
|
|
|
|
|
|
AUTHORS
|
|
Simon Michael <simon@joyful.com> and contributors.
|
|
See http://hledger.org/CREDITS.html
|
|
|
|
|
|
COPYRIGHT
|
|
Copyright 2007-2023 Simon Michael and contributors.
|
|
|
|
|
|
LICENSE
|
|
Released under GNU GPL v3 or later.
|
|
|
|
|
|
SEE ALSO
|
|
hledger(1), hledger-ui(1), hledger-web(1), ledger(1)
|
|
|
|
hledger-1.51.99 December 2025 HLEDGER(1)
|