> ## Documentation Index
> Fetch the complete documentation index at: https://developer.moltsets.com/llms.txt
> Use this file to discover all available pages before exploring further.

# MoltSets CLI

> Search people and companies, enrich CSV files with verified emails and mobile phones, and check your plan's limits from a terminal, a script, or an AI agent.

## Overview

The MoltSets CLI is the command-line tool for MoltSets. Use it to search people and companies, enrich CSV files with verified emails, mobile phones, and profiles, and check your plan's limits.

```bash theme={null}
npx moltsets whoami
```

* One command per API tool, generated from the MoltSets OpenAPI spec.
* `moltsets enrich` runs any lookup over a CSV, with batching, dedupe, resume, fair use waits, and plan-boundary notes built in.
* `--all` and `--max` page through searches within your plan's concurrency limit. `--out` writes straight to CSV.
* JSON on stdout when piped, readable tables in a terminal, logs on stderr, and documented exit codes.

> [!TIP]
>
> Use the CLI for bulk jobs, CSV files, scripts, and paginated searches. Use the [MoltSets MCP](https://developer.moltsets.com/integrations/moltsets-mcp.md) for one-off lookups in chat.

## Install

The CLI needs Node.js 18 or later.

```bash theme={null}
# Run without installing
npx moltsets --help

# Or install globally
npm install -g moltsets
```

The code is published as [`@moltsets/cli`](https://www.npmjs.com/package/@moltsets/cli). The `moltsets` package is a shortcut to it, so `npx moltsets` works. Both install the same `moltsets` command, so install only one of them globally.

## Quick start

**1. Create an API key**

Create a free account at [app.moltsets.com](https://app.moltsets.com), then create an API key under [API keys](https://app.moltsets.com/dashboard/api_keys). Keys start with `ms_`. See [Authentication](https://developer.moltsets.com/getting-started/authentication.md) for details.

**2. Save the key**

Run `moltsets login`, or set `export MOLTSETS_API_KEY=ms_...`.

**3. Check your setup**

Run `moltsets whoami`.

**4. Try a lookup**

```bash theme={null}
moltsets linkedin_to_best_email --linkedin-url https://linkedin.com/in/retentionadam
moltsets search_people --title "Head of Sales" --country "United Kingdom" --limit 5
```

## Authentication

The CLI looks for your API key in this order:

1. `--api-key ms_...` on the command line.
2. The `MOLTSETS_API_KEY` environment variable.
3. The config file saved by `moltsets login`:
   * macOS and Linux: `$XDG_CONFIG_HOME/moltsets/config.json`, or `~/.config/moltsets/config.json`.
   * Windows: `%APPDATA%\moltsets\config.json`.

`moltsets login` opens the API keys page in your browser and asks you to paste a key. It checks the key with `get_account` (free) and saves it with file permissions `600`. It only runs in an interactive terminal. In scripts, CI, and agents, set `MOLTSETS_API_KEY` instead.

`moltsets logout` removes the saved key.

These account commands are free. They spend no tokens or fair use records:

```bash theme={null}
moltsets whoami                 # plan, token and phone token balance, fair use headroom
moltsets account                # full get_account output
moltsets billing                # renewal dates and the token cost of each tool
moltsets usage --period week    # usage by day: today, week, month or billing_cycle
```

## Searching

`search_people` and `search_companies` return up to 25 records per call (10 on the Free plan). Each record returned counts against your plan's search records, so probe first:

```bash theme={null}
# One record shows total and whether the filters match what you meant.
moltsets search_people --title "VP of Sales" --seniority VP --employee-range 51-200 --country "United States" --limit 1
```

Then page through the results:

```bash theme={null}
# Up to 200 records, written to CSV
moltsets search_people --title "VP of Sales" --seniority VP --employee-range 51-200 \
  --country "United States" --max 200 --out vp-sales.csv

# Every result
moltsets search_companies --industry "Information Technology" --employee-range 51-200 \
  --revenue-range '$10M - $20M' --all --out companies.csv
```

* `--all` pages until the results run out. `--max <n>` stops after `n` records.
* The API caps `total` at 10,000, so a total of 10,000 means at least that many. When `total` is capped, the CLI keeps paging until a page comes back short.
* Pages run in parallel, never more at once than your plan allows: 3 on Free and Solo, 5 on Pro, 8 on Team and Max. See [Rate limits](https://developer.moltsets.com/getting-started/rate-limits.md).
* `--out file.csv` flattens nested objects with dot notation (`company.name`, `company.domain`). Lists are joined with `; `.

### Flag values

* Filters that accept one or more values take a repeated flag or commas: `--country "United States" --country Canada`, or `--seniority VP,Director`. Use `\,` for a literal comma, for example `--company "Acme\, Inc."`.
* List-only filters such as `--exclude-company-domain` are always sent as a list.
* Enum filters (`seniority`, `industry`, `department`, `functional_area`, `employee_range`, `revenue_range`, and their `exclude_` versions) are checked before any call. A bad value fails with exit code `2` and the list of allowed values.
* `--body '<json>'` or `--body-file path.json` sends a raw request body, for anything the flags can't express. Flags are applied on top.

### Suppression lists

Pass the accounts you already have with `--exclude-company-domain` (people) or `--exclude-domain` (companies). Excluded records cost nothing, so this is always cheaper than filtering the results yourself:

```bash theme={null}
moltsets search_people --title CFO --country "United Kingdom" \
  --exclude-company-domain acme.com,globex.com,initech.com --max 100 --out cfos.csv
```

## Enriching a CSV

```bash theme={null}
moltsets enrich <input.csv> --tool <tool_name> --column <column> [--out <output.csv>]
```

Always start with a dry run, then a small sample:

```bash theme={null}
# 1. Count rows, check headroom. No paid calls.
moltsets enrich leads.csv --tool linkedin_to_best_email --column linkedin --dry-run

# 2. First 10 rows only
moltsets enrich leads.csv --tool linkedin_to_best_email --column linkedin --limit 10 --out sample.csv

# 3. The whole file
moltsets enrich leads.csv --tool linkedin_to_best_email --column linkedin --out enriched.csv
```

Tools that take several inputs use `--map param=column`:

```bash theme={null}
moltsets enrich people.csv --tool search_business_email_by_name --map name=full_name --map company=domain
moltsets enrich people.csv --tool search_business_profile_by_name \
  --map first_name=first --map last_name=last --map company_domain=website --set include_experience=true
```

Not sure which tool to use? See [I have X, I want Y](https://developer.moltsets.com/use-cases/i-have-x-i-want-y.md).

### How enrichment works

* **Batching.** Tools with a batch parameter (`linkedin_urls` or `emails`) are sent 100 rows at a time. Results are matched back to rows by the input they echo, never by position. Other tools run one row per call, 5 at a time by default (`--concurrency`). For `search_*` tools, concurrency is capped at your plan's search limit. `--no-batch` forces one row per call.
* **Dedupe and skips.** The same input is looked up once, and the result is copied to every row that has it. Matching is case-insensitive, and a LinkedIn URL and its slug count as the same. Rows with an empty input are marked `skipped`.
* **Resume.** Progress is saved to `<output>.moltsets-state.json` after every batch. Re-run the same command to carry on, or pass `--restart` to start again.
* **Fair use.** Every response reports the records left in the 5-hour and weekly windows. If the 5-hour window can't cover the next batch, the CLI says so on stderr and waits until it resets, rather than running into a `429`. `--no-wait` saves and stops instead (exit code `5`).
* **Tokens and plan limits.** On `insufficient_tokens`, `insufficient_phone_tokens`, or `plan_restricted`, the CLI keeps any partial results, marks the rest `dropped`, saves, and stops (exit code `4`). The raw response is also kept in `<output>.moltsets-raw.json`, so results you already paid for are never lost.
* **Progress** shows on stderr: rows done, found, not found, errors, and an estimate of the time left.
* **Dry run.** `--dry-run` counts rows after dedupe and skips. It compares the expected usage with your fair use headroom, token balance, and phone token balance. For name-based tools, it samples up to 20 rows with the free `search_linkedin_profile` `count_only` search to estimate the match rate (`--sample <n>`).

### Output columns

The output keeps every original column and adds:

| Column | Meaning |
| :- | :- |
| `ms_status` | `ok`, `not_found`, `restricted` (missing because of a plan boundary), `skipped`, `error`, `dropped` (tokens ran out), or `pending` (not reached yet) |
| `ms_note` | Plan boundaries: `personal_email_redacted`, `personal_email_restricted`, `identity_hashes_restricted`. Skipped rows: `empty_input`, `missing_input:<param>` |
| `ms_<field>` | One column per result field, with nested fields in dot notation. For example `ms_email`, `ms_risk_score`, `ms_last_validated_at`, `ms_company.name` |
| `ms_error` | Error code and message, when a row failed |

Plan-boundary notes mean the value exists but your plan withheld it. They aren't misses:

* `personal_email_redacted`: personal email withheld past the Team and Max personal email cap (15,000 per 5 hours, 75,000 per week). It resets on its own.
* `personal_email_restricted`: personal email isn't available on your account.
* `identity_hashes_restricted`: SHA256 hashes aren't returned on the Team and Max plans.

Every email carries an A to F [risk score](https://developer.moltsets.com/moltsets-data/email-risk-scores.md). Where an email has no grade, the CLI fills in `F` in JSON, tables, and CSV.

## Output and exit codes

* When stdout isn't a terminal, commands print JSON: the full API envelope `{ "results": ..., "status": "ok" | "not_found", "metadata": ... }`. In a terminal, they print a readable table or summary. `--json` and `--table` force either.
* Logs, progress, and warnings go to stderr, so stdout is always clean data. `-q` hides progress and information messages.
* The CLI never prompts unless both stdin and stdout are terminals.
* `status: "not_found"` is a normal miss. Nothing is charged and the exit code is `0`.
* On a `429`, the CLI waits for `metadata.retry_after` or `Retry-After` and retries up to 4 times. Waits longer than 5 minutes fail straight away with exit code `5`. `search_concurrency_exceeded` is retried after 1 second.
* On a `500`, a batch is retried once as two halves, and any other request is retried once, before failing.

| Code | Meaning |
| :- | :- |
| `0` | Success, including `not_found` |
| `1` | Any other error (server error, network, unmatched batch response) |
| `2` | Invalid input: bad flag, value, or file, or `invalid_input` from the API |
| `3` | Authentication: no key, `unauthorized`, `forbidden`, or `account_inactive` |
| `4` | `plan_restricted`, `insufficient_tokens`, or `insufficient_phone_tokens` |
| `5` | Rate limited after retries ran out, or a fair use window is used up |

Errors print the API error code and a one-line suggestion:

```text theme={null}
Error: You have 0 tokens remaining. (insufficient_tokens, HTTP 402)
Next: Top up or upgrade at https://app.moltsets.com/dashboard/billing, then re-run to continue.
```

## Using the CLI with AI agents

The CLI is built to be driven by agents: JSON on stdout when piped, nothing interactive, stable exit codes, and resumable bulk jobs.

Install the agent skill to teach Claude when and how to use the CLI safely. It covers dry run first, sample, then the full run; suppression lists; reading `ms_status`, `ms_note`, and risk scores; and exit codes.

```bash theme={null}
moltsets skill install                 # to ~/.claude/skills/moltsets-cli/
moltsets skill install --dir ./skills  # or anywhere else
```

## Command reference

Every tool in the API is a subcommand with the same name. Each request body property is a flag, with snake\_case turned into kebab-case. For example, `linkedin_url` becomes `--linkedin-url`. Run `moltsets <tool> --help` to see the flags, allowed values, and an example. See the [API Reference](https://developer.moltsets.com/getting-started/overview.md) for every tool and its parameters.

All tools also take `--body` and `--body-file`, plus the global options `--api-key`, `--json`, `--table`, and `-q`.

Other commands: `whoami`, `account`, `billing`, `usage`, `login`, `logout`, `enrich`, and `skill install`.

***

## Related

* [Authentication](https://developer.moltsets.com/getting-started/authentication.md) — create and manage API keys
* [Rate limits](https://developer.moltsets.com/getting-started/rate-limits.md) — fair use windows and search concurrency
* [I have X, I want Y](https://developer.moltsets.com/use-cases/i-have-x-i-want-y.md) — find the right tool for your input data
* [MoltSets MCP](https://developer.moltsets.com/integrations/moltsets-mcp.md) — use MoltSets in chat and coding clients


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.