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.- One command per API tool, generated from the MoltSets OpenAPI spec.
moltsets enrichruns any lookup over a CSV, with batching, dedupe, resume, fair use waits, and plan-boundary notes built in.--alland--maxpage through searches within your plan’s concurrency limit.--outwrites straight to CSV.- JSON on stdout when piped, readable tables in a terminal, logs on stderr, and documented exit codes.
Install
The CLI needs Node.js 18 or later.@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, then create an API key under API keys. Keys start with
ms_. See Authentication 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
Authentication
The CLI looks for your API key in this order:--api-key ms_...on the command line.- The
MOLTSETS_API_KEYenvironment variable. - 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.
- macOS and Linux:
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:
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:
--allpages until the results run out.--max <n>stops afternrecords.- The API caps
totalat 10,000, so a total of 10,000 means at least that many. Whentotalis 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.
--out file.csvflattens 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-domainare always sent as a list. - Enum filters (
seniority,industry,department,functional_area,employee_range,revenue_range, and theirexclude_versions) are checked before any call. A bad value fails with exit code2and the list of allowed values. --body '<json>'or--body-file path.jsonsends 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:
Enriching a CSV
--map param=column:
How enrichment works
- Batching. Tools with a batch parameter (
linkedin_urlsoremails) 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). Forsearch_*tools, concurrency is capped at your plan’s search limit.--no-batchforces 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.jsonafter every batch. Re-run the same command to carry on, or pass--restartto 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-waitsaves and stops instead (exit code5). - Tokens and plan limits. On
insufficient_tokens,insufficient_phone_tokens, orplan_restricted, the CLI keeps any partial results, marks the restdropped, saves, and stops (exit code4). 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-runcounts 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 freesearch_linkedin_profilecount_onlysearch to estimate the match rate (--sample <n>).
Output columns
The output keeps every original column and adds:
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.
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.--jsonand--tableforce either. - Logs, progress, and warnings go to stderr, so stdout is always clean data.
-qhides 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 is0.- On a
429, the CLI waits formetadata.retry_afterorRetry-Afterand retries up to 4 times. Waits longer than 5 minutes fail straight away with exit code5.search_concurrency_exceededis retried after 1 second. - On a
500, a batch is retried once as two halves, and any other request is retried once, before failing.
Errors print the API error code and a one-line suggestion:
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; readingms_status, ms_note, and risk scores; and exit codes.
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 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 — create and manage API keys
- Rate limits — fair use windows and search concurrency
- I have X, I want Y — find the right tool for your input data
- MoltSets MCP — use MoltSets in chat and coding clients
