ynab-cli 0.3.0__tar.gz → 0.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/.github/workflows/pr.yml +3 -1
  2. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/.gitignore +3 -1
  3. ynab_cli-0.5.0/CHANGELOG.md +11 -0
  4. ynab_cli-0.5.0/Makefile +45 -0
  5. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/PKG-INFO +5 -1
  6. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/docs/index.md +16 -14
  7. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/mkdocs.yml +1 -1
  8. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/pyproject.toml +55 -39
  9. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/budget_summary_response_data.py +1 -1
  10. ynab_cli-0.5.0/src/ynab_cli/domain/use_cases/budgets.py +33 -0
  11. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/host/cli.py +1 -0
  12. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/host/click/cli.py +5 -6
  13. ynab_cli-0.5.0/src/ynab_cli/host/click/commands/budgets.py +54 -0
  14. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/host/click/commands/categories.py +7 -3
  15. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/host/click/commands/payees.py +8 -4
  16. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/host/click/commands/transactions.py +6 -2
  17. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/uv.lock +22 -22
  18. ynab_cli-0.3.0/CHANGELOG.md +0 -35
  19. ynab_cli-0.3.0/Makefile +0 -30
  20. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/.env-sample +0 -0
  21. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/.github/FUNDING.yml +0 -0
  22. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/.github/workflows/publish-to-pypi.yml +0 -0
  23. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/.python-version +0 -0
  24. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/LICENSE.md +0 -0
  25. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/README.md +0 -0
  26. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/docs/transaction_rules.md +0 -0
  27. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/__init__.py +0 -0
  28. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/__init__.py +0 -0
  29. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/rich/__init__.py +0 -0
  30. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/rich/io.py +0 -0
  31. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/textual/__init__.py +0 -0
  32. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/textual/io.py +0 -0
  33. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/__init__.py +0 -0
  34. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/__init__.py +0 -0
  35. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/accounts/__init__.py +0 -0
  36. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/accounts/create_account.py +0 -0
  37. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/accounts/get_account_by_id.py +0 -0
  38. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/accounts/get_accounts.py +0 -0
  39. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/budgets/__init__.py +0 -0
  40. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/budgets/get_budget_by_id.py +0 -0
  41. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/budgets/get_budget_settings_by_id.py +0 -0
  42. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/budgets/get_budgets.py +0 -0
  43. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/categories/__init__.py +0 -0
  44. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/categories/get_categories.py +0 -0
  45. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/categories/get_category_by_id.py +0 -0
  46. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/categories/get_month_category_by_id.py +0 -0
  47. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/categories/update_category.py +0 -0
  48. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/categories/update_month_category.py +0 -0
  49. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/months/__init__.py +0 -0
  50. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/months/get_budget_month.py +0 -0
  51. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/months/get_budget_months.py +0 -0
  52. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/payee_locations/__init__.py +0 -0
  53. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/payee_locations/get_payee_location_by_id.py +0 -0
  54. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/payee_locations/get_payee_locations.py +0 -0
  55. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/payee_locations/get_payee_locations_by_payee.py +0 -0
  56. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/payees/__init__.py +0 -0
  57. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/payees/get_payee_by_id.py +0 -0
  58. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/payees/get_payees.py +0 -0
  59. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/payees/update_payee.py +0 -0
  60. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/scheduled_transactions/__init__.py +0 -0
  61. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/scheduled_transactions/create_scheduled_transaction.py +0 -0
  62. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/scheduled_transactions/delete_scheduled_transaction.py +0 -0
  63. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/scheduled_transactions/get_scheduled_transaction_by_id.py +0 -0
  64. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/scheduled_transactions/get_scheduled_transactions.py +0 -0
  65. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/scheduled_transactions/update_scheduled_transaction.py +0 -0
  66. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/transactions/__init__.py +0 -0
  67. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/transactions/create_transaction.py +0 -0
  68. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/transactions/delete_transaction.py +0 -0
  69. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/transactions/get_transaction_by_id.py +0 -0
  70. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/transactions/get_transactions.py +0 -0
  71. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/transactions/get_transactions_by_account.py +0 -0
  72. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/transactions/get_transactions_by_category.py +0 -0
  73. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/transactions/get_transactions_by_month.py +0 -0
  74. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/transactions/get_transactions_by_payee.py +0 -0
  75. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/transactions/import_transactions.py +0 -0
  76. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/transactions/update_transaction.py +0 -0
  77. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/transactions/update_transactions.py +0 -0
  78. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/user/__init__.py +0 -0
  79. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/api/user/get_user.py +0 -0
  80. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/client.py +0 -0
  81. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/errors.py +0 -0
  82. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/__init__.py +0 -0
  83. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/account.py +0 -0
  84. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/account_response.py +0 -0
  85. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/account_response_data.py +0 -0
  86. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/account_type.py +0 -0
  87. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/accounts_response.py +0 -0
  88. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/accounts_response_data.py +0 -0
  89. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/budget_detail.py +0 -0
  90. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/budget_detail_response.py +0 -0
  91. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/budget_detail_response_data.py +0 -0
  92. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/budget_settings.py +0 -0
  93. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/budget_settings_response.py +0 -0
  94. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/budget_settings_response_data.py +0 -0
  95. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/budget_summary.py +0 -0
  96. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/budget_summary_response.py +0 -0
  97. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/bulk_response.py +0 -0
  98. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/bulk_response_data.py +0 -0
  99. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/bulk_response_data_bulk.py +0 -0
  100. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/bulk_transactions.py +0 -0
  101. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/categories_response.py +0 -0
  102. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/categories_response_data.py +0 -0
  103. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/category.py +0 -0
  104. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/category_goal_type_type_1.py +0 -0
  105. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/category_goal_type_type_2_type_1.py +0 -0
  106. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/category_goal_type_type_3_type_1.py +0 -0
  107. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/category_group.py +0 -0
  108. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/category_group_with_categories.py +0 -0
  109. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/category_response.py +0 -0
  110. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/category_response_data.py +0 -0
  111. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/currency_format_type_0.py +0 -0
  112. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/date_format_type_0.py +0 -0
  113. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/error_detail.py +0 -0
  114. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/error_response.py +0 -0
  115. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/existing_transaction.py +0 -0
  116. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/get_transactions_by_account_type.py +0 -0
  117. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/get_transactions_by_category_type.py +0 -0
  118. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/get_transactions_by_month_type.py +0 -0
  119. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/get_transactions_by_payee_type.py +0 -0
  120. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/get_transactions_type.py +0 -0
  121. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/hybrid_transaction.py +0 -0
  122. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/hybrid_transaction_type.py +0 -0
  123. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/hybrid_transactions_response.py +0 -0
  124. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/hybrid_transactions_response_data.py +0 -0
  125. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/loan_account_periodic_value_type_0.py +0 -0
  126. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/month_detail.py +0 -0
  127. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/month_detail_response.py +0 -0
  128. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/month_detail_response_data.py +0 -0
  129. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/month_summaries_response.py +0 -0
  130. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/month_summaries_response_data.py +0 -0
  131. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/month_summary.py +0 -0
  132. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/new_transaction.py +0 -0
  133. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/patch_category_wrapper.py +0 -0
  134. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/patch_month_category_wrapper.py +0 -0
  135. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/patch_payee_wrapper.py +0 -0
  136. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/patch_transactions_wrapper.py +0 -0
  137. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/payee.py +0 -0
  138. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/payee_location.py +0 -0
  139. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/payee_location_response.py +0 -0
  140. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/payee_location_response_data.py +0 -0
  141. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/payee_locations_response.py +0 -0
  142. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/payee_locations_response_data.py +0 -0
  143. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/payee_response.py +0 -0
  144. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/payee_response_data.py +0 -0
  145. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/payees_response.py +0 -0
  146. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/payees_response_data.py +0 -0
  147. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/post_account_wrapper.py +0 -0
  148. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/post_scheduled_transaction_wrapper.py +0 -0
  149. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/post_transactions_wrapper.py +0 -0
  150. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/put_scheduled_transaction_wrapper.py +0 -0
  151. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/put_transaction_wrapper.py +0 -0
  152. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/save_account.py +0 -0
  153. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/save_category.py +0 -0
  154. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/save_category_response.py +0 -0
  155. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/save_category_response_data.py +0 -0
  156. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/save_month_category.py +0 -0
  157. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/save_payee.py +0 -0
  158. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/save_payee_response.py +0 -0
  159. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/save_payee_response_data.py +0 -0
  160. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/save_scheduled_transaction.py +0 -0
  161. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/save_sub_transaction.py +0 -0
  162. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/save_transaction_with_id_or_import_id.py +0 -0
  163. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/save_transaction_with_optional_fields.py +0 -0
  164. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/save_transactions_response.py +0 -0
  165. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/save_transactions_response_data.py +0 -0
  166. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/scheduled_sub_transaction.py +0 -0
  167. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/scheduled_transaction_detail.py +0 -0
  168. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/scheduled_transaction_frequency.py +0 -0
  169. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/scheduled_transaction_response.py +0 -0
  170. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/scheduled_transaction_response_data.py +0 -0
  171. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/scheduled_transaction_summary.py +0 -0
  172. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/scheduled_transaction_summary_frequency.py +0 -0
  173. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/scheduled_transactions_response.py +0 -0
  174. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/scheduled_transactions_response_data.py +0 -0
  175. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/sub_transaction.py +0 -0
  176. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/transaction_cleared_status.py +0 -0
  177. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/transaction_detail.py +0 -0
  178. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/transaction_flag_color_type_1.py +0 -0
  179. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/transaction_flag_color_type_2_type_1.py +0 -0
  180. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/transaction_flag_color_type_3_type_1.py +0 -0
  181. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/transaction_response.py +0 -0
  182. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/transaction_response_data.py +0 -0
  183. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/transaction_summary.py +0 -0
  184. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/transaction_summary_debt_transaction_type_type_1.py +0 -0
  185. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/transaction_summary_debt_transaction_type_type_2_type_1.py +0 -0
  186. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/transaction_summary_debt_transaction_type_type_3_type_1.py +0 -0
  187. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/transactions_import_response.py +0 -0
  188. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/transactions_import_response_data.py +0 -0
  189. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/transactions_response.py +0 -0
  190. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/transactions_response_data.py +0 -0
  191. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/user.py +0 -0
  192. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/user_response.py +0 -0
  193. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/models/user_response_data.py +0 -0
  194. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/types.py +0 -0
  195. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/adapters/ynab/util.py +0 -0
  196. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/domain/__init__.py +0 -0
  197. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/domain/constants.py +0 -0
  198. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/domain/models/__init__.py +0 -0
  199. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/domain/models/rules.py +0 -0
  200. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/domain/ports/__init__.py +0 -0
  201. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/domain/ports/io.py +0 -0
  202. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/domain/settings.py +0 -0
  203. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/domain/use_cases/__init__.py +0 -0
  204. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/domain/use_cases/categories.py +0 -0
  205. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/domain/use_cases/payees.py +0 -0
  206. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/domain/use_cases/transactions.py +0 -0
  207. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/host/__init__.py +0 -0
  208. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/host/click/__init__.py +0 -0
  209. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/host/click/commands/__init__.py +0 -0
  210. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/host/click/commands/rich/__init__.py +0 -0
  211. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/host/click/commands/rich/progress_table.py +0 -0
  212. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/host/constants.py +0 -0
  213. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/host/textual/__init__.py +0 -0
  214. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/host/textual/app.py +0 -0
  215. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/host/textual/app.tcss +0 -0
  216. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/host/textual/cli.py +0 -0
  217. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/host/textual/widgets/__init__.py +0 -0
  218. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/host/textual/widgets/categories.py +0 -0
  219. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/host/textual/widgets/payees.py +0 -0
  220. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/host/textual/widgets/transactions.py +0 -0
  221. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/src/ynab_cli/py.typed +0 -0
  222. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/tests/__init__.py +0 -0
  223. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/tests/factories/__init__.py +0 -0
  224. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/tests/factories/ynab.py +0 -0
  225. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/tests/unit/__init__.py +0 -0
  226. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/tests/unit/conftest.py +0 -0
  227. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/tests/unit/domain/__init__.py +0 -0
  228. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/tests/unit/domain/use_cases/__init__.py +0 -0
  229. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/tests/unit/domain/use_cases/test_categories.py +0 -0
  230. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/tests/unit/domain/use_cases/test_payees.py +0 -0
  231. {ynab_cli-0.3.0 → ynab_cli-0.5.0}/tests/unit/domain/use_cases/test_transactions.py +0 -0
@@ -19,4 +19,6 @@ jobs:
19
19
  - run: uv run ruff format --check . # check formatting is correct
20
20
  - run: uv run ruff check --no-fix . # and linting
21
21
  - run: uv run mypy . # typecheck too
22
- - run: uv run pytest tests # then run your tests!
22
+ - run: uv run pytest tests # then run your tests!
23
+ - run: uv build # make sure the package builds
24
+ - run: uv run mkdocs build # make sure the docs build
@@ -7,4 +7,6 @@ __pycache__/
7
7
  .pytest_cache/
8
8
  .ruff_cache/
9
9
  .venv/
10
- .vscode/
10
+ .vscode/
11
+ dist/
12
+ site/
@@ -0,0 +1,11 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+ ## v0.5.0 (2025-06-06)
8
+
9
+ ### Feat
10
+
11
+ - implement initial cli
@@ -0,0 +1,45 @@
1
+ .PHONY: lint test clean version
2
+
3
+ .venv: pyproject.toml # the python virtual environment
4
+ uv sync
5
+ touch .venv
6
+
7
+ lint: .venv # run linters and type checkers
8
+ uv run ruff format .
9
+ uv run ruff check .
10
+ uv run mypy .
11
+
12
+ test: .venv lint # run tests with coverage
13
+ uv run pytest --cov=src tests
14
+
15
+ clean: # clean up build artifacts and caches
16
+ rm -f .coverage
17
+ rm -rf dist
18
+ rm -rf htmlcov
19
+ rm -rf site
20
+ find . -type f -name .DS_Store | xargs rm -rf
21
+ find . -type d -name __pycache__ | xargs rm -rf
22
+ find . -type d -name .mypy_cache | xargs rm -rf
23
+ find . -type d -name .pytest_cache | xargs rm -rf
24
+ find . -type d -name .ruff_cache | xargs rm -rf
25
+ find . -type d -empty -delete
26
+
27
+ ynab-sdk: # regenerate the YNAB SDK from the OpenAPI spec
28
+ rm -rf ./src/ynab_cli/adapters/ynab
29
+ mkdir -p ./src/ynab_cli/adapters/ynab
30
+ uvx openapi-python-client generate --meta none --url https://api.ynab.com/papi/open_api_spec.yaml --output-path ./src/ynab_cli/adapters/ynab --overwrite
31
+
32
+ dist: clean # build the distribution package
33
+ uv build
34
+
35
+ site: clean # build the documentation site
36
+ uv run mkdocs build
37
+
38
+ site-serve: clean # serve the documentation site locally
39
+ uv run mkdocs serve
40
+
41
+ site-gh: clean # deploy the documentation site to GitHub Pages
42
+ uv run mkdocs gh-deploy
43
+
44
+ version: clean # update the version in pyproject.toml and create a new tag
45
+ cz bump
@@ -1,9 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ynab-cli
3
- Version: 0.3.0
3
+ Version: 0.5.0
4
4
  Summary: YNAB Command Line Interface
5
+ Project-URL: documentation, https://jeffsawatzky.github.io/ynab-cli/
6
+ Project-URL: source, https://github.com/jeffsawatzky/ynab-cli
7
+ Project-URL: funding, https://github.com/sponsors/jeffsawatzky
5
8
  Author: Jeff Sawatzky
6
9
  License-File: LICENSE.md
10
+ Keywords: budget,cli,click,textual,ynab
7
11
  Requires-Python: >=3.11
8
12
  Requires-Dist: attrs~=25.3
9
13
  Requires-Dist: click-default-group~=1.2
@@ -4,33 +4,35 @@ This is a simple cli/tui application written in python to help manage your YNAB
4
4
 
5
5
  ## Requirements
6
6
 
7
- - Python 3.11+
8
- - [uv](https://docs.astral.sh/uv/)
9
- - Your [YNAB developer access token](https://api.ynab.com/#personal-access-tokens)
10
- - Your YNAB budget ID. You can get this from your browser URL while you have your budget open. For example, if the URL looks like `https://app.ynab.com/aaaaaaaa-1111-bbbb-2222-ddddddd` then the budget ID is `aaaaaaaa-1111-bbbb-2222-ddddddd`.
7
+ - [uv](https://docs.astral.sh/uv/getting-started/installation/) which allows you to easily run python applications.
8
+ - Your [YNAB developer access token](https://api.ynab.com/#personal-access-tokens).
9
+
10
+ !!! warning
11
+ Developer access tokens are rate limited to 200 requests per hour. Some of the commands below will provide you an opportunity to enter a new developer access token when the current one has exceeded it's limit. It also seems like there is a limit to how many developer access tokens you can create from the developer settings UI.
12
+
13
+ - Your YNAB budget ID. Once you have `uv` and your `access token` you can list your budgets by running:
11
14
 
12
- ## Installation
13
15
  ```sh
14
- $ git clone https://github.com/jeffsawatzky/ynab-cli.git
15
- $ cd ynab-cli
16
- $ uv sync
16
+ $ uvx ynab-cli run --access-token your_access_token budgets list-all
17
17
  ```
18
18
 
19
19
  ## Usage
20
20
 
21
- !!! warning
22
- Developer access tokens are rate limited to 200 requests per hour. Some of the commands below will provide you an opportunity to enter a new developer access token when the current one has exceeded it's limit. It also seems like there is a limit to how many developer access tokens you can create from the developer settings UI.
23
-
24
21
  !!! note
25
- YNAB CLI supports environment variables and dotenv (`.env`) files for specifying options. See the `.env-sample` file for some examples. It looks for the `.env` file in current working directory.
22
+ YNAB CLI supports environment variables and dotenv (`.env`) files for specifying options. See the `.env-sample` file for some examples. YNAB CLI looks for the `.env` file in current working directory. If you create a `.env` file with the following information you won't need to keep entering it on the command line.
23
+
24
+ ``` title=".env"
25
+ YNAB_CLI_ACCESS_TOKEN=your_access_token
26
+ YNAB_CLI_BUDGET_ID=your_budget_id
27
+ ```
26
28
 
27
29
  To run the text ui, execute the following command:
28
30
 
29
31
  ```sh
30
- $ uv run ynab-cli
32
+ $ uvx ynab-cli
31
33
  ```
32
34
 
33
- Full command line usage is below.
35
+ The individual CLI commands can be similarily run using `uvx`. Full command line usage is below.
34
36
 
35
37
  ::: mkdocs-click
36
38
  :module: ynab_cli.host.cli
@@ -1,5 +1,5 @@
1
1
  site_name: YNAB CLI
2
- site_url: http://jeffsawatzky.github.io/ynab-cli/
2
+ site_url: https://jeffsawatzky.github.io/ynab-cli/
3
3
  repo_url: https://github.com/jeffsawatzky/ynab-cli
4
4
 
5
5
  theme:
@@ -1,44 +1,59 @@
1
1
  [project]
2
2
  name = "ynab-cli"
3
- version = "0.3.0"
3
+ version = "0.5.0"
4
4
  description = "YNAB Command Line Interface"
5
5
  readme = "README.md"
6
+ requires-python = ">=3.11"
7
+ license-files = [
8
+ "LICENSE.md"
9
+ ]
6
10
  authors = [
7
- { name = "Jeff Sawatzky" }
11
+ { name = "Jeff Sawatzky" }
12
+ ]
13
+ keywords = [
14
+ "ynab",
15
+ "cli",
16
+ "textual",
17
+ "click",
18
+ "budget",
8
19
  ]
9
- requires-python = ">=3.11"
10
20
  dependencies = [
11
- "attrs~=25.3",
12
- "click-default-group~=1.2",
13
- "click~=8.2",
14
- "httpx~=0.28",
15
- "python-dotenv~=1.1",
16
- "rapidfuzz~=3.13",
17
- "rich~=14.0",
18
- "rule-engine~=4.5",
19
- "textual-fspicker~=0.4",
20
- "textual~=3.3",
21
- "typing-extensions~=4.14",
21
+ "attrs~=25.3",
22
+ "click-default-group~=1.2",
23
+ "click~=8.2",
24
+ "httpx~=0.28",
25
+ "python-dotenv~=1.1",
26
+ "rapidfuzz~=3.13",
27
+ "rich~=14.0",
28
+ "rule-engine~=4.5",
29
+ "textual-fspicker~=0.4",
30
+ "textual~=3.3",
31
+ "typing-extensions~=4.14",
22
32
  ]
23
33
 
34
+ [project.urls]
35
+ documentation = "https://jeffsawatzky.github.io/ynab-cli/"
36
+ source = "https://github.com/jeffsawatzky/ynab-cli"
37
+ funding = "https://github.com/sponsors/jeffsawatzky"
38
+
24
39
  [project.scripts]
25
40
  ynab-cli = "ynab_cli.host.cli:main"
26
41
 
27
42
 
28
43
  [dependency-groups]
29
44
  dev = [
30
- "factory-boy>=3.3.3",
31
- "mkdocs-click>=0.9.0",
32
- "mkdocs-material>=9.6.14",
33
- "mkdocs>=1.6.1",
34
- "mypy>=1.16.0",
35
- "pytest-asyncio>=1.0.0",
36
- "pytest-cov>=6.1.1",
37
- "pytest-mock>=3.14.1",
38
- "pytest>=8.4.0",
39
- "ruff>=0.11.12",
40
- "textual-dev>=1.7.0",
41
- "types-python-dateutil>=2.9.0.20250516",
45
+ "factory-boy>=3.3.3",
46
+ "mkdocs-click>=0.9.0",
47
+ "mkdocs-material>=9.6.14",
48
+ "mkdocs>=1.6.1",
49
+ "mypy>=1.16.0",
50
+ "pytest-asyncio>=1.0.0",
51
+ "pytest-cov>=6.1.1",
52
+ "pytest-mock>=3.14.1",
53
+ "pytest>=8.4.0",
54
+ "ruff>=0.11.12",
55
+ "textual-dev>=1.7.0",
56
+ "types-python-dateutil>=2.9.0.20250516",
42
57
  ]
43
58
 
44
59
 
@@ -73,21 +88,21 @@ target-version = "py311"
73
88
 
74
89
  [tool.ruff.lint]
75
90
  extend-select = [
76
- "W", # warnings
77
- "I", # isort
78
- "C90", # mccabe
79
- "N", # pep8-naming
80
- "UP", # pyupgrade
81
- "S", # flake8-bandit
82
- "B", # flake8-bugbear
83
- "A", # flake8-builtins
84
- "DTZ", # flake8-datetimez
85
- "PT", # flake8-pytest-style
86
- "TID", # flake8-tidy-imports
87
- "RUF", # ruff specific rules
91
+ "W", # warnings
92
+ "I", # isort
93
+ "C90", # mccabe
94
+ "N", # pep8-naming
95
+ "UP", # pyupgrade
96
+ "S", # flake8-bandit
97
+ "B", # flake8-bugbear
98
+ "A", # flake8-builtins
99
+ "DTZ", # flake8-datetimez
100
+ "PT", # flake8-pytest-style
101
+ "TID", # flake8-tidy-imports
102
+ "RUF", # ruff specific rules
88
103
  ]
89
104
  extend-ignore = [
90
- "S110", # `try`-`except`-`pass` detected
105
+ "S110", # `try`-`except`-`pass` detected
91
106
  ]
92
107
 
93
108
  [tool.ruff.lint.per-file-ignores]
@@ -105,6 +120,7 @@ builtins-ignorelist = ["type", "id"]
105
120
 
106
121
  [tool.commitizen]
107
122
  name = "cz_conventional_commits"
123
+ annotated_tag = true
108
124
  tag_format = "v$version"
109
125
  version_scheme = "pep440"
110
126
  version_provider = "uv"
@@ -61,7 +61,7 @@ class BudgetSummaryResponseData:
61
61
 
62
62
  _default_budget = d.pop("default_budget", UNSET)
63
63
  default_budget: Unset | BudgetSummary
64
- if isinstance(_default_budget, Unset):
64
+ if not _default_budget or isinstance(_default_budget, Unset):
65
65
  default_budget = UNSET
66
66
  else:
67
67
  default_budget = BudgetSummary.from_dict(_default_budget)
@@ -0,0 +1,33 @@
1
+ from collections.abc import AsyncIterator
2
+ from typing import TypedDict
3
+
4
+ from ynab_cli.adapters import ynab
5
+ from ynab_cli.adapters.ynab import models, util
6
+ from ynab_cli.adapters.ynab.api.budgets import get_budgets
7
+ from ynab_cli.domain import ports
8
+ from ynab_cli.domain.constants import YNAB_API_URL
9
+ from ynab_cli.domain.settings import Settings
10
+
11
+
12
+ class ListAllParams(TypedDict):
13
+ pass
14
+
15
+
16
+ async def list_all(settings: Settings, io: ports.IO, params: ListAllParams) -> AsyncIterator[models.BudgetSummary]:
17
+ async with ynab.AuthenticatedClient(base_url=YNAB_API_URL, token=settings.ynab.access_token) as client:
18
+ try:
19
+ budgets = (
20
+ await util.get_asyncio_detailed(io, get_budgets.asyncio_detailed, include_accounts=True, client=client)
21
+ ).data.budgets
22
+ budgets.sort(key=lambda b: b.name)
23
+
24
+ progress_total = len(budgets)
25
+ for budget in budgets:
26
+ await io.progress.update(total=progress_total, advance=1)
27
+ yield budget
28
+
29
+ except util.ApiError as e:
30
+ if e.status_code == 429:
31
+ await io.print("API rate limit exceeded. Try again later, or get a new access token.")
32
+ else:
33
+ await io.print(f"Exception when calling YNAB: {e}\n")
@@ -10,6 +10,7 @@ from ynab_cli.host.textual.cli import tui
10
10
  @click.group(cls=DefaultGroup, default="tui", default_if_no_args=True)
11
11
  @click.option("--dry-run", is_flag=True, default=False, help="Run without making any changes.")
12
12
  @click.option("--debug", is_flag=True, default=False, help="Enable debug mode for more verbose output.")
13
+ @click.version_option()
13
14
  @click.pass_context
14
15
  def cli(
15
16
  ctx: click.Context,
@@ -3,8 +3,8 @@ import logging
3
3
  import click
4
4
  from rich.logging import RichHandler
5
5
 
6
- from ynab_cli.domain.settings import Settings, YnabSettings
7
- from ynab_cli.host.click.commands import categories, payees, transactions
6
+ from ynab_cli.domain.settings import Settings
7
+ from ynab_cli.host.click.commands import budgets, categories, payees, transactions
8
8
  from ynab_cli.host.constants import CONTEXT_KEY_SETTINGS, ENV_PREFIX
9
9
 
10
10
 
@@ -17,18 +17,16 @@ from ynab_cli.host.constants import CONTEXT_KEY_SETTINGS, ENV_PREFIX
17
17
  show_envvar=True,
18
18
  help="YNAB API access token.",
19
19
  )
20
- @click.option("--budget-id", prompt=True, envvar=f"{ENV_PREFIX}_BUDGET_ID", show_envvar=True, help="YNAB budget ID.")
21
20
  @click.pass_context
22
21
  def run(
23
22
  ctx: click.Context,
24
23
  access_token: str,
25
- budget_id: str,
26
24
  ) -> None:
27
25
  """Main entrypoint for YNAB CLI commands."""
28
26
 
29
27
  ctx.ensure_object(dict)
30
28
  settings: Settings = ctx.obj.get(CONTEXT_KEY_SETTINGS, Settings())
31
- settings.ynab = YnabSettings(access_token=access_token, budget_id=budget_id)
29
+ settings.ynab.access_token = access_token
32
30
  ctx.obj[CONTEXT_KEY_SETTINGS] = settings
33
31
 
34
32
  logging.basicConfig(
@@ -39,6 +37,7 @@ def run(
39
37
  )
40
38
 
41
39
 
42
- run.add_command(payees.payees)
40
+ run.add_command(budgets.budgets)
43
41
  run.add_command(categories.categories)
42
+ run.add_command(payees.payees)
44
43
  run.add_command(transactions.transactions)
@@ -0,0 +1,54 @@
1
+ import asyncio
2
+
3
+ import click
4
+ from rich.table import Table
5
+
6
+ from ynab_cli.adapters.rich import io
7
+ from ynab_cli.domain.settings import Settings
8
+ from ynab_cli.domain.use_cases import budgets as use_cases
9
+ from ynab_cli.host.click.commands.rich.progress_table import ProgressTable
10
+ from ynab_cli.host.constants import CONTEXT_KEY_SETTINGS
11
+
12
+
13
+ async def _list_all(settings: Settings) -> None:
14
+ params: use_cases.ListAllParams = {}
15
+
16
+ table = Table(title="All Budgets")
17
+ table.add_column("Budget ID")
18
+ table.add_column("Budget Name")
19
+
20
+ console = None
21
+ with ProgressTable(table) as progress:
22
+ console = progress.console
23
+
24
+ task_id = progress.add_task("Loading all budgets...")
25
+ async for budget in use_cases.list_all(settings, io.RichIO((progress, task_id)), params):
26
+ table.add_row(
27
+ str(budget.id),
28
+ str(budget.name),
29
+ )
30
+
31
+ if console:
32
+ console.print(table)
33
+
34
+
35
+ @click.command()
36
+ @click.pass_context
37
+ def list_all(ctx: click.Context) -> None:
38
+ """List all budgets in YNAB."""
39
+
40
+ ctx.ensure_object(dict)
41
+ asyncio.run(_list_all(ctx.obj.get(CONTEXT_KEY_SETTINGS, Settings())))
42
+
43
+
44
+ @click.group()
45
+ @click.pass_context
46
+ def budgets(ctx: click.Context) -> None:
47
+ """Manage YNAB budgets in YNAB."""
48
+
49
+ ctx.ensure_object(dict)
50
+ settings: Settings = ctx.obj.get(CONTEXT_KEY_SETTINGS, Settings())
51
+ ctx.obj[CONTEXT_KEY_SETTINGS] = settings
52
+
53
+
54
+ budgets.add_command(list_all)
@@ -7,7 +7,7 @@ from ynab_cli.adapters.rich import io
7
7
  from ynab_cli.domain.settings import Settings
8
8
  from ynab_cli.domain.use_cases import categories as use_cases
9
9
  from ynab_cli.host.click.commands.rich.progress_table import ProgressTable
10
- from ynab_cli.host.constants import CONTEXT_KEY_SETTINGS
10
+ from ynab_cli.host.constants import CONTEXT_KEY_SETTINGS, ENV_PREFIX
11
11
 
12
12
 
13
13
  async def _list_unused(settings: Settings) -> None:
@@ -81,12 +81,16 @@ def list_all(ctx: click.Context) -> None:
81
81
 
82
82
 
83
83
  @click.group()
84
+ @click.option("--budget-id", prompt=True, envvar=f"{ENV_PREFIX}_BUDGET_ID", show_envvar=True, help="YNAB budget ID.")
84
85
  @click.pass_context
85
- def categories(ctx: click.Context) -> None:
86
+ def categories(ctx: click.Context, budget_id: str) -> None:
86
87
  """Manage YNAB categories in the YNAB budget."""
87
88
 
88
89
  ctx.ensure_object(dict)
90
+ settings: Settings = ctx.obj.get(CONTEXT_KEY_SETTINGS, Settings())
91
+ settings.ynab.budget_id = budget_id
92
+ ctx.obj[CONTEXT_KEY_SETTINGS] = settings
89
93
 
90
94
 
91
- categories.add_command(list_unused)
92
95
  categories.add_command(list_all)
96
+ categories.add_command(list_unused)
@@ -7,7 +7,7 @@ from ynab_cli.adapters.rich import io
7
7
  from ynab_cli.domain.settings import Settings
8
8
  from ynab_cli.domain.use_cases import payees as use_cases
9
9
  from ynab_cli.host.click.commands.rich.progress_table import ProgressTable
10
- from ynab_cli.host.constants import CONTEXT_KEY_SETTINGS
10
+ from ynab_cli.host.constants import CONTEXT_KEY_SETTINGS, ENV_PREFIX
11
11
 
12
12
 
13
13
  async def _normalize_names(settings: Settings) -> None:
@@ -144,14 +144,18 @@ def list_all(ctx: click.Context) -> None:
144
144
 
145
145
 
146
146
  @click.group()
147
+ @click.option("--budget-id", prompt=True, envvar=f"{ENV_PREFIX}_BUDGET_ID", show_envvar=True, help="YNAB budget ID.")
147
148
  @click.pass_context
148
- def payees(ctx: click.Context) -> None:
149
+ def payees(ctx: click.Context, budget_id: str) -> None:
149
150
  """Manage payees in the YNAB budget."""
150
151
 
151
152
  ctx.ensure_object(dict)
153
+ settings: Settings = ctx.obj.get(CONTEXT_KEY_SETTINGS, Settings())
154
+ settings.ynab.budget_id = budget_id
155
+ ctx.obj[CONTEXT_KEY_SETTINGS] = settings
152
156
 
153
157
 
154
- payees.add_command(normalize_names)
158
+ payees.add_command(list_all)
155
159
  payees.add_command(list_duplicates)
156
160
  payees.add_command(list_unused)
157
- payees.add_command(list_all)
161
+ payees.add_command(normalize_names)
@@ -10,7 +10,7 @@ from ynab_cli.domain.models import rules
10
10
  from ynab_cli.domain.settings import Settings
11
11
  from ynab_cli.domain.use_cases import transactions as use_cases
12
12
  from ynab_cli.host.click.commands.rich.progress_table import ProgressTable
13
- from ynab_cli.host.constants import CONTEXT_KEY_SETTINGS
13
+ from ynab_cli.host.constants import CONTEXT_KEY_SETTINGS, ENV_PREFIX
14
14
 
15
15
 
16
16
  async def _apply_rules(settings: Settings, transaction_rules: rules.TransactionRules) -> None:
@@ -66,11 +66,15 @@ def apply_rules(ctx: click.Context, rules_file: IO[Any]) -> None:
66
66
 
67
67
 
68
68
  @click.group()
69
+ @click.option("--budget-id", prompt=True, envvar=f"{ENV_PREFIX}_BUDGET_ID", show_envvar=True, help="YNAB budget ID.")
69
70
  @click.pass_context
70
- def transactions(ctx: click.Context) -> None:
71
+ def transactions(ctx: click.Context, budget_id: str) -> None:
71
72
  """Manage transactions in the YNAB budget."""
72
73
 
73
74
  ctx.ensure_object(dict)
75
+ settings: Settings = ctx.obj.get(CONTEXT_KEY_SETTINGS, Settings())
76
+ settings.ynab.budget_id = budget_id
77
+ ctx.obj[CONTEXT_KEY_SETTINGS] = settings
74
78
 
75
79
 
76
80
  transactions.add_command(apply_rules)
@@ -1197,27 +1197,27 @@ wheels = [
1197
1197
 
1198
1198
  [[package]]
1199
1199
  name = "ruff"
1200
- version = "0.11.12"
1201
- source = { registry = "https://pypi.org/simple" }
1202
- sdist = { url = "https://files.pythonhosted.org/packages/15/0a/92416b159ec00cdf11e5882a9d80d29bf84bba3dbebc51c4898bfbca1da6/ruff-0.11.12.tar.gz", hash = "sha256:43cf7f69c7d7c7d7513b9d59c5d8cafd704e05944f978614aa9faff6ac202603", size = 4202289, upload-time = "2025-05-29T13:31:40.037Z" }
1203
- wheels = [
1204
- { url = "https://files.pythonhosted.org/packages/60/cc/53eb79f012d15e136d40a8e8fc519ba8f55a057f60b29c2df34efd47c6e3/ruff-0.11.12-py3-none-linux_armv6l.whl", hash = "sha256:c7680aa2f0d4c4f43353d1e72123955c7a2159b8646cd43402de6d4a3a25d7cc", size = 10285597, upload-time = "2025-05-29T13:30:57.539Z" },
1205
- { url = "https://files.pythonhosted.org/packages/e7/d7/73386e9fb0232b015a23f62fea7503f96e29c29e6c45461d4a73bac74df9/ruff-0.11.12-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:2cad64843da9f134565c20bcc430642de897b8ea02e2e79e6e02a76b8dcad7c3", size = 11053154, upload-time = "2025-05-29T13:31:00.865Z" },
1206
- { url = "https://files.pythonhosted.org/packages/4e/eb/3eae144c5114e92deb65a0cb2c72326c8469e14991e9bc3ec0349da1331c/ruff-0.11.12-py3-none-macosx_11_0_arm64.whl", hash = "sha256:9b6886b524a1c659cee1758140138455d3c029783d1b9e643f3624a5ee0cb0aa", size = 10403048, upload-time = "2025-05-29T13:31:03.413Z" },
1207
- { url = "https://files.pythonhosted.org/packages/29/64/20c54b20e58b1058db6689e94731f2a22e9f7abab74e1a758dfba058b6ca/ruff-0.11.12-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cc3a3690aad6e86c1958d3ec3c38c4594b6ecec75c1f531e84160bd827b2012", size = 10597062, upload-time = "2025-05-29T13:31:05.539Z" },
1208
- { url = "https://files.pythonhosted.org/packages/29/3a/79fa6a9a39422a400564ca7233a689a151f1039110f0bbbabcb38106883a/ruff-0.11.12-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f97fdbc2549f456c65b3b0048560d44ddd540db1f27c778a938371424b49fe4a", size = 10155152, upload-time = "2025-05-29T13:31:07.986Z" },
1209
- { url = "https://files.pythonhosted.org/packages/e5/a4/22c2c97b2340aa968af3a39bc38045e78d36abd4ed3fa2bde91c31e712e3/ruff-0.11.12-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:74adf84960236961090e2d1348c1a67d940fd12e811a33fb3d107df61eef8fc7", size = 11723067, upload-time = "2025-05-29T13:31:10.57Z" },
1210
- { url = "https://files.pythonhosted.org/packages/bc/cf/3e452fbd9597bcd8058856ecd42b22751749d07935793a1856d988154151/ruff-0.11.12-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:b56697e5b8bcf1d61293ccfe63873aba08fdbcbbba839fc046ec5926bdb25a3a", size = 12460807, upload-time = "2025-05-29T13:31:12.88Z" },
1211
- { url = "https://files.pythonhosted.org/packages/2f/ec/8f170381a15e1eb7d93cb4feef8d17334d5a1eb33fee273aee5d1f8241a3/ruff-0.11.12-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4d47afa45e7b0eaf5e5969c6b39cbd108be83910b5c74626247e366fd7a36a13", size = 12063261, upload-time = "2025-05-29T13:31:15.236Z" },
1212
- { url = "https://files.pythonhosted.org/packages/0d/bf/57208f8c0a8153a14652a85f4116c0002148e83770d7a41f2e90b52d2b4e/ruff-0.11.12-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:692bf9603fe1bf949de8b09a2da896f05c01ed7a187f4a386cdba6760e7f61be", size = 11329601, upload-time = "2025-05-29T13:31:18.68Z" },
1213
- { url = "https://files.pythonhosted.org/packages/c3/56/edf942f7fdac5888094d9ffa303f12096f1a93eb46570bcf5f14c0c70880/ruff-0.11.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08033320e979df3b20dba567c62f69c45e01df708b0f9c83912d7abd3e0801cd", size = 11522186, upload-time = "2025-05-29T13:31:21.216Z" },
1214
- { url = "https://files.pythonhosted.org/packages/ed/63/79ffef65246911ed7e2290aeece48739d9603b3a35f9529fec0fc6c26400/ruff-0.11.12-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:929b7706584f5bfd61d67d5070f399057d07c70585fa8c4491d78ada452d3bef", size = 10449032, upload-time = "2025-05-29T13:31:23.417Z" },
1215
- { url = "https://files.pythonhosted.org/packages/88/19/8c9d4d8a1c2a3f5a1ea45a64b42593d50e28b8e038f1aafd65d6b43647f3/ruff-0.11.12-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:7de4a73205dc5756b8e09ee3ed67c38312dce1aa28972b93150f5751199981b5", size = 10129370, upload-time = "2025-05-29T13:31:25.777Z" },
1216
- { url = "https://files.pythonhosted.org/packages/bc/0f/2d15533eaa18f460530a857e1778900cd867ded67f16c85723569d54e410/ruff-0.11.12-py3-none-musllinux_1_2_i686.whl", hash = "sha256:2635c2a90ac1b8ca9e93b70af59dfd1dd2026a40e2d6eebaa3efb0465dd9cf02", size = 11123529, upload-time = "2025-05-29T13:31:28.396Z" },
1217
- { url = "https://files.pythonhosted.org/packages/4f/e2/4c2ac669534bdded835356813f48ea33cfb3a947dc47f270038364587088/ruff-0.11.12-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:d05d6a78a89166f03f03a198ecc9d18779076ad0eec476819467acb401028c0c", size = 11577642, upload-time = "2025-05-29T13:31:30.647Z" },
1218
- { url = "https://files.pythonhosted.org/packages/a7/9b/c9ddf7f924d5617a1c94a93ba595f4b24cb5bc50e98b94433ab3f7ad27e5/ruff-0.11.12-py3-none-win32.whl", hash = "sha256:f5a07f49767c4be4772d161bfc049c1f242db0cfe1bd976e0f0886732a4765d6", size = 10475511, upload-time = "2025-05-29T13:31:32.917Z" },
1219
- { url = "https://files.pythonhosted.org/packages/fd/d6/74fb6d3470c1aada019ffff33c0f9210af746cca0a4de19a1f10ce54968a/ruff-0.11.12-py3-none-win_amd64.whl", hash = "sha256:5a4d9f8030d8c3a45df201d7fb3ed38d0219bccd7955268e863ee4a115fa0832", size = 11523573, upload-time = "2025-05-29T13:31:35.782Z" },
1220
- { url = "https://files.pythonhosted.org/packages/44/42/d58086ec20f52d2b0140752ae54b355ea2be2ed46f914231136dd1effcc7/ruff-0.11.12-py3-none-win_arm64.whl", hash = "sha256:65194e37853158d368e333ba282217941029a28ea90913c67e558c611d04daa5", size = 10697770, upload-time = "2025-05-29T13:31:38.009Z" },
1200
+ version = "0.11.13"
1201
+ source = { registry = "https://pypi.org/simple" }
1202
+ sdist = { url = "https://files.pythonhosted.org/packages/ed/da/9c6f995903b4d9474b39da91d2d626659af3ff1eeb43e9ae7c119349dba6/ruff-0.11.13.tar.gz", hash = "sha256:26fa247dc68d1d4e72c179e08889a25ac0c7ba4d78aecfc835d49cbfd60bf514", size = 4282054, upload-time = "2025-06-05T21:00:15.721Z" }
1203
+ wheels = [
1204
+ { url = "https://files.pythonhosted.org/packages/7d/ce/a11d381192966e0b4290842cc8d4fac7dc9214ddf627c11c1afff87da29b/ruff-0.11.13-py3-none-linux_armv6l.whl", hash = "sha256:4bdfbf1240533f40042ec00c9e09a3aade6f8c10b6414cf11b519488d2635d46", size = 10292516, upload-time = "2025-06-05T20:59:32.944Z" },
1205
+ { url = "https://files.pythonhosted.org/packages/78/db/87c3b59b0d4e753e40b6a3b4a2642dfd1dcaefbff121ddc64d6c8b47ba00/ruff-0.11.13-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:aef9c9ed1b5ca28bb15c7eac83b8670cf3b20b478195bd49c8d756ba0a36cf48", size = 11106083, upload-time = "2025-06-05T20:59:37.03Z" },
1206
+ { url = "https://files.pythonhosted.org/packages/77/79/d8cec175856ff810a19825d09ce700265f905c643c69f45d2b737e4a470a/ruff-0.11.13-py3-none-macosx_11_0_arm64.whl", hash = "sha256:53b15a9dfdce029c842e9a5aebc3855e9ab7771395979ff85b7c1dedb53ddc2b", size = 10436024, upload-time = "2025-06-05T20:59:39.741Z" },
1207
+ { url = "https://files.pythonhosted.org/packages/8b/5b/f6d94f2980fa1ee854b41568368a2e1252681b9238ab2895e133d303538f/ruff-0.11.13-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab153241400789138d13f362c43f7edecc0edfffce2afa6a68434000ecd8f69a", size = 10646324, upload-time = "2025-06-05T20:59:42.185Z" },
1208
+ { url = "https://files.pythonhosted.org/packages/6c/9c/b4c2acf24ea4426016d511dfdc787f4ce1ceb835f3c5fbdbcb32b1c63bda/ruff-0.11.13-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6c51f93029d54a910d3d24f7dd0bb909e31b6cd989a5e4ac513f4eb41629f0dc", size = 10174416, upload-time = "2025-06-05T20:59:44.319Z" },
1209
+ { url = "https://files.pythonhosted.org/packages/f3/10/e2e62f77c65ede8cd032c2ca39c41f48feabedb6e282bfd6073d81bb671d/ruff-0.11.13-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1808b3ed53e1a777c2ef733aca9051dc9bf7c99b26ece15cb59a0320fbdbd629", size = 11724197, upload-time = "2025-06-05T20:59:46.935Z" },
1210
+ { url = "https://files.pythonhosted.org/packages/bb/f0/466fe8469b85c561e081d798c45f8a1d21e0b4a5ef795a1d7f1a9a9ec182/ruff-0.11.13-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d28ce58b5ecf0f43c1b71edffabe6ed7f245d5336b17805803312ec9bc665933", size = 12511615, upload-time = "2025-06-05T20:59:49.534Z" },
1211
+ { url = "https://files.pythonhosted.org/packages/17/0e/cefe778b46dbd0cbcb03a839946c8f80a06f7968eb298aa4d1a4293f3448/ruff-0.11.13-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:55e4bc3a77842da33c16d55b32c6cac1ec5fb0fbec9c8c513bdce76c4f922165", size = 12117080, upload-time = "2025-06-05T20:59:51.654Z" },
1212
+ { url = "https://files.pythonhosted.org/packages/5d/2c/caaeda564cbe103bed145ea557cb86795b18651b0f6b3ff6a10e84e5a33f/ruff-0.11.13-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:633bf2c6f35678c56ec73189ba6fa19ff1c5e4807a78bf60ef487b9dd272cc71", size = 11326315, upload-time = "2025-06-05T20:59:54.469Z" },
1213
+ { url = "https://files.pythonhosted.org/packages/75/f0/782e7d681d660eda8c536962920c41309e6dd4ebcea9a2714ed5127d44bd/ruff-0.11.13-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ffbc82d70424b275b089166310448051afdc6e914fdab90e08df66c43bb5ca9", size = 11555640, upload-time = "2025-06-05T20:59:56.986Z" },
1214
+ { url = "https://files.pythonhosted.org/packages/5d/d4/3d580c616316c7f07fb3c99dbecfe01fbaea7b6fd9a82b801e72e5de742a/ruff-0.11.13-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4a9ddd3ec62a9a89578c85842b836e4ac832d4a2e0bfaad3b02243f930ceafcc", size = 10507364, upload-time = "2025-06-05T20:59:59.154Z" },
1215
+ { url = "https://files.pythonhosted.org/packages/5a/dc/195e6f17d7b3ea6b12dc4f3e9de575db7983db187c378d44606e5d503319/ruff-0.11.13-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d237a496e0778d719efb05058c64d28b757c77824e04ffe8796c7436e26712b7", size = 10141462, upload-time = "2025-06-05T21:00:01.481Z" },
1216
+ { url = "https://files.pythonhosted.org/packages/f4/8e/39a094af6967faa57ecdeacb91bedfb232474ff8c3d20f16a5514e6b3534/ruff-0.11.13-py3-none-musllinux_1_2_i686.whl", hash = "sha256:26816a218ca6ef02142343fd24c70f7cd8c5aa6c203bca284407adf675984432", size = 11121028, upload-time = "2025-06-05T21:00:04.06Z" },
1217
+ { url = "https://files.pythonhosted.org/packages/5a/c0/b0b508193b0e8a1654ec683ebab18d309861f8bd64e3a2f9648b80d392cb/ruff-0.11.13-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:51c3f95abd9331dc5b87c47ac7f376db5616041173826dfd556cfe3d4977f492", size = 11602992, upload-time = "2025-06-05T21:00:06.249Z" },
1218
+ { url = "https://files.pythonhosted.org/packages/7c/91/263e33ab93ab09ca06ce4f8f8547a858cc198072f873ebc9be7466790bae/ruff-0.11.13-py3-none-win32.whl", hash = "sha256:96c27935418e4e8e77a26bb05962817f28b8ef3843a6c6cc49d8783b5507f250", size = 10474944, upload-time = "2025-06-05T21:00:08.459Z" },
1219
+ { url = "https://files.pythonhosted.org/packages/46/f4/7c27734ac2073aae8efb0119cae6931b6fb48017adf048fdf85c19337afc/ruff-0.11.13-py3-none-win_amd64.whl", hash = "sha256:29c3189895a8a6a657b7af4e97d330c8a3afd2c9c8f46c81e2fc5a31866517e3", size = 11548669, upload-time = "2025-06-05T21:00:11.147Z" },
1220
+ { url = "https://files.pythonhosted.org/packages/ec/bf/b273dd11673fed8a6bd46032c0ea2a04b2ac9bfa9c628756a5856ba113b0/ruff-0.11.13-py3-none-win_arm64.whl", hash = "sha256:b4385285e9179d608ff1d2fb9922062663c658605819a6876d8beef0c30b7f3b", size = 10683928, upload-time = "2025-06-05T21:00:13.758Z" },
1221
1221
  ]
1222
1222
 
1223
1223
  [[package]]
@@ -1503,7 +1503,7 @@ wheels = [
1503
1503
 
1504
1504
  [[package]]
1505
1505
  name = "ynab-cli"
1506
- version = "0.3.0"
1506
+ version = "0.5.0"
1507
1507
  source = { editable = "." }
1508
1508
  dependencies = [
1509
1509
  { name = "attrs" },
@@ -1,35 +0,0 @@
1
- ## 0.2.0 (2025-06-06)
2
-
3
- ### BREAKING CHANGE
4
-
5
- - changes the way the commands need to be run. You now need to specify the "run" command before any of the subcommands
6
-
7
- ### Feat
8
-
9
- - added a feature to prefix unused payees to make them easier to find and delete in ynab
10
- - added a list all command to payees
11
- - add a textual based tui
12
- - use rich for better user feedback
13
- - implement initial cli
14
-
15
- ### Refactor
16
-
17
- - cleaned up some code, sorted lists, and improved the file selector
18
-
19
- ## v0.3.0 (2025-06-06)
20
-
21
- ### BREAKING CHANGE
22
-
23
- - changes the way the commands need to be run. You now need to specify the "run" command before any of the subcommands
24
-
25
- ### Feat
26
-
27
- - added a feature to prefix unused payees to make them easier to find and delete in ynab
28
- - added a list all command to payees
29
- - add a textual based tui
30
- - use rich for better user feedback
31
- - implement initial cli
32
-
33
- ### Refactor
34
-
35
- - cleaned up some code, sorted lists, and improved the file selector