Token导航 LogoToken导航TokenDH.com
开发需要联网github未标认证来源可访问许可证需确认审计提醒

financekitfinancekit 命令行

Agent Skill

financekit 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

15,228

周安装

616

GitHub Stars

465

下载量

4,780
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:financekit(financekit 命令行)
来源仓库:https://github.com/dpearson2699/swift-ios-skills
仓库路径:skills/financekit
安装命令:
npx skills add https://github.com/dpearson2699/swift-ios-skills --skill financekit
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/dpearson2699/swift-ios-skills --skill financekit

简介

用于处理 GitHub 仓库、Issue、Pull Request 等协作信息。

  • 适合围绕代码变更或协作事项进行整理和跟踪。
  • 可结合来源仓库和原始 README 继续核验具体功能。
  • 安装前建议确认权限范围和仓库访问级别。financekit 属于开发类 Skill,可作为该场景下的辅助能力补充。
  • 注意维护状态及是否依赖外部 API 调用。

SKILL.md

FinanceKit

Access financial data from Apple Wallet including Apple Card, Apple Cash, and Apple Card Savings. FinanceKit provides on-device, offline access to accounts, balances, and transactions with user-controlled authorization. Targets Swift 6.3 / iOS 26+. Query APIs are available from iOS 17.4; background delivery requires iOS 26.

Contents

Setup and Entitlements

Requirements

  1. Managed entitlement -- request com.apple.developer.financekit from Apple via the FinanceKit entitlement request form. This is a managed capability; Apple reviews each application.
  2. Organization-level Apple Developer account (individual accounts are not eligible).
  3. Account Holder role required to request the entitlement.

Project Configuration

  1. Add the FinanceKit entitlement through Xcode managed capabilities after Apple approves the request.
  2. Add NSFinancialDataUsageDescription to Info.plist -- this string is shown to the user during the authorization prompt.
<key>NSFinancialDataUsageDescription</key>
<string>This app uses your financial data to track spending and provide budgeting insights.</string>

Data Availability

Check whether the device supports FinanceKit before making any API calls. This value is constant across launches and iOS versions.

import FinanceKit

guard FinanceStore.isDataAvailable(.financialData) else {
    // FinanceKit not available -- do not call any other financial data APIs.
    // The framework terminates the app if called when unavailable.
    return
}

For Wallet orders:

guard FinanceStore.isDataAvailable(.orders) else { return }

Data availability returning true does not guarantee data exists on the device. Data access can also become temporarily restricted (e.g., Wallet unavailable, MDM restrictions). Restricted access throws FinanceError.dataRestricted rather than terminating.

Authorization

Request authorization to access user-selected financial accounts. The system presents an account picker where the user chooses which accounts to share and the earliest transaction date to expose.

let store = FinanceStore.shared

let status = try await store.requestAuthorization()
switch status {
case .authorized:    break  // Proceed with queries
case .denied:        break  // User declined
case .notDetermined: break  // No meaningful choice made
@unknown default:    break
}

Checking Current Status

Query current authorization without prompting:

let currentStatus = try await store.authorizationStatus()

Once the user grants or denies access, requestAuthorization() returns the cached decision without showing the prompt again. Users can change access in Settings > Privacy & Security > Financial Data.

Querying Accounts

Accounts are modeled as an enum with two cases: .asset (e.g., Apple Cash, Savings) and .liability (e.g., Apple Card credit). Both share common properties (id, displayName, institutionName, currencyCode) while liability accounts add credit-specific fields.

func fetchAccounts() async throws -> [Account] {
    let query = AccountQuery(
        sortDescriptors: [SortDescriptor(\Account.displayName)],
        predicate: nil,
        limit: nil,
        offset: nil
    )

    return try await store.accounts(query: query)
}

Working with Account Types

switch account {
case .asset(let asset):
    print("Asset account, currency: \(asset.currencyCode)")
case .liability(let liability):
    if let limit = liability.creditInformation.creditLimit {
        print("Credit limit: \(limit.amount) \(limit.currencyCode)")
    }
}

Account Balances

Balances represent the amount in an account at a point in time. A CurrentBalance is one of three cases: .available (includes pending), .booked (posted only), or .availableAndBooked.

func fetchBalances(for accountID: UUID) async throws -> [AccountBalance] {
    let predicate = #Predicate<AccountBalance> { balance in
        balance.accountID == accountID
    }

    let query = AccountBalanceQuery(
        sortDescriptors: [SortDescriptor(\AccountBalance.id)],
        predicate: predicate,
        limit: nil,
        offset: nil
    )

    return try await store.accountBalances(query: query)
}

Reading Balance Amounts

Amounts are always positive decimals. Use creditDebitIndicator to determine the sign:

func formatBalance(_ balance: Balance) -> String {
    let sign = balance.creditDebitIndicator == .debit ? "-" : ""
    return "\(sign)\(balance.amount.amount) \(balance.amount.currencyCode)"
}

// Extract from CurrentBalance enum:
switch balance.currentBalance {
case .available(let bal):       formatBalance(bal)
case .booked(let bal):          formatBalance(bal)
case .availableAndBooked(let available, _): formatBalance(available)
@unknown default: "Unknown"
}

Querying Transactions

Use TransactionQuery with Swift predicates, sort descriptors, limit, and offset.

let predicate = #Predicate<Transaction> { $0.accountID == accountID }

let query = TransactionQuery(
    sortDescriptors: [SortDescriptor(\Transaction.transactionDate, order: .reverse)],
    predicate: predicate,
    limit: 50,
    offset: nil
)

let transactions = try await store.transactions(query: query)

Reading Transaction Data

let amount = transaction.transactionAmount
let direction = transaction.creditDebitIndicator == .debit ? "spent" : "received"
print("\(transaction.transactionDescription): \(direction) \(amount.amount) \(amount.currencyCode)")
// merchantName, merchantCategoryCode, foreignCurrencyAmount are optional

Built-In Predicate Helpers

FinanceKit provides factory methods for common filters:

// Filter by transaction status
let bookedOnly = TransactionQuery.predicate(forStatuses: [.booked])

// Filter by transaction type
let purchases = TransactionQuery.predicate(forTransactionTypes: [.pointOfSale, .directDebit])

// Filter by merchant category
let groceries = TransactionQuery.predicate(forMerchantCategoryCodes: [
    MerchantCategoryCode(rawValue: 5411)  // Grocery stores
])

Transaction Properties Reference

PropertyTypeNotes
idUUIDUnique per device
accountIDUUIDLinks to parent account
transactionDateDateWhen the transaction occurred
postedDateDate?When booked; nil if pending
transactionAmountCurrencyAmountAlways positive
creditDebitIndicatorCreditDebitIndicator.debit or .credit
transactionDescriptionStringDisplay-friendly description
originalTransactionDescriptionStringRaw institution description
merchantNameString?Merchant name if available
merchantCategoryCodeMerchantCategoryCode?ISO 18245 code
transactionTypeTransactionType.pointOfSale, .transfer, etc.
statusTransactionStatus.authorized, .pending, .booked, .memo, .rejected
foreignCurrencyAmountCurrencyAmount?Foreign currency if applicable
foreignCurrencyExchangeRateDecimal?Exchange rate if applicable

Long-Running Queries and History

Use AsyncSequence-based history APIs for live updates or resumable sync. These return FinanceStore.Changes (inserted, updated, deleted items) plus a HistoryToken for resumption.

func monitorTransactions(for accountID: UUID) async throws {
    let history = store.transactionHistory(
        forAccountID: accountID,
        since: loadSavedToken(),
        isMonitoring: true  // true = keep streaming; false = terminate after catch-up
    )

    for try await changes in history {
        // changes.inserted, changes.updated, changes.deleted
        saveToken(changes.newToken)
    }
}

History Token Persistence

HistoryToken conforms to Codable. Persist it to resume queries without reprocessing data:

func saveToken(_ token: FinanceStore.HistoryToken) {
    if let data = try? JSONEncoder().encode(token) {
        UserDefaults.standard.set(data, forKey: "financeHistoryToken")
    }
}

func loadSavedToken() -> FinanceStore.HistoryToken? {
    guard let data = UserDefaults.standard.data(forKey: "financeHistoryToken") else { return nil }
    return try? JSONDecoder().decode(FinanceStore.HistoryToken.self, from: data)
}

If a saved token points to compacted history, the framework throws FinanceError.historyTokenInvalid. Discard the token and start fresh.

Account and Balance History

let accountChanges = store.accountHistory(since: nil, isMonitoring: true)
let balanceChanges = store.accountBalanceHistory(forAccountID: accountID, since: nil, isMonitoring: true)

Transaction Picker

For apps that need selective, ephemeral access without full authorization, use TransactionPicker from FinanceKitUI. Access is not persisted -- transactions are passed directly for immediate use.

import FinanceKitUI

struct ExpenseImportView: View {
    @State private var selectedTransactions: [Transaction] = []

    var body: some View {
        if FinanceStore.isDataAvailable(.financialData) {
            TransactionPicker(selection: $selectedTransactions) {
                Label("Import Transactions", systemImage: "creditcard")
            }
        }
    }
}

Wallet Orders

FinanceKit supports saving and querying Wallet orders (e.g., purchase receipts, shipping tracking).

Saving an Order

let result = try await store.saveOrder(signedArchive: archiveData)
switch result {
case .added:        break  // Saved
case .cancelled:    break  // User cancelled
case .newerExisting: break // Newer version already in Wallet
@unknown default:   break
}

Checking for an Existing Order

let orderID = FullyQualifiedOrderIdentifier(
    orderTypeIdentifier: "com.merchant.order",
    orderIdentifier: "ORDER-123"
)
let result = try await store.containsOrder(matching: orderID, updatedDate: lastKnownDate)
// result: .exists, .newerExists, .olderExists, or .notFound

Add Order to Wallet Button (FinanceKitUI)

import FinanceKitUI

AddOrderToWalletButton(signedArchive: orderData) { result in
    // result: .success(SaveOrderResult) or .failure(Error)
}

Background Delivery

iOS 26+ supports background delivery extensions that notify your app of financial data changes outside its lifecycle. Requires App Groups to share data between the app and extension.

Enabling Background Delivery

try await store.enableBackgroundDelivery(
    for: [.transactions, .accountBalances],
    frequency: .daily
)

Available frequencies: .hourly, .daily, .weekly.

Disable selectively or entirely:

try await store.disableBackgroundDelivery(for: [.transactions])
try await store.disableAllBackgroundDelivery()

Background Delivery Extension

Create a background delivery extension target in Xcode (Background Delivery Extension template). Both the app and extension must belong to the same App Group.

import FinanceKit

struct MyFinanceExtension: BackgroundDeliveryExtension {
    var body: some BackgroundDeliveryExtensionProviding { FinanceDataHandler() }
}

struct FinanceDataHandler: BackgroundDeliveryExtensionProviding {
    func didReceiveData(for dataTypes: [FinanceStore.BackgroundDataType]) async {
        for dataType in dataTypes {
            switch dataType {
            case .transactions:    await processNewTransactions()
            case .accountBalances: await updateBalanceCache()
            case .accounts:        await refreshAccountList()
            @unknown default:      break
            }
        }
    }

    func willTerminate() async { /* Clean up */ }
}

Common Mistakes

1. Calling APIs when data is unavailable

DON'T -- skip availability check:

let store = FinanceStore.shared
let status = try await store.requestAuthorization() // Terminates if unavailable

DO -- guard availability first:

guard FinanceStore.isDataAvailable(.financialData) else {
    showUnavailableMessage()
    return
}
let status = try await FinanceStore.shared.requestAuthorization()

2. Ignoring the credit/debit indicator

DON'T -- treat amounts as signed values:

let spent = transaction.transactionAmount.amount // Always positive

DO -- apply the indicator:

let amount = transaction.transactionAmount.amount
let signed = transaction.creditDebitIndicator == .debit ? -amount : amount

3. Not handling data restriction errors

DON'T -- assume authorized access persists:

let transactions = try await store.transactions(query: query) // Fails if Wallet restricted

DO -- catch FinanceError:

do {
    let transactions = try await store.transactions(query: query)
} catch let error as FinanceError {
    if case .dataRestricted = error { showDataRestrictedMessage() }
}

4. Requesting full snapshots instead of resumable queries

DON'T -- fetch everything on every launch:

let allTransactions = try await store.transactions(query: TransactionQuery(
    sortDescriptors: [SortDescriptor(\Transaction.transactionDate)],
    predicate: nil, limit: nil, offset: nil
))

DO -- use history tokens for incremental sync:

let history = store.transactionHistory(
    forAccountID: accountID,
    since: loadSavedToken(),
    isMonitoring: false
)
for try await changes in history {
    processChanges(changes)
    saveToken(changes.newToken)
}

5. Not persisting history tokens

DON'T -- discard the token:

for try await changes in history {
    processChanges(changes)
    // Token lost -- next launch reprocesses everything
}

DO -- save every token:

for try await changes in history {
    processChanges(changes)
    saveToken(changes.newToken)
}

6. Misinterpreting credit/debit on liability accounts

Both asset and liability accounts use .debit for outgoing money. But .credit means different things: on an asset account it means money received; on a liability account it means a payment or refund that increases available credit. See references/financekit-patterns.md for a full interpretation table.

Review Checklist

  • FinanceStore.isDataAvailable(.financialData) checked before any API call
  • com.apple.developer.financekit entitlement requested and approved by Apple
  • NSFinancialDataUsageDescription set in Info.plist with a clear, specific message
  • Organization-level Apple Developer account used
  • Authorization status handled for all cases (.authorized, .denied, .notDetermined)
  • FinanceError.dataRestricted caught and handled gracefully
  • CreditDebitIndicator applied correctly to amounts (not treated as signed)
  • History tokens persisted for resumable queries
  • FinanceError.historyTokenInvalid handled by discarding token and restarting
  • Long-running queries use isMonitoring: false when live updates are not needed
  • Transaction picker used when full authorization is unnecessary
  • Only data the app genuinely needs is queried
  • Deleted data from history changes is removed from local storage
  • Background delivery extension in same App Group as the main app (iOS 26+)
  • Financial data deleted when user revokes access

References

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

36.82%
按下载量换算1,760

Claude

28.43%
按下载量换算1,359

Cursor

17.74%
按下载量换算848

Gemini CLI

8.48%
按下载量换算405

安全审计

Gen Agent Trust Hub

可疑

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在 warning/failed 结果,不能写成本站确认安全。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills