Claude Code plugin for the Spiffy platform — customer lookup, reports, notes, one-off promo codes
  • TypeScript 95.7%
  • JavaScript 3.3%
  • Shell 1%
Find a file
Julian Dickie 1216a3d14e
Merge pull request #22 from juliandickie/docs/release-0.3.0-handoff
Record v0.3.0 release and expired publish PAT in handoff
2026-08-22 02:24:46 -06:00
.githooks Add pre-push hook to prevent accidental direct pushes to main 2026-04-24 10:00:16 +10:00
.github/workflows Fix publish auth - explicit PAT push URL + persist-credentials false (#13) 2026-05-16 02:44:35 +10:00
docs Bring plugin to Spiffy r85 - analytics, reports, magic links, events (v0.3.0) 2026-08-22 02:13:41 -06:00
mcp Bring plugin to Spiffy r85 - analytics, reports, magic links, events (v0.3.0) 2026-08-22 02:13:41 -06:00
plugin Bring plugin to Spiffy r85 - analytics, reports, magic links, events (v0.3.0) 2026-08-22 02:13:41 -06:00
scripts Add pre-push hook to prevent accidental direct pushes to main 2026-04-24 10:00:16 +10:00
.env.example Fix #14 - config.toml failures fail loud, add /spiffy-doctor (v0.2.4) (#15) 2026-05-18 17:53:37 +10:00
.gitignore refactor: move plugin source into ./plugin/ subdirectory 2026-05-13 02:21:51 +10:00
CHANGELOG.md Bring plugin to Spiffy r85 - analytics, reports, magic links, events (v0.3.0) 2026-08-22 02:13:41 -06:00
CLAUDE.md Bring plugin to Spiffy r85 - analytics, reports, magic links, events (v0.3.0) 2026-08-22 02:13:41 -06:00
NEXT-SESSION.md Record v0.3.0 release and the expired publish PAT in the handoff 2026-08-22 02:24:37 -06:00
README.md Bring plugin to Spiffy r85 - analytics, reports, magic links, events (v0.3.0) 2026-08-22 02:13:41 -06:00
spiffy-openapi.json Bring plugin to Spiffy r85 - analytics, reports, magic links, events (v0.3.0) 2026-08-22 02:13:41 -06:00

Spiffy Claude Code Plugin

Talk to the Spiffy platform from Claude Code. Look up customers, generate reports, add notes, and create one-off promo codes, all in natural language.

What it does

  • Customer lookup. "look up jane@example.com" returns her orders, subscriptions, payments, and notes.
  • Analytics. Dashboard-accurate revenue, orders, AOV, LTV, conversion rate, MRR, churn, and refund numbers via the server-side analytics engine, with time series, period comparisons, and UTM/channel attribution breakdowns.
  • Server-side reports. Create, run, and export the six Spiffy report types (product sales, affiliate performance, attribution, checkout performance, payment plans, customer cohort LTV) with async runs and signed CSV downloads. /spiffy-report manages saved and scheduled reports with a confirmation gate.
  • Reports (client-side skills). MRR snapshots, affiliate performance, churn, top products, all with canonical markdown output; these now prefer the server-side engines and fall back to client-side computation.
  • Commerce diagnostics. Active commerce surface enumeration (what are we currently selling), checkout health snapshot (any stale or -em style variants to clean up), and a recent-orders smoke test for use after disabling checkouts.
  • Activity log. events_list reads the account audit trail (who changed what, automated billing actions, card updates).
  • Magic-link logins. /spiffy-login-link <customer> generates a customer or affiliate login token with a confirmation gate (the token is a live credential; Spiffy does not email it).
  • Add notes. /spiffy-note <customer> "<text>" with a confirmation gate.
  • Create one-off promo codes. /spiffy-promo <customer> --percent 20 --expires 7d creates the code and gives you a dashboard link + a draft customer message.

Requirements

  • Claude Code installed and working
  • Node.js ≥ 18
  • A Spiffy API key (get one from Settings → API in your Spiffy dashboard)
  • (Optional) 1Password CLI (op) if you want to store the key there instead of in an env file

Install

The plugin is distributed via a Claude Code plugin marketplace hosted in this repo. Inside Claude Code:

  1. Add the marketplace (one-time):

    /plugin marketplace add juliandickie/spiffy-plugin
    
  2. Install the plugin:

    /plugin install spiffy@idd-plugins
    

That's it. The MCP server ships as a self-contained pre-built bundle (plugin/mcp/dist/index.js), so no npm install step is needed on the user side. Restart Claude Code to pick up the new MCP server.

To get updates, run /plugin marketplace update idd-plugins and then /plugin install spiffy@idd-plugins again.

Local development install: if you've cloned the repo and want Claude Code to load it from your working tree, run cd mcp && npm install && npm run build once, then point Claude Code at ./plugin/ (the plugin source directory). See Development below.

Configure your API key

Choose one of three methods:

Option A: environment variable (simplest)

export SPIFFY_API_KEY=your_64_char_hex_key

(Real Spiffy keys are bare 64-character hex strings; there is no sk_live_ style prefix.)

Add it to your ~/.zshrc or ~/.bashrc to persist.

Store your key in 1Password, then set:

export SPIFFY_API_KEY=op://YourVault/Spiffy\ API/credential

Requires the 1Password CLI installed and signed in (op signin).

Option C: config.toml fallback

Create ~/.config/spiffy-plugin/config.toml:

api_key = "your_64_char_hex_key"

This is read if SPIFFY_API_KEY is not set.

Verify it works

Launch Claude Code and ask:

"Use the Spiffy plugin to look up my account."

Claude should call the account_get tool and return your account details (account_id, account_name, user_id, user_email, user_name).

Usage examples

Customer inquiry:

"Find jane@example.com in Spiffy and show me her subscription status and recent payments."

Add a note:

/spiffy-note jane@example.com She called today about a refund, approved for $99.

Generate a promo:

/spiffy-promo jane@example.com --percent 25 --expires 7d --checkout-url https://checkout.spiffy.co/advanced-endo

Run a report:

"Run the MRR snapshot for this month." "Show me the top 5 courses by revenue in Q1 2026."

Analytics:

"Revenue last month vs the month before." "Where did June orders come from, broken down by utm_source?" /spiffy-report run 31 (trigger a saved report, poll it, and read the stats)

Commerce diagnostics:

"What are we currently selling on Spiffy?" "Run a checkout snapshot and flag any stale -em variants." "Check recent orders to confirm the funnel is healthy after I disabled those checkouts."

Configuration reference

Env var Default Purpose
SPIFFY_API_KEY (none) Required. Your Spiffy API key (literal or op:// reference).
SPIFFY_BASE_URL https://api.spiffy.co Override for testing.
SPIFFY_DRY_RUN unset Set to 1 to block all writes and return synthetic responses (for testing).

Troubleshooting

"SPIFFY_API_KEY is not set". See Configure section. Check that the env var is visible to Claude Code (re-launch it after setting).

"API key invalid (401 Unauthorized)". Regenerate your key in the Spiffy dashboard at Settings → API, then update your env var or 1Password entry.

"Failed to resolve 1Password reference". Install op CLI and sign in with op signin. Verify the reference is valid: op read "op://Vault/Item/field".

Promo was created but doesn't apply at checkout. The v2 Spiffy API currently only creates the bare promo code. You still need to open the Spiffy dashboard to (1) add the promo to the correct checkout and (2) choose which products/options it applies to. The /spiffy-promo command includes a direct link to do this.

Audit log

Every write operation (notes, promo creation, saved-report changes, magic-link token generation) is logged to:

~/.local/share/spiffy-plugin/audit.log

One line per operation: timestamp, operator, action, response ID, and the confirmation summary the user approved. Rotate or archive periodically.

License

MIT (subject to IDD confirmation before open-sourcing).

Development

cd mcp
npm install           # installs deps AND configures git hooks (once)
npm run test          # run unit tests (mock-driven)
npm run test:watch    # watch mode
npm run smoke         # live-API smoke test (read-only, requires SPIFFY_API_KEY)
npm run typecheck     # TypeScript check (src + tests + scripts)
npm run build         # compile to dist/
npm run dev           # run via tsx (no build needed)

Live-API smoke

npm run smoke runs mcp/scripts/smoke.ts against your real Spiffy account. It is read-only (forces SPIFFY_DRY_RUN=1) and exits non-zero on any failure, so it is safe to wire into CI if you have a credential to stash there. It verifies the bug-fix regression guards and the documented gotcha behaviours.

The script loads SPIFFY_API_KEY from the repo-root .env automatically. If you do not have a .env, export the key in your shell first.

Why this exists. Mock-driven unit tests verify code against documentation; they cannot catch drift when documentation is wrong (which it has been multiple times for Spiffy). The live smoke is the only thing that catches structural drift early. See docs/spiffy-api-gotchas-and-patterns.md Part 7 for the story.

Git hooks

This repo uses a lightweight pre-push hook at .githooks/pre-push that blocks accidental direct pushes to main (GitHub free-tier private repos don't get platform-side branch protection). The hook is activated automatically by npm install in mcp/. It sets git config core.hooksPath .githooks for your clone.

To push changes, always use a feature branch + PR:

git checkout -b feat/your-feature
git push -u origin feat/your-feature
gh pr create --base main

Emergency override (use sparingly): git push --no-verify.

For plugin integrators

If you are extending this plugin or troubleshooting an integration, start with docs/spiffy-api-gotchas-and-patterns.md. It captures non-obvious behaviours of the Spiffy API discovered during real-world integration work. Highlights.

  • The /v2/checkouts endpoint does not exist. Checkouts are reached via /v1/checkouts. The plugin's checkout_list tool handles this.

  • status: "active" on a checkout means "exists in admin", not "publicly purchasable". The plugin's tool descriptions and the active-commerce-surface skill both surface this distinction.

  • is_active: true on a product is catalogue state, independent of whether any checkout is live. Legacy products often keep this flag true for grandfathered subscription delivery.

  • Prices live nested at options[].prices[].amount and are in cents, not dollars. Only the detail endpoint (product_get) exposes them.

  • Pagination shape differs between v1 ({count, page, checkouts[]}) and v2 ({data, meta: {pagination: {...}}}). Note pagination on v2 lives at meta.pagination, not top-level. The plugin passes both shapes through unchanged.

The full doc covers 12 gotchas plus reusable patterns. Reading it before extending the plugin will save you the same hours we spent.

Contributing

Currently closed for external contributions while we validate internally at IDD. Once open-sourced, we'll accept issues and PRs via the GitHub repository.