d132bfa238
Jarvis was grep-ing transaction JSON for text like "swim" instead of resolving the Swim Lessons category UUID first. Added: - Warning that payee/category fields are UUIDs - Two-step lookup patterns for category and payee searches - Date range guidance: topic queries without dates search all-time - Updated Groceries example with proper UUID filter
194 lines
6.8 KiB
Markdown
194 lines
6.8 KiB
Markdown
---
|
|
name: actual-budget
|
|
description: Use when the user asks about finances, budget, spending, account balances, transactions, categories, or money. Triggers on questions like "how much did I spend", "what's my balance", "budget status", "spending breakdown", "net worth", or any financial query against the Actual Budget server.
|
|
---
|
|
|
|
# Actual Budget Finance Skill
|
|
|
|
Query your Actual Budget instance for financial data — accounts, transactions, budgets, categories, and spending analysis. Read-only access.
|
|
|
|
## Setup
|
|
|
|
Run the setup wizard (one-time):
|
|
|
|
```bash
|
|
SKILL_DIR=$(dirname "$(find ~/.claude -path '*/actual-budget/scripts/setup.sh' 2>/dev/null | head -1)")
|
|
bash "${SKILL_DIR}/setup.sh"
|
|
```
|
|
|
|
The wizard prompts for:
|
|
- **Server URL** — Your Actual Budget instance (default: `https://budget.prettyhefty.com`)
|
|
- **Password** — Server authentication password
|
|
- **Budget sync ID** — Selected from the list of available budgets
|
|
|
|
Configuration is stored in:
|
|
- `~/.config/actual-budget/config` — Server URL, sync ID
|
|
- `~/.config/actual-budget/password` — Server password (chmod 600)
|
|
|
|
Override the config directory by setting `ACTUAL_BUDGET_CONFIG_DIR` environment variable.
|
|
|
|
## Using the Helper Functions
|
|
|
|
Source the helper script:
|
|
|
|
```bash
|
|
source "$(find ~/.claude -path '*/actual-budget/scripts/actual-helper.sh' 2>/dev/null | head -1)"
|
|
```
|
|
|
|
### Available Functions
|
|
|
|
**Configuration:**
|
|
- `actual_config` — Show current configuration
|
|
- `actual_check_config` — Verify configuration is complete
|
|
|
|
**Accounts:**
|
|
- `actual_accounts` — List all accounts with current balances
|
|
- `actual_balance [name]` — Get balance for specific account (fuzzy match by name)
|
|
|
|
**Budget:**
|
|
- `actual_budget_months` — List all months with budget data
|
|
- `actual_budget_month [YYYY-MM]` — Budget summary for a month (defaults to current)
|
|
|
|
**Transactions:**
|
|
- `actual_transactions [account] [start_date] [end_date]` — List transactions (all accounts if none specified)
|
|
- `actual_spending_by_category [start_date] [end_date]` — Spending breakdown by category
|
|
|
|
**Reference Data:**
|
|
- `actual_categories` — List all categories
|
|
- `actual_category_groups` — List category groups
|
|
- `actual_payees` — List all payees
|
|
- `actual_budgets` — List budgets available on server
|
|
|
|
**Advanced:**
|
|
- `actual_query '<json>'` — Run an arbitrary ActualQL query
|
|
|
|
### Output Format
|
|
|
|
All functions output JSON. Amounts are in decimal format (e.g., `123.45`), not Actual's internal integer format.
|
|
|
|
## Important: Transaction Fields Use UUIDs
|
|
|
|
Transaction `payee` and `category` fields are **UUIDs, not human-readable names**.
|
|
You MUST cross-reference them with `actual_categories` and `actual_payees` to get names.
|
|
|
|
**Never grep transaction JSON for category or payee names** — the names don't appear
|
|
in the transaction records. Only `imported_payee` and `notes` contain free text, and
|
|
these are unreliable (banks change formatting, Zelle shows generic "Zelle Transfer", etc.).
|
|
|
|
### Searching by Category Name
|
|
|
|
To find transactions in a category (e.g., "Swim Lessons"):
|
|
|
|
```bash
|
|
# Step 1: Get the category UUID
|
|
source /home/node/.openclaw/workspaces/family-assistant/skills/finance/scripts/actual-helper.sh
|
|
actual_categories # Find: {"id": "c830de67-...", "name": "Swim Lessons", ...}
|
|
|
|
# Step 2: Get transactions and filter by that UUID
|
|
actual_transactions "" "2024-01-01" "$(date +%Y-%m-%d)" \
|
|
| python3 -c "
|
|
import sys, json
|
|
txns = json.load(sys.stdin)
|
|
cat_id = 'c830de67-...' # from step 1
|
|
matches = [t for t in txns if t.get('category') == cat_id]
|
|
print(json.dumps(matches, indent=2))
|
|
"
|
|
```
|
|
|
|
### Searching by Payee Name
|
|
|
|
To find transactions for a payee (e.g., "Aqua Warriors"):
|
|
|
|
```bash
|
|
# Step 1: Get the payee UUID
|
|
actual_payees # Find the payee by name
|
|
|
|
# Step 2: Filter transactions by payee UUID
|
|
actual_transactions "" "2024-01-01" "$(date +%Y-%m-%d)" \
|
|
| python3 -c "
|
|
import sys, json
|
|
txns = json.load(sys.stdin)
|
|
payee_id = 'f26f8469-...' # from step 1
|
|
matches = [t for t in txns if t.get('payee') == payee_id]
|
|
print(json.dumps(matches, indent=2))
|
|
"
|
|
```
|
|
|
|
### Date Range for Topic-Specific Queries
|
|
|
|
When the user asks about spending on a **specific topic** without specifying dates
|
|
(e.g., "how much have we spent on swim lessons?"), search **all-time** (from 2024-01-01)
|
|
rather than defaulting to the current month. Only use narrow date ranges when the user
|
|
explicitly says "this month" or "in March".
|
|
|
|
## Common Query Patterns
|
|
|
|
### "How much did I spend this month?"
|
|
```bash
|
|
actual_spending_by_category "$(date +%Y-%m)-01" "$(date +%Y-%m-%d)"
|
|
```
|
|
|
|
### "What's my balance across all accounts?"
|
|
```bash
|
|
actual_accounts
|
|
```
|
|
|
|
### "Show me transactions for Groceries this month"
|
|
Two-step lookup — resolve category name to UUID, then filter:
|
|
```bash
|
|
# Step 1: Get the category UUID from actual_categories output
|
|
actual_categories # find {"id": "abc123...", "name": "Groceries"}
|
|
|
|
# Step 2: Filter transactions by that UUID
|
|
actual_transactions "" "$(date +%Y-%m)-01" "$(date +%Y-%m-%d)" \
|
|
| python3 -c "import sys,json; txns=json.load(sys.stdin); [print(json.dumps(t)) for t in txns if t.get("category")=="abc123..."]"
|
|
```
|
|
|
|
### "Am I over budget this month?"
|
|
```bash
|
|
actual_budget_month "$(date +%Y-%m)"
|
|
```
|
|
The result includes `budgeted`, `spent`, and `balance` per category.
|
|
|
|
### "What did I spend at [payee] recently?"
|
|
```bash
|
|
actual_transactions "" "2026-01-01" "$(date +%Y-%m-%d)"
|
|
```
|
|
Then filter the JSON output by payee name.
|
|
|
|
## ActualQL Quick Reference
|
|
|
|
For complex queries, use `actual_query` with a JSON query object:
|
|
|
|
```bash
|
|
actual_query '{"table":"transactions","filter":{"date":{"$gte":"2026-03-01"}},"select":["date","amount","payee","category"]}'
|
|
```
|
|
|
|
**Operators:** `$eq`, `$lt`, `$lte`, `$gt`, `$gte`, `$ne`, `$regex`, `$like`, `$oneof`, `$and`, `$or`
|
|
|
|
**Tables:** `transactions` (primary), plus accounts, categories, payees accessible via the helper functions.
|
|
|
|
## Troubleshooting
|
|
|
|
- **"Config not found"** — Run `setup.sh`
|
|
- **"@actual-app/api not installed"** — Run `cd <skill-scripts-dir> && npm install @actual-app/api`
|
|
- **Connection errors** — Check server URL and password in `~/.config/actual-budget/config`
|
|
- **Empty results** — Verify the sync ID matches an active budget (`actual_budgets`)
|
|
|
|
## Presentation Guidelines
|
|
|
|
- Format currency with dollar signs and commas ($1,234.56)
|
|
- Amounts are already in dollars — do not divide by 1000
|
|
- Highlight categories over budget
|
|
- Summarize before showing details — lead with the key insight
|
|
- For transaction lists, show date, payee, category, and amount in a clean table
|
|
- When computing frequency ("how often"), count unique dates, not transaction count
|
|
- Verify arithmetic before presenting — sanity-check that "X out of Y" values are logically possible
|
|
- Prefer concrete numbers over vague summaries
|
|
|
|
## Privacy
|
|
|
|
- Financial data is private to the family
|
|
- Present data matter-of-factly without judgment
|
|
- Do not modify transactions unless explicitly requested by Bill
|