overloop-cli
Advanced tools
+70
-2
@@ -172,2 +172,5 @@ #!/usr/bin/env node | ||
| } | ||
| async bulkCreateEnrollments(campaignId, data) { | ||
| return this.request(`/campaigns/${campaignId}/enrollments/bulk`, { method: "POST", body: JSON.stringify(data) }); | ||
| } | ||
| // -- Step Types -- | ||
@@ -202,2 +205,5 @@ async listStepTypes() { | ||
| } | ||
| async estimateSourcing(data) { | ||
| return this.request("/sourcings/estimate", { method: "POST", body: JSON.stringify(data) }); | ||
| } | ||
| async getSourcingSearchOptions(params = {}) { | ||
@@ -691,2 +697,5 @@ return this.request(`/sourcings/search_options${this.buildQuery(params)}`); | ||
| if (args["sender-id"]) body.sender_id = args["sender-id"]; | ||
| if (args["sourcing-id"]) body.sourcing_id = args["sourcing-id"]; | ||
| if (args["auto-enroll"]) body.only_allow_manual_enrollment = false; | ||
| if (args["auto-reenroll"] !== void 0) body.automatically_reenroll = args["auto-reenroll"]; | ||
| if (args.steps) { | ||
@@ -725,2 +734,7 @@ try { | ||
| if (args.status) body.status = args.status; | ||
| if (args["sourcing-id"]) body.sourcing_id = args["sourcing-id"]; | ||
| if (args["auto-enroll"]) body.only_allow_manual_enrollment = false; | ||
| if (args["no-auto-enroll"]) body.only_allow_manual_enrollment = true; | ||
| if (args["auto-reenroll"] !== void 0) body.automatically_reenroll = args["auto-reenroll"]; | ||
| if (args["no-auto-reenroll"]) body.automatically_reenroll = false; | ||
| try { | ||
@@ -901,2 +915,25 @@ const result = await api.updateCampaign(args.id, body); | ||
| } | ||
| async function bulkCreateEnrollments(args) { | ||
| const api = new OverloopAPI(getConfig()); | ||
| if (!args.prospects) { | ||
| console.error("--prospects is required (comma-separated IDs)."); | ||
| process.exit(1); | ||
| } | ||
| const prospectIds = args.prospects.split(",").map((id) => id.trim()).filter(Boolean); | ||
| if (prospectIds.length === 0) { | ||
| console.error("No prospect IDs provided."); | ||
| process.exit(1); | ||
| } | ||
| const body = { prospect_ids: prospectIds }; | ||
| if (args["step-id"]) body.step_id = args["step-id"]; | ||
| if (args.reenroll !== void 0) body.reenroll = args.reenroll; | ||
| if (args["start-at"]) body.start_at = args["start-at"]; | ||
| try { | ||
| const result = await api.bulkCreateEnrollments(args.campaign, body); | ||
| console.log(JSON.stringify(result, null, 2)); | ||
| } catch (error) { | ||
| console.error("Failed to bulk enroll:", error.message); | ||
| process.exit(1); | ||
| } | ||
| } | ||
| async function deleteEnrollment(args) { | ||
@@ -1079,2 +1116,23 @@ const api = new OverloopAPI(getConfig()); | ||
| } | ||
| async function estimateSourcing(args) { | ||
| const api = new OverloopAPI(getConfig()); | ||
| if (!args["search-criteria"]) { | ||
| console.error("--search-criteria is required."); | ||
| process.exit(1); | ||
| } | ||
| let searchCriteria; | ||
| try { | ||
| searchCriteria = JSON.parse(args["search-criteria"]); | ||
| } catch { | ||
| console.error("Failed to parse --search-criteria JSON:", args["search-criteria"]); | ||
| process.exit(1); | ||
| } | ||
| try { | ||
| const result = await api.estimateSourcing({ search_criteria: searchCriteria }); | ||
| console.log(JSON.stringify(result, null, 2)); | ||
| } catch (error) { | ||
| console.error("Failed to estimate sourcing:", error.message); | ||
| process.exit(1); | ||
| } | ||
| } | ||
| async function searchOptions(args) { | ||
@@ -1418,3 +1476,3 @@ const api = new OverloopAPI(getConfig()); | ||
| "Create a campaign", | ||
| (y) => dataOption(y).option("name", { describe: "Campaign name", type: "string" }).option("timezone", { describe: "Timezone", type: "string" }).option("sender-id", { describe: "Sender user ID", type: "string" }).option("steps", { describe: "Inline steps as JSON array", type: "string" }), | ||
| (y) => dataOption(y).option("name", { describe: "Campaign name", type: "string" }).option("timezone", { describe: "Timezone", type: "string" }).option("sender-id", { describe: "Sender user ID", type: "string" }).option("sourcing-id", { describe: "Link an existing sourcing by ID", type: "string" }).option("auto-enroll", { describe: "Enable automatic enrollment", type: "boolean" }).option("auto-reenroll", { describe: "Enable automatic re-enrollment", type: "boolean" }).option("steps", { describe: "Inline steps as JSON array", type: "string" }), | ||
| createCampaign | ||
@@ -1424,3 +1482,3 @@ ).command( | ||
| "Update a campaign", | ||
| (y) => dataOption(y.positional("id", { describe: "Campaign ID", type: "string" })).option("name", { describe: "Campaign name", type: "string" }).option("status", { describe: "Campaign status (on/off)", type: "string" }), | ||
| (y) => dataOption(y.positional("id", { describe: "Campaign ID", type: "string" })).option("name", { describe: "Campaign name", type: "string" }).option("status", { describe: "Campaign status (on/off)", type: "string" }).option("sourcing-id", { describe: "Link an existing sourcing by ID", type: "string" }).option("auto-enroll", { describe: "Enable automatic enrollment", type: "boolean" }).option("no-auto-enroll", { describe: "Disable automatic enrollment", type: "boolean" }).option("auto-reenroll", { describe: "Enable automatic re-enrollment", type: "boolean" }).option("no-auto-reenroll", { describe: "Disable automatic re-enrollment", type: "boolean" }), | ||
| updateCampaign | ||
@@ -1473,2 +1531,7 @@ ).command( | ||
| ).command( | ||
| "enrollments:bulk", | ||
| "Bulk enroll prospects into a campaign", | ||
| (y) => campaignOption(y).option("prospects", { describe: "Comma-separated prospect IDs", type: "string", demandOption: true }).option("step-id", { describe: "Start at specific step ID", type: "string" }).option("reenroll", { describe: "Re-enroll if already enrolled", type: "boolean" }).option("start-at", { describe: "Schedule enrollment (ISO 8601)", type: "string" }), | ||
| bulkCreateEnrollments | ||
| ).command( | ||
| "enrollments:delete <id>", | ||
@@ -1514,2 +1577,7 @@ "Disenroll a prospect from a campaign", | ||
| ).command( | ||
| "sourcings:estimate", | ||
| "Estimate prospect match count without creating a sourcing", | ||
| (y) => y.option("search-criteria", { describe: "Search criteria as JSON string", type: "string", demandOption: true }), | ||
| estimateSourcing | ||
| ).command( | ||
| "sourcings:search-options", | ||
@@ -1516,0 +1584,0 @@ "Get available search criteria options", |
+1
-1
| { | ||
| "name": "overloop-cli", | ||
| "version": "1.0.0", | ||
| "version": "1.1.0", | ||
| "description": "Overloop CLI - Command line interface for the Overloop sales automation API v2. Manage prospects, campaigns, sourcings, and more from the terminal or AI agents.", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
+14
-4
| # Overloop CLI | ||
| npm License: MIT | ||
| [](https://www.npmjs.com/package/overloop-cli) [](https://opensource.org/licenses/MIT) | ||
| > ⚠️ **Beta Notice:** This CLI is currently in beta. APIs and tool interfaces may change between versions. Please report any issues on [GitHub](https://github.com/sortlist/overloop-cli/issues). | ||
| **Sales automation CLI for developers and AI agents** — Manage prospects, campaigns, sourcings, and more from the terminal. | ||
@@ -92,4 +94,7 @@ | ||
| overloop campaigns:create --name "Q1 Outreach" --timezone "Etc/UTC" | ||
| overloop campaigns:create --name "Q1" --auto-enroll --sourcing-id <id> # auto-enroll sourced prospects | ||
| overloop campaigns:create --data '{"name":"Q1 Outreach","steps":[{"type":"delay","config":{"days_delay":5}}]}' | ||
| overloop campaigns:update <id> --status on | ||
| overloop campaigns:update <id> --auto-enroll # enable auto-enrollment | ||
| overloop campaigns:update <id> --no-auto-enroll # switch back to manual | ||
| overloop campaigns:delete <id> | ||
@@ -115,2 +120,3 @@ ``` | ||
| overloop enrollments:create --campaign <id> --prospect <prospect_id> --reenroll | ||
| overloop enrollments:bulk --campaign <id> --prospects "id1,id2,id3" # bulk enroll up to 100 | ||
| overloop enrollments:delete <enrollment_id> --campaign <id> | ||
@@ -136,2 +142,3 @@ ``` | ||
| overloop sourcings:clone <id> | ||
| overloop sourcings:estimate --search-criteria '{"job_titles":["CEO"]}' # Preview match count | ||
| overloop sourcings:search-options # Get all available search criteria | ||
@@ -230,6 +237,9 @@ overloop sourcings:search-options --field locations --q "Bel" # Search specific field options | ||
| # 2. Create a sourcing | ||
| overloop sourcings:create --name "Belgian Sales" --search-criteria '{"keywords":"sales","locations":["Belgium"],"company_size":["1-10"]}' | ||
| # 2. Estimate match count before creating (no credits used) | ||
| overloop sourcings:estimate --search-criteria '{"job_titles":["Sales"],"locations":[{"id":22,"name":"Belgium","type":"Country"}]}' | ||
| # 3. Start sourcing | ||
| # 3. Create a sourcing | ||
| overloop sourcings:create --name "Belgian Sales" --search-criteria '{"job_titles":["Sales"],"locations":[{"id":22,"name":"Belgium","type":"Country"}],"company_sizes":["1-10 employees"]}' | ||
| # 4. Start sourcing | ||
| overloop sourcings:start <id> | ||
@@ -236,0 +246,0 @@ ``` |
+143
-20
@@ -0,1 +1,6 @@ | ||
| --- | ||
| name: overloop-cli | ||
| description: Overloop CLI skill — manage prospects, campaigns, sourcings, and outreach via the Overloop API v2 from the terminal. | ||
| --- | ||
| # Overloop CLI Skill | ||
@@ -77,5 +82,8 @@ | ||
| overloop campaigns:create --name "Q1 Outreach" [--timezone "Etc/UTC"] [--sender-id ID] | ||
| overloop campaigns:create --name "Q1" --auto-enroll --sourcing-id <id> # auto-enroll sourced prospects | ||
| overloop campaigns:create --name "Q1" --auto-enroll --auto-reenroll # auto-enroll + re-enroll | ||
| overloop campaigns:create --data '{"name":"Q1","steps":[{"type":"delay","config":{"days_delay":5}},{"type":"email","config":{"subject":"Hi","content":"Hello"}}]}' | ||
| overloop campaigns:update <id> --status on | ||
| overloop campaigns:update <id> --name "Updated Name" | ||
| overloop campaigns:update <id> --auto-enroll # enable auto-enrollment | ||
| overloop campaigns:update <id> --no-auto-enroll # disable auto-enrollment | ||
| overloop campaigns:delete <id> | ||
@@ -105,2 +113,3 @@ ``` | ||
| overloop enrollments:create --campaign <id> --prospect <prospect_id> --reenroll --start-at "2026-04-01T09:00:00Z" | ||
| overloop enrollments:bulk --campaign <id> --prospects "id1,id2,id3" # bulk enroll up to 100 | ||
| overloop enrollments:delete <enrollment_id> --campaign <id> | ||
@@ -120,4 +129,4 @@ ``` | ||
| overloop sourcings:get <id> | ||
| overloop sourcings:create --name "Sales Belgium" --search-criteria '{"keywords":"sales","locations":["Belgium"],"company_size":["1-10"]}' | ||
| overloop sourcings:create --data '{"name":"DevOps EU","search_criteria":{"keywords":"devops","locations":["France","Germany"]},"sourcing_limit":100}' | ||
| overloop sourcings:create --name "Sales Belgium" --search-criteria '{"job_titles":["sales"],"locations":[{"id":22,"name":"Belgium","type":"Country"}],"size":["1-10 employees"]}' | ||
| overloop sourcings:create --data '{"name":"DevOps EU","search_criteria":{"job_titles":["devops"],"locations":[{"id":75,"name":"France","type":"Country"},{"id":56,"name":"Germany","type":"Country"}]},"sourcing_limit":100}' | ||
| overloop sourcings:update <id> --name "Updated" --sourcing-limit 200 | ||
@@ -130,4 +139,17 @@ overloop sourcings:delete <id> | ||
| ### Estimate Prospect Match Count | ||
| Preview how many prospects match search criteria **before** creating a sourcing (no credits consumed): | ||
| ```bash | ||
| overloop sourcings:estimate --search-criteria '{"job_titles":["CEO"],"locations":[{"id":22,"name":"Belgium","type":"Country"}],"company_sizes":["1-10 employees"]}' | ||
| # Returns: { estimated_count: 2450, estimated_count_after_rejection: 1837, preview: [...] } | ||
| ``` | ||
| Use this to validate criteria and avoid wasted iterations. The `preview` array contains up to 5 sample prospect profiles. | ||
| ### Sourcing Search Options | ||
| **Important:** `locations` and `industries` must be objects (not plain strings). Use `search-options` to find valid values with their IDs. | ||
| Discover available values for sourcing search criteria fields: | ||
@@ -188,34 +210,135 @@ | ||
| ## search_criteria Format Reference | ||
| ### Locations — MUST be objects | ||
| Locations must be objects with `id`, `name`, and `type` fields. **Plain strings silently match nothing.** | ||
| ``` | ||
| Correct: {"id": 22, "name": "Belgium", "type": "Country"} | ||
| Wrong: "Belgium" ← silently matches nothing | ||
| Wrong: {"name": "Belgium"} ← missing id and type, rejected | ||
| ``` | ||
| Valid `type` values: `Region`, `Country`, `State`, `City`. | ||
| Always look up locations first: | ||
| ```bash | ||
| overloop sourcings:search-options --field locations --q "Belgium" | ||
| # Returns: [{"id": 22, "name": "Belgium", "type": "Country"}, {"id": 1376, "name": "Brussels-Capital Region", "type": "State"}, ...] | ||
| ``` | ||
| ### Industries — MUST use API names, not LinkedIn names | ||
| Industries must be objects with `id` and `name`. The API uses its own industry names, which differ from LinkedIn names. | ||
| ``` | ||
| Correct: {"id": 575, "name": "Information Technology"} | ||
| Wrong: "Information Technology and Services" ← LinkedIn name, matches nothing | ||
| Wrong: {"name": "Information Technology"} ← missing id, rejected | ||
| ``` | ||
| Common LinkedIn → API name mappings: | ||
| | LinkedIn name | API name | ID | | ||
| |---|---|---| | ||
| | Information Technology and Services | Information Technology | 575 | | ||
| | Financial Services | Accounting & Financial Services | 541 | | ||
| | Management Consulting | Business Consulting | 552 | | ||
| | Computer Software | Software Development | 4 | | ||
| | Internet | Internet & Web Services | 577 | | ||
| | Marketing and Advertising | Marketing & Advertising | 1 | | ||
| | Telecommunications | Telecommunications | 614 | | ||
| | Banking | Banking & Lending | 547 | | ||
| Always look up industries: | ||
| ```bash | ||
| overloop sourcings:search-options --field industries --q "Information" | ||
| # Returns: [{"id": 575, "name": "Information Technology", "alternates": ["Information Technology and Services"]}, ...] | ||
| ``` | ||
| ### Other search_criteria fields | ||
| | Field | Format | Lookup | | ||
| |---|---|---| | ||
| | `job_titles` | `["CEO", "CTO"]` (free text) | No lookup needed | | ||
| | `company_sizes` | `["1-10 employees"]` | `search-options --field company_sizes` | | ||
| | `management_level` | `["C-Level", "Director"]` | `search-options --field management_levels` | | ||
| | `departments` | `["Sales", "Marketing"]` | `search-options --field departments` | | ||
| | `prospect_keywords` | `["saas", "ai"]` (free text) | No lookup needed | | ||
| | `technologies` | `["React", "Python"]` | `search-options --field technologies` | | ||
| ## Message Personalization Settings | ||
| When creating or updating campaigns, you can set `message_personalization_settings` and `pitch_settings` to control AI-generated messages. | ||
| ### message_personalization_settings | ||
| | Field | Accepted values | Default | | ||
| |---|---|---| | ||
| | `language` | `english (United States)`, `english (United Kingdom)`, `french`, `spanish`, `german`, `dutch`, `portuguese (Brazil)`, `portuguese (Portugal)`, `danish`, `finnish`, `swedish`, `italian`, `norwegian`, `romanian`, `hebrew`, `turkish`, `polish` | `english (United States)` | | ||
| | `formality` | `formal`, `friendly`, `neutral` | `friendly` | | ||
| | `tone_of_voice` | `confident`, `persuasive`, `witty`, `straightforward`, `empathetic` | `persuasive` | | ||
| | `length` | `short`, `medium`, `long` | `short` | | ||
| ### pitch_settings | ||
| | Field | Description | | ||
| |---|---| | ||
| | `website_url` | Your company website | | ||
| | `selling_description` | What you sell / your value proposition | | ||
| | `pain_points` | Problems your product solves | | ||
| | `benefits` | Key benefits for the prospect | | ||
| | `proof_points` | Social proof, case studies, numbers | | ||
| | `campaign_intent` | What you want from the prospect (e.g. "Book a demo") | | ||
| ## Common Workflows | ||
| ### Create a full campaign with steps | ||
| ### End-to-end: source prospects → create campaign → enroll → activate | ||
| ```bash | ||
| # 1. Create campaign | ||
| overloop campaigns:create --name "Q1 Cold Outreach" --timezone "Europe/Brussels" | ||
| # 1. Look up location and industry IDs | ||
| overloop sourcings:search-options --field locations --q "Belgium" | ||
| overloop sourcings:search-options --field industries --q "Software" | ||
| # 2. Add a delay step | ||
| overloop steps:create --campaign <campaign_id> --type delay --config '{"days_delay":1}' | ||
| # 2. Estimate match count (no credits consumed) | ||
| overloop sourcings:estimate --search-criteria '{"job_titles":["CTO","VP Engineering"],"locations":[{"id":22,"name":"Belgium","type":"Country"}],"industries":[{"id":4,"name":"Software Development"}],"company_sizes":["11-50 employees","51-200 employees"]}' | ||
| # 3. Add an email step | ||
| overloop steps:create --campaign <campaign_id> --type email --config '{"subject":"Quick question","content":"Hi {{first_name}},\n\nWould love to chat about...\n\nBest"}' | ||
| # 3. Create the sourcing | ||
| overloop sourcings:create --name "Belgian Tech CTOs" --search-criteria '{"job_titles":["CTO","VP Engineering"],"locations":[{"id":22,"name":"Belgium","type":"Country"}],"industries":[{"id":4,"name":"Software Development"}],"company_sizes":["11-50 employees","51-200 employees"]}' --sourcing-limit 200 | ||
| # 4. Enroll prospects | ||
| overloop enrollments:create --campaign <campaign_id> --prospect <prospect_id> | ||
| # 4. Create campaign with auto-enrollment linked to the sourcing | ||
| overloop campaigns:create --name "Q1 Tech Outreach" --timezone "Europe/Brussels" --auto-enroll --sourcing-id <sourcing_id> | ||
| # 5. Activate | ||
| # 5. Add steps to the campaign | ||
| overloop steps:create --campaign <campaign_id> --type delay --config '{"days_delay":2}' | ||
| overloop steps:create --campaign <campaign_id> --type email --config '{"subject":"Quick question about {{company_name}}","content":"Hi {{first_name}},\n\nI noticed {{company_name}} is growing fast...","generate_with_ai":true}' | ||
| overloop steps:create --campaign <campaign_id> --type delay --config '{"days_delay":3}' | ||
| overloop steps:create --campaign <campaign_id> --type email --config '{"subject":"Following up","content":"Hi {{first_name}}, just wanted to follow up...","generate_with_ai":true}' | ||
| # 6. Start the sourcing (prospects will auto-enroll into the campaign) | ||
| overloop sourcings:start <sourcing_id> | ||
| # 7. Activate the campaign | ||
| overloop campaigns:update <campaign_id> --status on | ||
| ``` | ||
| ### Source prospects and enroll | ||
| ### Manual enrollment flow | ||
| ```bash | ||
| # Check search options | ||
| overloop sourcings:search-options --field locations --q "Belgium" | ||
| # 1. Create campaign | ||
| overloop campaigns:create --name "Q1 Cold Outreach" --timezone "Europe/Brussels" | ||
| # Create sourcing | ||
| overloop sourcings:create --name "Belgian CTOs" --search-criteria '{"keywords":"CTO","locations":["Belgium"],"company_size":["11-50","51-200"]}' | ||
| # 2. Add steps | ||
| overloop steps:create --campaign <campaign_id> --type delay --config '{"days_delay":1}' | ||
| overloop steps:create --campaign <campaign_id> --type email --config '{"subject":"Quick question","content":"Hi {{first_name}},\n\nWould love to chat about...\n\nBest"}' | ||
| # Start it | ||
| overloop sourcings:start <id> | ||
| # 3. Enroll prospects (single or bulk) | ||
| overloop enrollments:create --campaign <campaign_id> --prospect <prospect_id> | ||
| overloop enrollments:bulk --campaign <campaign_id> --prospects "id1,id2,id3" | ||
| # 4. Activate | ||
| overloop campaigns:update <campaign_id> --status on | ||
| ``` | ||
@@ -222,0 +345,0 @@ |
Sorry, the diff of this file is too big to display
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
192628
10.68%1624
4.64%310
3.33%