Documentation

Install, authenticate, query. Everything ships as structured data you can pipe, filter, and script.

Quickstart #

1

Install

$ npm install -g @fin/cli

# verify
$ fin --version
@fin/cli/0.1.0
2

Authenticate

# API key auth
$ fin auth:login stripe --api-key sk_live_...

# or interactive mode
$ fin auth:login stripe --interactive
3

Query

$ fin stripe:invoices:list --status unpaid --json
[
  { "id": "inv_4a8Bx", "customer": "cus_R1k9", "amount": 15000, "status": "unpaid" },
  { "id": "inv_9zKm2", "customer": "cus_T4w7", "amount": 8400, "status": "unpaid" }
]

$ fin stripe:invoices:list --status unpaid --json | jq '.[].amount'
15000
8400

$ fin stripe:customers:list --csv > customers.csv
4

Verify

$ fin doctor
  ✓  stripe    authenticated · reachable · api v2024-06-20

Command grammar #

Every command follows one pattern. No provider-specific syntax to memorize.

fin [provider]:[object]:[verb] [--flags]
fin stripe:invoices:list List all Stripe invoices
fin quickbooks:accounts:sync Sync QuickBooks chart of accounts
fin gusto:payroll:run --period 2026-03 Run Gusto payroll for March
fin ramp:expenses:export --csv Export Ramp expenses as CSV
fin carta:cap-table:get --json Get cap table from Carta as JSON

Standard verbs

listPaginated collection → stdout
getSingle record by ID → stdout
createCreate a resource, returns created object
updatePatch a resource by ID
deleteDelete a resource by ID
runLong-running job (e.g. payroll run)
syncPull remote state into local cache
exportSerialize to file (CSV, JSONL)

Authentication #

Credentials are encrypted with AES-256-CBC and stored locally. Never in plaintext.

# authenticate with an API key
$ fin auth:login stripe --api-key sk_live_...
✓ Authenticated with Stripe (api v2024-06-20)

# interactive mode (guided prompts)
$ fin auth:login stripe --interactive

# check status of all providers
$ fin auth:status
  stripe      ✓ authenticated (expires: never)
  quickbooks  ✓ authenticated (expires: 2026-04-15)
  gusto       ✗ token expired

# rotate credentials
$ fin auth:rotate stripe

# remove credentials
$ fin auth:logout stripe

Provider coverage #

599 providers across 20 categories. Same grammar, same flags, same output format. Swap the provider prefix and everything works.

Architecture #

A TypeScript monorepo designed for isolation, extensibility, and security.

packages/
  core/                 @fin/core - CLI framework
    src/
      commands/          auth/*, doctor
      lib/
        auth/            AES-256-CBC encrypted credential storage
        errors/          Normalized FinError codes
        output/          JSON, CSV, table renderers
        providers/       Plugin registry
    bin/run.js           CLI entry point
  plugin-stripe/       @fin/plugin-stripe
    src/
      commands/stripe/
        customers/       list, get
        invoices/        list, get
        payments/        list, get
  plugin-accounting/   @fin/plugin-accounting (14 providers)
    src/
      lib/             Shared base, mock data factory
      commands/
        xero/            accounts, invoices, bills, contacts, payments, credit-notes, journals, items, tax-rates
        quickbooks/      accounts, invoices, bills, contacts, payments, credit-notes, journals, items, tax-rates
        freshbooks/      ... (same 9 objects for all 14 providers)

Stack

  • LanguageTypeScript (ES2022)
  • Frameworkoclif v4
  • Monorepopnpm workspaces
  • TUI@clack/prompts
  • ValidationZod
  • CredentialsAES-256-CBC

Error codes

  • AUTH_REQUIREDNot authenticated
  • AUTH_EXPIREDToken expired
  • RATE_LIMITRate limited
  • NOT_FOUNDResource missing
  • VALIDATIONInvalid input
  • NETWORKConnection failed

Plugin contract

  • IsolationIndependent npm packages
  • VersioningSemver per provider
  • AuthShared credential store
  • OutputShared renderer
  • ErrorsNormalized FinError
  • TestingVitest per package

Security model #

fin handles credentials and financial data. Here's how it protects both.

Credential lifecycle

  • Encryption at restAES-256-CBC
  • StorageIsolated keychain per provider
  • OAuth tokensAutomatic rotation on expiry
  • API keysManual rotation via fin auth:rotate
  • LogoutCredential wipe with fin auth:logout

Transport security

  • ProtocolTLS 1.2+ enforced
  • ProxyNone — direct to provider API
  • Data persistenceNone — all output to stdout
  • TelemetryNone — no usage tracking

Least-privilege model

  • Default modeRead-only
  • PermissionsScoped per provider
  • Safety net--dry-run previews without executing
  • No writesNo create, update, or delete operations

Audit & compliance

  • Audit logStructured JSON via --audit
  • ReplayCommand replay from audit log
  • OutputDeterministic, pipeable formats
  • Visibility--verbose shows request/response headers