🎁 Get the FREE AI Skills Starter Guide β€” Subscribe β†’
BytesAgainBytesAgain
πŸ¦€ ClawHub

Treeline Money

by @zack-schrag

Chat with your finances from Treeline Money. Query balances, spending, budgets, and transactions.

Versionv26.5.2402
Downloads3,603
Installs3
Stars⭐ 2
TERMINAL
clawhub install treeline-money

πŸ“– About This Skill


name: treeline description: Chat with your finances from Treeline Money. Query balances, spending, budgets, and transactions. user-invocable: true homepage: https://treeline.money metadata: {"openclaw":{"emoji":"🌲","requires":{"bins":["tl"]},"install":[{"id":"tl-mac","kind":"download","url":"https://github.com/treeline-money/treeline/releases/latest/download/tl-macos-arm64","bins":["tl"],"label":"Install Treeline CLI (macOS)","os":["darwin"]},{"id":"tl-linux","kind":"download","url":"https://github.com/treeline-money/treeline/releases/latest/download/tl-linux-x64","bins":["tl"],"label":"Install Treeline CLI (Linux)","os":["linux"]},{"id":"tl-win","kind":"download","url":"https://github.com/treeline-money/treeline/releases/latest/download/tl-windows-x64.exe","bins":["tl.exe"],"label":"Install Treeline CLI (Windows)","os":["win32"]}]}}

Treeline Money

Chat with your finances. Ask questions like "What's my net worth?", "How much did I spend on groceries?", or "Am I over budget?" and get instant answers from your own financial data.


Quick Start

# 1. Install the CLI (OpenClaw handles this automatically)

2. Enable demo mode (sample data)

tl demo on

3. Try it out

tl status


First Time Setup

> For agents: If tl commands fail with "command not found", the CLI needs to be installed. OpenClaw handles installation automatically via the skill metadata. Start with demo mode so users can try queries immediately.

Verify the CLI is available with tl --version. Start with demo mode so users can try queries immediately.

Optional: Download the desktop app for visual exploration of your data.

Demo Mode

Demo mode loads sample data so users can try queries without connecting a bank:

tl demo on

To switch to real data later:

tl demo off

Demo data is separate from real data.

CLI Behavior Notes

  • tl demo on prints a success message β€” if it seems to hang, wait a few seconds (first run initializes the database)
  • Use tl demo status to verify demo mode is enabled
  • Some commands may take a few seconds on first run due to database initialization
  • If you see errors about missing tables, try tl demo on again
  • Connecting Real Data

    When the user is ready to move beyond demo mode, direct them to set up a data source with the guides linked below.

    Data source options:

  • SimpleFIN ($1.50/month, US & Canada)
  • Lunch Flow (~$3/month, global)
  • CSV Import (free)
  • Setup guides: Bank Sync Β· CSV Import

    Once set up, use tl sync to pull bank transactions or tl import to load a CSV.


    What is Treeline?

    Treeline Money is a local-first personal finance app. All your data stays on your device in a local DuckDB database. No cloud accounts, no subscriptions required (sync services are optional), full SQL access to your financial data.


    Encrypted Databases

    Encrypted databases work automatically when unlocked β€” the encryption key is stored in the OS keychain.

    If you see "database is encrypted and locked" errors, tell the user to unlock it themselves before continuing:

  • Open the Treeline desktop app and unlock from there, or
  • Run tl encrypt unlock in their own terminal
  • Do not attempt to unlock the database or handle credentials. Unlocking must be done by the user directly, outside this conversation. Once unlocked, the key persists in the keychain until the user locks it.


    Response Formatting

    Format all responses for mobile/chat:

  • Use bullet points, not markdown tables
  • Round numbers for readability ($1,234 not $1,234.56)
  • Lead with the answer, details second
  • Keep responses concise β€” chat isn't a spreadsheet
  • Use line breaks to separate sections
  • Example good response:

    Your net worth is $125k

    Assets: $180k

  • Retirement: $85k
  • Savings: $25k
  • Checking: $10k
  • Home equity: $60k
  • Liabilities: $55k

  • Mortgage: $52k
  • Credit cards: $3k
  • Example bad response:

    | Account | Type | Balance |
    |---------|------|---------|
    | My 401k Account | asset | 85234.56 |
    ...
    


    CLI Commands

    Read commands (run freely)

    These commands are read-only and safe to run autonomously:

    tl status              # Quick account summary with balances
    tl status --json       # Same, but JSON output

    tl query "SQL" --json # Run any SQL query (database opened in read-only mode) tl sql "SQL" --json # Same as tl query (alias)

    tl backup list # List available backups tl doctor # Check database health tl demo status # Check if demo mode is on/off

    > Note: tl query and tl sql open the database in read-only mode by default. They cannot modify data unless --allow-writes is passed (see write commands below).

    Use tl status for quick balance checks β€” it's faster than a SQL query.

    Write commands (ask the user first)

    These commands modify local data. Always ask the user for confirmation before running them.

    tl query "SQL" --allow-writes --json  # Run a SQL query with write access
    tl sql "SQL" --allow-writes --json    # Same (alias)

    tl sync # Sync accounts/transactions from bank integrations tl sync --dry-run # Preview what would sync (read-only, safe to run)

    tl import FILE -a ACCOUNT # Import transactions from CSV tl import FILE -a ACCOUNT --dry-run # Preview import without applying (read-only, safe to run) tl import FILE -a ACCOUNT --json # JSON output for scripting

    tl backup create # Create a backup tl backup restore NAME # Restore a backup

    tl compact # Compact database (reclaim space, optimize)

    tl tag "groceries" --ids ID1,ID2 # Apply tags to transactions

    tl demo on|off # Toggle demo mode (sample data)

    > Tip: --dry-run variants are read-only and safe to run without confirmation. Use them to preview before asking the user to confirm the actual operation.

    Use tl compact if the user mentions slow queries β€” it optimizes the database.

    CSV Import Details

    tl import auto-detects column mappings from CSV headers. Most bank CSVs work out of the box:

    tl import bank_export.csv --account "Chase Checking"
    

    The --account / -a flag accepts an account name (case-insensitive, substring match) or UUID.

    Always preview first with --dry-run to verify columns were detected correctly:

    tl import bank_export.csv -a "Checking" --dry-run --json
    

    All import flags (all optional except --account):

    | Flag | Purpose | Example | |------|---------|---------| | --date-column | Override date column | --date-column "Post Date" | | --amount-column | Override amount column | --amount-column "Amt" | | --description-column | Override description column | --description-column "Memo" | | --debit-column | Use debit column (instead of amount) | --debit-column "Debit" | | --credit-column | Use credit column (instead of amount) | --credit-column "Credit" | | --balance-column | Running balance (creates snapshots) | --balance-column "Balance" | | --flip-signs | Negate amounts (credit card CSVs) | --flip-signs | | --debit-negative | Negate positive debits | --debit-negative | | --skip-rows N | Skip N rows before header | --skip-rows 3 | | --number-format | us, eu, or eu_space | --number-format eu | | --profile NAME | Load a saved profile | --profile chase | | --save-profile NAME | Save settings as profile | --save-profile chase | | --dry-run | Preview without importing | --dry-run | | --json | JSON output | --json |

    Common patterns for agents:

    # Step 1: Find the account UUID
    tl status --json

    Step 2: Preview import

    tl import transactions.csv -a "550e8400-e29b-41d4-a716-446655440000" --dry-run --json

    Step 3: Execute import

    tl import transactions.csv -a "550e8400-e29b-41d4-a716-446655440000" --json

    Duplicate transactions are automatically detected and skipped on re-import via fingerprinting.


    User Skills

    Treeline supports user-created skills for personal financial knowledge. Use tl skills list --json to discover existing skills and tl skills read to read them.

    Creating skills: When you learn something reusable about the user's finances β€” tag conventions, account meanings, tax categories, budget targets β€” ask if they'd like to save it as a skill for future conversations. To create one, write a SKILL.md file to ~/.treeline/skills//SKILL.md (use tl skills path to get the directory). Follow the Agent Skills standard (agentskills.io).


    Quick Reference

    Net Worth

    tl query "
    WITH latest AS (
      SELECT DISTINCT ON (account_id) account_id, balance
      FROM sys_balance_snapshots
      ORDER BY account_id, snapshot_time DESC
    )
    SELECT
      SUM(CASE WHEN a.classification = 'asset' THEN s.balance ELSE 0 END) as assets,
      SUM(CASE WHEN a.classification = 'liability' THEN ABS(s.balance) ELSE 0 END) as liabilities,
      SUM(CASE WHEN a.classification = 'asset' THEN s.balance ELSE -ABS(s.balance) END) as net_worth
    FROM accounts a
    JOIN latest s ON a.account_id = s.account_id
    " --json
    

    Account Balances

    tl query "
    WITH latest AS (
      SELECT DISTINCT ON (account_id) account_id, balance
      FROM sys_balance_snapshots
      ORDER BY account_id, snapshot_time DESC
    )
    SELECT a.name, a.classification, a.institution_name, s.balance
    FROM accounts a
    JOIN latest s ON a.account_id = s.account_id
    ORDER BY s.balance DESC
    " --json
    

    True Spending (Excluding Internal Moves)

    Default pattern (exclude internal moves):

    tl query "
    SELECT SUM(ABS(amount)) as total_spent
    FROM transactions
    WHERE amount < 0
      AND transaction_date >= date_trunc('month', current_date)
      AND NOT (tags && ARRAY['transfer', 'savings', 'investment'])
    " --json
    

    Spending by Tag

    tl query "
    SELECT tags, SUM(ABS(amount)) as spent
    FROM transactions
    WHERE amount < 0
      AND transaction_date >= '2026-01-01' AND transaction_date < '2026-02-01'
      AND tags IS NOT NULL AND tags != '[]'
    GROUP BY tags
    ORDER BY spent DESC
    " --json
    

    Recent Transactions

    tl query "
    SELECT t.description, t.amount, t.transaction_date, a.name as account
    FROM transactions t
    JOIN accounts a ON t.account_id = a.account_id
    ORDER BY t.transaction_date DESC
    LIMIT 10
    " --json
    


    Database Schema

    Core Tables

    accounts | Column | Description | |--------|-------------| | account_id | UUID primary key | | name | Account display name | | classification | asset or liability | | account_type | credit, investment, Loan, other, or null | | institution_name | Bank/institution name | | currency | Currency code (e.g., USD) | | is_manual | Boolean β€” manually added vs synced |

    sys_balance_snapshots β€” Source of truth for balances | Column | Description | |--------|-------------| | snapshot_id | UUID primary key | | account_id | FK to accounts | | balance | Balance at snapshot time | | snapshot_time | When recorded | | source | sync, manual, etc. |

    transactions | Column | Description | |--------|-------------| | transaction_id | UUID primary key | | account_id | FK to accounts | | amount | Signed (negative = expense) | | description | Transaction description | | transaction_date | When it occurred | | posted_date | When it cleared | | tags | Array of tags |

    Tags vs Categories

    Tags are the primary concept in Treeline β€” transactions can have multiple tags.

    Categories come from the budget plugin (plugin_budget), which maps tags to budget categories. Not all users have this plugin.


    Plugin System

    Plugins have their own DuckDB schemas: plugin_.*

    Discovering Installed Plugins

    tl query "
    SELECT schema_name
    FROM information_schema.schemata
    WHERE schema_name LIKE 'plugin_%'
    " --json
    

    Common Plugin Schemas

    plugin_budget.categories β€” Budget categories | Column | Description | |--------|-------------| | category_id | UUID primary key | | month | YYYY-MM format | | type | income or expense | | name | Category name | | expected | Budgeted amount | | tags | Array of tags to match |

    plugin_goals.goals β€” Savings goals | Column | Description | |--------|-------------| | id | UUID primary key | | name | Goal name | | target_amount | Target amount | | target_date | Target date | | completed | Boolean | | active | Boolean |

    plugin_subscriptions β€” Detected recurring charges

    plugin_cashflow β€” Cash flow projections

    plugin_emergency_fund β€” Emergency fund tracking

    Check tl skills list for user-specific plugin preferences.


    Common Patterns

    Getting Current Balances

    Always use latest snapshot:

    WITH latest AS (
      SELECT DISTINCT ON (account_id) account_id, balance
      FROM sys_balance_snapshots
      ORDER BY account_id, snapshot_time DESC
    )
    SELECT a.name, s.balance
    FROM accounts a
    JOIN latest s ON a.account_id = s.account_id
    

    Working with Tags

    Tags are arrays:

    -- Contains a specific tag
    WHERE tags @> ARRAY['groceries']

    -- Contains any of these tags WHERE tags && ARRAY['food', 'dining']

    -- Note: UNNEST doesn't work in all contexts in DuckDB -- Instead, GROUP BY tags directly

    Date Filters

    -- This month
    WHERE transaction_date >= date_trunc('month', current_date)

    -- Specific month WHERE transaction_date >= '2026-01-01' AND transaction_date < '2026-02-01'

    Budget vs Actual

    SELECT
      c.name,
      c.expected,
      COALESCE(SUM(ABS(t.amount)), 0) as actual,
      c.expected - COALESCE(SUM(ABS(t.amount)), 0) as remaining
    FROM plugin_budget.categories c
    LEFT JOIN transactions t ON t.tags && c.tags
      AND t.amount < 0
      AND t.transaction_date >= (c.month || '-01')::DATE
      AND t.transaction_date < (c.month || '-01')::DATE + INTERVAL '1 month'
    WHERE c.month = strftime(current_date, '%Y-%m')
      AND c.type = 'expense'
    GROUP BY c.category_id, c.name, c.expected
    


    Question Mapping

    | User asks | Approach | |-----------|----------| | "Net worth?" | Net worth query | | "Balances?" | Account balances query | | "How much in [X]?" | Filter by name ILIKE '%X%' | | "How much did I spend?" | True spending query (exclude internal moves) | | "Spending on [tag]?" | Filter by tag | | "Am I over budget?" | Budget vs actual (requires budget plugin) | | "Recent transactions" | Order by date DESC, limit | | "Savings?" | Filter accounts by name/type | | "Retirement?" | Filter by 401k, IRA, retirement keywords | | "Import CSV" / "Upload transactions" | Guide through tl import β€” preview first with --dry-run | | "Import from [bank name]" | Use tl import with appropriate flags for that bank's CSV format |


    Tips

    1. Always use --json for parseable output 2. Amounts are signed β€” negative = expense 3. Use classification for asset/liability 4. Balances live in snapshots, not the accounts table 5. Check tl skills list for user-specific account meanings and tag conventions


    Privacy Note

    All data is local (~/.treeline/treeline.duckdb). Never share transaction descriptions or account details outside the conversation unless explicitly asked.

    πŸ’‘ Examples

    # 1. Install the CLI (OpenClaw handles this automatically)

    2. Enable demo mode (sample data)

    tl demo on

    3. Try it out

    tl status


    πŸ“‹ Tips & Best Practices

    1. Always use --json for parseable output 2. Amounts are signed β€” negative = expense 3. Use classification for asset/liability 4. Balances live in snapshots, not the accounts table 5. Check tl skills list for user-specific account meanings and tag conventions