{"ok":true,"site":{"host":"glassbook.vercel.app","url":"https://glassbook.vercel.app/","type":"live","desc":"Glassbook is local-first budgeting behind glass: an AI agent works beside you in this tab, and every action is visible and undoable. No server, no accounts, no API keys. Your money. Your browser.…","tools":[{"name":"get_overview","kind":"answer","impl":"imperative","description":"Call this first to understand the user's ledger. Returns a one-line app description, months present with transaction counts, totals, categories, budgets, rules count, and the current view. No input. Amounts in the rest of the tool API are dollars (negative = expense).","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"list_transactions","kind":"answer","impl":"imperative","description":"List transactions to get ids before categorize_transactions or highlight_transactions. Filter by month (YYYY-MM), category id/name (or \"uncategorized\"), and a case-insensitive query on merchant+rawDescription. Returns cleaned merchant names only (no rawDescription). Default limit 50, max 100. Amounts are dollars (negative = expense).","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"month":{"type":"string","description":"Optional calendar month filter as YYYY-MM (e.g. 2026-07)."},"category":{"type":"string","description":"Optional category id or name (case-insensitive), or \"uncategorized\"."},"query":{"type":"string","description":"Optional case-insensitive substring matched against merchant and rawDescription."},"limit":{"type":"number","description":"Max rows to return. Default 50, maximum 100."},"offset":{"type":"number","description":"Number of matching rows to skip. Default 0."}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"get_spending_summary","kind":"answer","impl":"imperative","description":"Summarize expenses (negative amounts only) grouped by category, merchant, or month. Use after categorizing to answer \"where did the money go?\" and \"why was <month> expensive?\". Optional month (YYYY-MM) scopes the period; omit for all months. Returns groups sorted by spend desc plus grand expense total and income total. Amounts in dollars.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"group_by":{"type":"string","enum":["category","merchant","month"],"description":"How to group expenses: category, merchant, or month."},"month":{"type":"string","description":"Optional YYYY-MM period. Omit to include every month in the ledger."}},"required":["group_by"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"find_recurring","kind":"answer","impl":"imperative","description":"Detect recurring expense charges (subscriptions, rent, retainers). Groups expenses by merchant: recurring means ≥3 occurrences, amount variance under 15%, and a weekly (6-8d) or monthly (25-35d) cadence. Call when hunting forgotten subscriptions or forecasting annual cost. No input. Amounts in dollars (negative = typical charge).","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"get_budget_status","kind":"answer","impl":"imperative","description":"Check each budgeted category for a month (default: the dashboard month, which is the latest month with data if the user has not picked one): limit, spent, remaining, percent used, and over. Also returns totals. Use after set_budget or to see if the user is over. Amounts in dollars. Spent counts only categorized expenses.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"month":{"type":"string","description":"Optional YYYY-MM to evaluate. Defaults to the dashboard month."}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"categorize_transactions","kind":"act","impl":"imperative","description":"Flagship write: assign categories in one batched call (one undo frame). First list_transactions to collect ids, then batch aggressively (up to ~100 ids per call) instead of one-by-one. Input is assignments: [{transaction_ids, category}] so one call can sort many categories. Category accepts id or name. Amounts elsewhere are dollars (negative = expense).","inputSchema":{"type":"object","properties":{"assignments":{"type":"array","description":"Groups of transaction ids to assign to a category. Each item: { transaction_ids: string[], category: string }.","items":{"type":"object","properties":{"transaction_ids":{"type":"array","items":{"type":"string"},"description":"Transaction ids from list_transactions."},"category":{"type":"string","description":"Category id or name (case-insensitive), or \"uncategorized\" to clear."}},"required":["transaction_ids","category"]}}},"required":["assignments"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"create_category","kind":"act","impl":"imperative","description":"Create a new spending or income category when none of the defaults fit. Rejects duplicate names (case-insensitive). Optional hex color; a default color/icon is chosen if omitted. Use before create_rule or categorize_transactions if you need a new bucket.","inputSchema":{"type":"object","properties":{"name":{"type":"string","description":"Display name for the new category."},"color":{"type":"string","description":"Optional hex color like #22c55e."}},"required":["name"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"create_rule","kind":"act","impl":"imperative","description":"Add an auto-categorization rule when the user corrects a category or wants future imports auto-sorted. Matches a case-insensitive substring on merchant (default) or rawDescription. apply_now (default true) immediately categorizes existing uncategorized matches. Use after spotting a recurring merchant.","inputSchema":{"type":"object","properties":{"match":{"type":"string","description":"Case-insensitive substring to match."},"category":{"type":"string","description":"Category id or name to assign when the rule hits."},"field":{"type":"string","enum":["merchant","rawDescription"],"description":"Which field to search. Default merchant."},"apply_now":{"type":"boolean","description":"If true (default), apply all rules to current uncategorized transactions."}},"required":["match","category"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"apply_rules","kind":"act","impl":"imperative","description":"Run every saved rule over currently uncategorized transactions. Use after importing or when create_rule was called with apply_now false. Returns how many rows were categorized. No input.","inputSchema":{"type":"object","properties":{},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_budget","kind":"act","impl":"imperative","description":"Set or remove a monthly budget for a category (id or name). monthly_limit is dollars; pass null or 0 to remove the budget. Use after get_spending_summary to lock in a limit. Undoable.","inputSchema":{"type":"object","properties":{"category":{"type":"string","description":"Category id or name (case-insensitive)."},"monthly_limit":{"description":"Monthly limit in dollars, or null/0 to remove the budget."}},"required":["category","monthly_limit"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"add_transaction","kind":"act","impl":"imperative","description":"Manually add one transaction sourced as agent. date is YYYY-MM-DD, amount is dollars (negative = expense, positive = income), optional category id/name and note. Use for missing cash or a correction, not for bulk imports.","inputSchema":{"type":"object","properties":{"date":{"type":"string","description":"ISO date YYYY-MM-DD."},"merchant":{"type":"string","description":"Cleaned merchant name shown in the ledger."},"amount":{"type":"number","description":"Amount in dollars. Negative = expense, positive = income."},"category":{"type":"string","description":"Optional category id or name."},"note":{"type":"string","description":"Optional note stored on the transaction."}},"required":["date","merchant","amount"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"delete_transactions","kind":"transact","impl":"imperative","description":"Remove transactions by id. Undoable. Use for duplicates, junk, or a mistaken add_transaction. Prefer categorize when the charge is real.","inputSchema":{"type":"object","properties":{"transaction_ids":{"type":"array","items":{"type":"string"},"description":"Ids to delete. Call list_transactions first."}},"required":["transaction_ids"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"annotate_transaction","kind":"act","impl":"imperative","description":"Set or clear a note on a single transaction. Pass an empty string to clear. Use to remember context (\"work lunch\", \"reimburse\") without changing the category. Undoable.","inputSchema":{"type":"object","properties":{"transaction_id":{"type":"string","description":"Id of the transaction to annotate."},"note":{"type":"string","description":"Note text. Empty string clears the note."}},"required":["transaction_id","note"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"highlight_transactions","kind":"act","impl":"imperative","description":"Visually point the user at specific transactions you are discussing. Switches to the transactions view, rings the rows, scrolls the first into view, and auto-clears after 10s. Pass an empty transaction_ids array to clear immediately. Not undoable.","inputSchema":{"type":"object","properties":{"transaction_ids":{"type":"array","items":{"type":"string"},"description":"Ids to highlight. Empty array clears the current highlight."},"note":{"type":"string","description":"Optional context remembered only in the activity log."}},"required":["transaction_ids"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"set_view_filters","kind":"act","impl":"imperative","description":"Update the human's visible transaction filters so you and the user look at the same slice. Navigates to the transactions view. Pass null on a field to clear it. Not undoable.","inputSchema":{"type":"object","properties":{"month":{"description":"YYYY-MM to filter, or null to show all months."},"category":{"description":"Category id/name, \"uncategorized\", or null to clear the category filter."},"query":{"description":"Search substring, or null to clear search."},"uncategorized_only":{"type":"boolean","description":"If true, show only uncategorized rows."},"kind":{"type":"string","description":"all, spend, or income. Filters the visible list by amount sign."},"view":{"type":"string","description":"Optional. If \"transactions\", navigate there (always does)."}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"navigate_to_view","kind":"act","impl":"imperative","description":"Switch the visible Glassbook page so the user follows along. Views: dashboard, transactions, budgets, import, rules. Log-only; not undoable.","inputSchema":{"type":"object","properties":{"view":{"type":"string","enum":["dashboard","transactions","budgets","import","rules"],"description":"Which app view to show."}},"required":["view"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"pin_insight","kind":"act","impl":"imperative","description":"Pin a durable finding the user should remember (shows on the Dashboard). Keep body under ~200 characters. Optional emoji. Undoable write. Use for conclusions, not transient status.","inputSchema":{"type":"object","properties":{"title":{"type":"string","description":"Short insight headline."},"body":{"type":"string","description":"Supporting detail, ideally under 200 characters."},"emoji":{"type":"string","description":"Optional emoji prefix for the card."}},"required":["title","body"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"},{"name":"get_dashboard_state","kind":"answer","impl":"imperative","description":"Call to see exactly what the user is currently looking at, so you can talk about what's on their screen. Returns current view, dashboard selected month, active transaction filters, highlighted transaction ids, and pinned insight titles. No input.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute"}],"category":"Finance & Crypto","favicon":"/favicons/glassbook.vercel.app.ico","apiSurface":"spec","toolCount":18}}