salesprompter-cli 0.1.19 → 0.1.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -280
- package/dist/cli.js +1618 -128
- package/dist/linkedin-products.js +29 -8
- package/dist/linkedin-session.js +751 -0
- package/dist/sales-navigator.js +207 -36
- package/dist/salesnav-backfill.js +710 -0
- package/package.json +13 -1
package/README.md
CHANGED
|
@@ -1,309 +1,58 @@
|
|
|
1
1
|
# salesprompter-cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Salesprompter CLI helps you go from company or product input to qualified leads with a guided terminal flow.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
- Define an ideal customer profile
|
|
7
|
-
- Resolve a target account from a domain
|
|
8
|
-
- Generate seed leads
|
|
9
|
-
- Enrich leads
|
|
10
|
-
- Score leads
|
|
11
|
-
- Sync leads into CRM and outreach systems
|
|
12
|
-
- Analyze upstream lead-list and domain-enrichment bottlenecks
|
|
13
|
-
- Replace opaque Pipedream logic with deterministic CLI workflows
|
|
14
|
-
|
|
15
|
-
It is built for two users at the same time:
|
|
16
|
-
|
|
17
|
-
- humans working in a terminal
|
|
18
|
-
- coding agents such as Codex, Claude Code, and other LLM-driven shell workflows
|
|
19
|
-
|
|
20
|
-
## Start Here
|
|
21
|
-
|
|
22
|
-
If someone discovers Salesprompter from a vague prompt, give them the shortest working path for their context.
|
|
23
|
-
|
|
24
|
-
```bash
|
|
25
|
-
## Human-friendly guided path
|
|
26
|
-
npx -y salesprompter-cli@latest
|
|
27
|
-
|
|
28
|
-
## Explicit guided path
|
|
29
|
-
npx -y salesprompter-cli@latest wizard
|
|
30
|
-
|
|
31
|
-
## Raw command surface for agents and scripts
|
|
32
|
-
npx salesprompter-cli@latest --help
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
Or install it globally:
|
|
5
|
+
## Install
|
|
36
6
|
|
|
37
7
|
```bash
|
|
38
|
-
npm
|
|
39
|
-
salesprompter
|
|
40
|
-
salesprompter wizard
|
|
41
|
-
salesprompter --help
|
|
8
|
+
npm i -g salesprompter-cli
|
|
42
9
|
```
|
|
43
10
|
|
|
44
|
-
|
|
45
|
-
If your Salesprompter user belongs to multiple organizations, browser login asks which organization the CLI session should use.
|
|
46
|
-
|
|
47
|
-
## Prompt To Command
|
|
48
|
-
|
|
49
|
-
If the user says something like "I need to determine the ICP of deel.com", there are two different meanings.
|
|
50
|
-
|
|
51
|
-
### 1. They want leads at Deel itself
|
|
52
|
-
|
|
53
|
-
This means Deel is the target account.
|
|
11
|
+
or run directly:
|
|
54
12
|
|
|
55
13
|
```bash
|
|
56
|
-
|
|
57
|
-
salesprompter leads:generate --icp ./data/icp.json --count 5 --domain deel.com --company-name Deel --out ./data/deel-leads.json
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
### 2. They sell for Deel and need Deel's ideal customer profile
|
|
61
|
-
|
|
62
|
-
This means Deel is the vendor, not the target account.
|
|
63
|
-
|
|
64
|
-
```bash
|
|
65
|
-
salesprompter icp:vendor --vendor deel --market dach --out ./data/deel-icp.json
|
|
66
|
-
salesprompter leads:lookup:bq --icp ./data/deel-icp.json --limit 100 --execute --out ./data/deel-leads-raw.json --lead-out ./data/deel-leads.json
|
|
67
|
-
salesprompter leads:enrich --in ./data/deel-leads.json --out ./data/deel-enriched.json
|
|
68
|
-
salesprompter leads:score --icp ./data/deel-icp.json --in ./data/deel-enriched.json --out ./data/deel-scored.json
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
### 3. They want the LLM to call the CLI directly
|
|
72
|
-
|
|
73
|
-
Use the same commands, but prefer machine-readable output:
|
|
74
|
-
|
|
75
|
-
```bash
|
|
76
|
-
salesprompter --json icp:vendor --vendor deel --market dach
|
|
77
|
-
salesprompter --json icp:vendor --vendor deel --market dach --out ./data/deel-icp.json
|
|
78
|
-
salesprompter --json leads:lookup:bq --icp ./data/deel-icp.json --limit 100 --lead-out ./data/deel-leads.json
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
## Documentation
|
|
82
|
-
|
|
83
|
-
This repository now includes the public Salesprompter docs site for the wider Salesprompter universe, including the app contract, CLI surface, Chrome extension contract, and the main warehouse-backed workflows.
|
|
84
|
-
|
|
85
|
-
- Live docs: `https://salesprompter-cli.vercel.app`
|
|
86
|
-
|
|
87
|
-
- Docs home: `./index.mdx`
|
|
88
|
-
- Quickstart: `./quickstart.mdx`
|
|
89
|
-
- Architecture: `./architecture.mdx`
|
|
90
|
-
- App: `./platform/app.mdx`
|
|
91
|
-
- CLI: `./platform/cli.mdx`
|
|
92
|
-
- Chrome extension: `./platform/chrome-extension.mdx`
|
|
93
|
-
- Domain finder: `./workflows/domain-finder.mdx`
|
|
94
|
-
- Command reference: `./reference/cli.mdx`
|
|
95
|
-
- Environment variables: `./reference/environment-variables.mdx`
|
|
96
|
-
- Troubleshooting: `./operations/troubleshooting.mdx`
|
|
97
|
-
|
|
98
|
-
Run the docs locally with:
|
|
99
|
-
|
|
100
|
-
```bash
|
|
101
|
-
npm run docs:dev
|
|
14
|
+
npx -y salesprompter-cli@latest
|
|
102
15
|
```
|
|
103
16
|
|
|
104
|
-
|
|
17
|
+
## Quickstart
|
|
105
18
|
|
|
106
19
|
```bash
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
## Integration Contract
|
|
111
|
-
|
|
112
|
-
This CLI is not a standalone toy. It is a production integration surface for the Salesprompter app.
|
|
113
|
-
|
|
114
|
-
- The Domain Finder flow in this repository is a real end-to-end test case for Salesprompter app integration.
|
|
115
|
-
- CLI behavior should be treated as an app contract: auth, BigQuery execution, artifacts, and writeback semantics must remain stable.
|
|
116
|
-
- Changes to domain selection, writeback, or audit logic should always be validated with:
|
|
117
|
-
- CLI tests (`npm test`)
|
|
118
|
-
- BigQuery-backed runs (`domainfinder:run:bq`, `domainfinder:audit-existing:bq`)
|
|
119
|
-
- before/after delta checks (`domainfinder:audit-delta`)
|
|
120
|
-
|
|
121
|
-
The current version is account-first. It resolves a company from a domain, then generates contacts for that account through provider interfaces. The default providers are still fallback heuristics, but the JSON contracts are now stable for real company and people-data integrations.
|
|
122
|
-
|
|
123
|
-
When the output `mode` is `fallback`, the leads are modeled contacts for workflow testing, not verified real contacts. A real provider path should return `mode: "real"` using the same JSON shape.
|
|
124
|
-
|
|
125
|
-
All non-auth commands require a logged-in CLI session. This gives you one identity model across Salesprompter app, CLI, and Chrome extension.
|
|
126
|
-
|
|
127
|
-
Global output flags:
|
|
128
|
-
|
|
129
|
-
- `--json`: compact machine-readable JSON (optimized for agent/LLM parsers)
|
|
130
|
-
- `--quiet`: suppress successful stdout payloads (errors still surface)
|
|
131
|
-
|
|
132
|
-
## Auth and Session
|
|
133
|
-
|
|
134
|
-
The CLI stores a local session file at `~/.config/salesprompter/auth-session.json` (or `SALESPROMPTER_CONFIG_DIR`).
|
|
20
|
+
# Start the interactive wizard
|
|
21
|
+
salesprompter
|
|
135
22
|
|
|
136
|
-
|
|
137
|
-
# Preferred path: browser/device login
|
|
23
|
+
# Login explicitly
|
|
138
24
|
salesprompter auth:login
|
|
139
25
|
|
|
140
|
-
#
|
|
141
|
-
salesprompter auth:
|
|
142
|
-
|
|
143
|
-
# Verify active identity with backend
|
|
144
|
-
salesprompter auth:whoami --verify
|
|
145
|
-
|
|
146
|
-
# Clear local session
|
|
147
|
-
salesprompter auth:logout
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
If your user belongs to multiple organizations, the browser flow asks you to choose the organization for that CLI session before returning to the terminal.
|
|
151
|
-
|
|
152
|
-
Environment variables:
|
|
153
|
-
|
|
154
|
-
- `SALESPROMPTER_API_BASE_URL`: override backend URL (default `https://salesprompter.ai`)
|
|
155
|
-
- `SALESPROMPTER_CONFIG_DIR`: override local config dir
|
|
156
|
-
- `SALESPROMPTER_SKIP_AUTH=1`: bypass auth guard (tests/dev only)
|
|
157
|
-
- `INSTANTLY_API_KEY`: required for real `sync:outreach --target instantly`
|
|
158
|
-
- `INSTANTLY_CAMPAIGN_ID`: default campaign id for Instantly sync
|
|
159
|
-
- `SALESPROMPTER_INSTANTLY_BASE_URL`: override Instantly API base URL (tests/local proxies)
|
|
160
|
-
|
|
161
|
-
App compatibility:
|
|
162
|
-
|
|
163
|
-
- Salesprompter app should expose `/api/cli/auth/device/start`, `/api/cli/auth/device/poll`, and `/api/cli/auth/me`.
|
|
164
|
-
- `salesprompter auth:login` uses browser/device login and prints the verification URL plus code before polling.
|
|
165
|
-
- `POST /api/cli/auth/token` remains the fallback path when browser/device login is disabled or unavailable.
|
|
166
|
-
|
|
167
|
-
Fallback command:
|
|
168
|
-
|
|
169
|
-
```bash
|
|
170
|
-
salesprompter auth:login --token "<token-from-app>" --api-url "https://salesprompter.ai"
|
|
26
|
+
# Verify your session
|
|
27
|
+
salesprompter auth:whoami
|
|
171
28
|
```
|
|
172
29
|
|
|
173
|
-
##
|
|
174
|
-
|
|
175
|
-
- Every command reads and writes plain JSON.
|
|
176
|
-
- Output is machine-readable and composable (`--json` for compact transport).
|
|
177
|
-
- The top-level use cases map ambiguous prompts like "determine the ICP of deel.com" into explicit command paths.
|
|
178
|
-
- Domain contracts are explicit and validated with `zod`.
|
|
179
|
-
- External integrations are behind narrow provider interfaces.
|
|
180
|
-
- Lead generation reports which provider and mode produced the result.
|
|
181
|
-
- Workflow bottlenecks become inspectable artifacts instead of hidden Pipedream state.
|
|
182
|
-
- Real prospect lookup can be normalized straight into the CLI lead schema with `--lead-out`.
|
|
183
|
-
|
|
184
|
-
## Commands
|
|
30
|
+
## Common commands
|
|
185
31
|
|
|
186
32
|
```bash
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
--industries "Software,Financial Services" \
|
|
190
|
-
--company-sizes "50-199,200-499" \
|
|
191
|
-
--regions "Europe" \
|
|
192
|
-
--countries "DE,NL,GB" \
|
|
193
|
-
--titles "Head of Revenue Operations,VP Sales" \
|
|
194
|
-
--required-signals "recent funding,growing outbound team" \
|
|
195
|
-
--keywords "revenue operations,outbound,sales tooling" \
|
|
196
|
-
--out ./data/icp.json
|
|
197
|
-
|
|
198
|
-
salesprompter auth:login
|
|
199
|
-
salesprompter auth:whoami --verify
|
|
200
|
-
salesprompter icp:vendor --vendor deel --market dach --out ./data/deel-icp.json
|
|
201
|
-
salesprompter leads:lookup:bq --icp ./data/deel-icp.json --limit 100 --execute --out ./data/deel-leads-raw.json --lead-out ./data/deel-leads.json
|
|
202
|
-
salesprompter leads:enrich --in ./data/deel-leads.json --out ./data/deel-enriched.json
|
|
203
|
-
salesprompter leads:score --icp ./data/deel-icp.json --in ./data/deel-enriched.json --out ./data/deel-scored.json
|
|
204
|
-
salesprompter sync:outreach --target instantly --in ./data/deel-scored.json --campaign-id "$INSTANTLY_CAMPAIGN_ID"
|
|
205
|
-
salesprompter sync:outreach --target instantly --in ./data/deel-scored.json --campaign-id "$INSTANTLY_CAMPAIGN_ID" --apply
|
|
206
|
-
salesprompter icp:from-historical-queries:bq --vendor deel --market dach --out ./data/deel-icp-historical.json --report-out ./data/deel-historical-report.json
|
|
207
|
-
salesprompter leadlists:funnel:bq --vendor deel --market dach --out ./data/deel-leadlists-funnel.json
|
|
208
|
-
salesprompter leadlists:direct-export:bq --vendor deel --market dach --limit 20000 --out-dir ./data/direct-path --sql-out ./data/direct-path/deel-direct-dach.sql
|
|
209
|
-
salesprompter domainfinder:backlog:bq --market dach --out ./data/deel-domainfinder-backlog.json
|
|
210
|
-
salesprompter domainfinder:candidates:bq --market dach --limit 500 --out ./data/domain-candidates.json --sql-out ./data/domain-candidates.sql
|
|
211
|
-
salesprompter domainfinder:input-sql --market dach --out ./data/domainFinder_input_v2.sql
|
|
212
|
-
salesprompter domainfinder:select --in ./data/domain-candidates.json --out ./data/domain-decisions.json
|
|
213
|
-
salesprompter domainfinder:audit --in ./data/domain-decisions.json --out ./data/domain-audit.json
|
|
214
|
-
salesprompter domainfinder:compare-pipedream --in ./data/domain-candidates.json --out ./data/domain-comparison.json
|
|
215
|
-
salesprompter domainfinder:audit-existing:bq --market dach --out ./data/domain-existing-audit.json
|
|
216
|
-
salesprompter domainfinder:audit-delta --before ./data/domain-existing-audit-before.json --after ./data/domain-existing-audit-after.json --out ./data/domain-existing-audit-delta.json
|
|
217
|
-
salesprompter domainfinder:repair-existing:bq --market dach --mode conservative --limit 5000 --out ./data/domain-repair.sql --trace-id salesprompter-cli-repair-dach
|
|
218
|
-
salesprompter domainfinder:writeback-sql --in ./data/domain-decisions.json --out ./data/domain-writeback.sql --trace-id salesprompter-cli-dach-20260308
|
|
219
|
-
salesprompter domainfinder:writeback:bq --in ./data/domain-decisions.json --out ./data/domain-writeback.sql --trace-id salesprompter-cli-dach-20260308
|
|
220
|
-
salesprompter domainfinder:run:bq --market dach --limit 500 --out-dir ./data/domainfinder-run --trace-id salesprompter-cli-dach-20260308
|
|
221
|
-
salesprompter account:resolve --domain deel.com --company-name Deel --out ./data/deel-account.json
|
|
222
|
-
salesprompter leads:generate --icp ./data/icp.json --count 5 --out ./data/leads.json
|
|
223
|
-
salesprompter leads:generate --icp ./data/icp.json --count 5 --domain deel.com --company-name Deel --out ./data/deel-leads.json
|
|
224
|
-
salesprompter leads:enrich --in ./data/leads.json --out ./data/enriched.json
|
|
225
|
-
salesprompter leads:score --icp ./data/icp.json --in ./data/enriched.json --out ./data/scored.json
|
|
226
|
-
salesprompter leads:lookup:bq --icp ./data/deel-icp.json --limit 100
|
|
227
|
-
salesprompter queries:analyze:bq --search-kind sales-people --include-function "Human Resources" --out ./data/hr-query-report.json
|
|
228
|
-
salesprompter sync:crm --target hubspot --in ./data/scored.json
|
|
229
|
-
salesprompter sync:outreach --target instantly --in ./data/scored.json
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
## Domain Finder Migration
|
|
233
|
-
|
|
234
|
-
The original Pipedream `domainFinder` workflow was doing three things:
|
|
235
|
-
|
|
236
|
-
1. fetch a small input set from BigQuery
|
|
237
|
-
2. ask OpenAI / Hunter for candidate domains
|
|
238
|
-
3. pick a domain and write it back
|
|
239
|
-
|
|
240
|
-
The CLI now models that logic directly and improves it:
|
|
33
|
+
# Product/category to leads workflow
|
|
34
|
+
salesprompter salesnav:from-product-category --input "https://www.linkedin.com/company/example/"
|
|
241
35
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
- `domainfinder:input-sql` generates a replacement input view driven by `linkedin_companies`, not `leadPool_new`
|
|
245
|
-
- `domainfinder:select` applies deterministic domain selection rules
|
|
246
|
-
- `domainfinder:audit` turns decisions into a review queue and writeback summary
|
|
247
|
-
- `domainfinder:compare-pipedream` quantifies how often the old selector would disagree with the improved selector
|
|
248
|
-
- `domainfinder:audit-existing:bq` measures current warehouse-visible mismatches and bad chosen domains
|
|
249
|
-
- `domainfinder:audit-delta` compares two audit snapshots and reports metric deltas
|
|
250
|
-
- `domainfinder:repair-existing:bq` generates (and optionally executes) targeted repair writes with selectable mode:
|
|
251
|
-
- `conservative`: only missing/blacklisted chosen domains
|
|
252
|
-
- `aggressive`: missing/blacklisted plus all mismatches
|
|
253
|
-
- `mismatch-only`: only mismatched chosen domains
|
|
254
|
-
- `domainfinder:writeback-sql` emits conservative SQL for `domainFinder_output`
|
|
255
|
-
- `domainfinder:writeback:bq` can execute that writeback in BigQuery when explicitly asked
|
|
256
|
-
- `domainfinder:run:bq` runs the full candidate -> decision -> audit -> writeback pipeline and stores all artifacts
|
|
36
|
+
# Run a Sales Navigator crawl from a query URL
|
|
37
|
+
salesprompter salesnav:crawl --query-url "https://www.linkedin.com/sales/search/people?query=..."
|
|
257
38
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
1. prefer `domain_linkedin` when present and not blacklisted
|
|
261
|
-
2. otherwise prefer `website_linkedin` root domain when present and not blacklisted
|
|
262
|
-
3. otherwise choose the non-blacklisted candidate with the highest Hunter email count
|
|
263
|
-
4. otherwise fall back to the first non-null candidate
|
|
264
|
-
|
|
265
|
-
This removes the earlier failure mode where OpenAI or Hunter could override a good LinkedIn domain purely because of a higher Hunter count.
|
|
266
|
-
|
|
267
|
-
Writeback policy:
|
|
268
|
-
|
|
269
|
-
- write to `SalesPrompter.domainFinder_output`, which is the source feeding `linkedin_companies.domain`
|
|
270
|
-
- exclude `no-domain` decisions
|
|
271
|
-
- exclude blacklisted domains from generated writeback SQL
|
|
272
|
-
- preserve batch provenance through `trace_id`
|
|
273
|
-
|
|
274
|
-
## Development
|
|
275
|
-
|
|
276
|
-
```bash
|
|
277
|
-
npm install
|
|
278
|
-
npm run build
|
|
279
|
-
node ./dist/cli.js --help
|
|
280
|
-
npm test
|
|
39
|
+
# Check crawl status
|
|
40
|
+
salesprompter salesnav:crawl:status --job-id "<job-id>"
|
|
281
41
|
```
|
|
282
42
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
- The CLI runs `bq query` with `--project_id` from `BQ_PROJECT_ID`.
|
|
286
|
-
- Fallback order: `BQ_PROJECT_ID` -> `GOOGLE_CLOUD_PROJECT` -> `GCLOUD_PROJECT` -> `icpidentifier`.
|
|
287
|
-
|
|
288
|
-
## Real Deel Flow
|
|
43
|
+
## Output modes
|
|
289
44
|
|
|
290
|
-
|
|
45
|
+
- `--json` for machine-readable output
|
|
46
|
+
- `--quiet` to suppress successful payload output
|
|
291
47
|
|
|
292
|
-
|
|
48
|
+
## Notes
|
|
293
49
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
4. `salesprompter leads:score --icp ./data/deel-icp.json --in ./data/deel-enriched.json --out ./data/deel-scored.json`
|
|
298
|
-
5. `salesprompter sync:outreach --target instantly --in ./data/deel-scored.json --campaign-id "$INSTANTLY_CAMPAIGN_ID"`
|
|
299
|
-
6. Add `--apply` only when the dry-run output looks correct.
|
|
50
|
+
- Use your own authorized LinkedIn / Sales Navigator access.
|
|
51
|
+
- Respect LinkedIn and provider terms.
|
|
52
|
+
- The CLI is designed for interactive users and agent-assisted workflows.
|
|
300
53
|
|
|
301
|
-
##
|
|
54
|
+
## Links
|
|
302
55
|
|
|
303
|
-
-
|
|
304
|
-
-
|
|
305
|
-
-
|
|
306
|
-
- Replace `DryRunSyncProvider` with real HubSpot, Salesforce, Pipedrive, Instantly, Apollo, or Outreach clients.
|
|
307
|
-
- Add provider selection and credentials for a first real `--domain deel.com` workflow.
|
|
308
|
-
- Replace configurable `bq` field mapping with a typed adapter per warehouse schema.
|
|
309
|
-
- Add a real candidate-fetch command that reads domain candidates from BigQuery and feeds them into `domainfinder:select`.
|
|
56
|
+
- Docs: https://salesprompter-cli.vercel.app
|
|
57
|
+
- App: https://salesprompter.ai
|
|
58
|
+
- Repository: https://github.com/danielsinewe/salesprompter-cli
|