The Cord CLI: your integration, ready from the terminal

What the Cord CLI 2.1 does: browser sign-in, then it integrates your project, connects your apps, adds the MCP to your agents and tests webhooks on localhost.

Integrating a payments platform usually starts the same way: find the keys section in a dashboard, copy a long string into a .env, write the route that receives webhooks, verify their signature, open a tunnel to test it on your machine and do it all again when you switch computers. We wanted Cord to be a single command:

npx @flouviahq/cli

Last night we published version 2.1 of @flouviahq/cli. This article walks through what it does, screen by screen. The images are replicas of the real wizard: the same text, colors and steps you’ll see in your terminal.

When it opens, the wizard already knows where it is: the folder, the framework and the apps your project uses.

A full-screen wizard

Run with no command, the CLI opens a wizard that takes over the terminal. Before touching anything it reads your project: it recognizes Next.js (App Router and Pages Router), Astro, Express, Laravel, Django, Flask and FastAPI, and tells you what it’s going to integrate. From the menu you can change the framework, see the exact list of what it will do or open Privacy and data before continuing.

It needs a terminal of at least 80 by 28 characters; with --simple it opens the inline version. It speaks Spanish, English, Portuguese, French and German depending on your system, or the language you set with CORD_LANG. And everything the wizard does is still available as standalone commands for scripts and CI, each with --json.

Sign in from the browser, no keys to copy

To connect your account, the terminal opens your browser on the authorize page. There you choose the organization, see that the wizard only works in test mode and decide what your project key can do: five resources (products, customers, quotes, webhooks and Elements), each with no access, read or write. Suggested is the minimum used by the files it’s going to create: read your catalog and write quotes and the Elements configuration.

You click Authorize wizard, Cord confirms it’s you and the terminal connects on its own. No code to compare, no key to paste.

The terminal waits; in the browser you choose the organization and the permissions of the project key.

How it works under the hood

The return to the terminal follows the pattern for native apps with OAuth (RFC 8252) plus PKCE (RFC 7636). The terminal opens a random port on 127.0.0.1, generates a code_verifier that never leaves your machine and sends Cord only its S256 hash, along with a state. When you authorize, Cord sends the browser back to 127.0.0.1/callback with a single-use code, and the terminal redeems it with the verifier.

Without the verifier, the browser’s code is useless: intercepting it isn’t enough to walk away with the keys.

A few decisions that aren’t obvious:

  • Only hashes live in the database. For the device code and the browser code, Cord stores the sha256, never the value.
  • The return only accepts your own computer. The address has to be 127.0.0.1 or localhost with a port and the /callback path; any other is rejected when the sign-in is requested.
  • The keys are handed over once. They’re stored encrypted until the terminal claims them, and at that moment they’re deleted.
  • Two keys with different jobs. The CLI key is restricted and for testing, expires in 90 days and only uses simulators, events, setup proposals and the AI assistant; it doesn’t count toward your plan’s key limit. The project key carries the permissions you chose, counts as one of your plan’s keys and is saved to your .env.local.

Over SSH, in CI, with --no-browser or with --json there’s no browser to come back to: there the CLI uses the code to compare, the device flow we described in cord login without copying keys.

The wizard works in plain sight

While it integrates, the screen shows each task with its progress, the action underway and four tabs: Status, Log (every file it reads or writes and every command it runs), What’s new (the latest releases in Cord) and Visualizer.

Tasks are checked off as they finish; whatever doesn’t apply to your project is skipped, and the wizard says so.

In a Next.js project with App Router, the wizard:

  1. Installs @flouviahq/node and @flouviahq/elements with your package manager (npm, pnpm, yarn or bun, based on your lockfile).
  2. Creates app/api/webhooks/cord/route.ts, which verifies the signature of every webhook against the raw body.
  3. Creates app/api/cord/[...path]/route.ts, the proxy through which Cord Elements talks to Cord without exposing your key.
  4. Saves the project key to .env.local.
  5. If you gave it your website and what you do, asks Cord for a setup proposal (products, taxes and templates) that you approve in the browser.
  6. Writes CORD-INTEGRACION.md with what changed.

Three rules it never breaks: it doesn’t overwrite a file that already exists, it only writes keys to an environment file that git ignores and it doesn’t touch the other lines in your .env.

The AI that integrates, and its limits

2.1 brings an agent that reads your project and adapts the integration to it: it places the routes in your structure, mounts the quote builder on your page and then runs your build and your tests. It reasons on Cord’s side, but its tools run on your machine and are confined to the project folder:

  • It never opens a .env*, your .git folder or node_modules. A path that leaves the project, including through a symbolic link, fails.
  • It only runs commands from a list: installing @flouviahq/* packages with npm, pnpm, yarn or bun, your build, lint, typecheck and test scripts, and npx tsc --noEmit. Any other, or one with shell characters, is rejected and recorded in the log.

For now, Cord keeps it off: the server responds that the assistant isn’t available and the CLI continues with templates, without you having to do anything. We’ll turn it on when our Artificial Intelligence Disclosure covers the AI reading the code of whoever is integrating. The wizard will then ask whether to integrate with AI or with templates, and everything it changes will be recorded in CORD-INTEGRACION.md.

Before you start, Privacy and data says what leaves your computer and what never does.

Connect the apps you already use

The wizard looks through your dependencies (package.json, composer.json or the Python ones) for the SDKs of the apps Cord connects: @hubspot/api-client is HubSpot, @shopify/shopify-api or Hydrogen is Shopify, @slack/bolt or @slack/web-api is Slack. It also recognizes QuickBooks Online, Xero, Google Sheets and Microsoft Teams.

If it finds any, it offers to connect them to Cord. You press o, that integration’s page opens in your browser and, when you finish, the screen checks it off on its own. To know that, Cord only returns the status of each connection, never any of its data.

HubSpot was connected from the browser; Shopify and Slack wait their turn.

The Cord MCP in your agents

When it’s done, the wizard offers to add the Cord MCP server to Claude Code (.mcp.json), Cursor (.cursor/mcp.json) and VS Code (.vscode/mcp.json). It only writes the server’s address, without touching any others you already have: the first time, your agent asks you to authorize in Cord with OAuth, so no file holds a key.

You select the agents with the space bar and the wizard writes their file.

With the MCP, your agent looks up quotes, customers and payments and prepares drafts. Anything that sends, charges or changes a customer, you approve in Cord. The same is available as commands: cord mcp add, cord mcp remove and cord mcp tutorial, which explains how to add it as a custom connector in Claude and ChatGPT. The details are in the MCP guide.

Signed webhooks on your localhost

cord listen opens a test session and forwards every event to your server with the same signature production would use. With --env-file it saves the signing secret to your .env.local, and it’s the same in every session of your key: restarting doesn’t force you to change it.

npx @flouviahq/cli listen --forward-to http://localhost:3000/api/webhooks/cord --env-file .env.local

Every forward is acknowledged: if your server doesn’t respond, the event goes back into the queue and is retried after 5, 15, 30 and 60 seconds. In another terminal, cord trigger fires any event in the catalog; with --objeto and the id of a test quote or invoice, the event carries its real data.

Fire an event in one terminal and watch it reach your route, signed, in the other.

There are more commands for everyday work: cord events tail and cord logs tail show events and requests as they arrive, cord api calls any route with your key and cord simulate forces the outcome of the next tax issuance or expires a quote. The CLI guide has the full list.

A summary at the end

The wizard finishes with what it did, what’s left and the webhooks already listening on your local server. What changed is recorded in CORD-INTEGRACION.md, without any value from your .env.

The summary says what’s ready and what’s left, with the link to finish it.

Try it

You need Node 22 or later and a Cord account.

npx create-next-app@latest my-store --ts --app
cd my-store
npx @flouviahq/cli

When it’s done, leave npm run dev running in one terminal and run npx @flouviahq/cli trigger quote.approved in another: the event reaches your route, signed, and the wizard shows you the 200.

END OF ARTICLE

From proposal to payment. All in one link.

Send a quote your client approves and pays from one link, with no account to create, then invoice it in one click. In 12 countries, with a free plan and no credit card.