salesprompter-cli 0.1.2 → 0.1.4

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 CHANGED
@@ -12,6 +12,80 @@
12
12
  - Analyze upstream lead-list and domain-enrichment bottlenecks
13
13
  - Replace opaque Pipedream logic with deterministic CLI workflows
14
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, the first thing they need is the shortest working path.
23
+
24
+ ```bash
25
+ npx salesprompter-cli@latest --help
26
+ ```
27
+
28
+ Or install it globally:
29
+
30
+ ```bash
31
+ npm install -g salesprompter-cli
32
+ salesprompter --help
33
+ ```
34
+
35
+ ## Prompt To Command
36
+
37
+ If the user says something like "I need to determine the ICP of deel.com", there are two different meanings.
38
+
39
+ ### 1. They want leads at Deel itself
40
+
41
+ This means Deel is the target account.
42
+
43
+ ```bash
44
+ salesprompter account:resolve --domain deel.com --company-name Deel --out ./data/deel-account.json
45
+ salesprompter leads:generate --icp ./data/icp.json --count 5 --domain deel.com --company-name Deel --out ./data/deel-leads.json
46
+ ```
47
+
48
+ ### 2. They sell for Deel and need Deel's ideal customer profile
49
+
50
+ This means Deel is the vendor, not the target account.
51
+
52
+ ```bash
53
+ salesprompter icp:vendor --vendor deel --market dach --out ./data/deel-icp.json
54
+ salesprompter leads:lookup:bq --icp ./data/deel-icp.json --limit 100 --execute --out ./data/deel-leads-raw.json --lead-out ./data/deel-leads.json
55
+ salesprompter leads:enrich --in ./data/deel-leads.json --out ./data/deel-enriched.json
56
+ salesprompter leads:score --icp ./data/deel-icp.json --in ./data/deel-enriched.json --out ./data/deel-scored.json
57
+ ```
58
+
59
+ ### 3. They want the LLM to call the CLI directly
60
+
61
+ Use the same commands, but prefer machine-readable output:
62
+
63
+ ```bash
64
+ salesprompter --json icp:vendor --vendor deel --market dach --out ./data/deel-icp.json
65
+ salesprompter --json leads:lookup:bq --icp ./data/deel-icp.json --limit 100 --lead-out ./data/deel-leads.json
66
+ ```
67
+
68
+ ## Documentation
69
+
70
+ This repository now includes a Mintlify docs site for the wider Salesprompter universe, including the app contract, CLI surface, Chrome extension contract, and the main warehouse-backed workflows.
71
+
72
+ - Docs home: `./index.mdx`
73
+ - Quickstart: `./quickstart.mdx`
74
+ - Architecture: `./architecture.mdx`
75
+ - App: `./platform/app.mdx`
76
+ - CLI: `./platform/cli.mdx`
77
+ - Chrome extension: `./platform/chrome-extension.mdx`
78
+ - Domain finder: `./workflows/domain-finder.mdx`
79
+ - Command reference: `./reference/cli.mdx`
80
+ - Environment variables: `./reference/environment-variables.mdx`
81
+ - Troubleshooting: `./operations/troubleshooting.mdx`
82
+
83
+ Run the docs locally with:
84
+
85
+ ```bash
86
+ npm run docs:dev
87
+ ```
88
+
15
89
  ## Integration Contract
16
90
 
17
91
  This CLI is not a standalone toy. It is a production integration surface for the Salesprompter app.
@@ -39,11 +113,11 @@ Global output flags:
39
113
  The CLI stores a local session file at `~/.config/salesprompter/auth-session.json` (or `SALESPROMPTER_CONFIG_DIR`).
40
114
 
41
115
  ```bash
42
- # Device flow through Salesprompter backend (recommended)
43
- salesprompter auth:login
116
+ # Production path: generate a short-lived CLI token in the Salesprompter app
117
+ salesprompter auth:login --token "$SALESPROMPTER_TOKEN" --api-url "https://salesprompter.ai"
44
118
 
45
- # Direct login using app-issued bearer token
46
- salesprompter auth:login --token "$SALESPROMPTER_TOKEN"
119
+ # Optional: use device flow only if your Salesprompter app exposes it
120
+ salesprompter auth:login
47
121
 
48
122
  # Verify active identity with backend
49
123
  salesprompter auth:whoami --verify
@@ -54,7 +128,7 @@ salesprompter auth:logout
54
128
 
55
129
  Environment variables:
56
130
 
57
- - `SALESPROMPTER_API_BASE_URL`: override backend URL (default `https://app.salesprompter.com`)
131
+ - `SALESPROMPTER_API_BASE_URL`: override backend URL (default `https://salesprompter.ai`)
58
132
  - `SALESPROMPTER_CONFIG_DIR`: override local config dir
59
133
  - `SALESPROMPTER_SKIP_AUTH=1`: bypass auth guard (tests/dev only)
60
134
  - `INSTANTLY_API_KEY`: required for real `sync:outreach --target instantly`
@@ -63,17 +137,19 @@ Environment variables:
63
137
 
64
138
  App compatibility:
65
139
 
66
- - If your app exposes `/api/cli/auth/device/start` and `/api/cli/auth/device/poll`, use `salesprompter auth:login`.
140
+ - Current Salesprompter production uses app-issued CLI tokens.
141
+ - If your app exposes `/api/cli/auth/device/start` and `/api/cli/auth/device/poll`, `salesprompter auth:login` will use device flow.
67
142
  - If device auth is not enabled, create a CLI token from the app endpoint `POST /api/cli/auth/token` and use:
68
143
 
69
144
  ```bash
70
- salesprompter auth:login --token "<token-from-app>"
145
+ salesprompter auth:login --token "<token-from-app>" --api-url "https://salesprompter.ai"
71
146
  ```
72
147
 
73
148
  ## Why this shape works for humans and LLMs
74
149
 
75
150
  - Every command reads and writes plain JSON.
76
151
  - Output is machine-readable and composable (`--json` for compact transport).
152
+ - The top-level use cases map ambiguous prompts like "determine the ICP of deel.com" into explicit command paths.
77
153
  - Domain contracts are explicit and validated with `zod`.
78
154
  - External integrations are behind narrow provider interfaces.
79
155
  - Lead generation reports which provider and mode produced the result.
package/dist/auth.js CHANGED
@@ -2,7 +2,7 @@ import os from "node:os";
2
2
  import path from "node:path";
3
3
  import { access, mkdir, readFile, rm, writeFile } from "node:fs/promises";
4
4
  import { z } from "zod";
5
- const DEFAULT_API_BASE_URL = "https://app.salesprompter.com";
5
+ const DEFAULT_API_BASE_URL = "https://salesprompter.ai";
6
6
  const CLIENT_HEADER = "salesprompter-cli/0.2";
7
7
  const DEFAULT_DEVICE_POLL_INTERVAL_SECONDS = 3;
8
8
  const DEFAULT_DEVICE_TIMEOUT_SECONDS = 180;
@@ -94,6 +94,18 @@ function normalizeApiBaseUrl(apiBaseUrl) {
94
94
  const value = (apiBaseUrl ?? process.env.SALESPROMPTER_API_BASE_URL ?? DEFAULT_API_BASE_URL).trim();
95
95
  return value.replace(/\/+$/, "");
96
96
  }
97
+ function isDeviceFlowUnavailableError(message) {
98
+ if (message.includes("invalid JSON response")) {
99
+ return true;
100
+ }
101
+ return /request failed \((401|403|404|405|500|501|502|503|504)\)/.test(message);
102
+ }
103
+ function buildDeviceFlowUnavailableMessage(apiBaseUrl) {
104
+ return [
105
+ "device login is not configured on this Salesprompter app.",
106
+ `Generate a CLI token in the app and run \`salesprompter auth:login --token <token> --api-url "${apiBaseUrl}"\`.`
107
+ ].join(" ");
108
+ }
97
109
  async function hasSessionFile() {
98
110
  try {
99
111
  await access(getSessionPath());
@@ -106,7 +118,18 @@ async function hasSessionFile() {
106
118
  async function httpJson(url, init, schema) {
107
119
  const response = await fetch(url, init);
108
120
  const text = await response.text();
109
- const payload = text.length > 0 ? JSON.parse(text) : {};
121
+ let payload = {};
122
+ if (text.length > 0) {
123
+ try {
124
+ payload = JSON.parse(text);
125
+ }
126
+ catch {
127
+ if (!response.ok) {
128
+ throw new Error(`request failed (${response.status}) for ${url}`);
129
+ }
130
+ throw new Error(`invalid JSON response for ${url}`);
131
+ }
132
+ }
110
133
  if (!response.ok) {
111
134
  throw new Error(`request failed (${response.status}) for ${url}`);
112
135
  }
@@ -195,8 +218,8 @@ export async function loginWithDeviceFlow(options) {
195
218
  }
196
219
  catch (error) {
197
220
  const message = error instanceof Error ? error.message : String(error);
198
- if (message.includes("(404)")) {
199
- throw new Error("device login is not configured on this Salesprompter app. Generate a CLI token in the app and run `salesprompter auth:login --token <token>`.");
221
+ if (isDeviceFlowUnavailableError(message)) {
222
+ throw new Error(buildDeviceFlowUnavailableMessage(apiBaseUrl));
200
223
  }
201
224
  throw error;
202
225
  }
package/dist/cli.js CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { createRequire } from "node:module";
2
3
  import { Command } from "commander";
3
4
  import { z } from "zod";
4
5
  import { clearAuthSession, loginWithDeviceFlow, loginWithToken, requireAuthSession, shouldBypassAuth, verifySession } from "./auth.js";
@@ -11,6 +12,8 @@ import { buildHistoricalVendorIcp, buildVendorIcp } from "./icp-templates.js";
11
12
  import { InstantlySyncProvider } from "./instantly.js";
12
13
  import { buildLeadlistsFunnelQueries } from "./leadlists-funnel.js";
13
14
  import { readJsonFile, splitCsv, writeJsonFile, writeTextFile } from "./io.js";
15
+ const require = createRequire(import.meta.url);
16
+ const { version: packageVersion } = require("../package.json");
14
17
  const program = new Command();
15
18
  const leadProvider = new AccountLeadProvider(new HeuristicCompanyProvider(), new HeuristicPeopleSearchProvider());
16
19
  const enrichmentProvider = new HeuristicEnrichmentProvider();
@@ -166,14 +169,14 @@ async function fetchHistoricalQueryRows(tables) {
166
169
  program
167
170
  .name("salesprompter")
168
171
  .description("Sales workflow CLI for ICP definition, lead generation, enrichment, scoring, and sync.")
169
- .version("0.1.1")
172
+ .version(packageVersion)
170
173
  .option("--json", "Emit compact machine-readable JSON output", false)
171
174
  .option("--quiet", "Suppress successful stdout output", false);
172
175
  program
173
176
  .command("auth:login")
174
- .description("Authenticate CLI with Salesprompter app credentials.")
177
+ .description("Authenticate CLI with a Salesprompter app token, or device flow if the app supports it.")
175
178
  .option("--token <token>", "App-issued bearer token for direct login")
176
- .option("--api-url <url>", "Salesprompter API base URL, defaults to SALESPROMPTER_API_BASE_URL or app.salesprompter.com")
179
+ .option("--api-url <url>", "Salesprompter API base URL, defaults to SALESPROMPTER_API_BASE_URL or salesprompter.ai")
177
180
  .option("--timeout-seconds <number>", "Device flow wait timeout in seconds", "180")
178
181
  .action(async (options) => {
179
182
  const timeoutSeconds = z.coerce.number().int().min(30).max(1800).parse(options.timeoutSeconds);
@@ -190,7 +193,9 @@ program
190
193
  return;
191
194
  }
192
195
  const startedAt = new Date().toISOString();
193
- process.stderr.write("Starting device login flow. Complete login in the browser.\n");
196
+ if (!runtimeOutputOptions.json && !runtimeOutputOptions.quiet) {
197
+ process.stderr.write("Starting device login flow. Complete login in the browser.\n");
198
+ }
194
199
  const result = await loginWithDeviceFlow({
195
200
  apiBaseUrl: options.apiUrl,
196
201
  timeoutSeconds
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "salesprompter-cli",
3
- "version": "0.1.2",
4
- "description": "CLI for defining ICPs, generating leads, enriching them, scoring them, and syncing to GTM tools.",
3
+ "version": "0.1.4",
4
+ "description": "JSON-first sales prospecting CLI for ICP definition, lead generation, enrichment, scoring, and CRM/outreach sync.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "salesprompter": "dist/cli.js"
@@ -13,16 +13,39 @@
13
13
  "scripts": {
14
14
  "build": "tsc -p tsconfig.json",
15
15
  "check": "tsc --noEmit -p tsconfig.json",
16
+ "docs:dev": "mint dev",
17
+ "docs:broken-links": "mint broken-links",
18
+ "docs:a11y": "mint a11y",
16
19
  "start": "node ./dist/cli.js",
17
20
  "test": "npm run build && tsc -p tsconfig.test.json && node --test dist-tests/tests/**/*.test.js"
18
21
  },
19
22
  "keywords": [
20
23
  "sales",
24
+ "salesprompter",
21
25
  "cli",
26
+ "icp",
27
+ "ideal-customer-profile",
28
+ "prospecting",
22
29
  "lead-generation",
30
+ "lead-enrichment",
31
+ "lead-scoring",
32
+ "sales-intelligence",
23
33
  "crm",
24
- "outreach"
34
+ "outreach",
35
+ "instantly",
36
+ "hubspot",
37
+ "llm",
38
+ "ai-agent",
39
+ "codex"
25
40
  ],
41
+ "homepage": "https://salesprompter.ai/docs",
42
+ "repository": {
43
+ "type": "git",
44
+ "url": "git+https://github.com/danielsinewe/salesprompter-cli.git"
45
+ },
46
+ "bugs": {
47
+ "url": "https://github.com/danielsinewe/salesprompter-cli/issues"
48
+ },
26
49
  "license": "MIT",
27
50
  "dependencies": {
28
51
  "commander": "^14.0.1",
@@ -30,6 +53,7 @@
30
53
  },
31
54
  "devDependencies": {
32
55
  "@types/node": "^24.3.0",
56
+ "mint": "^4.2.420",
33
57
  "typescript": "^5.9.2"
34
58
  }
35
59
  }