{"id":13936331,"url":"https://github.com/pylipp/financeager","last_synced_at":"2026-02-06T21:04:55.120Z","repository":{"id":27127165,"uuid":"30595542","full_name":"pylipp/financeager","owner":"pylipp","description":"Organize your finances easily - from the command line!","archived":false,"fork":false,"pushed_at":"2026-02-03T23:51:30.000Z","size":1492,"stargazers_count":83,"open_issues_count":4,"forks_count":21,"subscribers_count":3,"default_branch":"master","last_synced_at":"2026-02-04T10:47:15.975Z","etag":null,"topics":["bookkeeping","cli","command-line","finances","flask","python","python3","tinydb","webservice"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pylipp.png","metadata":{"files":{"readme":"README.md","changelog":"Changelog.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2015-02-10T14:21:59.000Z","updated_at":"2026-02-03T23:16:06.000Z","dependencies_parsed_at":"2023-09-22T06:22:58.194Z","dependency_job_id":"94d8c28e-07fd-46a9-bb1a-4ce28cb9a53c","html_url":"https://github.com/pylipp/financeager","commit_stats":{"total_commits":1170,"total_committers":13,"mean_commits":90.0,"dds":"0.18632478632478633","last_synced_commit":"9c0f4273277f08c397de1dfb4fbd9c5f367c0ad9"},"previous_names":[],"tags_count":73,"template":false,"template_full_name":null,"purl":"pkg:github/pylipp/financeager","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pylipp%2Ffinanceager","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pylipp%2Ffinanceager/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pylipp%2Ffinanceager/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pylipp%2Ffinanceager/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pylipp","download_url":"https://codeload.github.com/pylipp/financeager/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pylipp%2Ffinanceager/sbom","scorecard":{"id":751554,"data":{"date":"2025-08-11","repo":{"name":"github.com/pylipp/financeager","commit":"24f8e804e139eb4a7c70e8e67db4be817bfc019f"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.7,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/10 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":10,"reason":"23 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:30: update your workflow using https://app.stepsecurity.io/secureworkflow/pylipp/financeager/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:33: update your workflow using https://app.stepsecurity.io/secureworkflow/pylipp/financeager/ci.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:43: update your workflow using https://app.stepsecurity.io/secureworkflow/pylipp/financeager/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/copilot-setup-steps.yml:30: update your workflow using https://app.stepsecurity.io/secureworkflow/pylipp/financeager/copilot-setup-steps.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/copilot-setup-steps.yml:34: update your workflow using https://app.stepsecurity.io/secureworkflow/pylipp/financeager/copilot-setup-steps.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/pylipp/financeager/release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/pylipp/financeager/release.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:32: update your workflow using https://app.stepsecurity.io/secureworkflow/pylipp/financeager/release.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:40: update your workflow using https://app.stepsecurity.io/secureworkflow/pylipp/financeager/release.yml/master?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:39","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:40","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:41","Warn: pipCommand not pinned by hash: .github/workflows/copilot-setup-steps.yml:42","Warn: pipCommand not pinned by hash: .github/workflows/copilot-setup-steps.yml:43","Warn: pipCommand not pinned by hash: .github/workflows/release.yml:24","Warn: pipCommand not pinned by hash: .github/workflows/release.yml:25","Info:   0 out of   6 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   3 third-party GitHubAction dependencies pinned","Info:   0 out of   7 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'contents' permission set to 'read': .github/workflows/copilot-setup-steps.yml:24","Warn: jobLevel 'contents' permission set to 'write': .github/workflows/release.yml:15","Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Warn: no topLevel permission defined: .github/workflows/copilot-setup-steps.yml:1","Warn: no topLevel permission defined: .github/workflows/release.yml:1"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.md:0","Info: FSF or OSI recognized license: GNU General Public License v3.0: LICENSE.md:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/release.yml:9"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 20 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-22T20:31:41.753Z","repository_id":27127165,"created_at":"2025-08-22T20:31:41.754Z","updated_at":"2025-08-22T20:31:41.754Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29175851,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-06T20:14:21.878Z","status":"ssl_error","status_checked_at":"2026-02-06T20:14:21.443Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bookkeeping","cli","command-line","finances","flask","python","python3","tinydb","webservice"],"created_at":"2024-08-07T23:02:34.526Z","updated_at":"2026-02-06T21:04:55.114Z","avatar_url":"https://github.com/pylipp.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"[![pypi](https://badge.fury.io/py/financeager.svg)](https://pypi.org/project/financeager)\n[![Python: 3.10+](https://img.shields.io/badge/Python-3.10+-blue.svg)](https://pypi.org/project/financeager)\n[![Downloads](https://img.shields.io/pypi/dm/financeager.svg)](https://pypistats.org/packages/financeager)\n![Build Status](https://github.com/pylipp/financeager/workflows/CI/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/pylipp/financeager/badge.svg?branch=master)](https://coveralls.io/github/pylipp/financeager?branch=master)\n[![License: GPLv3](https://img.shields.io/badge/License-GPLv3-green.svg)](https://en.wikipedia.org/wiki/GNU_General_Public_License#Version_3)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)\n\n\u003cp align=\"center\"\u003e\n  \u003ch1 align=\"center\"\u003efinanceager\u003c/h1\u003e\n  \u003cp align=\"center\"\u003eOrganize your finances from the command line\u003c/p\u003e\n\u003c/p\u003e\n\nAn application that helps you administering your daily expenses and earnings using single-entry book-keeping. Interact via the command line interface `fina`.\n\nThe `financeager` backend holds databases (internally referred to as 'pockets', stored in `~/.local/share/financeager`). A pocket contains entries for a certain project.\n\n## Quickstart\n\n![Quickstart](./examples/quickstart.svg)\n\nWho is this for?\n----------------\nYou might be someone who wants to organize finances with a simple software because you're tired of Excel and the like. And you like the command line. And Python.\n\n## Installation\n\n`financeager` requires Python 3.10 or higher.\n\n### From PyPI package\n\n    pip install --user --upgrade financeager\n\n### Using pipx\n\nIf you have [`pipx`](https://pipxproject.github.io/pipx/) installed, install `financeager` into an isolated environment via\n\n    pipx install financeager\n\n### Backwards compatibility\n\n- `v1.4.6` is the last version to support Python 3.9\n- `v1.3.10` is the last version to support Python 3.8\n- `v1.2.1` is the last version to support Python 3.7\n- `v1.0.3` is the last version to support Python 3.6\n\n## Usage\n\nYou can use `financeager` as a client-server or a serverless application (default). The user interacts via the command line interface (CLI).\n\n\u003cdetails\u003e\n  \u003csummary\u003eClick here for background information about the modes.\u003c/summary\u003e\n\n### Serverless mode\n\nThe user request invoked from the CLI is passed to the backend which opens the appropriate database, processes the request, closes the database and returns a response. All communication happens within a single process, hence the label 'serverless'.\n\nIn vanilla financeager, this is the default mode.\n\nYou can explicitly specify it in the configuration file `~/.config/financeager/config`  via\n\n    [SERVICE]\n    name = local\n\n### Client-server mode\n\nInstall the [financeager-flask](https://github.com/pylipp/financeager-flask) plugin.\n\nIn any case, you're all set up! See the next section about the available client CLI commands and options.\n\n\u003c/details\u003e\n\n### Command line interface\n\nThe main CLI entry point is called `fina`.\n\n    usage: fina [-h] [-V] {add,get,remove,update,copy,list,pockets,migrate-pockets} ...\n\n    optional arguments:\n      -h, --help          show this help message and exit\n      -V, --version       display version info and exit\n\n    command\n      add                 add an entry to the database\n      get                 show information about single entry\n      remove              remove an entry from the database\n      update              update one or more fields of an entry\n      copy                copy an entry from one pocket to another, or within one pocket\n      list                list all entries in the pocket database\n      pockets             list all pocket databases\n      migrate-pockets     migrate TinyDB pocket(s) to SQLite format\n\n*Add* earnings (no/positive sign) and expenses (negative sign) to the database:\n\n    \u003e fina add burgers -19.99 --category Restaurants\n    \u003e fina add lottery 123.45 --date 03-14\n\nCategory and date can be optionally specified. They default to None and the current day's date, resp. The program will try to derive the entry category from the database if not specified. If several matches are found, the default category is used.\n\n\u003e The date format can be anything that the [parser module](https://dateutil.readthedocs.io/en/stable/parser.html) of the `python-dateutil` library understands (e.g. YYYY-MM-DD, YY-MM-DD or MM-DD).\n\n*Add recurrent* entries by specifying the frequency (yearly, half-yearly, quarterly, bi-monthly, monthly, weekly, daily) with the `-f` flag and optionally start and end date with the `-s` and `-e` flags, resp.\n\n    \u003e fina add rent -500 -f monthly -s 01-01 -c rent\n\nBy default, the start date is the current date. The entry exists for infinite times, i.e. the end date is evaluated as the current date at query runtime.\n\nDid you make a mistake when adding a new entry? *Update* one or more fields by calling the `update` command with the entry's ID and the respective corrected fields:\n\n    \u003e fina update 1 --name \"McKing Burgers\" --value -18.59\n\nTo unset the end date of a recurrent entry, or the category of an entry, use a special indicator: `--end -` and `--category -`\n\n*Remove* an entry by specifying its ID (visible in the output of the `list` command). This removes the `burgers` entry:\n\n    \u003e fina remove 1\n\nThis would remove the recurrent rent entries (ID is also 1 because standard and recurrent entries are stored in separate tables):\n\n    \u003e fina remove 1 --recurrent\n\nShow a side-by-side *overview* of earnings and expenses (filter by date/category/name/value by passing the `--filter` option, e.g. `--filter category=food` to show entries in the categories `food`)\n\n    \u003e fina list\n\n                   Earnings               |                Expenses\n    Name               Value    Date  ID  | Name               Value    Date  ID\n    Unspecified          123.45           | Rent                1500.00\n      Lottery            123.45 03-14   2 |   Rent January       500.00 01-01   1\n                                          |   Rent February      500.00 02-01   1\n                                          |   Rent March         500.00 03-01   1\n    =============================================================================\n    Total                123.45           | Total               1500.00\n    Difference         -1376.55\n\nIt might be convenient to list entries of the current month, or a specific month only (example output is omitted):\n\n    \u003e fina list --month\n    \u003e fina list --month January\n    \u003e fina list --month Dec\n    \u003e fina list --month 7\n    \u003e fina list --month 03\n\nIn order to only list category entries incl. their respective percentage of earnings/expenses use\n\n    \u003e fina list --category-percentage\n\nIn order to only list recurrent entries run (you can apply additional filtering (use `-f end=` to list entries with indefinite end) and sorting)\n\n    \u003e fina list --recurrent-only\n\nThe aforementioned `fina` commands operate on the default database (`main`) unless another pocket is specified by the `--pocket` flag.\n\n    \u003e fina add xmas-gifts -42 --date 12-23 --pocket personal\n\n*Copy* an entry from one database to another by specifying entry ID and source/destination pocket:\n\n    \u003e fina copy 1 --source 2017 --destination 2018\n\nDetailed information is available from\n\n    \u003e fina --help\n    \u003e fina \u003csubcommand\u003e --help\n\nYou can turn on printing debug messages to the terminal using the `--verbose` option, e.g.\n\n    \u003e fina list --verbose\n\nYou can find a log of interactions at `~/.local/share/financeager/log` (on both the client machine and the server).\n\n### More on configuration\n\nBy default, financeager uses a `tinydb` database. If you want to use an `sqlite` database, specify it in the configuration file:\n\n    [SERVICE]\n    database_type = sqlite\n\n**NOTE**: the `sqlite` back-end will become the default in v2.0. See below on how to migrate existing `tinydb` databases.\n\nYou can also configure frontend options: the name of the default category (assigned when omitting the category option when e.g. adding an entry). The defaults are:\n\n    [FRONTEND]\n    default_category = unspecified\n\nThe CLI `fina` tries to read the configuration from `~/.config/financeager/config`. You can specify a custom path by passing it along with the `-C`/`--config` command line option.\n\n### Migrating from TinyDB to SQLite\n\nIf you have existing TinyDB databases (`.json` files) and want to migrate to SQLite format (`.sqlite` files), use the `migrate-pockets` command:\n\n    \u003e fina migrate-pockets main work\n\nThis will:\n- Read the TinyDB files (`main.json`, `work.json`) from your data directory\n- Create new SQLite files (`main.sqlite`, `work.sqlite`) in the same directory\n- Migrate all entries from both the standard and recurrent tables\n- Preserve the original entry IDs\n\n**Note**: The migration does **not** delete the original `.json` files. After verifying that the migration was successful (by running `fina list --pocket \u003cname\u003e` with the `database_type = sqlite` configuration), you can manually delete the old `.json` files if desired.\n\n### More Goodies\n\n**Command line tab completion** is provided by the `argcomplete` package (for bash; limited support for zsh, fish, tcsh). Completion should work for all commands and CLI options incl. selections for values of `--category`, `--table-name`, `--pocket`, and `--frequency`.\n\nCompletion has to be enabled by running `activate-global-python-argcomplete`. Read the [instructions](https://github.com/kislyuk/argcomplete#activating-global-completion) if you want to know more.\n\n### Database back-ends\n\nWant to use a different database? Derive a custom class from `pocket.Pocket` and `pocket.utils.DatabaseInterface` and implement the CRUD methods. Modify `pocket.POCKET_CLASSES` accordingly to register the new pocket type.\n\n### Plugin support\n\nThe `financeager` core package can be extended by Python plugins.\nThe supported groups are:\n\n- `financeager.services`\n\nAvailable plugins are:\n\n- [financeager-flask](https://github.com/pylipp/financeager-flask)\n\n\u003cdetails\u003e\n  \u003csummary\u003eClick here for instructions about creating plugins.\u003c/summary\u003e\n\n#### All plugin types\n\nFor developing a plugin, create a plugin package containing a `main.py` file:\n\n    from financeager import plugin\n\n    class _Configuration(plugin.PluginConfiguration):\n        \"\"\"Configuration actions specific to the plugin.\"\"\"\n\nand implement the required `PluginConfiguration` methods.\nFinally, specify the entry point for loading the plugin in `setup.py`:\n\n    setup(\n        ...,\n        entry_points={\n            \u003cgroup_name\u003e: \u003cplugin-name\u003e = \u003cpackage\u003e.main:main,\n            # e.g.\n            # \"financeager.services\": \"fancy-service = fancy_service.main:main\",\n        },\n    )\n\nThe plugin name can be different from the package name.\nThe package name should be prefixed with `financeager-`.\n\n#### Service plugins\n\nFor developing a service plugin, extend the aforementioned `main.py` file:\n\n    # fancy_service/main.py in the fancy-service package\n    from financeager import plugin, clients\n\n    class _Configuration(plugin.PluginConfiguration):\n        \"\"\"Configuration actions specific to the plugin.\"\"\"\n\n    class _Client(clients.Client):\n        \"\"\"Client to communicate with fancy-service.\"\"\"\n\n    def main():\n        return plugin.ServicePlugin(\n            name=\"fancy-service\",\n            config=_Configuration(),\n            client=_Client,\n        )\n\nProvide a suitable client implementation.\n\nDone! When the plugin is correctly installed, and configured to be used (`name = fancy-service`), `financeager` picks it up automatically. The plugin configuration is applied, and the plugin client created.\n\n\u003c/details\u003e\n\n## Architecture\n\nThe following diagram sketches the relationship between financeager's modules. See the module docstrings for more information.\n\n          +--------+\n          | plugin |\n          +--------+\n           ¦      ¦\n           V      V\n    +--------+   +-----------+\n    | config |--\u003e|    cli    |\n    +--------+   +-----------+\n\n                     ¦   Λ                     +---------+     +---------+\n    [pre-processing] ¦   ¦  [formatting]  \u003c--  | listing | \u003c-- | entries |\n                     V   ¦                     +---------+     +---------+\n\n    +-------------------------------------+\n    |                clients              |\n    +-------------------------------------+\n\n            ¦                     Λ\n            V                     ¦\n\n    +-------------------------------------+\n    |                                     |     FRONTEND\n    |                                     |\n    |            localserver              |    ==========\n    |                                     |\n    |                                     |     BACKEND\n    +-------------------------------------+\n\n            ¦                     Λ\n            V                     ¦\n    +-------------------------------------+\n    |                server               |\n    +-------------------------------------+\n            ¦                     Λ\n            V                     ¦\n    +-------------------------------------+\n    |                pocket               |\n    +-------------------------------------+\n\n## Contributing\n\nAlways welcome! Clone the repo\n\n    git clone https://github.com/pylipp/financeager\n    cd financeager\n\nCreate a virtual environment\n\n    python3 -m venv .venv\n    source .venv/bin/activate\n\nInstall development dependencies\n\n    make install\n\nYou're all set for hacking!\nPlease adhere to test-driven development, if possible: When adding a feature, or fixing a bug, try to construct a test first, and subsequently adapt the implementation. Run the tests from the root directory via\n\n    make test\n\nIf you added a non-cosmetic change (i.e. a change in functionality, e.g. a bug fix or a new feature), please update `Changelog.md` accordingly as well. Check this README whether the content is still up to date.\n\n## Releasing\n\n1. Tag the latest commit on master by incrementing the current version accordingly (scheme `vmajor.minor.patch`).\n1. Run `make release`.\n1. The package is automatically published to PyPI using a Github action.\n\n## Related projects\n\n`financeager` aims to be simple in functionality. A related command-line tool is [expenses](https://github.com/manojkarthick/expenses).\n\nFor more holistic management of your financial affairs you might consider double-entry book-keeping. The following projects provide mature support:\n\nCLI-focused (GUI/browser extensions available):\n- [beancount](https://github.com/beancount/beancount)\n- [ledger](https://www.ledger-cli.org/index.html)\n\nTUI applications\n- [budget_tracker_tui](https://github.com/Feromond/budget_tracker_tui)\n- [moneyterm](https://github.com/ChrisBuilds/moneyterm)\n\nClient-server applications\n- [firefly-iii](https://www.firefly-iii.org/)\n- [maybe](https://github.com/maybe-finance/maybe)\n\nLocal GUI applications\n- [kmymoney](https://kmymoney.org/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpylipp%2Ffinanceager","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpylipp%2Ffinanceager","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpylipp%2Ffinanceager/lists"}