{
  "schemaVersion": "1.0",
  "item": {
    "slug": "treeline-money",
    "name": "Treeline Money",
    "source": "tencent",
    "type": "skill",
    "category": "通讯协作",
    "sourceUrl": "https://clawhub.ai/zack-schrag/treeline-money",
    "canonicalUrl": "https://clawhub.ai/zack-schrag/treeline-money",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/treeline-money",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=treeline-money",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "SKILL.md"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T16:55:25.780Z",
      "expiresAt": "2026-05-07T16:55:25.780Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
        "contentDisposition": "attachment; filename=\"network-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/treeline-money"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/treeline-money",
    "agentPageUrl": "https://openagent3.xyz/skills/treeline-money/agent",
    "manifestUrl": "https://openagent3.xyz/skills/treeline-money/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/treeline-money/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "Treeline Money",
        "body": "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."
      },
      {
        "title": "Quick Start",
        "body": "# 1. Install the CLI (OpenClaw handles this automatically)\n\n# 2. Enable demo mode (sample data)\ntl demo on\n\n# 3. Try it out\ntl status"
      },
      {
        "title": "First Time Setup",
        "body": "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.\n\nVerify the CLI is available with tl --version. Start with demo mode so users can try queries immediately.\n\nOptional: Download the desktop app for visual exploration of your data."
      },
      {
        "title": "Demo Mode",
        "body": "Demo mode loads sample data so users can try queries without connecting a bank:\n\ntl demo on\n\nTo switch to real data later:\n\ntl demo off\n\nDemo data is separate from real data."
      },
      {
        "title": "CLI Behavior Notes",
        "body": "tl demo on prints a success message — if it seems to hang, wait a few seconds (first run initializes the database)\nUse tl demo status to verify demo mode is enabled\nSome commands may take a few seconds on first run due to database initialization\nIf you see errors about missing tables, try tl demo on again"
      },
      {
        "title": "Connecting Real Data",
        "body": "When the user is ready to move beyond demo mode, direct them to set up a data source with the guides linked below.\n\nData source options:\n\nSimpleFIN ($1.50/month, US & Canada)\nLunch Flow (~$3/month, global)\nCSV Import (free)\n\nSetup guides: Bank Sync · CSV Import\n\nOnce set up, use tl sync to pull bank transactions or tl import to load a CSV."
      },
      {
        "title": "What is Treeline?",
        "body": "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."
      },
      {
        "title": "Encrypted Databases",
        "body": "Encrypted databases work automatically when unlocked — the encryption key is stored in the OS keychain.\n\nIf you see \"database is encrypted and locked\" errors, tell the user to unlock it themselves before continuing:\n\nOpen the Treeline desktop app and unlock from there, or\nRun tl encrypt unlock in their own terminal\n\nDo 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."
      },
      {
        "title": "Response Formatting",
        "body": "Format all responses for mobile/chat:\n\nUse bullet points, not markdown tables\nRound numbers for readability ($1,234 not $1,234.56)\nLead with the answer, details second\nKeep responses concise — chat isn't a spreadsheet\nUse line breaks to separate sections\n\nExample good response:\n\nYour net worth is $125k\n\nAssets: $180k\n- Retirement: $85k\n- Savings: $25k\n- Checking: $10k\n- Home equity: $60k\n\nLiabilities: $55k\n- Mortgage: $52k\n- Credit cards: $3k\n\nExample bad response:\n\n| Account | Type | Balance |\n|---------|------|---------|\n| My 401k Account | asset | 85234.56 |\n..."
      },
      {
        "title": "Read commands (run freely)",
        "body": "These commands are read-only and safe to run autonomously:\n\ntl status              # Quick account summary with balances\ntl status --json       # Same, but JSON output\n\ntl query \"SQL\" --json  # Run any SQL query (database opened in read-only mode)\ntl sql \"SQL\" --json    # Same as tl query (alias)\n\ntl backup list         # List available backups\ntl doctor              # Check database health\ntl demo status         # Check if demo mode is on/off\n\nNote: 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).\n\nUse tl status for quick balance checks — it's faster than a SQL query."
      },
      {
        "title": "Write commands (ask the user first)",
        "body": "These commands modify local data. Always ask the user for confirmation before running them.\n\ntl query \"SQL\" --allow-writes --json  # Run a SQL query with write access\ntl sql \"SQL\" --allow-writes --json    # Same (alias)\n\ntl sync                # Sync accounts/transactions from bank integrations\ntl sync --dry-run      # Preview what would sync (read-only, safe to run)\n\ntl import FILE -a ACCOUNT          # Import transactions from CSV\ntl import FILE -a ACCOUNT --dry-run  # Preview import without applying (read-only, safe to run)\ntl import FILE -a ACCOUNT --json   # JSON output for scripting\n\ntl backup create       # Create a backup\ntl backup restore NAME # Restore a backup\n\ntl compact             # Compact database (reclaim space, optimize)\n\ntl tag \"groceries\" --ids ID1,ID2  # Apply tags to transactions\n\ntl demo on|off         # Toggle demo mode (sample data)\n\nTip: --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.\n\nUse tl compact if the user mentions slow queries — it optimizes the database."
      },
      {
        "title": "CSV Import Details",
        "body": "tl import auto-detects column mappings from CSV headers. Most bank CSVs work out of the box:\n\ntl import bank_export.csv --account \"Chase Checking\"\n\nThe --account / -a flag accepts an account name (case-insensitive, substring match) or UUID.\n\nAlways preview first with --dry-run to verify columns were detected correctly:\n\ntl import bank_export.csv -a \"Checking\" --dry-run --json\n\nAll import flags (all optional except --account):\n\nFlagPurposeExample--date-columnOverride date column--date-column \"Post Date\"--amount-columnOverride amount column--amount-column \"Amt\"--description-columnOverride description column--description-column \"Memo\"--debit-columnUse debit column (instead of amount)--debit-column \"Debit\"--credit-columnUse credit column (instead of amount)--credit-column \"Credit\"--balance-columnRunning balance (creates snapshots)--balance-column \"Balance\"--flip-signsNegate amounts (credit card CSVs)--flip-signs--debit-negativeNegate positive debits--debit-negative--skip-rows NSkip N rows before header--skip-rows 3--number-formatus, eu, or eu_space--number-format eu--profile NAMELoad a saved profile--profile chase--save-profile NAMESave settings as profile--save-profile chase--dry-runPreview without importing--dry-run--jsonJSON output--json\n\nCommon patterns for agents:\n\n# Step 1: Find the account UUID\ntl status --json\n\n# Step 2: Preview import\ntl import transactions.csv -a \"550e8400-e29b-41d4-a716-446655440000\" --dry-run --json\n\n# Step 3: Execute import\ntl import transactions.csv -a \"550e8400-e29b-41d4-a716-446655440000\" --json\n\nDuplicate transactions are automatically detected and skipped on re-import via fingerprinting."
      },
      {
        "title": "User Skills",
        "body": "Treeline supports user-created skills for personal financial knowledge. Use tl skills list --json to discover existing skills and tl skills read <path> to read them.\n\nCreating 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/<name>/SKILL.md (use tl skills path to get the directory). Follow the Agent Skills standard (agentskills.io)."
      },
      {
        "title": "Net Worth",
        "body": "tl query \"\nWITH latest AS (\n  SELECT DISTINCT ON (account_id) account_id, balance\n  FROM sys_balance_snapshots\n  ORDER BY account_id, snapshot_time DESC\n)\nSELECT\n  SUM(CASE WHEN a.classification = 'asset' THEN s.balance ELSE 0 END) as assets,\n  SUM(CASE WHEN a.classification = 'liability' THEN ABS(s.balance) ELSE 0 END) as liabilities,\n  SUM(CASE WHEN a.classification = 'asset' THEN s.balance ELSE -ABS(s.balance) END) as net_worth\nFROM accounts a\nJOIN latest s ON a.account_id = s.account_id\n\" --json"
      },
      {
        "title": "Account Balances",
        "body": "tl query \"\nWITH latest AS (\n  SELECT DISTINCT ON (account_id) account_id, balance\n  FROM sys_balance_snapshots\n  ORDER BY account_id, snapshot_time DESC\n)\nSELECT a.name, a.classification, a.institution_name, s.balance\nFROM accounts a\nJOIN latest s ON a.account_id = s.account_id\nORDER BY s.balance DESC\n\" --json"
      },
      {
        "title": "True Spending (Excluding Internal Moves)",
        "body": "Default pattern (exclude internal moves):\n\ntl query \"\nSELECT SUM(ABS(amount)) as total_spent\nFROM transactions\nWHERE amount < 0\n  AND transaction_date >= date_trunc('month', current_date)\n  AND NOT (tags && ARRAY['transfer', 'savings', 'investment'])\n\" --json"
      },
      {
        "title": "Spending by Tag",
        "body": "tl query \"\nSELECT tags, SUM(ABS(amount)) as spent\nFROM transactions\nWHERE amount < 0\n  AND transaction_date >= '2026-01-01' AND transaction_date < '2026-02-01'\n  AND tags IS NOT NULL AND tags != '[]'\nGROUP BY tags\nORDER BY spent DESC\n\" --json"
      },
      {
        "title": "Recent Transactions",
        "body": "tl query \"\nSELECT t.description, t.amount, t.transaction_date, a.name as account\nFROM transactions t\nJOIN accounts a ON t.account_id = a.account_id\nORDER BY t.transaction_date DESC\nLIMIT 10\n\" --json"
      },
      {
        "title": "Core Tables",
        "body": "accounts\n\nColumnDescriptionaccount_idUUID primary keynameAccount display nameclassificationasset or liabilityaccount_typecredit, investment, Loan, other, or nullinstitution_nameBank/institution namecurrencyCurrency code (e.g., USD)is_manualBoolean — manually added vs synced\n\nsys_balance_snapshots — Source of truth for balances\n\nColumnDescriptionsnapshot_idUUID primary keyaccount_idFK to accountsbalanceBalance at snapshot timesnapshot_timeWhen recordedsourcesync, manual, etc.\n\ntransactions\n\nColumnDescriptiontransaction_idUUID primary keyaccount_idFK to accountsamountSigned (negative = expense)descriptionTransaction descriptiontransaction_dateWhen it occurredposted_dateWhen it clearedtagsArray of tags"
      },
      {
        "title": "Tags vs Categories",
        "body": "Tags are the primary concept in Treeline — transactions can have multiple tags.\n\nCategories come from the budget plugin (plugin_budget), which maps tags to budget categories. Not all users have this plugin."
      },
      {
        "title": "Plugin System",
        "body": "Plugins have their own DuckDB schemas: plugin_<name>.*"
      },
      {
        "title": "Discovering Installed Plugins",
        "body": "tl query \"\nSELECT schema_name\nFROM information_schema.schemata\nWHERE schema_name LIKE 'plugin_%'\n\" --json"
      },
      {
        "title": "Common Plugin Schemas",
        "body": "plugin_budget.categories — Budget categories\n\nColumnDescriptioncategory_idUUID primary keymonthYYYY-MM formattypeincome or expensenameCategory nameexpectedBudgeted amounttagsArray of tags to match\n\nplugin_goals.goals — Savings goals\n\nColumnDescriptionidUUID primary keynameGoal nametarget_amountTarget amounttarget_dateTarget datecompletedBooleanactiveBoolean\n\nplugin_subscriptions — Detected recurring charges\n\nplugin_cashflow — Cash flow projections\n\nplugin_emergency_fund — Emergency fund tracking\n\nCheck tl skills list for user-specific plugin preferences."
      },
      {
        "title": "Getting Current Balances",
        "body": "Always use latest snapshot:\n\nWITH latest AS (\n  SELECT DISTINCT ON (account_id) account_id, balance\n  FROM sys_balance_snapshots\n  ORDER BY account_id, snapshot_time DESC\n)\nSELECT a.name, s.balance\nFROM accounts a\nJOIN latest s ON a.account_id = s.account_id"
      },
      {
        "title": "Working with Tags",
        "body": "Tags are arrays:\n\n-- Contains a specific tag\nWHERE tags @> ARRAY['groceries']\n\n-- Contains any of these tags\nWHERE tags && ARRAY['food', 'dining']\n\n-- Note: UNNEST doesn't work in all contexts in DuckDB\n-- Instead, GROUP BY tags directly"
      },
      {
        "title": "Date Filters",
        "body": "-- This month\nWHERE transaction_date >= date_trunc('month', current_date)\n\n-- Specific month\nWHERE transaction_date >= '2026-01-01'\n  AND transaction_date < '2026-02-01'"
      },
      {
        "title": "Budget vs Actual",
        "body": "SELECT\n  c.name,\n  c.expected,\n  COALESCE(SUM(ABS(t.amount)), 0) as actual,\n  c.expected - COALESCE(SUM(ABS(t.amount)), 0) as remaining\nFROM plugin_budget.categories c\nLEFT JOIN transactions t ON t.tags && c.tags\n  AND t.amount < 0\n  AND t.transaction_date >= (c.month || '-01')::DATE\n  AND t.transaction_date < (c.month || '-01')::DATE + INTERVAL '1 month'\nWHERE c.month = strftime(current_date, '%Y-%m')\n  AND c.type = 'expense'\nGROUP BY c.category_id, c.name, c.expected"
      },
      {
        "title": "Question Mapping",
        "body": "User asksApproach\"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"
      },
      {
        "title": "Tips",
        "body": "Always use --json for parseable output\nAmounts are signed — negative = expense\nUse classification for asset/liability\nBalances live in snapshots, not the accounts table\nCheck tl skills list for user-specific account meanings and tag conventions"
      },
      {
        "title": "Privacy Note",
        "body": "All data is local (~/.treeline/treeline.duckdb). Never share transaction descriptions or account details outside the conversation unless explicitly asked."
      }
    ],
    "body": "Treeline Money\n\nChat 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.\n\nQuick Start\n# 1. Install the CLI (OpenClaw handles this automatically)\n\n# 2. Enable demo mode (sample data)\ntl demo on\n\n# 3. Try it out\ntl status\n\nFirst Time Setup\n\nFor 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.\n\nVerify the CLI is available with tl --version. Start with demo mode so users can try queries immediately.\n\nOptional: Download the desktop app for visual exploration of your data.\n\nDemo Mode\n\nDemo mode loads sample data so users can try queries without connecting a bank:\n\ntl demo on\n\n\nTo switch to real data later:\n\ntl demo off\n\n\nDemo data is separate from real data.\n\nCLI Behavior Notes\ntl demo on prints a success message — if it seems to hang, wait a few seconds (first run initializes the database)\nUse tl demo status to verify demo mode is enabled\nSome commands may take a few seconds on first run due to database initialization\nIf you see errors about missing tables, try tl demo on again\nConnecting Real Data\n\nWhen the user is ready to move beyond demo mode, direct them to set up a data source with the guides linked below.\n\nData source options:\n\nSimpleFIN ($1.50/month, US & Canada)\nLunch Flow (~$3/month, global)\nCSV Import (free)\n\nSetup guides: Bank Sync · CSV Import\n\nOnce set up, use tl sync to pull bank transactions or tl import to load a CSV.\n\nWhat is Treeline?\n\nTreeline 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.\n\nEncrypted Databases\n\nEncrypted databases work automatically when unlocked — the encryption key is stored in the OS keychain.\n\nIf you see \"database is encrypted and locked\" errors, tell the user to unlock it themselves before continuing:\n\nOpen the Treeline desktop app and unlock from there, or\nRun tl encrypt unlock in their own terminal\n\nDo 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.\n\nResponse Formatting\n\nFormat all responses for mobile/chat:\n\nUse bullet points, not markdown tables\nRound numbers for readability ($1,234 not $1,234.56)\nLead with the answer, details second\nKeep responses concise — chat isn't a spreadsheet\nUse line breaks to separate sections\n\nExample good response:\n\nYour net worth is $125k\n\nAssets: $180k\n- Retirement: $85k\n- Savings: $25k\n- Checking: $10k\n- Home equity: $60k\n\nLiabilities: $55k\n- Mortgage: $52k\n- Credit cards: $3k\n\n\nExample bad response:\n\n| Account | Type | Balance |\n|---------|------|---------|\n| My 401k Account | asset | 85234.56 |\n...\n\nCLI Commands\nRead commands (run freely)\n\nThese commands are read-only and safe to run autonomously:\n\ntl status              # Quick account summary with balances\ntl status --json       # Same, but JSON output\n\ntl query \"SQL\" --json  # Run any SQL query (database opened in read-only mode)\ntl sql \"SQL\" --json    # Same as tl query (alias)\n\ntl backup list         # List available backups\ntl doctor              # Check database health\ntl demo status         # Check if demo mode is on/off\n\n\nNote: 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).\n\nUse tl status for quick balance checks — it's faster than a SQL query.\n\nWrite commands (ask the user first)\n\nThese commands modify local data. Always ask the user for confirmation before running them.\n\ntl query \"SQL\" --allow-writes --json  # Run a SQL query with write access\ntl sql \"SQL\" --allow-writes --json    # Same (alias)\n\ntl sync                # Sync accounts/transactions from bank integrations\ntl sync --dry-run      # Preview what would sync (read-only, safe to run)\n\ntl import FILE -a ACCOUNT          # Import transactions from CSV\ntl import FILE -a ACCOUNT --dry-run  # Preview import without applying (read-only, safe to run)\ntl import FILE -a ACCOUNT --json   # JSON output for scripting\n\ntl backup create       # Create a backup\ntl backup restore NAME # Restore a backup\n\ntl compact             # Compact database (reclaim space, optimize)\n\ntl tag \"groceries\" --ids ID1,ID2  # Apply tags to transactions\n\ntl demo on|off         # Toggle demo mode (sample data)\n\n\nTip: --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.\n\nUse tl compact if the user mentions slow queries — it optimizes the database.\n\nCSV Import Details\n\ntl import auto-detects column mappings from CSV headers. Most bank CSVs work out of the box:\n\ntl import bank_export.csv --account \"Chase Checking\"\n\n\nThe --account / -a flag accepts an account name (case-insensitive, substring match) or UUID.\n\nAlways preview first with --dry-run to verify columns were detected correctly:\n\ntl import bank_export.csv -a \"Checking\" --dry-run --json\n\n\nAll import flags (all optional except --account):\n\nFlag\tPurpose\tExample\n--date-column\tOverride date column\t--date-column \"Post Date\"\n--amount-column\tOverride amount column\t--amount-column \"Amt\"\n--description-column\tOverride description column\t--description-column \"Memo\"\n--debit-column\tUse debit column (instead of amount)\t--debit-column \"Debit\"\n--credit-column\tUse credit column (instead of amount)\t--credit-column \"Credit\"\n--balance-column\tRunning balance (creates snapshots)\t--balance-column \"Balance\"\n--flip-signs\tNegate amounts (credit card CSVs)\t--flip-signs\n--debit-negative\tNegate positive debits\t--debit-negative\n--skip-rows N\tSkip N rows before header\t--skip-rows 3\n--number-format\tus, eu, or eu_space\t--number-format eu\n--profile NAME\tLoad a saved profile\t--profile chase\n--save-profile NAME\tSave settings as profile\t--save-profile chase\n--dry-run\tPreview without importing\t--dry-run\n--json\tJSON output\t--json\n\nCommon patterns for agents:\n\n# Step 1: Find the account UUID\ntl status --json\n\n# Step 2: Preview import\ntl import transactions.csv -a \"550e8400-e29b-41d4-a716-446655440000\" --dry-run --json\n\n# Step 3: Execute import\ntl import transactions.csv -a \"550e8400-e29b-41d4-a716-446655440000\" --json\n\n\nDuplicate transactions are automatically detected and skipped on re-import via fingerprinting.\n\nUser Skills\n\nTreeline supports user-created skills for personal financial knowledge. Use tl skills list --json to discover existing skills and tl skills read <path> to read them.\n\nCreating 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/<name>/SKILL.md (use tl skills path to get the directory). Follow the Agent Skills standard (agentskills.io).\n\nQuick Reference\nNet Worth\ntl query \"\nWITH latest AS (\n  SELECT DISTINCT ON (account_id) account_id, balance\n  FROM sys_balance_snapshots\n  ORDER BY account_id, snapshot_time DESC\n)\nSELECT\n  SUM(CASE WHEN a.classification = 'asset' THEN s.balance ELSE 0 END) as assets,\n  SUM(CASE WHEN a.classification = 'liability' THEN ABS(s.balance) ELSE 0 END) as liabilities,\n  SUM(CASE WHEN a.classification = 'asset' THEN s.balance ELSE -ABS(s.balance) END) as net_worth\nFROM accounts a\nJOIN latest s ON a.account_id = s.account_id\n\" --json\n\nAccount Balances\ntl query \"\nWITH latest AS (\n  SELECT DISTINCT ON (account_id) account_id, balance\n  FROM sys_balance_snapshots\n  ORDER BY account_id, snapshot_time DESC\n)\nSELECT a.name, a.classification, a.institution_name, s.balance\nFROM accounts a\nJOIN latest s ON a.account_id = s.account_id\nORDER BY s.balance DESC\n\" --json\n\nTrue Spending (Excluding Internal Moves)\n\nDefault pattern (exclude internal moves):\n\ntl query \"\nSELECT SUM(ABS(amount)) as total_spent\nFROM transactions\nWHERE amount < 0\n  AND transaction_date >= date_trunc('month', current_date)\n  AND NOT (tags && ARRAY['transfer', 'savings', 'investment'])\n\" --json\n\nSpending by Tag\ntl query \"\nSELECT tags, SUM(ABS(amount)) as spent\nFROM transactions\nWHERE amount < 0\n  AND transaction_date >= '2026-01-01' AND transaction_date < '2026-02-01'\n  AND tags IS NOT NULL AND tags != '[]'\nGROUP BY tags\nORDER BY spent DESC\n\" --json\n\nRecent Transactions\ntl query \"\nSELECT t.description, t.amount, t.transaction_date, a.name as account\nFROM transactions t\nJOIN accounts a ON t.account_id = a.account_id\nORDER BY t.transaction_date DESC\nLIMIT 10\n\" --json\n\nDatabase Schema\nCore Tables\n\naccounts\n\nColumn\tDescription\naccount_id\tUUID primary key\nname\tAccount display name\nclassification\tasset or liability\naccount_type\tcredit, investment, Loan, other, or null\ninstitution_name\tBank/institution name\ncurrency\tCurrency code (e.g., USD)\nis_manual\tBoolean — manually added vs synced\n\nsys_balance_snapshots — Source of truth for balances\n\nColumn\tDescription\nsnapshot_id\tUUID primary key\naccount_id\tFK to accounts\nbalance\tBalance at snapshot time\nsnapshot_time\tWhen recorded\nsource\tsync, manual, etc.\n\ntransactions\n\nColumn\tDescription\ntransaction_id\tUUID primary key\naccount_id\tFK to accounts\namount\tSigned (negative = expense)\ndescription\tTransaction description\ntransaction_date\tWhen it occurred\nposted_date\tWhen it cleared\ntags\tArray of tags\nTags vs Categories\n\nTags are the primary concept in Treeline — transactions can have multiple tags.\n\nCategories come from the budget plugin (plugin_budget), which maps tags to budget categories. Not all users have this plugin.\n\nPlugin System\n\nPlugins have their own DuckDB schemas: plugin_<name>.*\n\nDiscovering Installed Plugins\ntl query \"\nSELECT schema_name\nFROM information_schema.schemata\nWHERE schema_name LIKE 'plugin_%'\n\" --json\n\nCommon Plugin Schemas\n\nplugin_budget.categories — Budget categories\n\nColumn\tDescription\ncategory_id\tUUID primary key\nmonth\tYYYY-MM format\ntype\tincome or expense\nname\tCategory name\nexpected\tBudgeted amount\ntags\tArray of tags to match\n\nplugin_goals.goals — Savings goals\n\nColumn\tDescription\nid\tUUID primary key\nname\tGoal name\ntarget_amount\tTarget amount\ntarget_date\tTarget date\ncompleted\tBoolean\nactive\tBoolean\n\nplugin_subscriptions — Detected recurring charges\n\nplugin_cashflow — Cash flow projections\n\nplugin_emergency_fund — Emergency fund tracking\n\nCheck tl skills list for user-specific plugin preferences.\n\nCommon Patterns\nGetting Current Balances\n\nAlways use latest snapshot:\n\nWITH latest AS (\n  SELECT DISTINCT ON (account_id) account_id, balance\n  FROM sys_balance_snapshots\n  ORDER BY account_id, snapshot_time DESC\n)\nSELECT a.name, s.balance\nFROM accounts a\nJOIN latest s ON a.account_id = s.account_id\n\nWorking with Tags\n\nTags are arrays:\n\n-- Contains a specific tag\nWHERE tags @> ARRAY['groceries']\n\n-- Contains any of these tags\nWHERE tags && ARRAY['food', 'dining']\n\n-- Note: UNNEST doesn't work in all contexts in DuckDB\n-- Instead, GROUP BY tags directly\n\nDate Filters\n-- This month\nWHERE transaction_date >= date_trunc('month', current_date)\n\n-- Specific month\nWHERE transaction_date >= '2026-01-01'\n  AND transaction_date < '2026-02-01'\n\nBudget vs Actual\nSELECT\n  c.name,\n  c.expected,\n  COALESCE(SUM(ABS(t.amount)), 0) as actual,\n  c.expected - COALESCE(SUM(ABS(t.amount)), 0) as remaining\nFROM plugin_budget.categories c\nLEFT JOIN transactions t ON t.tags && c.tags\n  AND t.amount < 0\n  AND t.transaction_date >= (c.month || '-01')::DATE\n  AND t.transaction_date < (c.month || '-01')::DATE + INTERVAL '1 month'\nWHERE c.month = strftime(current_date, '%Y-%m')\n  AND c.type = 'expense'\nGROUP BY c.category_id, c.name, c.expected\n\nQuestion Mapping\nUser asks\tApproach\n\"Net worth?\"\tNet worth query\n\"Balances?\"\tAccount balances query\n\"How much in [X]?\"\tFilter by name ILIKE '%X%'\n\"How much did I spend?\"\tTrue spending query (exclude internal moves)\n\"Spending on [tag]?\"\tFilter by tag\n\"Am I over budget?\"\tBudget vs actual (requires budget plugin)\n\"Recent transactions\"\tOrder by date DESC, limit\n\"Savings?\"\tFilter accounts by name/type\n\"Retirement?\"\tFilter by 401k, IRA, retirement keywords\n\"Import CSV\" / \"Upload transactions\"\tGuide through tl import — preview first with --dry-run\n\"Import from [bank name]\"\tUse tl import with appropriate flags for that bank's CSV format\nTips\nAlways use --json for parseable output\nAmounts are signed — negative = expense\nUse classification for asset/liability\nBalances live in snapshots, not the accounts table\nCheck tl skills list for user-specific account meanings and tag conventions\nPrivacy Note\n\nAll data is local (~/.treeline/treeline.duckdb). Never share transaction descriptions or account details outside the conversation unless explicitly asked."
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/zack-schrag/treeline-money",
    "publisherUrl": "https://clawhub.ai/zack-schrag/treeline-money",
    "owner": "zack-schrag",
    "version": "26.3.1401",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/treeline-money",
    "downloadUrl": "https://openagent3.xyz/downloads/treeline-money",
    "agentUrl": "https://openagent3.xyz/skills/treeline-money/agent",
    "manifestUrl": "https://openagent3.xyz/skills/treeline-money/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/treeline-money/agent.md"
  }
}