Cashy / CLAUDE.md
GitHub Actions
Deploy to HF Spaces
17a78b5

A newer version of the Gradio SDK is available: 6.13.0

Upgrade

Claude Code Instructions for Cashy Project

Project Summary

Cashy is an AI-powered personal financial advisor built with LangGraph + LangChain + Gradio + PostgreSQL. It queries a financial database to answer questions about accounts, transactions, and spending. Supports multiple LLM providers (OpenAI, Anthropic, Google, HuggingFace) plus a free tier for zero-config demo access.

Tech Stack: LangGraph (orchestration) + LangChain (tools + LLM abstractions) + Gradio (UI) + PostgreSQL (data + checkpoints) + LangSmith (tracing)

How to Run

# Configure your LLM provider in .env (see .env.example)
# Personal mode (default β€” connects to financial_db):
uv run python app.py

# Demo mode (seeded showcase data in cashy_demo):
APP_MODE=demo uv run python app.py

Project Structure

cashy-poc/
β”œβ”€β”€ app.py                    # Entry point (logging, checkpointer, Gradio)
β”œβ”€β”€ pyproject.toml            # Dependencies (managed by uv)
β”œβ”€β”€ .env.example              # Template for environment variables
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ config.py             # Pydantic BaseSettings β€” app mode, multi-provider config
β”‚   β”œβ”€β”€ ui.py                 # Gradio Blocks UI (chat, sidebar, thread history, themes)
β”‚   β”œβ”€β”€ agent/
β”‚   β”‚   β”œβ”€β”€ graph.py          # LangGraph StateGraph factory
β”‚   β”‚   β”œβ”€β”€ nodes.py          # LLM factory (5 providers incl. free-tier), call_model, should_continue
β”‚   β”‚   β”œβ”€β”€ prompts.py        # System prompts (demo + personal modes)
β”‚   β”‚   └── state.py          # AgentState (extends MessagesState)
β”‚   β”œβ”€β”€ tools/
β”‚   β”‚   β”œβ”€β”€ __init__.py       # Exports all_tools list
β”‚   β”‚   β”œβ”€β”€ finance_query.py  # @tool β€” custom SELECT queries
β”‚   β”‚   β”œβ”€β”€ account_balance.py
β”‚   β”‚   β”œβ”€β”€ recent_transactions.py
β”‚   β”‚   β”œβ”€β”€ spending_by_category.py
β”‚   β”‚   β”œβ”€β”€ all_accounts.py
β”‚   β”‚   β”œβ”€β”€ create_transaction.py
β”‚   β”‚   └── generate_chart.py # @tool β€” matplotlib charts (bar, pie, line, grouped)
β”‚   └── db/
β”‚       └── connection.py     # psycopg2 context manager
β”œβ”€β”€ eval_cases/               # Evaluation test cases (JSON)
β”œβ”€β”€ scripts/
β”‚   β”œβ”€β”€ run_eval.py           # Eval runner
β”‚   β”œβ”€β”€ seed_demo_db.sql      # Demo DB schema + seed data
β”‚   └── sanitize_agent_export.py
β”œβ”€β”€ dev/                      # Developer documentation
β”‚   β”œβ”€β”€ active/               # In-progress task docs
β”‚   └── archive/              # Completed task docs
└── .env                      # Credentials (not committed)

Key Technical Details

  • Package manager: uv (not pip). Use uv sync and uv run.
  • LLM providers: OpenAI, Anthropic, Google, HuggingFace, free-tier β€” configured via LLM_PROVIDER env var or auto-detected from API keys (priority: openai > anthropic > google > huggingface). Free-tier is auto-detected in demo mode when HF_TOKEN is the only key set.
  • Free-tier provider: Uses the Space owner's HF_TOKEN (captured at startup as _SPACE_HF_TOKEN in nodes.py). Locked to Qwen/Qwen2.5-7B-Instruct β€” no model override, no inference provider param (HF auto-routes). UI hides API key input, Save button, and model textbox when selected. Responses include a disclaimer nudging users toward paid providers.
  • Default models: gpt-5-mini, claude-sonnet-4-20250514, gemini-2.5-flash, Llama-3.3-70B-Instruct, Qwen2.5-7B-Instruct (free-tier). Users can override via the model name textbox in the sidebar (except free-tier).
  • HF inference providers: When HuggingFace is selected, a dropdown lets users pick from 14 inference providers (cerebras, groq, together, etc.).
  • Lazy imports: Provider packages are imported inside if-branches in nodes.py to avoid errors when only one provider is installed.
  • ChatHuggingFace does NOT support with_structured_output() β€” use bind_tools().
  • Latin-1 sanitization: HuggingFace's HTTP transport uses latin-1 encoding. _sanitize_for_latin1() in nodes.py strips non-latin-1 chars from messages and tool descriptions before sending to HF. Applies to both huggingface and free-tier providers.
  • Prompt guidelines: System prompts include "NEVER show SQL queries in responses" and "Always execute tools immediately" β€” critical for smaller models (7B) that otherwise dump raw SQL.
  • Memory: LangGraph MessagesState (session) + PostgresSaver (cross-session via psycopg v3).
  • Tools use psycopg2, checkpointer uses psycopg v3 β€” both coexist in pyproject.toml.
  • System prompt: Has {today} and {year} placeholders injected dynamically in call_model().
  • 9 tools: finance_db_query, get_account_balance, get_recent_transactions, get_spending_by_category, get_all_accounts, create_transaction, update_transaction, delete_transaction, generate_chart.
  • Human-in-the-loop: Write tools (create/update/delete) use LangGraph interrupt() for user confirmation before DB writes. UI handles via pending_interrupt state + Command(resume=...).
  • Chart rendering: generate_chart saves matplotlib PNGs to /tmp. UI scans ToolMessages for chart_path and renders inline via Gradio's {"path": ...} format.
  • Session memory: gr.State holds a per-session thread_id so follow-up messages share LangGraph conversation context.
  • Thread management: "New Chat" button + "Chat History" accordion to start fresh or resume past threads.
  • Transfers: get_recent_transactions collapses transfer entries into single rows with from_account/to_account.
  • App mode: APP_MODE=demo (cashy_demo DB, Glass indigo theme, freelancer prompt) or APP_MODE=personal (financial_db, Default theme, generic prompt). Default: personal.
  • Themes: Demo uses gr.themes.Glass(primary_hue="indigo"), personal uses gr.themes.Default().

Database

  • Host: localhost:5432, User: financial_advisor
  • Demo DB: cashy_demo β€” English, US freelancer, USD. Seed: scripts/seed_demo_db.sql
  • Personal DB: financial_db β€” user's real financial data, same schema
  • Schema: 11 tables + 8 views (see dev/DATABASE_SCHEMA.md)
  • Key tables: accounts, transactions, transaction_entries, categories, budgets
  • Key views: v_transaction_details, v_monthly_spending, v_account_summary

Development Guidelines

  • Prefer editing existing files over creating new ones
  • Run code to validate β€” uv run python app.py or Python REPL
  • Keep dev/active/ task docs updated for complex work
  • Never commit .env or files with credentials
  • Use structured logging (cashy.agent, cashy.tools, cashy.db, cashy.ui)

Rules

  • Python: Always run with uv run python, never python or python3 directly
  • Libraries: Use Context7 MCP (resolve-library-id β†’ query-docs) for external docs
  • Git commits: Single-line commit message. Never include Co-Authored-By
  • Language: English only (portfolio project targeting US/international clients)
  • Timezone: Assume America/Mexico_City unless specified
  • Secrets: NEVER hardcode API keys, tokens, passwords, or secrets in commands, code, or chat output. Always reference them via environment variables from .env files (e.g., $API_KEY). If a needed var isn't set, ask the user to add it to .env β€” never ask for the raw value

Quick References

  • Live Demo: https://huggingface.co/spaces/SeasonalFall84/cashy (deployed from main, demo mode)
  • Architecture: dev/ARCHITECTURE.md
  • DB Schema: dev/DATABASE_SCHEMA.md
  • Branches: dev/BRANCHES.md
  • Troubleshooting: dev/TROUBLESHOOTING.md
  • Eval cases: eval_cases/eval_cases_v1.json
  • Env template: .env.example