ssdavidai/alfred/alfred-sure-operations

Claude Code and agent skill by ssdavidai/alfred

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Read net worth, accounts, transactions, categories, and merchants from Sir's self-hosted Sure personal-finance app, log manual transactions and reconcile illiquid asset valuations, and trigger family-wide bank-feed syncs. Use when Sir asks about money (net worth, spending, balances), when generating Money Day briefs, when logging cash movements, or when setting up Lunchflow as a bank-feed provider.

Install

npx vskill@latest install ssdavidai/alfred/alfred-sure-operations

SKILL.md

Alfred — Sure Operations

Sure is Sir's self-hosted personal-finance app — a Rails service running as sure-web in the tenant Docker stack. It holds every account, transaction, holding, category, and merchant across Sir's financial life, in whichever currencies he uses.

You reach Sure through the MCP self tool by hitting ctrl-api at /api/v1/sure/<endpoint>. Ctrl-api proxies to sure-web:3000/api/v1/<endpoint> and attaches the X-Api-Key header — never call sure-web directly, the API key is held by ctrl-api. The proxy forwards request method, query string, and body verbatim and returns the response unchanged.

The endpoint paths below match Sure's OpenAPI spec exactly. Note balance_sheet uses an underscore — that's deliberate, the spec uses snake_case.

Endpoints

1. Balance sheet — net worth in one call

self({endpoint: "/api/v1/sure/balance_sheet", method: "GET"})

Returns {currency, net_worth, assets, liabilities} with totals broken down by classification. This is the top-line number for any "what's my net worth?" question and the anchor of every Money Day brief. One call, no pagination, no filters — cheap and idempotent.

Use it when:

  • Sir asks "what's my net worth?" or "where do I stand?".
  • You're opening a Money Day Tuesday brief and need the headline figure.
  • Sir wants a quick sanity-check before a large purchase or transfer.
2. List accounts

self({endpoint: "/api/v1/sure/accounts", method: "GET", query: {page: 1, per_page: 50}})

Paginated list of every account — bank, investment, crypto, property, manual. Each carries its current balance, currency, and classification. Use this when Sir asks "what accounts do I have?", "what's the balance on my Example Bank EUR?", or when you need to resolve an account name to its account_id before posting a transaction.

Pitfall: the response is paginated. If Sir has more than 50 accounts (rare but possible across HUF/EUR/USD/GBP), walk pages until exhausted before claiming a complete list.

3. List transactions (with filters)

self({endpoint: "/api/v1/sure/transactions", method: "GET", query: {start_date: "2026-04-01", end_date: "2026-04-29", category_ids: ["<groceries-id>"], per_page: 100}})

This is the workhorse read endpoint. Useful query params (all optional):

  • start_date, end_date — ISO dates (YYYY-MM-DD). Filter by transaction date.
  • account_id or account_ids[] — single or multiple account scoping.
  • category_id or category_ids[] — filter by spending category.
  • merchant_id or merchant_ids[] — filter by merchant.
  • tag_ids[] — filter by tag.
  • min_amount, max_amount — amount bounds.
  • type — restrict to inflows/outflows/transfers.
  • search — free-text match against name/description/notes.
  • page, per_page — pagination (default 25, max usually 100).

Each transaction returns {id, date, amount, amount_cents, signed_amount_cents, currency, name, classification, account, category, merchant, tags[], transfer, ...}. The signed_amount_cents is what you want for arithmetic (negative = outflow).

Pitfall: don't fetch every transaction ever for a wide question — narrow with start_date/end_date first. Sir's transaction count grows fast and a category-spend question rarely needs more than one month of data.

4. Create a transaction (manual entry)

self({endpoint: "/api/v1/sure/transactions", method: "POST", body: {transaction: {account_id: "<id>", date: "2026-04-29", amount: -400, currency: "EUR", name: "Cash withdrawal", category_id: "<cash-id>"}}})

Use this when Sir hands you a movement that won't show up in any bank feed — cash withdrawals and spends, between-spouse transfers reconciled by hand, a one-off reimbursement, etc.

Body wraps everything under a transaction key. Fields:

  • account_id (required) — resolve via /accounts first if Sir gave you a human name.
  • date (required) — ISO YYYY-MM-DD. Default to today if Sir didn't say.
  • amount (required) — signed; negative for outflows, positive for inflows. Currency-native units (e.g. -400.00 for €400 spent).
  • currency — three-letter ISO. Defaults to the account's currency if omitted.
  • name, description, notes — human labels.
  • category_id, merchant_id, tag_ids[] — optional classification.
  • nature — inflow / outflow / transfer.

Pitfall: Sure expects the sign on amount to match Sir's intent. €400 cash withdrawal from the EUR current account is amount: -400, not 400.

5. Update / recategorize a transaction

self({endpoint: "/api/v1/sure/transactions/{id}", method: "PATCH", body: {transaction: {category_id: "<groceries-id>"}}})

Use this when Sir wants to recategorize ("that Example Grocer run was groceries, not entertainment"), correct an amount, attach a tag, or rename a transaction. Same transaction.{field} body shape as create — only include the fields you're changing.

Pitfall: don't issue a PATCH without first reading the transaction to confirm it's the one Sir means. Multiple Example Grocer runs land each week.

6. List categories (with budget status)

self({endpoint: "/api/v1/sure/categories", method: "GET", query: {classification: "expense", roots_only: true}})

Returns categories with {id, name, classification, color, icon, parent, subcategories_count}. Use it to:

  • Resolve a category name to its id before filtering transactions or creating one.
  • Surface Sir's category tree when he asks "what am I tracking?".
  • Check whether a category Sir mentioned actually exists ("groceries" might be filed under "Food & Drink → Groceries").

roots_only: true collapses subcategories. parent_id: <id> walks the children of a node. classification filters expense vs. income vs. transfer.

7. List merchants

self({endpoint: "/api/v1/sure/merchants", method: "GET"})

Returns {id, name, type} per merchant. Use this when Sir asks "how much did I spend at Example Grocer this year?" — resolve "Example Grocer" to its merchant id, then call /transactions?merchant_id=<id>&start_date=.... Cheaper than search for repeat merchants.

8. Trigger a sync

self({endpoint: "/api/v1/sure/sync", method: "POST"})

Queues a full family-wide sync across every connected provider (Lunchflow, Plaid, SimpleFIN, Binance, Coinbase, etc.). Returns {id, status, syncing_at, completed_at, ...}. The sync itself runs asynchronously — the response confirms it's queued, not finished.

Use it before generating a Money Day brief so the figures Sir sees are fresh. Once per session is plenty — calling it on every question wastes provider rate-limit and won't make the data any newer than the last upstream pull.

9. Manual valuation (illiquid assets)

self({endpoint: "/api/v1/sure/valuations", method: "POST", body: {valuation: {account_id: "<property-id>", amount: 165000000, date: "2026-04-29", notes: "Q2 2026 mark"}}})

Use this for assets that don't have a live feed — the flat, crypto held in a cold wallet outside connected exchanges, a private-company stake. Posting a valuation re-marks the account's balance to that amount on that date; the balance sheet picks it up on the next read.

Pitfall: amount is in currency-native units (HUF for a HUF property account, USD for USD-denominated). Ask Sir for the currency if it isn't obvious from the account.

10. API usage

self({endpoint: "/api/v1/sure/usage", method: "GET"})

Returns the current rate-limit window: {rate_limit: {tier, limit, current_count, remaining, reset_in_seconds, reset_at}, api_key: {...}}. Use it when a sequence of calls starts 429-ing, or when Sir asks "are we hitting a Sure rate limit?". Not a substitute for restraint — see "Good behaviour".

Worked examples

Sir: "What's my net worth?"

self({endpoint: "/api/v1/sure/balance_sheet", method: "GET"})
// → {currency: "EUR", net_worth: 412350.22, assets: 458100.00, liabilities: 45749.78}

Reply in prose with the right currency symbol, not the raw JSON: "Sir, your net worth sits at €412,350 — €458,100 in assets against €45,750 in liabilities. Want the breakdown by account?"

Money Day Tuesday brief generation

// 1. Refresh the data first
self({endpoint: "/api/v1/sure/sync", method: "POST"})
// 2. Headline figure
self({endpoint: "/api/v1/sure/balance_sheet", method: "GET"})
// 3. Last-7-day cash movement, grouped later by category
self({endpoint: "/api/v1/sure/transactions", method: "GET", query: {start_date: "2026-04-22", end_date: "2026-04-29", per_page: 100}})
// 4. Account balances for the table
self({endpoint: "/api/v1/sure/accounts", method: "GET", query: {per_page: 100}})

Compose the brief in prose: net worth WoW delta, top 3 outflow categories, any anomaly (a transaction more than 2σ above its category mean), and the per-account balance table grouped by currency. Don't paste any of the raw responses.

Sir: "Log €400 cash I just took out."

// 1. Resolve the EUR current account if you don't already know the id
self({endpoint: "/api/v1/sure/accounts", method: "GET"})
// → find the account, e.g. {id: "acc_123", name: "Example Bank EUR", currency: "EUR"}
// 2. Find the cash category (or whichever Sir prefers)
self({endpoint: "/api/v1/sure/categories", method: "GET", query: {classification: "expense"}})
// 3. Post the transaction
self({
endpoint: "/api/v1/sure/transactions",
method: "POST",
body: {transaction: {
account_id: "acc_123",
date: "2026-04-29",
amount: -400,
currency: "EUR",
name: "Cash withdrawal",
category_id: "cat_cash",
nature: "outflow"
}}
})

Confirm back to Sir with all three concrete details: "Logged, Sir — €400 out of Example Bank EUR on 29 April, filed under Cash. Anything else?"

Sir: "How much did I spend on groceries last month?"

// 1. Resolve the groceries category id
self({endpoint: "/api/v1/sure/categories", method: "GET", query: {classification: "expense"}})
// → find {id: "cat_groceries", name: "Groceries"} (or its parent "Food & Drink" if Sir's tree is hierarchical)
// 2. Pull March transactions for that category
self({
endpoint: "/api/v1/sure/transactions",
method: "GET",
query: {start_date: "2026-03-01", end_date: "2026-03-31", category_ids: ["cat_groceries"], per_page: 100}
})

Sum signed_amount_cents per currency (Sir's groceries split across HUF and EUR — Example Grocer runs at home are HUF, FoodCo abroad is EUR). Reply with each currency total and the combined picture if a clean FX rate is available: "Sir, March groceries: Ft 412,300 at home plus €218 abroad — roughly €1,250 total at current FX. Example Grocer was the largest single merchant at Ft 187,000 across nine visits."

Connecting bank feeds via Lunchflow

Sure handles bank feeds through provider plugins — Plaid (US/CA), SimpleFIN, Sophtron, Enable Banking (EU), Binance, Coinbase, CoinStats, and Lunchflow. For Sir, who runs across HUF, EUR, GBP, and USD with accounts at multiple European banks, Lunchflow is the recommended option because it consolidates 25,000+ banks across 40+ countries through a single BYOK key (PSD2 in EU/UK, MX/Plaid for US/CA, regional providers elsewhere).

Setup is BYOK and Alfred has no Lunchflow-specific code — Sure handles the entire integration:

  1. Sir signs up at lunchflow.app and starts a paid plan (~£2.50/month at the base yearly tier, with a 7-day trial; yearly plans require a 2-connection minimum, monthly plans start at 4 connections).
  2. From the Lunchflow dashboard, Sir generates an API key.
  3. Sir opens his Sure UI at <subdomain>-sure.<domain> (the per-tenant Sure web URL).
  4. In Sure → Settings → Providers → Lunchflow, Sir pastes the API key.
  5. Sure auto-discovers connected accounts and starts syncing balances + transactions. Holdings sync where the upstream provider supports it.

Once configured, calling POST /api/v1/sure/sync fans out to every Lunchflow-connected institution alongside the other providers — you don't speak to Lunchflow directly.

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 95 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

7-day trend score
0

Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/ssdavidai/alfred/alfred-sure-operations/badge)](https://verified-skill.com/skills/ssdavidai/alfred/alfred-sure-operations)

Something wrong with this skill or its page? Tell us.