YNAB Manager CLI
Overview
YNAB is excellent for day-to-day budgeting, but it falls short on a very common real-world use case: installment purchases. For every 6x, 10x or 12x purchase, users must manually create each monthly installment. Over time this becomes tedious, error-prone and is one of the first habits people drop when their finances get more complex.
YNAB Manager CLI started as a personal tool to remove that friction. Instead of manually adding each installment, the user provides the total amount, number of installments, start date and account. The CLI then generates all transactions in YNAB automatically, respecting the API rules. Past installments are created as regular transactions; future ones are created as scheduled transactions. Optionally, the user can enable AI suggestions for payees and categories.
This is a solo project where I designed a layered architecture (CLI, core, services, storage), implemented the full installment expansion and deduplication logic, integrated with the YNAB API, and added automated tests plus local quality tools. The result is a tool I’ve been using daily since early 2026 and decided to open-source for other power users facing the exact same issue.
Key Differentiator
The main differentiator of YNAB Manager CLI is not just “automating installments”, but treating writes to YNAB as a critical, idempotent operation constrained by under-documented API rules.
Two aspects stand out: an explicit split between past and future installments (calling different endpoints to work around the “no scheduled transactions more than 7 days in the past” rule) and a deterministic import_id scheme based on a hash of the installment plan. This makes the wizard safely re-runnable: you can execute the same plan twice and YNAB will silently ignore duplicates rather than polluting your budget.
On top of that, AI is used pragmatically. It’s an optional service, not a hard dependency: GPT-4o-mini is used to suggest categories and payees with a low temperature setting, keeping suggestions consistent without making the CLI rely on OpenAI to function.
Architecture
- CLI Layer (app.py, commands/, wizards/): Drives the terminal interaction using Rich and Questionary; implements guided flows to create installments, configure settings and inspect existing data.
- Installment Wizard: Collects plan data (account, total amount, number of installments, frequency, start date) and expands it into a list of individual transactions shaped exactly as required by the YNAB API.
- Core – installment.py: Pydantic v2 models for the installment plan and business rules for generating installments (dates, amounts, rounding, memos) plus functions to compute deterministic hashes.
- Core – deduplication.py / similarity.py: Responsible for generating SHA256-based plan hashes and
import_ids, and for searching/reconciling recent transactions to detect potential duplicates. - Services – ynab_client.py: A thin wrapper over the official YNAB SDK, exposing read/write operations for transactions and scheduled transactions with error handling and CLI-friendly feedback.
- Services – ai_suggester.py: Integration with OpenAI (GPT-4o-mini) to propose payees and categories from free-text purchase descriptions, using a low temperature to keep the output stable.
- Storage – config.py: Handles local configuration (default budget, currency symbol, AI settings), loading and persisting user preferences on disk.
- Storage – cache.py: Local cache for data that rarely changes (budgets, accounts, categories), reducing round-trips to the YNAB API and improving perceived responsiveness.
- Storage – keyring_storage.py: Persists sensitive tokens (YNAB and optional OpenAI API keys) in the OS keyring rather than environment variables or plain files.
- Test Suite (pytest): Automated tests covering plan generation, hashing/import_id, deduplication behavior and core integration pieces, combined with Black, Ruff and mypy to keep the codebase consistent and maintainable.
Technical Highlights
- Modeled the installment plan with Pydantic v2, centralizing validation logic for dates, frequencies, installment count and total amount, reducing edge-case bugs around dates and rounding.
- Implemented an idempotency mechanism based on a SHA256 hash of the plan (
account_id,payee_name,total_amount,installment_count,start_date,frequency), generating deterministicimport_ids per installment compatible with YNAB’s built-in deduplication. - Explicitly handled YNAB’s “no scheduled transactions more than 7 days in the past” constraint by splitting the write operation into two API calls:
TransactionsApifor historical installments andScheduledTransactionsApifor future ones. - Used the system keyring to store API tokens securely, eliminating the need for
.envfiles or environment variables with long-lived credentials. - Built the CLI with Rich and Questionary to provide navigable menus, colored tables and visual feedback, making a terminal-based tool approachable for non-power users.
- Set up a local quality pipeline with pytest, Black, Ruff and mypy, keeping the Python codebase typed, formatted and linted for long-term evolution as a personal “daily driver” tool.
- Kept the AI integration optional and isolated; the CLI remains fully functional without an OpenAI key, and GPT-4o-mini is used with
temperature=0.3to favor consistency over creativity in suggestions.