{"id":24995333,"url":"https://github.com/launchplatform/beanhub-import","last_synced_at":"2026-03-04T03:32:01.237Z","repository":{"id":238211840,"uuid":"796107617","full_name":"LaunchPlatform/beanhub-import","owner":"LaunchPlatform","description":"Beanhub-import is a simple, declarative, smart, and easy-to-use library for importing extracted transactions from beanhub-extract. It generates Beancount transactions based on predefined rules.","archived":false,"fork":false,"pushed_at":"2026-01-11T00:48:37.000Z","size":1809,"stargazers_count":24,"open_issues_count":0,"forks_count":6,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-01-11T08:24:43.963Z","etag":null,"topics":["automation","beancount","csv","import"],"latest_commit_sha":null,"homepage":"https://beanhub-import-docs.beanhub.io","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LaunchPlatform.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2024-05-05T00:28:30.000Z","updated_at":"2026-01-11T00:48:34.000Z","dependencies_parsed_at":null,"dependency_job_id":"0254c377-b240-4d2b-ae4e-eb2df92c3307","html_url":"https://github.com/LaunchPlatform/beanhub-import","commit_stats":null,"previous_names":["launchplatform/beanhub-import"],"tags_count":38,"template":false,"template_full_name":null,"purl":"pkg:github/LaunchPlatform/beanhub-import","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LaunchPlatform%2Fbeanhub-import","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LaunchPlatform%2Fbeanhub-import/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LaunchPlatform%2Fbeanhub-import/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LaunchPlatform%2Fbeanhub-import/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LaunchPlatform","download_url":"https://codeload.github.com/LaunchPlatform/beanhub-import/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LaunchPlatform%2Fbeanhub-import/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30070760,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-04T03:25:38.285Z","status":"ssl_error","status_checked_at":"2026-03-04T03:25:05.086Z","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":["automation","beancount","csv","import"],"created_at":"2025-02-04T15:35:14.352Z","updated_at":"2026-03-04T03:32:01.219Z","avatar_url":"https://github.com/LaunchPlatform.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# beanhub-import [![CircleCI](https://dl.circleci.com/status-badge/img/gh/LaunchPlatform/beanhub-import/tree/master.svg?style=svg)](https://dl.circleci.com/status-badge/redirect/gh/LaunchPlatform/beanhub-import/tree/master)\n\nBeanhub-import is a simple, declarative, smart, and easy-to-use library for importing extracted transactions from [beanhub-extract](https://github.com/LaunchPlatform/beanhub-extract).\nIt generates Beancount transactions based on predefined rules.\n\nRead the [documentations here](https://beanhub-import-docs.beanhub.io/).\n\nPlease also checkout our blog posts about the BeanHub Import and BeanHub Connect features based on this tool:\n- [BeanHub Import - One small step closer to fully automating transaction importing](https://beanhub.io/blog/2024/05/27/introduction-of-beanhub-import/)\n- [BeanHub Connect - one giant leap with fully automatic bank transactions import from 12,000+ financial institutions in 17 countries for all Beancount users!](https://beanhub.io/blog/2024/06/24/introduction-of-beanhub-connect/)\n- [Direct Connect: Pulling transactions as CSV files from banks via Plaid directly](https://beanhub.io/blog/2025/01/16/direct-connect-repository/)\n\n## Features\n\n- **Easy-to-use** - you only need to know a little bit about YAML and Jinja2 template syntax.\n- **Simple declarative rules** - A single import file for all imports\n- **Idempotent** - As long as the input data and rules are the same, the Beancount files will be the same.\n- **Auto-update existing transactions** - When you update the rules or data, corresponding Beancount transactions will be updated automatically. \n- **Auto-move transactions to a different file** - When you change the rules to output the transactions to a different file, it will automatically remove the old ones and add the new ones for you\n- **Merge data from multiple files (coming soon)** - You can define rules to match transactions from multiple sources for generating your transactions\n\nFor example, change the import rules like this to output transactions to files grouped by quarter instead of year:\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/LaunchPlatform/beanhub-import/raw/master/assets/quater-output-file.png?raw=true\" alt=\"Git diff screenshot showing default_file changed to output quater file names instead of just year\" /\u003e\n\u003c/p\u003e\n\nThen run the import again, and you will get this:\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/LaunchPlatform/beanhub-import/raw/master/assets/auto-txn-migration.png?raw=true\" alt=\"Git diff screenshot showing Beancount transactions removed from the books/2024.bean file and new quater beancount files added\" /\u003e\n\u003c/p\u003e\n\nAnother example is when you want to add new tags to the generated transactions, so you change the rules with new tags like this:\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/LaunchPlatform/beanhub-import/raw/master/assets/new-tags.png?raw=true\" alt=\"Git diff screenshot showing new line\" /\u003e\n\u003c/p\u003e\n\nWhen you run import again, you will get this:\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/LaunchPlatform/beanhub-import/raw/master/assets/new-tags-result.png?raw=true\" alt=\"Git diff screenshot showing new tags added to all imported Beancount transactions\" /\u003e\n\u003c/p\u003e\n\nPlease check out our demonstration repository [beanhub-import-demo](https://github.com/LaunchPlatform/beanhub-import-demo) to try it yourself.\n\nIt's all declarative and idempotent. With beanhub-import, you say goodbye to manually importing and maintaining transactions!\nWe hope you like this tool. It's still in the early stage of development.\nWe are also working on making generating transactions from multiple sources possible.\nPlease feel free to open issues in the repository if you have any feedback 🙌\n\n## Why?\n\nThere are countless Beancount importer projects out there, so why do we have to build a new one from the ground up?\nWe are building a new one with a completely new design because we cannot find an importer that meets our requirements for [BeanHub](https://beanhub.io).\nThere are a few critical problems we saw in the existing Beancount importers:\n\n- Need to write Python code to make it work\n- Doesn't handle duplication problem\n- Hard to reuse because extracting logic is coupled with generating logic\n- Hard to customize for our own needs\n- Can only handle a single source file\n\n## Example\n\nThe rules of beanhub-import is defined in YAML format at `.beanhub/imports.yaml`. Here's an example\n\n```YAML\n# the `context` defines global variables to be referenced in the Jinja2 template for\n# generating transactions\ncontext:\n  routine_expenses:\n    \"Amazon Web Services\":\n      account: Expenses:Engineering:Servers:AWS\n    Netlify:\n      account: Expenses:Engineering:ServiceSubscription\n    Mailchimp:\n      account: Expenses:Marketing:ServiceSubscription\n    Circleci:\n      account: Expenses:Engineering:ServiceSubscription\n    Adobe:\n      account: Expenses:Design:ServiceSubscription\n    Digital Ocean:\n      account: Expenses:Engineering:ServiceSubscription\n    Microsoft:\n      account: Expenses:Office:Supplies:SoftwareAsService\n      narration: \"Microsoft 365 Apps for Business Subscription\"\n    Mercury IO Cashback:\n      account: Expenses:CreditCardCashback\n      narration: \"Mercury IO Cashback\"\n    WeWork:\n      account: Expenses:Office\n      narration: \"Virtual mailing address service fee from WeWork\"\n\n# the `inputs` defines which files to import, what type of beanhub-extract extractor to use,\n# and other configurations, such as `prepend_postings` or default values for generating\n# a transaction\ninputs:\n  - match: \"import-data/connect/{{ match_path }}\"\n    config:\n      # use the extractor from loop variables for extracting transactions from the input file\n      extractor: \"{{ extractor }}\"\n      # the default output file to use\n      default_file: \"books/{{ date.year }}.bean\"\n      # postings to prepend for all transactions generated from this input file\n      prepend_postings:\n        # the `input_account` will be replaced with the variable value provided in the loop\n        - account: \"{{ input_account }}\"\n          amount:\n            number: \"{{ amount }}\"\n            currency: \"{{ currency | default('USD', true) }}\"\n    # extra attrs allows you to define extra attributes to pass down to import stage\n    extra_attrs:\n      input_method: \"{{ input_method | default('auto') }}\"\n      # extra attrs are rendered with txn attributes before processing import rules,\n      # so that you can also use attributes from the transaction, making it a very powerful\n      # way to define custom matching logic\n      high_amount_purchase: \"{{ amount \u003e 1000 }}\"\n      # You can also set a simple value like str, bool, or number\n      tag_name: \"my-value\"\n    # filter allows you to consume only the transactions from input which meet certain conditions.\n    # For example, the example below consumes transactions only after 2024-01-01.\n    # This is particular useful when you have hand-crafted books in the past and you also have\n    # bank transactions in CSV input files from that period. To avoid duplication and only\n    # let beanhub-import generate transactions for you with the new transactions, you can add a filter\n    # like this.\n    filter:\n      - field: date\n        op: \"\u003e=\"\n        value: \"2024-01-01\"\n    # loop through different variables with the same input file template to avoid repeating\n    # the same input config over and over\n    loop:\n    - match_path: mercury/*.csv\n      input_account: Assets:Bank:US:Mercury\n      extractor: mercury\n      input_method: \"manual\"\n    - match_path: chase/*.csv\n      input_account: Liabilities:CreditCard:US:ChaseFreedom\n      extractor: chase_credit_card\n\n# the `imports` defines the rules to match transactions extracted from the input files and\n# how to generate the transaction\nimports:\n  - name: Routine expenses\n    match:\n      extractor:\n        equals: \"mercury\"\n      desc:\n        one_of:\n          - Amazon Web Services\n          - Netlify\n          - Mailchimp\n          - Circleci\n          - WeWork\n          - Adobe\n          - Digital Ocean\n          - Microsoft\n          - Mercury IO Cashback\n    actions:\n      # generate a transaction into the beancount file\n      - file: \"books/{{ date.year }}.bean\"\n        txn:\n          narration: \"{{ routine_expenses[desc].narration | default(desc, true) | default(bank_desc, true) }}\"\n          postings:\n            - account: \"{{ routine_expenses[desc].account }}\"\n              amount:\n                number: \"{{ -amount }}\"\n                currency: \"{{ currency | default('USD', true) }}\"\n\n  # To avoid many match/actions statements for mostly identical transaction template,\n  # you can also define different match conditions and the corresponding variables for the transaction template\n  - name: Routine Wells Fargo expenses\n    # the condition shared between all the matches\n    common_cond:\n      extractor:\n        equals: \"plaid\"\n      file:\n        # You can also use named group to capture variables in the regular expression\n        # to be used in generating transactions, like the `filename` as shown in the\n        # regex expression\n        suffix: \"(.+)/Wells Fargo/(?P\u003cfilename\u003e.+).csv\"\n    match:\n      - cond:\n          desc: \"Comcast\"\n        vars:\n          account: Expenses:Internet:Comcast\n          narration: \"Comcast internet fee\"\n      - cond:\n          desc: \"PG\u0026E\"\n        vars:\n          account: Expenses:Gas:PGE\n          narration: \"PG\u0026E Gas\"\n      - cond:\n          # This is the extra attribute value defined in `extra_attrs` under the input rules\n          # We can also use them as part of the matching conditions.\n          input_method:\n            equals: manual\n        vars:\n          account: Expenses:Others\n          narration: \"Manual input\"          \n    actions:\n      # generate a transaction into the beancount file\n      - file: \"books/{{ date.year }}.bean\"\n        txn:\n          payee: \"{{ payee | default(omit, true) }}\"\n          narration: \"{{ narration | default(desc, true) | default(bank_desc, true) }}\"\n          postings:\n            - account: \"{{ account }}\"\n              amount:\n                number: \"{{ -amount }}\"\n                currency: \"{{ currency | default('USD', true) }}\"\n\n  - name: Receive payments from contracting client\n    match:\n      extractor:\n        equals: \"mercury\"\n      desc:\n        equals: Evil Corp\n    actions:\n      - txn:\n          narration: \"Receive payment from Evil Corp\"\n          postings:\n            - account: \"Assets:AccountsReceivable:EvilCorpContracting\"\n              amount:\n                number: \"{{ -amount / 300 }}\"\n                currency: \"EVIL.WORK_HOUR\"\n              price:\n                number: \"300.0\"\n                currency: \"USD\"\n\n  - name: Ignore unused entries\n    match:\n      extractor:\n        equals: \"mercury\"\n      desc:\n        one_of:\n        - Mercury Credit\n        - Mercury Checking xx1234\n    actions:\n      # ignore action is a special type of import rule action to tell the importer to ignore the\n      # transaction so that it won't show up in the \"unprocessed\" section in the import result\n      - type: ignore\n\n```\n\n## Usage\n\nThis project is a library and not meant for end-users.\nIf you simply want to import transactions from CSV into their beancount files, please checkout the `import` command of [beanhub-cli](https://github.com/LaunchPlatform/beanhub-cli).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flaunchplatform%2Fbeanhub-import","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flaunchplatform%2Fbeanhub-import","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flaunchplatform%2Fbeanhub-import/lists"}