@rentaltide/cli exists to remove one loop: before it, seeing a code change inside a real RentalTide meant deploying your app somewhere public, pasting the URL into a web form, and reinstalling. Every change.
Edit a file, refresh the page. No redeploy, no reinstall.
No tunnel needed
Your app is an iframe on a RentalTide page, rendered by your browser — so http://localhost:5173 resolves perfectly well. rentaltide dev changes your app's embed URL to your local one, prints the sandbox links, and changes it back when you stop it.
Repointing the embed URL of an app that merchants have installed points all of them at your laptop. dev checks the status and stops. Work on a draft app, or a draft copy.
http://localhost is a potentially-trustworthy origin, so Chrome and Firefox embed it inside an https page. Safari does not, and shows an empty frame with the reason only in its console. On Safari, serve your app over https locally and run rentaltide dev --url https://localhost:5173.
If dev cannot restore your previous embed URL on exit — network dropped, laptop slept — it says so and names the URL to put back. An app left pointing at a laptop renders nothing for anyone, and the cause is invisible from the portal.
Commands
| Command | What it does |
|---|---|
init [dir] | Scaffold an app that already runs and proves the handshake |
login · logout · whoami | Your partner account |
link | Attach this directory to one of your apps |
pull | Write the app record into rentaltide.app.json |
push [--yes] | Apply rentaltide.app.json to the app record, showing a diff first |
dev [--url <url>] | Point your sandbox at your local app |
webhook trigger <event> | Send yourself a signed webhook |
open [booking|portal|docs] | Open a sandbox surface |
Credentials live in ~/.rentaltide/credentials.json, readable only by you. They are never written into the project — a token committed to a repo is a partner account handed to whoever clones it.
Embedded insurance
An underwriter builds no iframe and holds no OAuth token — RentalTide calls them. Different shape, same CLI.
The scaffold is built on @rentaltide/underwriter, so what you edit is underwriting and nothing else — the SDK verifies the signature, routes each call, checks what you return, and makes /bind idempotent. It ships with a decline path and a premium that loads when a prior claim is declared, because both are worth seeing before you write your own.
coverage test
Signs its requests exactly as the platform does — same headers, same {timestamp}.{body} payload, same deadlines — and checks the rules that fail quietly:
Every one of those is something that type-checks, returns 200, and breaks a renter: a premium sent as "44.50", a reduce_to with no value (which renders as a saving and then changes nothing at hold time), a decline returned as a 500 (which drops the coverage with no explanation), a bind that writes a second policy when we retry a timeout.
It exits non-zero when anything fails, so it belongs in your CI.
One call at a time
While you are writing the thing, you usually want one endpoint and one payload, not the whole suite:
Signed with your real secret, same as test. Prints the request, the status, the timing and the body; exits non-zero on anything but a 200. --data '{…}' replaces the body outright, --url points it elsewhere.
The rest
| Command | What it does |
|---|---|
coverage create | Register the offering; saves the signing secret for you |
coverage link · pull · push | The offering as code — base URL, countries, currencies, timeout |
coverage secret | Store the signing secret for this machine only |
coverage test [--url] | The checks above |
coverage dev --url https://… | Point the offering at an endpoint while you work, restore on exit |
coverage status | What still has to be true before review |
coverage submit | Send it for review |
Repointing the base URL of an approved offering sends real renters' quotes — and their identity at bind — to wherever you pointed it.
rentaltide.coverage.json holds the base URL, the countries you are licensed to write in, the currencies you price in, and the quote timeout. Those three decide whether a renter is ever offered your policy, so they belong somewhere reviewable. The signing secret never goes in it — it lives in ~/.rentaltide/credentials.json, or RENTALTIDE_SIGNING_SECRET.
Full contract: Embedded insurance.
rentaltide.app.json
Scopes and embed locations decide what your app may read and where it renders. Typed into a web form they are invisible to review and the only record of a change is that it happened. In your repo, they diff.
dev is local. It is never pushed.
push prints what will change and asks before applying it:
What init gives you
One page, the App Bridge SDK wired to the host, a live context readout and one scope-checked API call. Small on purpose: the thing you need on minute one is proof that the handshake works, not a framework.
Your sandbox
dev creates it if you do not have one: a real tenant with a seeded marina — boats, tours, a bundle — and Stripe test keys. Your app installs into it with no approval step, reads real records through the scoped API proxy, and takes bookings with test cards.
Nothing in it is visible to anyone else, and nothing in it moves money.
Environment
| Variable | Default |
|---|---|
RENTALTIDE_API_URL | https://v3.api.rentaltide.com |
RENTALTIDE_APP_URL | https://app.rentaltide.com |
NO_COLOR | honoured when set |
Requirements
Node 18 or newer. The CLI has no runtime dependencies.

