This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
# Build the executable
go build -o dave.exe
# Download dependencies
go mod download# Run all tests
go test ./tests/...
# Run a specific test file
go test ./tests/calculator_test.go
# Run a specific test function
go test -run TestCalculateMonthlyInterest ./tests/# Run the built executable
./dave.exe
# Or run directly with go
go run main.goDave is a CLI debt tracking tool built with Go using the Cobra command framework and SQLite for persistence.
main.go: Entry point that delegates tocmd.Execute()cmd/: Cobra command definitions (add, pay, remove, adjust-*, mode, snowball, reset, show)root.go: Base command setup, database initialization lifecycle, and command registration- Each command file defines a single Cobra command
internal/models/: Data models and database operationsdebt.go: Debt CRUD operations with support for position-based (#) or name-based lookuppayment.go: Payment history trackingsettings.go: User settings (sort mode, snowball amount)
internal/database/: SQLite database wrapper and schema managementdb.go: Database connection wrapperschema.go: Table creation and schema initialization
internal/calculator/: Financial calculation engineinterest.go: Monthly interest calculationsprojections.go: Simulates monthly payments with compound interest to project payoff timelines
internal/display/: Terminal UI rendering with Lipglosstable.go: Debt table formatting with ASCII art headerformatter.go: Currency, date, and percentage formatting utilitiesstyles.go: Lipgloss style definitions
internal/config/: Configuration and path managementpaths.go: Database path resolution (~/.dave/debts.db)
Database Lifecycle: The database connection is initialized in cmd/root.go's init() via Cobra's OnInitialize hook and closed in PersistentPostRun. All commands access the shared DB via GetDB().
Dual Identifier System: Most commands accept either a position number (1, 2, 3...) or creditor name. The GetDebtByIndexOrName() function handles this by attempting integer parsing first, then falling back to name lookup.
Sort Modes: Three modes control debt ordering:
snowball: Smallest balance first (psychological wins)avalanche: Highest APR first (mathematically optimal)manual: Custom ordering viacustom_ordercolumn
Mode changes are handled in models/settings.go and affect how GetAllDebts() sorts results.
Projection Algorithm (calculator/projections.go):
The ProjectPayoffTimeline() function simulates month-by-month payments:
- Apply monthly interest to all active debts
- Apply minimum payments to all active debts
- Apply snowball amount to highest-priority unpaid debt
- When a debt is paid off, add its minimum payment to the snowball (auto-snowball)
- Repeat for up to 600 months (50 years) or until all debts are paid
This simulation accounts for compound interest and the cascading snowball effect.
Hidden Paid Debts: Debts with current_balance = 0 are automatically filtered out by GetAllDebts() (via WHERE current_balance > 0), but remain in the database for historical tracking.
Payment History: The payments table tracks all payments with interest/principal breakdown. When recording a payment, the debt balance is updated and a payment record is inserted.
SQLite database at ~/.dave/debts.db with three tables:
- debts: id, creditor, original_balance, current_balance, apr, minimum_payment, custom_order (nullable), created_at, updated_at
- payments: id, debt_id (FK), amount, interest_paid, principal_paid, payment_date, created_at
- settings: key-value pairs (sort_mode, snowball_amount)
- Cobra: CLI framework for command structure
- Lipgloss: Terminal UI styling and table rendering
- modernc.org/sqlite: Pure-Go SQLite driver (no CGo)