Answers · Billing

How do I remove billing from an app that will be free?

Use the remove-billing skill. It removes the Stripe subscription flow and the mobile in-app purchase path, and leaves authentication, tenancy and the entitlement seam in place. The seam matters: include RequireEntitlement keeps working against an open strategy, so gated controllers are not rewritten and can be gated again later.

What it does

The skill lives in .claude/skills/remove-billing and removes the Stripe slice, the in-app purchase path, the pricing page and the associated specs. What it deliberately keeps is the seam:

def for(account) = Entitlement::Open.new(account)

app/models/entitlement.rb ships an Open strategy that gates nothing. Switching to it means every controller with include RequireEntitlement still compiles, still runs, and simply lets everyone through. Nothing is edited, and turning a feature paid again later is one line rather than an audit.

Stop if you have ever charged a real card

This is the warning the skill leads with, and it is the right one. Removing the webhook handler while live subscriptions exist means Stripe keeps billing customers and your app stops hearing about it. Cancel the subscriptions in Stripe first, let the refunds settle, and then remove the code.

The files agents skip

Removing a slice is mostly deletion, and deletion is the easy part. The residue is in shared files that only partly relate to billing: a route, a nav link, a line in the CSP for Stripe's host, a seeded subscription in db/seeds.rb. The skill has a section listing exactly these, because they are what gets left behind and they are invisible until something breaks.

Verify rather than assume

bin/check

Green means the specs that referenced the removed slice are gone and nothing left behind references it. Then boot the app and walk the flow a paying user would have taken. A dangling link to a removed pricing page is a 404 that no spec covers.

The alternative, if you are unsure

Do not remove anything. Point Entitlement.for at the open strategy and leave the code in place. The app is free, nothing is gated, and the day you want to charge you change one line back. The cost is some unused code; the benefit is that you have not made a decision you cannot cheaply reverse.

Related questions

How do I change what a paid plan unlocks in my app?

To gate a feature, add include RequireEntitlement to its controller. To ungate it, delete that line. To change what counts as paid at all, edit the single strategy line in app/models/entitlement.rb. Those are two different decisions and they live in two different places on purpose.

How do I gate a feature behind a paid subscription in Rails?

Add include RequireEntitlement to the controller. Unentitled accounts are redirected to the pricing page with a message; admins are exempt. What "entitled" means is defined separately in app/models/entitlement.rb, so you can change the gate from a subscription to a token balance or to nothing without touching any controller.

Can I charge a one-time price instead of a subscription?

Yes. Create a one-time price in Stripe, use payment mode rather than subscription mode in the checkout session, and change what Entitlement.for returns so a completed purchase entitles the account permanently. The gate on each controller does not change, because RequireEntitlement never knew what it was checking.