# EximAgent CLI documentation — full text Last updated: 2026-08-02 --- # EximAgent CLI > Trade intelligence from the command line: find importers, classify products, check tariffs, screen sanctions, and draft outreach — every result labelled with its confidence. EximAgent is a trade-intelligence CLI. From one command line you can find real importers and distributors in customs records, classify a product into an HS code, check duties, screen a name against sanctions, enrich a company from its website, and draft outreach — with every field labelled by how much you should trust it. It is built to be driven either by you, directly in a terminal, or by a coding agent running on your machine. ## Start here - [Install](https://eximagent.ai/docs/get-started/install) — One command on macOS, Linux, or Windows. No runtime to set up. - [Authenticate](https://eximagent.ai/docs/get-started/authenticate) — Sign in with the device flow — no API keys to copy around. - [Your first result](https://eximagent.ai/docs/get-started/first-result) — From a fresh terminal to a classified product in about two minutes. - [How it works](https://eximagent.ai/docs/get-started/how-it-works) — The golden path, and who orchestrates it. ## What it does | Family | What you reach for | Commands | | ------------------------- | ------------------------------------------------ | --------------------------------------------------------- | | Buyer discovery | Finding companies that are not yet in the corpus | `search run`, `search refine`, `prospects find` | | Classification and duties | Turning a product into a code, then a cost | `hscode search`, `tariff`, `trade lookup`, `landed cost` | | Shipment records | Who actually shipped what, where, and when | `shipments search`, `company shipments`, `evidence show` | | Signals and analytics | Market questions answered over the full corpus | `shipments market-signals`, `analytics query`, `market …` | | Company intelligence | Who they buy from, sell to, and trade like | `companies profile`, `companies suppliers` | | Enrichment | Understanding a company and reaching its people | `enrich company`, `enrich contacts`, `profile-match …` | | Outreach | Drafting, reviewing, sending, and following up | `email draft`, `email send`, `sequence …`, `reply …` | | Monitoring | Being told when something moves | `watch …`, `monitor …`, `reminder …` | | Saved state | Profiles, collections, corridors, knowledge | `profile`, `collection`, `corridor`, `kb` | The full surface is in the [command reference](https://eximagent.ai/docs/reference/commands). ## The three rules worth knowing first 1. **Preview anything billable.** `--dry-run` wraps any expensive or irreversible command and shows the plan before it runs. See [previews and confirmation](https://eximagent.ai/docs/concepts/previews-and-confirmation). 2. **Read the confidence label.** No field is just a value — each carries a source and a confidence tier, and you should never speak above it. See the [confidence model](https://eximagent.ai/docs/concepts/confidence). 3. **Batch, never loop.** A list of companies, URLs, or queries goes in one call via `--inputs`. See [bulk input and streaming](https://eximagent.ai/docs/reference/bulk-and-streaming). > **Prefer not to install anything?** > > The hosted MCP server exposes the same verbs as tools and needs no sandbox > change. See [MCP server](https://eximagent.ai/docs/integrations/mcp). --- # Install > Install the EximAgent CLI on macOS, Linux, or Windows with one command. No runtime to set up. The installer drops a single binary on your `PATH`. There is no runtime to install first — no Node, no Python, no Docker. ## macOS and Linux ```bash curl -fsSL https://cli.eximagent.ai/install | sh ``` ## Windows Run this in PowerShell: ```powershell irm https://cli.eximagent.ai/install.ps1 | iex ``` ## Verify ```bash eximagent --version ``` If the shell reports that the command is not found, open a new terminal so it picks up the updated `PATH`, then try again. ## What else the installer does Alongside the binary, the installer writes the EximAgent skill into the skill directories of any coding agents it finds on the machine. That is what lets an agent discover the CLI and drive it for you without further setup — see [AI agents and editors](https://eximagent.ai/docs/integrations/agents). ## Network requirements Every command makes an HTTPS call to the EximAgent server, so the CLI needs outbound network access on port 443. Behind a proxy, set `HTTPS_PROXY` before running commands: ```bash export HTTPS_PROXY="http://proxy.internal:8080" ``` > **A blocked socket is an environment problem** > > A connection or socket error means the environment is blocking egress, not > that the server is down. Grant egress to the sandbox rather than turning the > sandbox off — [exit codes and errors](https://eximagent.ai/docs/reference/errors) lists the fixes > in order. ## Next Continue to [authenticate](https://eximagent.ai/docs/get-started/authenticate). --- # Authenticate > Sign in with the OAuth device flow or a personal access token, verify with whoami, and switch between accounts with profiles. Authentication is a one-time browser sign-in. There are no API keys to copy between machines. ## Sign in ```bash eximagent login ``` This opens your browser with a device code to approve. Once approved, the CLI stores the credential locally and every later command picks it up. ## Sign in without a browser On a headless box, or inside an agent sandbox, use a personal access token: ```bash eximagent login --token ``` ## Confirm who you are ```bash eximagent whoami ``` A successful response confirms the credential is live. Run this first whenever a command fails unexpectedly — an expired session looks like a broken command. ## Ground yourself in the operator profile Your profile holds the defaults that shape later results: product, target markets, signature, incoterm, and timezone. ```bash eximagent profile get ``` If it comes back `{exists: false, profile: null}`, nothing is grounded yet and commands will need those details spelled out each time. Filling the profile in once is the highest-leverage minute you can spend. ## Multiple accounts Saved accounts are switched per command with `--profile`, or for a whole shell session with an environment variable: ```bash eximagent --profile client-a whoami EXIMAGENT_PROFILE=client-a eximagent whoami ``` ## Next Continue to [your first result](https://eximagent.ai/docs/get-started/first-result). --- # Your first result > Go from a fresh terminal to a classified product and a previewed buyer search in about two minutes. This is the whole chain, end to end, in a fresh terminal. It assumes you have [installed](https://eximagent.ai/docs/get-started/install) and [signed in](https://eximagent.ai/docs/get-started/authenticate). ## 1. Confirm auth and grounding ```bash eximagent whoami eximagent profile get ``` ## 2. Settle the HS code Nearly every downstream command is sharper with a code than with a product name. If you do not already know yours, disambiguate it: ```bash eximagent hscode search --query "roasted arabica coffee beans" ``` Pick the code that matches what you actually ship. Classification is a judgement call, and the CLI returns candidates rather than pretending there is one answer. ## 3. Check a duty ```bash eximagent tariff --exporter VN --importer DE --product 090111 ``` This is a free structured lookup — nothing is billed and nothing is sent. ## 4. Preview a buyer search Buyer discovery spends credits, so preview it first: ```bash eximagent --dry-run search run --product "roasted coffee" --location DE --hsCode 090111 ``` The preview shows the plan and the expected cost. Nothing has run yet. ## 5. Run it ```bash eximagent search run --product "roasted coffee" --location DE --hsCode 090111 --confirmed ``` The kickoff response carries a `runId`. Searches are asynchronous, so attach to the stream and wait for the terminal event before reading any rows: ```bash eximagent stream --run-id ``` > **Do not read rows early** > > Results are incomplete until the stream emits its terminal `complete` event. > Reading the collection before then gives you a partial list that looks final. ## 6. Look at what came back ```bash eximagent collection list eximagent collection get --name ``` From here the path forks: shortlist the standouts and [enrich them](https://eximagent.ai/docs/guides/enrich-companies), or step back and read the [market signals](https://eximagent.ai/docs/guides/trade-signals) before spending anything more. ## Where to go next - [How EximAgent works](https://eximagent.ai/docs/get-started/how-it-works) — why the order above is the order - [Find buyers](https://eximagent.ai/docs/guides/find-buyers) — the same flow, in depth - [Command reference](https://eximagent.ai/docs/reference/commands) — the full surface --- # How EximAgent works > EximAgent is a dispatcher, not a workflow engine. Understand the golden path, who orchestrates it, and where the corpus ends and the live web begins. EximAgent is a dispatcher, not an autonomous workflow engine. Each command does one thing well. Choosing the order, batching the work, previewing the expensive steps, and deciding when the list is good enough — that is the operator's job, whether the operator is you or an agent acting for you. ## The golden path Unless you have a reason to do otherwise, work in this order: 1. Ground in auth and profile 2. Clarify product, market, and HS code 3. Preview the buyer search, confirm, then stream it 4. Inspect the results and shortlist 5. Enrich company data on the shortlist only 6. Enrich contacts only for validated targets 7. Draft outreach, preview it, then send Skipping step 4 is the most common way to waste both budget and time. Enrichment and contact discovery are the expensive steps, and running them across an unfiltered result set spends most of the budget on companies you were never going to contact. ## Two doors, one service The CLI and the hosted MCP server reach the same server, the same corpus, and the same response envelope. They are one service with two doors: - The **CLI** runs inside your shell or your agent's sandbox and needs outbound network access. - The **MCP server** connects from the agent host and needs no sandbox change, which makes it the answer when egress is blocked or nothing may be installed. See [MCP server](https://eximagent.ai/docs/integrations/mcp). ## What it is good at Buyer discovery from a vague prompt, HS-code and tariff research, collections of trade prospects, website enrichment, raw-markdown crawl, bulk lists in a single call, and outreach drafting once the list is clean. ## What it is not good at Send-ready contact data without review — every contact carries a confidence tag and you should never speak above it. Exact profile URLs from bare company names at scale. And anything outside the trade domain, which it cannot answer at all. > **Corpus first, web second** > > Questions about who already imports something are answered from the indexed > corpus, which is fast and exact. Finding companies that are *not* in the > corpus means live discovery, which costs credits. Knowing which of the two you > are asking for is most of the skill. ## Ask back before guessing When a required argument is missing or ambiguous, the right move is one concrete question rather than an invented value. Product names, target countries, HS codes, and recipient titles are never safe to guess — a plausible wrong code produces a confident, wrong answer all the way down the chain. --- # Command shape > Every command is `eximagent [] --flags`. Argument casing, aliases, and the shell-safe way to pass list values. Every command follows one shape: ```text eximagent [] [--flag value ...] ``` The `exim` prefix is optional, so both of these work: ```bash eximagent profile get eximagent exim profile get ``` ## Argument casing Arguments are camelCase across the whole surface — `exporterCountry`, `hsCode`, `businessType`. Kebab-case is accepted as an alias, so `--hs-code` and `--hsCode` are the same flag. ## Output format Responses default to JSON, or NDJSON for streamed commands. Switch with `--output`: ```bash eximagent tariff --exporter VN --importer DE --product 090111 --output table ``` `yaml`, `table`, and `json` are all accepted. Use `table` when you are reading with your eyes and `json` when something downstream is parsing. ## Passing list values safely Comma-list flags such as `--titles` and `--departments` break an _unquoted_ command when a value contains a shell-sensitive character. `&` is a shell control operator, so this runs `D,formulation` as a separate command: ```bash # Wrong — the shell splits this at the ampersand eximagent employees filter --titles procurement,R&D,formulation ``` Two safe forms. Repeat the flag — repeated flags are merged into one list: ```bash eximagent employees filter --titles procurement --titles "R&D" --titles formulation ``` Or quote the whole value: ```bash eximagent employees filter --titles "procurement,R&D,formulation" ``` > **Quote anything with punctuation** > > Never emit an unquoted value containing `&`, spaces, `|`, `;`, `$`, or `*`. > This bites hardest when an agent composes the command, because the failure > looks like a CLI bug rather than a quoting bug. ## Following nextActions Many responses carry a `nextActions` block containing ready-to-run commands with valid flags for the logical next step. Following those is faster and less error-prone than composing the next call by hand, and it is how paging works for [bulk results](https://eximagent.ai/docs/reference/bulk-and-streaming). --- # Output protocol > stdout carries the result envelope, stderr carries progress only. How to read nextActions and keep a long-running call alive. Every command writes to two streams with a strict division of labour. | Stream | Carries | | -------- | --------------------------------------------------------- | | `stdout` | The result envelope, or the error envelope. Nothing else. | | `stderr` | Progress breadcrumbs only — heartbeats and stage events. | Parse `stdout`. Never parse `stderr`, and never treat something on `stderr` as a failure. ## Exit codes and the envelope disagree on purpose A non-zero exit means the call failed, and the reason is in the `stdout` envelope — not in the exit code. Read the envelope for the cause; use the exit code only to decide whether to continue. ## Heartbeats are not errors Long operations print a heartbeat to `stderr` roughly every 30 seconds: ```text [eximagent] still working (60s) ``` > **Do not kill a slow command** > > A heartbeat means the call is alive and the server is working. Killing it > loses the result of work that has already been paid for. Raise the timeout > instead — see [limits and timeouts](https://eximagent.ai/docs/reference/limits). ## `nextActions` Every successful response carries a `nextActions[]` array of ready-to-run commands with valid flags for the logical next step. It is also how paging works on `analytics query` and `analytics sql` — each full page returns the next-page command with its cursor already bound. Use them rather than composing the next call by hand. A reasonable policy when an agent is driving: - Exactly one action, it is free or low cost, and it is inside what the user asked for → run it. - Otherwise → surface the actions as a pick list and let the user choose. ## Reporting what happened A multi-step run should never be silent. The expected narration is a plan up front, an entry and exit line per step, the reason for any branch taken, and a plain-English summary at the end. See [operating doctrine](https://eximagent.ai/docs/concepts/operating-doctrine). --- # Confidence model > Every field returns as {value, source, confidence}. What verified, extracted, heuristic, and inferred mean — and how to speak to each level. No field comes back as a bare value. Every company and contact field returns as a small envelope: ```json { "value": "procurement@example.com", "source": "provider", "confidence": "verified" } ``` The `confidence` tier tells you how far you are allowed to go when you repeat the claim to someone else. ## The four tiers | Tier | What it means | How to speak about it | | ----------- | --------------------------------- | -------------------------- | | `verified` | Provider-confirmed | Treat as fact | | `extracted` | Pulled from a website crawl | Candidate data, not a fact | | `heuristic` | Derived from secondary signals | A suggestion | | `inferred` | A model's best guess from context | A hypothesis | ## Why this matters more than it looks The tiers exist because the alternative is a list that looks uniformly authoritative while being built from four different kinds of evidence. An `inferred` job title presented as a fact is how outreach ends up addressed to someone who does not hold that role. > **Never speak above the label** > > If a contact's email is `heuristic`, say it is a likely address, not a > confirmed one. This applies with particular force when an agent is summarising > results for a person who will not see the raw envelope. ## Reviewing before sending Contact data is the place where the tiers bind hardest. The CLI is deliberately weak at producing send-ready contacts without review — that is a design position, not a gap. Before an outreach run, filter the list down to the tiers you are willing to stand behind, and treat the rest as leads to confirm elsewhere. ## Related - [Coverage and data sources](https://eximagent.ai/docs/concepts/coverage) — the parallel envelope on shipment queries - [Enrich companies and contacts](https://eximagent.ai/docs/guides/enrich-companies) — where the tiers show up in practice --- # Coverage and data sources > Where the data comes from and how to read the coverage envelope on every shipment query before drawing a conclusion. Shipment queries return a `coverage` envelope alongside the rows. Read it before drawing a conclusion — it is the difference between "there is no trade here" and "we cannot see this lane". ## The envelope ```json { "coveredCountries": ["US", "CO"], "periodStart": "2024-01", "periodEnd": "2026-06", "status": "covered", "confidenceLevel": "high", "completenessRatio": 0.91, "usageGuidance": "…", "blindSpot": "…" } ``` ## Reading `status` | Status | What you may conclude | | ------------- | ------------------------------------------------------- | | `covered` | Strong evidence — the query saw the lane properly | | `partial` | Directional only — trends are usable, absolutes are not | | `limited` | Directional only, and weakly so | | `unavailable` | Nothing usable for that query or period | > **Absence of data is not absence of trade** > > On `unavailable`, the honest statement is that there is no visible data for > that query — never that the trade does not happen. Corpus depth varies by > lane, and a quiet lane and an unobserved lane look identical in the rows. ## Where the data comes from - Importer and exporter discovery data - WTO and national tariff schedules - The OFAC SDN sanctions list - Per-shipment customs and bill-of-lading records - Live company-website crawls - People-search sources for contacts Every row carries the source it came from, so a result can always be traced back rather than taken on trust. ## Surfacing it honestly When you report a finding, report its coverage with it. "Top five buyers in this lane, from a partially covered feed" is a usable sentence. "Top five buyers in this lane" alone, built on `partial` coverage, is one that will be wrong at the worst possible moment. Methodology and the published benchmark for the corpus are documented on the [main site](https://eximagent.ai/methodology). --- # Previews and confirmation > Billable and irreversible commands preview first. How --dry-run, previewToken binding, and --confirm keep you out of bad runs. Anything that spends credits or leaves your machine previews first. The pattern is the same everywhere, so you can apply it to a command you have never run. ## `--dry-run` `--dry-run` is a safe wrapper for any billable or irreversible command. It sets `confirmed=false` and `dryRun=true` on the server, and returns the plan and the expected cost instead of doing the work: ```bash eximagent --dry-run search run --product "roasted coffee" --location DE --hsCode 090111 ``` Nothing is billed and nothing is sent. ## Confirming a search Buyer discovery takes `--confirmed` to actually start: ```bash eximagent search run --product "roasted coffee" --location DE --hsCode 090111 --confirmed ``` ## Confirming a send Outreach is the one place where the consequence is external and permanent, so it takes a distinct flag and a countdown before messages leave: ```bash eximagent email draft --dry-run --collectionId eximagent email send --confirm ``` > **Preview, then confirm — in that order** > > Draft with `--dry-run` and read the messages before `email send --confirm`. > The countdown exists so an accidental confirm is still recoverable; a skipped > preview is not. ## What is free Lookups over the indexed corpus cost nothing: `tariff`, `hscode search`, `trade lookup`, `analytics query`, the `shipments` verbs, and every `list` or `get` on your own saved state. These are exact, fast, and safe to run speculatively. The billable steps are the ones that reach outside the corpus — buyer discovery, website enrichment, and contact discovery. ## Habit worth forming Preview the expensive step, look at the plan, and only then confirm. It is not ceremony: the preview is where a wrong HS code or a mistyped country shows up while it still costs nothing to fix. --- # Scale and batching > One call per list, never one call per row. Batching tiers, the 1000-row cap, worker concurrency, and how to size a run before starting it. One call per list, never one call per row. Looping a single-entity command over a list is the single most expensive mistake available in this CLI — it burns time, rate budget, and context for no gain. ```bash eximagent enrich company --inputs companies.ndjson ``` One call in, one streamed batch result out, one context fill. ## Sizing a run | Rows | Approach | | ------ | -------------------------------------------- | | 1–10 | Single call, or bulk — either is fine | | 10–50 | Bulk only | | 50–200 | Bulk, and shortlist before touching contacts | | 200+ | Bulk, with aggressive shortlisting first | The shortlist step is what keeps a large run affordable. Contact discovery across an unfiltered 200-row list spends most of the budget on companies you were never going to contact. ## Hard caps - **1000 rows per `--inputs` call.** Above that the call fails with `INVALID_ARG`; split into sequential bulk calls. - **25 server-side workers.** Passing a higher `--concurrency` is silently clamped, and the `started` event reports `concurrencyClamped: true`. - Default concurrency is 10 and reduces automatically under upstream rate pressure. ## Long runs Bulk enrichment over 200+ rows, and any confirmed `search run`, can take several minutes. The client timeout defaults to 180s — raise it with `EXIMAGENT_TIMEOUT_MS` or re-run with `--stream` to watch progress live. > **A timeout is not a failure** > > `CLIENT_TIMEOUT` is the CLI's own clock firing, not the server giving up. The > job may still be running. Re-attach with `--stream` rather than starting a > second run. ## Related - [Bulk input and streaming](https://eximagent.ai/docs/reference/bulk-and-streaming) - [Limits and timeouts](https://eximagent.ai/docs/reference/limits) --- # Operating doctrine > The rules an agent driving EximAgent is expected to follow: clarify before guessing, narrate every step, shortlist before enriching, and the anti-patterns that waste budget. EximAgent is a dispatcher. It executes one verb well and returns; it does not decide what should happen next. These are the rules the operator — you, or an agent acting for you — is expected to follow. ## Clarify before guessing If a required argument is missing or ambiguous, ask one concrete question and wait. Product names, target countries, HS codes, and recipient titles are never safe to invent: a plausible wrong code produces a confident wrong answer all the way down the chain. Ground first: ```bash eximagent whoami eximagent profile get ``` If the profile is empty, fill it rather than working around it: ```bash eximagent profile extract --from text ``` ## Narrate every step A multi-step run has five mandatory moments: 1. **Plan** — what will run, in what order, and what it will cost 2. **Entry** — before each step 3. **Exit** — the result of each step 4. **Rationale** — why a branch was taken 5. **Summary** — a plain-English close Silent multi-step runs are a defect, not efficiency. ## Read state instead of re-deriving it `collection get` and `run summary` already carry `enrichmentStatus: {company, contacts, drafts}` with values `not-started`, `partial`, or `complete`. Read it. Never recompute it, and never ask the user something the state already answers. ## Anti-patterns > **Each of these has a real cost** > > These are not style preferences — every one wastes money, context, or trust. - Looping a command instead of using `--inputs` - Enriching contacts before shortlisting - Treating `extracted` or `heuristic` values as `verified` - Sending email without an explicit confirmation - Blind-retrying `INVALID_ARG` - Inventing commands or flags that do not exist - Using `snake_case` arguments — the surface is camelCase - Calling any `_admin/*` command ## Auto-pick and `--strict` On ambiguous input, bulk runs auto-pick the top candidate by confidence and record `autoResolved: true` alongside an `alternatives[]` array so the choice can be audited. Single runs also auto-pick by default; pass `--strict` to get the blocking disambiguation flow instead. ## Related - [Output protocol](https://eximagent.ai/docs/concepts/output-protocol) - [Confidence model](https://eximagent.ai/docs/concepts/confidence) - [Scale and batching](https://eximagent.ai/docs/concepts/batching) --- # Find buyers > Ground in your profile, settle the HS code, preview the search, then stream results into a collection you can shortlist. Buyer discovery finds companies that are **not** already in the corpus. That is what makes it the one genuinely expensive step in the toolkit, and why it is worth doing in the right order. > **Asking a different question?** > > "Who are the biggest importers of this product?" is a corpus ranking, not a > discovery run — use `analytics query` or the [signal > verbs](https://eximagent.ai/docs/guides/trade-signals) instead. They are free and exact. ## 1. Ground in the profile ```bash eximagent profile get ``` The profile supplies product, target markets, and defaults. If it is empty, the search has nothing to anchor on and you should fill in the details explicitly. ## 2. Settle the HS code ```bash eximagent hscode search --query "roasted arabica coffee beans" ``` Choose the code deliberately. A search run against the wrong code returns a clean, plausible list of the wrong companies. ## 3. Preview ```bash eximagent --dry-run search run \ --product "roasted coffee" \ --location DE \ --hsCode 090111 \ --direction buyers ``` Read the plan and the cost. This is the last free checkpoint. ## 4. Run and stream ```bash eximagent search run --product "roasted coffee" --location DE --hsCode 090111 --confirmed ``` Capture the `runId` from the kickoff response, then block on the stream until the terminal `complete` event: ```bash eximagent stream --run-id ``` ## 5. Shortlist before spending more ```bash eximagent collection get --name ``` This is the step people skip, and skipping it is what makes a run expensive. Enrichment and contact discovery should only ever touch companies you have already decided are worth contacting. When the list is large or the criteria are fuzzy, rank it with reasoning instead of eyeballing it: ```bash eximagent collection analyze --collectionId \ --question "which of these actually import at scale and would buy from a mid-size Vietnamese roaster?" ``` The response ranks the collection with auditable evidence per rank, so you can check the reasoning rather than trusting the order. ## 6. Refine rather than re-run If the shape of the results is wrong, refine the existing run before paying for a new one: ```bash eximagent search refine --run-id --product "specialty green coffee" ``` ## Next - [Enrich companies and contacts](https://eximagent.ai/docs/guides/enrich-companies) - [Market and shipment signals](https://eximagent.ai/docs/guides/trade-signals) --- # HS codes and tariffs > Disambiguate a product into an HS code, then look up duties, taxes, remedies, non-tariff measures, and the all-in landed cost. Classification comes first, because almost everything else — duties, shipment records, market signals — is keyed on the code. ## Find the code ```bash eximagent hscode search --query "cold-rolled stainless steel coils" ``` You get candidates, not a single verdict. Classification is a judgement with legal consequences, and the honest output is a shortlist with the reasoning attached. ## Look up the duty With a code in hand: ```bash eximagent tariff --exporter VN --importer DE --product 720915 ``` `tariff` is the first stop for duty rates. It reads structured tariff schedules and is free to run. ## Go deeper than the headline rate The headline duty is rarely the whole cost. For custom duties, taxes, trade remedies, and non-tariff measures: ```bash eximagent trade lookup --type duties --exporter VN --importer DE --product 720915 eximagent trade lookup --type all --exporter VN --importer DE --product 720915 ``` `--type` accepts `duties`, `taxes`, `remedies`, `ntm`, or `all`. ## Preferential rates and landed cost ```bash eximagent duty fta --exporter VN --importer DE --product 720915 eximagent landed cost --exporter VN --importer DE --product 720915 eximagent duty exposure --collectionId ``` `duty fta` checks whether a trade agreement gives you a better rate than the most-favoured-nation one. `landed cost` builds the delivered figure. `duty exposure` runs the question across a whole collection at once. > **These are research outputs** > > Tariff and classification results are research, not a customs ruling. They are > strong enough to price a deal and shortlist a market; binding classification > stays with your broker or the customs authority. ## Browsing the code tree For reading rather than querying, the HS chapters, headings, and subheadings are published as a browsable reference on the EximAgent HS Codes site — linked from the header and footer of every page here. ## Next - [Market and shipment signals](https://eximagent.ai/docs/guides/trade-signals) — what is actually moving under that code - [Find buyers](https://eximagent.ai/docs/guides/find-buyers) — turning the code into a prospect list --- # Market and shipment signals > Answer market questions with server-side signal verbs instead of paging raw shipment rows: attractiveness, recurrence, price direction, and lanes. For any question about a market — size, price, concentration, recurrence, direction — call a signal verb. Do not page raw shipment rows and aggregate them yourself. > **Why not just page the rows?** > > `shipments search` caps at a 1000-row page. It is a browsing tool. Any metric > computed from that page is a metric computed from an arbitrary slice, and it > will be wrong in a way that looks right. The signal verbs aggregate server-side over the **full** matching corpus and return a small, business-ready result. ## The four verbs ```bash eximagent shipments market-signals --hs6 090111 --dest DE eximagent shipments buyer-recurrence --hs6 090111 --dest DE eximagent shipments price-trend --hs6 090111 --dest DE eximagent shipments route-signals --hs6 090111 --dest DE ``` | Verb | The question it answers | | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `market-signals` | Is this market attractive? Shipment count, unique buyers and sellers, average and median price per kg, top-five buyer share, month-over-month volume and price direction | | `buyer-recurrence` | Which buyers are durable accounts? Active months, recurring/new/returning counts, retention, repeat-shipment ratio, per-buyer scale | | `price-trend` | Where are prices heading? Monthly average, median, p25, p75, standard deviation, and month-over-month change | | `route-signals` | Which origin→destination lanes lead, ranked by traded value | All four scope with `--hs6` or `--dest`, plus optional `--origin`, `--source`, `--from`, and `--to` (months as `YYYY-MM`). ## The chain worth following 1. `market-signals` — is it worth entering? 2. `buyer-recurrence` — who are the durable accounts? This ranks the outreach shortlist. 3. `price-trend` — what negotiating posture does the price direction imply? 4. `route-signals` — which lane? 5. Verify one account before acting on the picture. Lead with the commercial read — concentrated or broadening, rising or falling, who recurs — not with the data source. ## Verifying a single account ```bash eximagent company shipments --name "Example Handels GmbH" eximagent shipments get --id --view detail eximagent evidence show --id --normalized ``` `shipments get --view` projects richer fields (`detail`, `logistics`, `financials`, `parties`, `evidence`); the 24-field `summary` view stays the default. `evidence show --normalized` returns English-normalized semantic fields next to the raw source record. ## Full-corpus analytics When the question does not fit a signal verb, push the computation down rather than pulling rows up: ```bash eximagent analytics catalog eximagent analytics query --groupBy importer --measures shipments --filters '{"hs6":"090111"}' eximagent analytics sql --query "SELECT ..." ``` Read `analytics catalog` first for the schema. `analytics sql` accepts a guarded read-only `SELECT`. For a genuine bulk export, write it to disk instead of into your context: ```bash eximagent analytics query --groupBy importer --measures shipments --out buyers.ndjson --format ndjson ``` The CLI auto-pages the entire result set to the file and prints only a summary. Analyse the file with `duckdb`, `jq`, or pandas, and read only your computed aggregates back. ## Next - [Find buyers](https://eximagent.ai/docs/guides/find-buyers) — for companies not yet in the corpus - [Coverage and data sources](https://eximagent.ai/docs/concepts/coverage) — read this before quoting a number --- # Full-corpus analytics > Push the computation down with analytics query and sql, walk the market verbs, and export large result sets to disk instead of into context. When a question does not fit a [signal verb](https://eximagent.ai/docs/guides/trade-signals), push the computation down to the server rather than pulling rows up into context. ## Read the schema first ```bash eximagent analytics catalog ``` This reports the dimensions and measures available. Composing a query without it is guesswork. ## Structured queries ```bash eximagent analytics query \ --groupBy importer \ --measures shipments \ --filters '{"hs6":"090111","dest":"DE"}' ``` `analytics query` aggregates server-side over the full corpus and returns a small result. This is almost always what "analyse the whole database" actually needs. ## Guarded SQL ```bash eximagent analytics sql --query_sql "SELECT ..." ``` Read-only `SELECT` against the trade corpus, for questions the structured shape cannot express. > **Named verbs before SQL** > > Named verbs are not a convenience layer — they carry the scope a figure was > counted over, cross-source deduplication, and a refusal when the corpus lacks > the dimension asked for. Drop to SQL only when no verb fits. ## Market movement ```bash eximagent market trend --hs6 090111 --dest DE eximagent market momentum --hs6 090111 --dest DE eximagent market growth --hs6 090111 --dest DE eximagent market entrants --hs6 090111 --dest DE eximagent market churned --hs6 090111 --dest DE eximagent market compare --hs6 090111 --dest DE eximagent market anomalies --hs6 090111 --dest DE ``` `entrants` and `churned` are the two most actionable: who just started buying, and who just stopped. Both are outreach triggers. ## Paging and export Both `analytics query` and `analytics sql` page the full result set. Each full page returns a `nextActions` entry with the next-page cursor bound; follow it until empty. For anything large, write it to disk instead: ```bash eximagent analytics query \ --groupBy importer --measures shipments \ --out buyers.ndjson --format ndjson ``` The CLI auto-pages the entire result set at 10,000 rows per page and prints only a summary — row count, pages, columns, a three-row sample, and byte size. > **Never read a large dump into context** > > Analyse the file with `duckdb`, `jq`, or pandas and read back only your > computed aggregates. A multi-thousand-row dump in context is both expensive > and worse at answering the question than a five-row aggregate. ## Related - [Market and shipment signals](https://eximagent.ai/docs/guides/trade-signals) - [Coverage and data sources](https://eximagent.ai/docs/concepts/coverage) --- # Company intelligence > Resolve a company, read its trade fingerprint, and map its customers, suppliers, competitors, and trajectory. Before enriching a company from its website, see what the corpus already knows about it. That part is free and exact. ## Resolve the entity ```bash eximagent company resolve --name "Example Handels GmbH" eximagent company verify --name "Example Handels GmbH" eximagent company split --name "Example Group" ``` `resolve` maps a messy name to a canonical entity. `verify` confirms a match. `split` separates a name that has collapsed several distinct entities together — common with group structures and transliterated names. ## Read the trade fingerprint ```bash eximagent companies profile --name "Example Handels GmbH" eximagent companies trajectory --name "Example Handels GmbH" ``` `profile` is the shape of what they trade. `trajectory` is the direction — growing, flat, or receding. ## Map the relationships ```bash eximagent companies customers --name "Example Handels GmbH" eximagent companies suppliers --name "Example Handels GmbH" eximagent companies competitors --name "Example Handels GmbH" ``` `suppliers` is the one that matters most for outreach: it tells you who they buy from today, and therefore who you would be displacing. ## Their actual shipments ```bash eximagent company shipments --name "Example Handels GmbH" eximagent shipments get --id --view detail eximagent evidence show --id --normalized ``` `shipments get --view` projects richer fields — `detail`, `logistics`, `financials`, `parties`, `evidence` — over the default 24-field `summary`. `evidence show --normalized` returns English-normalized semantic fields next to the raw source record. > **This is the cheap half** > > Corpus lookups cost nothing and are exact. Website enrichment costs credits > and returns candidate data. Exhaust the first before reaching for the second. ## Then enrich Once the corpus picture justifies it, move to [enrichment](https://eximagent.ai/docs/guides/enrich-companies). ## Related - [Lookalike matching](https://eximagent.ai/docs/guides/lookalike-matching) - [Market and shipment signals](https://eximagent.ai/docs/guides/trade-signals) --- # Enrich companies and contacts > Deep-crawl a company website into structured facts, then find and verify decision-maker contacts for a validated shortlist. Enrichment is the step that turns a name in a list into something you can act on. It is also billable, so it belongs after the shortlist, not before it. ## Profile a company from its website ```bash eximagent enrich company --url https://example-imports.de ``` This deep-crawls the site and returns structured facts — what they sell, where they operate, how they describe themselves — each field carrying its [confidence tier](https://eximagent.ai/docs/concepts/confidence). For a whole shortlist, one call: ```bash eximagent enrich company --inputs companies.ndjson ``` ## Just the raw text When you want the markdown without the structuring pass: ```bash eximagent crawl run --url https://example-imports.de ``` ## What do they actually sell? Bulk `enrich company` returns image URLs in `keyFacts.images` — product and facility photography pulled from the site. Passing those to a vision-capable host answers "what do these companies actually make" far more reliably than their own copy does. ## Identify a company from a name ```bash eximagent company --name "Example Handels GmbH" eximagent company --inputs names.ndjson ``` Related resolution verbs: `company verify`, `company resolve`, `company split`, and `linkedin lookup`. ## Find the people Discover wide first, with no filters: ```bash eximagent enrich contacts --collectionId ``` Then narrow: ```bash eximagent employees filter --departments procurement ``` Doing it in this order matters. A filter-free first pass is recall-first — it finds people whose titles do not match the words you would have thought to search for. Filtering first quietly drops them. > **Quote flags with punctuation** > > `--titles procurement,R&D,formulation` breaks unquoted, because `&` is a shell > operator. Repeat the flag or quote the whole value — see [command > shape](https://eximagent.ai/docs/concepts/command-shape). ## Re-verify one person ```bash eximagent enrich contact --employeeId ``` ## Rank the shortlist ```bash eximagent collection analyze --collectionId \ --question "which of these have a procurement function big enough to run a tender?" ``` You get a ranking with evidence per rank, which you can audit rather than accept. ## Next - [Outreach](https://eximagent.ai/docs/guides/outreach) — once the list is clean - [Sanctions screening](https://eximagent.ai/docs/guides/sanctions-screening) — before you contact anyone --- # Lookalike matching > Save an ideal customer profile, then score, rank, and expand a list of companies that trade like your best account. Give EximAgent the customer you already like, and get more companies that trade like it. ## Save the profile ```bash eximagent ideal-profile save --name "core-account" --from-company "Example Handels GmbH" eximagent ideal-profile list eximagent ideal-profile get --name "core-account" ``` ## Score and rank ```bash eximagent profile-match score --collectionId --profile core-account eximagent profile-match rank --collectionId --profile core-account eximagent profile-match analyze --collectionId --profile core-account ``` `score` attaches a fit score per company. `rank` orders the list. `analyze` explains the ordering — use it when you need to defend the shortlist to someone else, or when the ranking looks wrong and you need to see why. ## Expand the list ```bash eximagent profile-match lookalike --profile core-account eximagent profile-match search --profile core-account ``` `lookalike` finds companies resembling the saved profile. `search` runs the profile as a query against the corpus. ## Keep it running ```bash eximagent profile-match watch --profile core-account ``` New companies matching the profile surface as they appear, instead of on the next manual sweep. ## Compound lead query When the criteria are commercial rather than structural, `prospects find` combines them in one call — growing importers, reachable email, not already on your list, buying from someone else: ```bash eximagent prospects find --hs6 090111 --dest DE ``` > **Ranking beats filtering** > > A hard filter drops companies that miss one criterion but are otherwise ideal. > Scoring keeps them visible and lets you decide where to cut. ## Related - [Collections and lists](https://eximagent.ai/docs/guides/collections) - [Company intelligence](https://eximagent.ai/docs/guides/company-intelligence) --- # Collections and lists > Build, refine, and analyse saved lists — and read the enrichment state already recorded on them instead of re-deriving it. A collection is the working list every other step reads from and writes back to. ## Create and inspect ```bash eximagent collection create --name "de-coffee-buyers" eximagent collection list eximagent collection get --name "de-coffee-buyers" ``` Collections are referenced by bare name or by UUID — the server resolves both, and no sigil is needed. > **Saved state is server-side** > > "My", "saved", and "existing" always mean the authenticated account's > server-side state. Never search the local filesystem, session state, or temp > directories for a collection, corridor, template, or knowledge-base entry. ## Add and remove members ```bash eximagent collection items add --name "de-coffee-buyers" --inputs companies.ndjson eximagent collection items remove --name "de-coffee-buyers" --id ``` ## Read the enrichment state `collection get` returns an `enrichmentStatus` block: ```json { "enrichmentStatus": { "company": "complete", "contacts": "partial", "drafts": "not-started" } } ``` Read it before deciding what to run. It is the answer to "where did I get to" — re-deriving it costs money, and asking the user costs trust. ## Rank with reasoning ```bash eximagent collection analyze --collectionId \ --question "which of these import at scale and would buy from a mid-size roaster?" ``` You get a ranking with auditable evidence per rank, rather than an opaque order. ## Fill from the corpus ```bash eximagent collection enrich-from-corpus --collectionId ``` This attaches what the trade corpus already knows to every member — free, and worth doing before any billable enrichment. ## Corridors A corridor is a saved trade lane you reuse across runs: ```bash eximagent corridor save --name "vn-de-coffee" --origin VN --dest DE --hs6 090111 eximagent corridor list eximagent corridor get --name "vn-de-coffee" ``` ## Related - [Find buyers](https://eximagent.ai/docs/guides/find-buyers) - [Lookalike matching](https://eximagent.ai/docs/guides/lookalike-matching) --- # Sanctions screening > Screen one name or a bulk list against the OFAC SDN list, and read the result as the advisory signal it is. Screening checks a name against the OFAC Specially Designated Nationals list. ## Screen one name ```bash eximagent sanctions check --name "Example Trading LLC" ``` ## Screen a list Put one entity per line in an NDJSON file and screen the batch in a single call: ```bash eximagent sanctions check --inputs names.ndjson ``` ```json {"name": "Example Trading LLC"} {"name": "Another Company Ltd"} ``` Never loop the single-name form over a list — see [bulk input](https://eximagent.ai/docs/reference/bulk-and-streaming). ## Reading the result Matching is fuzzy by necessity. Company names transliterate inconsistently, get abbreviated, and collide with unrelated entities that happen to share a word. The result tells you what matched and how closely; it does not tell you whether you may proceed. > **Advisory, not clearance** > > This is a screening signal against one list. Final clearance stays with you > and your compliance process. A clean result is not a compliance sign-off, and > a fuzzy hit is not an accusation — both need a human decision. ## Where it fits Screen before outreach, not after. Running it across a shortlist is cheap, and finding out late is the expensive version. ```bash eximagent collection get --name eximagent sanctions check --inputs shortlist.ndjson ``` ## Related - [Confidence model](https://eximagent.ai/docs/concepts/confidence) - [Outreach](https://eximagent.ai/docs/guides/outreach) --- # Outreach > Turn trade context into buyer-ready drafts, preview every message, and send only after confirmation. Outreach drafts from your real context — company profile, product notes, pricing files, saved templates — and nothing leaves without an explicit confirmation. ## Check the list first Outreach quality is mostly list quality. Before drafting, confirm the shortlist is enriched, screened, and filtered to [confidence tiers](https://eximagent.ai/docs/concepts/confidence) you will stand behind. ## Draft ```bash eximagent email draft --dry-run --collectionId ``` `--dry-run` shows every message without sending anything. Read them. Drafts are grounded in your context, which means a wrong profile produces wrong messages at scale. ## Send ```bash eximagent email send --confirm ``` Sending requires the explicit `--confirm` flag and runs a short countdown before messages leave. > **There is no undo** > > A sent message is external and permanent. The countdown is the last checkpoint > — the preview is the real one. ## Templates ```bash eximagent template list eximagent template get --name ``` Templates keep the parts you have already argued about — positioning, disclaimers, signature — stable across runs. ## Sequences, replies, and suppression ```bash eximagent sequence list eximagent reply list eximagent suppression list ``` Replies stay attached to the company they came from, so the negotiation history travels with the account rather than living in someone's inbox. Suppression lists keep people you should not contact out of every later run. ## Saved state is server-side Collections, corridors, templates, and knowledge-base entries belong to your authenticated account and live on the server. "My saved templates" means `eximagent template list` — never a search of local files. ```bash eximagent collection list eximagent corridor list eximagent template list eximagent kb list ``` ## Related - [Enrich companies and contacts](https://eximagent.ai/docs/guides/enrich-companies) - [Previews and confirmation](https://eximagent.ai/docs/concepts/previews-and-confirmation) --- # Sequences and replies > Run multi-step cadences, triage inbound replies, watch deliverability stats, and keep guardrails and suppression lists enforced. Once a single send works, cadences and reply handling are what make outreach sustainable. ## Sequences ```bash eximagent sequence create --name "q3-coffee" --collectionId eximagent sequence from-brief --brief "3 touches over 10 days, value-led" eximagent sequence from-template --template "intro-roaster" eximagent sequence validate --name "q3-coffee" eximagent sequence start --name "q3-coffee" eximagent sequence pause --name "q3-coffee" eximagent sequence metrics --name "q3-coffee" ``` Run `validate` before `start`. It catches the failures that are expensive after the fact — missing merge fields, suppressed recipients, guardrail violations. ## Triage replies ```bash eximagent reply list eximagent reply show --id eximagent reply approve --id eximagent reply edit --id eximagent reply reject --id eximagent reply request-rewrite --id ``` Replies stay attached to the company they came from, so negotiation history travels with the account rather than living in one person's inbox. ## Guardrails ```bash eximagent policy get eximagent policy set --max-daily 200 eximagent policy history ``` Policy is the standing constraint on outreach — volume, tone, and what may never be claimed. `policy history` shows when it changed and to what. ## Suppression ```bash eximagent suppression add --email someone@example.com eximagent suppression list eximagent suppression remove --email someone@example.com ``` Suppression is enforced across every later run, sequence included. ## Deliverability ```bash eximagent stats show ``` Reply, open, click, and bounce rates. A rising bounce rate is a list-quality problem, not a copy problem — go back to [contact verification](https://eximagent.ai/docs/guides/enrich-companies). > **Cadence multiplies mistakes** > > A single bad message reaches one person. A bad sequence reaches everyone on > the list, several times. `validate` and a small first cohort are cheaper than > a damaged sending domain. ## Related - [Outreach](https://eximagent.ai/docs/guides/outreach) - [Monitoring and alerts](https://eximagent.ai/docs/guides/monitoring) --- # Monitoring and alerts > Watch companies, markets, and tariff changes; schedule reminders; and get told when something you care about moves. Standing watches turn EximAgent from something you query into something that tells you when to act. ## Watch a company or a market ```bash eximagent watch company --name "Example Handels GmbH" eximagent watch market --hs6 090111 --dest DE eximagent watch list eximagent watch remove --id ``` A company watch fires on new shipment activity. A market watch fires on movement in the lane — new entrants, churn, price shifts. ## Monitors ```bash eximagent monitor create --kind replies eximagent monitor create --kind tariff-changes --hs6 090111 --dest DE eximagent monitor list eximagent monitor get --id eximagent monitor cancel --id ``` Monitors are recurring signal watches — inbound replies, tariff changes, and other events you would otherwise have to poll for. ## Reminders ```bash eximagent reminder create --at 2026-09-01 --note "follow up with Example GmbH" eximagent reminder list eximagent reminder get --id eximagent reminder cancel --id ``` One-shot, date-based, and attached to your account rather than your calendar. ## Which to use | You want | Use | | ------------------------------- | ------------------------------- | | Told when a company ships again | `watch company` | | Told when a lane moves | `watch market` | | Told when a duty rate changes | `monitor --kind tariff-changes` | | Told when someone replies | `monitor --kind replies` | | Nudged on a specific date | `reminder create` | > **Tariff monitors earn their keep** > > A duty change on a lane you are quoting invalidates the landed cost you built > the offer on. That is worth knowing on the day it happens, not at the next > manual check. ## Related - [HS codes and tariffs](https://eximagent.ai/docs/guides/hs-codes-and-tariffs) - [Sequences and replies](https://eximagent.ai/docs/guides/sequences-and-replies) --- # Knowledge and profile > Ground every answer in your own products, notes, and playbook so results reflect what you already know. Everything EximAgent drafts or ranks is shaped by what it knows about you. That context is explicit and editable. ## The operator profile ```bash eximagent profile get eximagent profile update --incoterm FOB --timezone Asia/Ho_Chi_Minh eximagent profile reset ``` The profile carries your product, target markets, signature, incoterm, and timezone. It is the first thing to check when results feel generic. If you are starting cold, extract it from something you already have rather than filling fields by hand: ```bash eximagent profile extract --from text ``` ## Your products ```bash eximagent products add --name "Washed arabica, grade 1" --hsCode 090111 eximagent products list eximagent products get --name "Washed arabica, grade 1" eximagent products update --name "Washed arabica, grade 1" --hsCode 090111 eximagent products remove --name "Washed arabica, grade 1" ``` A saved product means later commands stop asking you for the HS code. ## Knowledge base ```bash eximagent kb add --title "Pricing floor 2026" --file pricing.md eximagent kb list eximagent kb get --title "Pricing floor 2026" eximagent kb preview --title "Pricing floor 2026" eximagent kb update --title "Pricing floor 2026" --file pricing.md eximagent kb remove --title "Pricing floor 2026" ``` Knowledge-base entries are injected as context when drafting and analysing. This is where your negotiation playbook, pricing floors, certifications, and objection handling belong. `kb preview` shows what would actually be injected — use it when a draft cites something you did not expect. > **Context is why drafts read as yours** > > A draft grounded in a real pricing floor and a real certification list reads > differently from one grounded in nothing. This is the highest-leverage setup > step in the product. ## Related - [Outreach](https://eximagent.ai/docs/guides/outreach) - [Lookalike matching](https://eximagent.ai/docs/guides/lookalike-matching) --- # Share and export > Turn any result into a no-login preview link with PII redacted, or page an entire result set to a file on disk. Two ways to get a result out of the CLI: a link someone can open, or a file you can query. ## Share links ```bash eximagent share create --collectionId eximagent share list eximagent share set-expiry --id --days 14 eximagent share set-passcode --id --passcode eximagent share revoke --id ``` A share link is an anonymous, no-login web preview of a result. Contact PII is redacted in the shared view. > **A link is a disclosure** > > Anyone holding the URL can open it until it expires or is revoked. Set an > expiry when you create it, add a passcode for anything commercially sensitive, > and revoke when the deal moves on. ## File export ```bash eximagent analytics query \ --groupBy importer --measures shipments \ --out buyers.ndjson --format ndjson eximagent analytics sql --query_sql "SELECT ..." --out rows.csv --format csv ``` `--out` auto-pages the entire result set to disk at 10,000 rows per page and prints only a summary — row count, pages, columns, a three-row sample, and byte size. Analyse the file with code and read back only the aggregates: ```bash duckdb -c "SELECT importer, sum(shipments) FROM 'buyers.ndjson' GROUP BY 1 ORDER BY 2 DESC LIMIT 10" ``` ## Choosing between them | You want | Use | | ----------------------------------------- | -------------------------- | | Hand a result to a colleague or buyer | `share create` | | Compute something the CLI does not expose | `--out` and query the file | | Keep a record outside the account | `--out` | ## Related - [Full-corpus analytics](https://eximagent.ai/docs/guides/analytics) - [Collections and lists](https://eximagent.ai/docs/guides/collections) --- # Command reference > Every command category and its verbs — discovery, classification, shipments, analytics, enrichment, outreach, monitoring, and saved state. The full command surface, grouped by what you are trying to do. Every command follows the [standard shape](https://eximagent.ai/docs/concepts/command-shape). > **The always-current reference** > > This page is maintained alongside the site. The authoritative, always-current > surface — every flag and the full usage doctrine — is published for agents at > [cli.eximagent.ai/skill](https://cli.eximagent.ai/skill). ## Account and grounding | Command | Verbs | Purpose | | --------- | ----------------------------------- | ------------------------------------ | | `whoami` | — | Current account identity | | `login` | — | Device flow, or `--token ` | | `connect` | — | Device-code setup for the MCP server | | `profile` | `get`, `update`, `reset`, `extract` | Operator profile | | `usage` | — | Daily metered spend | ## Discovery | Command | Verbs | Purpose | | ----------- | -------------------------------------- | --------------------------------------------------- | | `search` | `run`, `refine` | Buyer discovery and refinement. Billable | | `run` | `status`, `summary`, `cancel`, `retry` | Run lifecycle and idempotency | | `pipeline` | `stop` | Cancel an in-flight discovery pipeline | | `prospects` | `find` | Compound lead query — growing, reachable, unclaimed | ## Classification and duties | Command | Verbs | Purpose | | ------------- | ----------------- | -------------------------------------------- | | `hscode` | `search` | HS disambiguation | | `tariff` | — | Duty rate for a corridor and product | | `trade` | `lookup` | Duties, taxes, remedies, NTMs | | `duty` | `exposure`, `fta` | Collection-wide exposure; preferential rates | | `landed cost` | — | Duty, freight, and insurance breakdown | ## Shipment records | Command | Verbs | Purpose | | ----------- | ----------------------------------------- | ----------------------------------------- | | `shipments` | `search`, `get` | Browse records; project one with `--view` | | `company` | `shipments`, `resolve`, `verify`, `split` | Single-entity lookup and history | | `product` | `shipments` | Who ships an HS code | | `route` | `shipments` | Origin→destination flows | | `price` | `shipments` | Price-per-weight evidence | | `evidence` | `show` | Provenance, raw or `--normalized` | ## Signals and analytics | Command | Verbs | Purpose | | ----------- | ---------------------------------------------------------------------------- | ----------------------------- | | `shipments` | `market-signals`, `buyer-recurrence`, `price-trend`, `route-signals` | Server-side market aggregates | | `analytics` | `catalog`, `query`, `sql` | Full-corpus aggregation | | `market` | `trend`, `momentum`, `growth`, `entrants`, `churned`, `compare`, `anomalies` | Market movement | | `companies` | `profile`, `customers`, `suppliers`, `competitors`, `trajectory` | Relationship graph | ## Enrichment | Command | Verbs | Purpose | | --------------- | ---------------------------------------------------------- | ---------------------------------- | | `enrich` | `company`, `contact`, `contacts` | Website profile; people. Billable | | `crawl` | `run` | Raw markdown, no structuring pass | | `contacts` | `add`, `enrich` | Manual and bulk people search | | `employees` | `filter`, `rank` | Narrow a discovered people set | | `linkedin` | `lookup` | Profile page resolution and scrape | | `profile-match` | `score`, `rank`, `analyze`, `lookalike`, `search`, `watch` | Ideal-customer fit | ## Outreach | Command | Verbs | Purpose | | ------------- | ---------------------------------------------------------------------------------------- | -------------------------------- | | `email` | `draft`, `send`, `cancel`, `followup`, `history` | Outreach lifecycle | | `sequence` | `create`, `from-brief`, `from-template`, `validate`, `start`, `pause`, `list`, `metrics` | Multi-step cadences | | `template` | `save`, `create`, `get`, `list`, `edit`, `generate`, `recall`, `delete` | Reusable messages | | `reply` | `list`, `show`, `approve`, `edit`, `reject`, `request-rewrite` | Inbound triage | | `policy` | `get`, `set`, `history` | Outreach guardrails | | `suppression` | `add`, `list`, `remove` | Do-not-contact list | | `stats` | `show` | Reply, open, click, bounce rates | ## Compliance | Command | Verbs | Purpose | | ----------- | ------- | ---------------------------- | | `sanctions` | `check` | OFAC SDN screening. Advisory | ## Saved state | Command | Verbs | Purpose | | --------------- | ------------------------------------------------------------------------------------- | ---------------------- | | `collection` | `create`, `get`, `list`, `items add`, `items remove`, `analyze`, `enrich-from-corpus` | Working lists | | `corridor` | `save`, `get`, `list`, `remove` | Reusable trade lanes | | `products` | `add`, `get`, `list`, `update`, `remove` | Your product catalogue | | `ideal-profile` | `save`, `get`, `list`, `delete` | Saved buyer personas | | `kb` | `add`, `get`, `list`, `preview`, `update`, `remove` | Knowledge base | ## Monitoring | Command | Verbs | Purpose | | ---------- | ------------------------------------- | ------------------------ | | `watch` | `company`, `market`, `list`, `remove` | Proactive trade alerts | | `monitor` | `create`, `get`, `list`, `cancel` | Recurring signal watches | | `reminder` | `create`, `get`, `list`, `cancel` | One-shot date alerts | ## Sharing | Command | Verbs | Purpose | | ------- | -------------------------------------------------------- | ------------------------------- | | `share` | `create`, `list`, `revoke`, `set-expiry`, `set-passcode` | No-login previews, PII redacted | > **Two rules that hold everywhere** > > Saved state is server-side — `list` it, never search the filesystem for it. > And `_admin/*` commands are not part of the public surface; do not call them. --- # Global flags > Flags every command accepts: --inputs, --dry-run, --profile, --strict, --output, --stream, and --out. These flags work across the command surface. ## `--inputs ` Bulk input. An NDJSON file with one entity per line, or `-` to read stdin. The server processes the batch with bounded concurrency and streams back one NDJSON document covering the whole batch. ```bash eximagent enrich company --inputs companies.ndjson ``` Always prefer this to looping the single-entity form. See [bulk input and streaming](https://eximagent.ai/docs/reference/bulk-and-streaming). ## `--dry-run` Preview only. Sets `confirmed=false` and `dryRun=true` server-side, making it a safe wrapper around any billable or irreversible command. ```bash eximagent --dry-run search run --product "roasted coffee" --location DE ``` ## `--profile ` Run against a different saved account. Equivalent to the `EXIMAGENT_PROFILE` environment variable. ```bash eximagent --profile client-a whoami ``` ## `--strict` Single-input only. Opts back into the blocking-candidates flow when input is ambiguous. The default is auto-pick, which keeps bulk runs moving; `--strict` is for when you would rather be asked than have a choice made for you. ## `--output yaml|table|json` Output format. Defaults to JSON, or NDJSON for streamed commands. ## `--stream` Emit NDJSON stream events for long-running commands. ## `--out [--format ndjson|csv]` Bulk export for `analytics query` and `analytics sql`. Auto-pages the **entire** result set to a file at 10,000 rows per page, printing only a small summary — row count, page count, columns, a three-row sample, and byte size. ```bash eximagent analytics query --groupBy importer --measures shipments --out buyers.ndjson --format ndjson ``` > **Why this exists** > > It keeps a multi-thousand-row result out of your context. Write it to disk, > query the file with `duckdb`, `jq`, or pandas, and read back only the > aggregates you actually need. ## Environment variables | Variable | Effect | | ------------------- | ---------------------------------------- | | `EXIMAGENT_PROFILE` | Default saved account for the session | | `HTTPS_PROXY` | Proxy for the CLI's outbound HTTPS calls | --- # Bulk input and streaming > Process a list in one call with NDJSON input, and block on the stream until the terminal event before reading rows. ## Bulk input Any list of entities — companies, URLs, names, HS queries — goes through `--inputs` in a single call. One NDJSON entity per line: ```json {"url": "https://example-imports.de"} {"url": "https://another-importer.fr"} {"url": "https://third-buyer.nl"} ``` ```bash eximagent enrich company --inputs companies.ndjson ``` The server processes the batch with bounded concurrency and returns one streamed NDJSON document covering all of it. > **Never loop the single form** > > Looping the single-entity command over a list is slower, noisier, and loses > the batch semantics the server applies. If you have more than one input, you > want `--inputs`. Reading from stdin works too: ```bash jq -c '{url: .website}' shortlist.json | eximagent enrich company --inputs - ``` ## Streaming Long-running commands — buyer discovery in particular — are asynchronous. The kickoff response returns a `runId`; the results arrive on a stream. ```bash eximagent search run --product "roasted coffee" --location DE --confirmed # → { "runId": "run_…" } eximagent stream --run-id run_… ``` Block until the terminal `complete` event. Rows read before it are a partial set that gives no indication it is partial. ## Paging `analytics query` and `analytics sql` page the full result set. Each full page returns a `nextActions` entry containing the next-page command, cursor included. Follow it until the response comes back empty. For anything large, skip paging by hand and export straight to disk: ```bash eximagent analytics query \ --groupBy importer --measures shipments \ --out buyers.ndjson --format ndjson ``` Then analyse the file programmatically and read back only your aggregates. ## Related - [Global flags](https://eximagent.ai/docs/reference/global-flags) - [Exit codes and errors](https://eximagent.ai/docs/reference/errors) --- # Search run lifecycle > Preview to confirmation to stream to collection — previewToken binding, run status and retry, and cancelling an in-flight pipeline. `search run` is the only command with a multi-stage lifecycle. Getting the order wrong is how runs get paid for twice. ## The stages ```text preview → confirm → stream → collection ``` ## 1. Preview ```bash eximagent --dry-run search run --product "roasted coffee" --location DE --hsCode 090111 ``` Returns the plan, the expected cost, and a **`previewToken`**. ## 2. Confirm with the same token ```bash eximagent search run \ --product "roasted coffee" --location DE --hsCode 090111 \ --confirmed --previewToken ``` > **Arguments must not drift** > > The confirm call must carry the same arguments as the preview. Changing them > fails with `INVALID_ARG: previewToken mismatch` — deliberately, so a run > cannot be priced on one query and executed on another. ## 3. Block on the stream The kickoff response returns a `runId`. Results land only at completion. ```bash eximagent stream --run-id ``` Block until the terminal `{kind: "complete"}` event. Rows read before it are a partial set that gives no indication of being partial. ## 4. Read the collection ```bash eximagent run summary --run-id eximagent collection get --name ``` ## Managing a run ```bash eximagent run status --run-id eximagent run summary --run-id eximagent run retry --run-id eximagent run cancel --run-id eximagent pipeline stop --run-id ``` `run retry` is idempotent — it resumes rather than re-charging for completed work. `pipeline stop` halts an in-flight discovery pipeline. ## Refine instead of re-running If the shape of the results is wrong, refine the existing run: ```bash eximagent search refine --run-id --product "specialty green coffee" ``` > **Never re-run for the same intent** > > A second `search run` for a question already asked is a second charge for an > answer you already hold. Refine, or read the existing collection. ## Related - [Previews and confirmation](https://eximagent.ai/docs/concepts/previews-and-confirmation) - [Bulk input and streaming](https://eximagent.ai/docs/reference/bulk-and-streaming) --- # Errors and exit codes > Typed error codes with retry guidance, what each exit code means, and why a blocked socket is an environment problem. ## Exit codes | Code | Meaning | What to do | | ---- | ----------- | ------------------------------------ | | `0` | Success | — | | `1` | Recoverable | Retry with backoff | | `2` | Fatal | Surface it to the user; do not retry | | `64` | Usage error | Fix the call shape | The exit code tells you whether to continue. The **reason** is always in the `stdout` envelope — see [output protocol](https://eximagent.ai/docs/concepts/output-protocol). ## Typed error codes | Code | Retry? | What it means and what to do | | ---------------- | ------ | ------------------------------------------------------------------------------------------- | | `INVALID_ARG` | No | Your call is malformed. Read `error.details.expected` and `did_you_mean`, repair, run once. | | `NOT_FOUND` | No | The named entity does not exist. `list` first, then call with a real name or id. | | `RATE_LIMITED` | Yes | Back off and retry, up to three times. | | `CLIENT_TIMEOUT` | Yes | The CLI's own clock fired, not a server failure. The job may still be running. | | `NETWORK_ERROR` | Yes | Egress is blocked in this environment. Grant access, or use the MCP server. | ## `INVALID_ARG` A usage error is a bug in the call, not a transient failure: ```json { "error": { "code": "INVALID_ARG", "details": { "expected": "hsCode (6-digit string)", "did_you_mean": "--hsCode" } } } ``` > **Never blind-retry a usage error** > > Retrying unchanged produces the same error and spends rate budget doing it. > The response already tells you the fix. Common causes: a flag that does not exist on that verb, a value in the wrong format, `snake_case` instead of camelCase, a `--inputs` file over 1000 rows, and [list values broken by shell quoting](https://eximagent.ai/docs/concepts/command-shape). ## `CLIENT_TIMEOUT` The client-side timeout — 180s by default — fired before the server replied. `error.details.timeoutMs` shows the limit, and the envelope's `nextActions` carries the exact `--stream` re-run. ```bash EXIMAGENT_TIMEOUT_MS=600000 eximagent enrich contacts --collectionId ``` > **A slow command is not a failed one** > > The server may still be working. Re-attach with `--stream` rather than > starting a second run and paying twice. ## `NETWORK_ERROR` Every command makes an HTTPS call on port 443. A connection or socket error is this environment blocking egress — not an outage. Fixes, in order of preference: 1. **Grant egress and keep the sandbox on.** Under a coding agent, enable network access for the workspace rather than disabling isolation. 2. **Use the [hosted MCP server](https://eximagent.ai/docs/integrations/mcp)**, which connects from the host and needs no sandbox change. 3. **Set `HTTPS_PROXY`** behind a corporate proxy. 4. **Allow the host** through firewall or antivirus. Never disable the sandbox wholesale. ## Authentication failures An expired session presents as a command that used to work and now does not: ```bash eximagent whoami eximagent login ``` ## Empty results An empty result set is not necessarily an error. On shipment queries check the `coverage` envelope first — `status: unavailable` means the lane is not visible, which is different from the trade not happening. See [coverage and data sources](https://eximagent.ai/docs/concepts/coverage). --- # Limits and timeouts > Row caps, worker concurrency, client timeouts, cache lifetimes, and the environment variables that move them. ## Bulk and concurrency | Limit | Value | On breach | | ------------------------ | ----------- | -------------------------------------------------- | | Rows per `--inputs` call | 1000 | `INVALID_ARG` — split into sequential calls | | Server-side workers | 25 | Higher `--concurrency` is silently clamped | | Default concurrency | 10 | Reduces automatically under upstream rate pressure | | Export page size | 10,000 rows | Auto-paged to the `--out` file | When concurrency is clamped, the `started` event reports `concurrencyClamped: true` — the run still completes. ## Timeouts | Setting | Default | Override | | ----------------------- | ------- | ---------------------- | | Per-call client timeout | 180s | `EXIMAGENT_TIMEOUT_MS` | | Heartbeat interval | 30s | — | ```bash EXIMAGENT_TIMEOUT_MS=900000 eximagent enrich contacts --collectionId ``` Operations that routinely exceed the default: `enrich contacts` over 200+ rows, and any confirmed `search run`. ## Caches | Cache | Lifetime | Key | | -------------- | -------- | -------------------- | | Website crawl | 100 days | Canonical URL | | Profile lookup | 100 days | Resolved profile URL | Repeat requests inside the window are free. Re-crawl when a source page has changed materially — cached does not mean current. ## Environment variables | Variable | Effect | | ---------------------- | --------------------------------------- | | `EXIMAGENT_PROFILE` | Default saved account for the session | | `EXIMAGENT_TIMEOUT_MS` | Per-call client timeout in milliseconds | | `HTTPS_PROXY` | Proxy for outbound HTTPS | ## Known limitations - Profile resolution is most reliable from canonical URLs; resolving from a bare company name is weaker. - `enrich contacts` is collection-scoped — narrow with row-subset flags rather than expecting an arbitrary input set. - Enrichment returns image **URLs**, not stored bytes, so source-page rot is possible. Re-enrich when images stop resolving. - `--strict` applies to single-input calls only; bulk runs always auto-pick. > **Caps are guidance made enforceable** > > Each limit here encodes something that goes wrong past it — a 1000-row batch > that times out, a concurrency setting that trips upstream rate limits. Sizing > a run inside them is faster than discovering them. ## Related - [Scale and batching](https://eximagent.ai/docs/concepts/batching) - [Errors and exit codes](https://eximagent.ai/docs/reference/errors) --- # MCP server > Connect the hosted MCP server when the CLI cannot be installed or outbound network is blocked. Same server, same corpus, no sandbox change. The hosted MCP server exposes the same verbs as tools, reaching the same server and the same corpus as the CLI. It connects from the agent host rather than from inside the sandbox, so it needs no sandbox change and nothing installed on the machine. Recommend it when egress is blocked, or when the environment does not allow installing a binary. ## Set it up The endpoint is `https://mcp.eximagent.ai/mcp` — a remote streamable-HTTP MCP server. **Codex** ```bash codex mcp add eximagent --url https://mcp.eximagent.ai/mcp codex mcp login eximagent ``` **Claude Code** ```bash claude mcp add --transport http eximagent https://mcp.eximagent.ai/mcp --scope user ``` Then run `/mcp` to confirm the connection. **Desktop and web clients** Settings → Connectors → Add custom connector, and paste the URL above. **Any other host** Point it at `https://mcp.eximagent.ai/mcp` as a remote streamable-HTTP server. ## Setting it up from the CLI If the CLI is already installed, it can walk you through the connection with a device code and verify it worked: ```bash eximagent connect ``` > **An agent cannot add this for you** > > Registering an MCP server is a host-level configuration change. An agent can > hand you the command, but you run it — that boundary is deliberate. ## Authentication Sign-in is a browser flow with no key to paste, and access is revocable at any time from your account. ## Which door should I use? | Situation | Use | | ------------------------------------------- | ---------- | | Terminal work, full network access | CLI | | Agent sandbox with egress granted | CLI | | Egress blocked, or nothing may be installed | MCP server | | You want tools rather than shell commands | MCP server | Both are the same service. Whichever you pick, the corpus, the confidence tiers, and the coverage envelope are identical. --- # AI agents and editors > Load the EximAgent skill into a coding agent so it drives the CLI for you, and keep it inside a sandbox that still has egress. EximAgent is designed to be driven by a coding agent as much as by a person. The installer sets this up automatically — the interesting part is knowing what the agent has been told. ## The skill The installer writes the EximAgent skill into the skill directories of coding agents it finds on the machine. The skill teaches the agent the intent map, which commands cost money, the preview-first doctrine, and how to read the confidence and coverage envelopes. Load or inspect it directly at [cli.eximagent.ai/skill](https://cli.eximagent.ai/skill). It is the always-current command reference — this documentation orients, the skill is authoritative. ## What the agent is expected to do - Ground in `profile get` before acting on a vague request - Ask one concrete question rather than inventing a product, country, or HS code - Preview billable steps with `--dry-run` and show you the cost first - Batch lists through `--inputs` instead of looping - Never speak above a field's [confidence tier](https://eximagent.ai/docs/concepts/confidence) - Block on the stream before reading results If an agent skips the shortlist step and enriches an entire result set, stop it. That is the failure mode that costs real money. ## Sandboxing The CLI needs outbound HTTPS. The correct configuration grants egress while keeping isolation on — for example, a workspace-write sandbox with network access enabled, rather than an unsandboxed run. If egress cannot be granted, use the [hosted MCP server](https://eximagent.ai/docs/integrations/mcp) instead. It needs no sandbox change because it connects from the host, not from inside the sandbox. > **Do not disable the sandbox** > > A blocked socket is an egress problem with two clean fixes. Turning isolation > off to make an error go away trades a configuration issue for a much larger > one. ## Reading results back into context Bulk results belong on disk, not in an agent's context window. Use `--out ` for exports, analyse the file with code, and read back only the computed aggregates. See [bulk input and streaming](https://eximagent.ai/docs/reference/bulk-and-streaming). ## Related - [How EximAgent works](https://eximagent.ai/docs/get-started/how-it-works) - [MCP server](https://eximagent.ai/docs/integrations/mcp)