beancount-hooks
Rule-based beangulp import hooks for Beancount v3. A Ruleset asserts what a transaction is; predictors then fill only the blanks from the existing ledger. No ML, no runtime dependency beyond Beancount.
Ruleset.hook # facts — first match wins
RulesPayeePredictor.hook # fill an empty payee from the narration
RulesPostingsPredictor.hook # fill the other leg(s) from history
RulesTagsPredictor.hook # add tags the payee usually carries
That order is the contract. Reverse it and a guess lands before the rule that should have won.
Install
Requires Python 3.11+ and Beancount 3. After the first release (v0.6.1):
uv add beancount-hooks
Until that tag is on PyPI, install from a checkout:
uv add --editable /path/to/beancount-hooks
Use
from decimal import Decimal as D
from beancount.core.amount import Amount
from beancount_hooks import (
Actions,
Match,
Rule,
Ruleset,
RulesPayeePredictor,
RulesPostingsPredictor,
RulesTagsPredictor,
)
RULES = [
Rule(
Match(payee='Coop'),
Actions(post='Expenses:Groceries'),
name='coop',
),
Rule(
Match(payee='Landlord', sign='debit'),
Actions(
post=(
('Expenses:Housing:Utilities', Amount(D('150.00'), 'CHF')),
'Expenses:Housing:Rent',
),
tags=('recurring',),
),
name='rent',
),
]
# Limit the ruleset to the importers it was written for. A card that
# already assigns its own accounts is left alone.
LEDGER_RULES = Ruleset(RULES, label='LedgerRules', accounts=('Assets:Bank',))
HOOKS = [
LEDGER_RULES.hook,
RulesPayeePredictor().hook,
RulesPostingsPredictor().hook,
RulesTagsPredictor().hook,
]
Pass HOOKS to beangulp.Ingest(CONFIG, HOOKS). The same list is what Fava
ingest runs.
Match amounts are absolute; direction is sign='debit' or 'credit'.
amount=D("10.00") without a sign matches both the charge and the refund —
add sign if you mean only one.
Ruleset.shadowed() returns (earlier, unreachable) pairs for rules that
can never fire. Ruleset.explain(txn, account) lists every match in
precedence order.
Fava
Fava sends the beangulp 4-tuple only to hooks whose annotations contain the
literal text Importer. Every hook in this package does. If you wrap
hook, keep that word in the signature or Fava will call you with
(filename, entries), the importer account will be missing, and
map_transactions will raise.
Documentation
| Doc | What it is |
|---|---|
| docs/PRD.md | Scope, users, non-goals |
| docs/SAD.md | Components, data flow, the posting ladder |
| docs/glossary.md | Shared vocabulary |
| docs/adr/ | Binding decisions |
Develop
make install
uv run pre-commit install
make check
make test
make install syncs the lockfile into .venv. pre-commit formats staged
files; pre-push runs make check (the same gate CI uses).
make format # rewrite the tree
make build # sdist + wheel, no local path sources
make audit # zizmor over the workflows
Release
uv version --bump patch # or minor / major
git add pyproject.toml uv.lock
git commit -m "Release 0.6.2"
git tag v0.6.2
git push origin main --tags
The tag must equal v plus the version in pyproject.toml. A mismatch fails
before any PyPI contact. That tag push is the only publish trigger.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file beancount_hooks-0.7.0.tar.gz.
File metadata
- Download URL: beancount_hooks-0.7.0.tar.gz
- Upload date:
- Size: 21.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
78fe47c7428def7837c9b1f9305d549db999fcb3c228df06fd3e64fdb21bb5e2
|
|
| MD5 |
d876fe2e7b2c3a73f60f19c86f4b4398
|
|
| BLAKE2b-256 |
bca90a2fe1a7560ccdce7b6d645ae8ab47445df3f88ce07729f34114b67b7ca7
|
Provenance
The following attestation bundles were made for beancount_hooks-0.7.0.tar.gz:
Publisher:
release.yml on mekanics/beancount-hooks
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
beancount_hooks-0.7.0.tar.gz -
Subject digest:
78fe47c7428def7837c9b1f9305d549db999fcb3c228df06fd3e64fdb21bb5e2 - Sigstore transparency entry: 2498845867
- Sigstore integration time:
-
Permalink:
mekanics/beancount-hooks@a3d2ae606847af1bc2c955988b52a15112803755 -
Branch / Tag:
refs/tags/v0.7.0 - Owner: https://github.com/mekanics
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a3d2ae606847af1bc2c955988b52a15112803755 -
Trigger Event:
push
-
Statement type:
File details
Details for the file beancount_hooks-0.7.0-py3-none-any.whl.
File metadata
- Download URL: beancount_hooks-0.7.0-py3-none-any.whl
- Upload date:
- Size: 26.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bab9cb85446a7cf77784b91fa69be4f164f61e877239afed8d161096da6df880
|
|
| MD5 |
9ff527e3a4769855b0f4b093bd1066ed
|
|
| BLAKE2b-256 |
5736f3aa7819ae49f06e9dc923e4da53a1cdcd2eb8dedd611ef4bcb951b2a245
|
Provenance
The following attestation bundles were made for beancount_hooks-0.7.0-py3-none-any.whl:
Publisher:
release.yml on mekanics/beancount-hooks
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
beancount_hooks-0.7.0-py3-none-any.whl -
Subject digest:
bab9cb85446a7cf77784b91fa69be4f164f61e877239afed8d161096da6df880 - Sigstore transparency entry: 2498845873
- Sigstore integration time:
-
Permalink:
mekanics/beancount-hooks@a3d2ae606847af1bc2c955988b52a15112803755 -
Branch / Tag:
refs/tags/v0.7.0 - Owner: https://github.com/mekanics
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a3d2ae606847af1bc2c955988b52a15112803755 -
Trigger Event:
push
-
Statement type: