The command line
The `leadbind` CLI, for people who live in a terminal.
Same data as the app, no browser. Useful if you already live in a terminal, and useful for scripting things the app does not do. It runs on the same scoped keys as everything else, so there is one auth surface to reason about and one place to revoke.
Install
One line. macOS or Linux, needs Node installed:
curl -fsSL https://leadbind.org/install.sh | sh
That drops a leadbind command in ~/.leadbind/bin and adds it to your PATH. Open a new terminal, or source ~/.zshrc, and leadbind is on your path.
Prefer to run the file directly, or scripting a machine where you do not want it on the PATH? The CLI is a single zero-dependency file. Download it and run it with Node:
curl -fsSL https://leadbind.org/leadbind.mjs -o leadbind.mjs
node leadbind.mjs --help
No dependencies is deliberate: a tool you use to check on your business should not break because something four levels down published a bad version.
Sign in
leadbind login
Paste a key from Setup, then AI access in the web app. See Connect an assistant for how to make one. On success it prints exactly which tools that key can use, so you find out about a missing scope now rather than mid-script:
Saved to /Users/you/.leadbind/config.json
This key can use: list_leads, list_calls, list_appointments, get_call_metrics, get_next_actions, get_availability
The key is stored at ~/.leadbind/config.json with permissions 0600, meaning only your user account can read it. Sign out with leadbind logout, which deletes it.
Warning:
logoutremoves the key from your machine. It does not revoke it. If you think a key leaked, revoke it in the web app, which kills it everywhere at once.
Commands
| Command | What it does | Scope |
|---|---|---|
leadbind today |
Bookings, callbacks due, and leads going cold | read |
leadbind leads |
Your leads, newest first (--stage=new --limit=20) |
read |
leadbind calls |
Recent calls with outcomes (--direction=inbound --limit=10) |
read |
leadbind bookings |
Upcoming appointments (--limit=10) |
read |
leadbind availability |
Your genuinely open slots (--tz=America/Chicago) |
read |
leadbind metrics |
Calls, connect rate, and bookings over a window (--days=30) |
read |
leadbind call |
Place a call from your number (--lead=<id> or --phone= --name=) |
dial |
leadbind bill |
Create a pay link to your connected Stripe (--amount=250 --for="Deposit") |
write |
leadbind connect |
Configure every AI client on this machine at once | n/a |
leadbind mcp |
Run the local stdio MCP server (used by connect) |
any |
leadbind install-claude |
Configure Claude Desktop only | n/a |
leadbind install-cursor |
Write .cursor/mcp.json in the current directory |
n/a |
leadbind login / logout |
Manage your key on this machine | n/a |
leadbind --help prints the same list. Most read commands take --limit; metrics takes --days; availability takes --tz.
The first command after login
leadbind today
It runs get_next_actions and prints only what is actually there. A section with nothing in it is left out, and a genuinely quiet morning says so rather than rendering three empty headings:
Coming up (1)
2026-08-31T14:00:00-05:00 Maria Lopez
Talked, never booked (2)
Dan Reyes contacted
Priya Shah contacted
Going cold (3)
...
Place a call from the terminal
Call a saved lead by id (uses the consent already on file), or an ad-hoc number:
leadbind call --lead=ld_abc123
# or
leadbind call --phone=8325550134 --name="Maria Lopez"
Calling +18325550134. It will show up in 'leadbind calls' when it finishes.
The AI agent holds the conversation and books. Needs a key with the dial scope. Every guard the app enforces runs server-side here too: rate limit, billing gate, plan entitlement, Do-Not-Call, and per-lead consent. A blocked call is refused with a reason rather than dialed.
Important: placing a call is consent-gated server-side. Everything in Consent and opt-outs and Disclosing the AI applies to every call, whether you place it from the CLI, the app, or your AI tool.
Text a deposit link
leadbind bill --amount=250 --for="Roof deposit" --lead=ld_abc123
Pay link for $250.00: https://leadbind.org/pay/pr_...
Send it to your customer. You will see it in Stripe when they pay.
The money routes to your own connected Stripe account. Needs a write key and your Stripe connected (leadbind.org → Settings → Payments); if it is not connected yet, the command tells you so instead of making a half-finished request.
Put LeadBind inside your AI tools
leadbind connect
One command finds every AI client on the machine and wires LeadBind into each. It reports per target what it did, including the ones it skipped and why, so it never claims a blanket success over a client it never touched:
added Claude Desktop
/Users/you/Library/Application Support/Claude/claude_desktop_config.json
restart Claude Desktop to pick it up
skipped Cursor (not found on this machine)
connect writes a stdio MCP server (leadbind mcp) for Claude Desktop and an HTTP config for Cursor. If you want to point a client at LeadBind by hand instead, see Connect an assistant for the raw config. install-claude and install-cursor still exist as single-target aliases.
Scripting it
Every read command prints plain text, so it pipes:
# Anything with no answer, into a file for the morning
leadbind calls --limit=100 | grep no_answer > callbacks.txt
For structured output, skip the wrapper and call the MCP endpoint directly with curl. The CLI is a thin wrapper over exactly those calls.
The same permissions apply as everywhere else. A read-only key runs the read commands and refuses call (needs dial) and bill (needs write). See Keys and permissions.
CLI or assistant?
Both hit the same API, so it is purely about how you want to work.
- The CLI is exact. You said
leadbind bookings, you got bookings. Good for scripts and for anything running unattended. - An assistant is better when the question is fuzzy, or when the answer needs something outside LeadBind. "Which leads went cold and are worth another call" is a question the CLI cannot answer and Claude can.
Anything the CLI can do, a connected assistant can do too. The reverse is not true.