@sellable/install 0.1.3 → 0.1.5
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 +2 -1
- package/bin/sellable-install.mjs +238 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -31,6 +31,7 @@ Auth is stored once at:
|
|
|
31
31
|
Claude Code and Codex are configured to launch the same packaged MCP server.
|
|
32
32
|
|
|
33
33
|
For Codex Desktop, the installer also writes a local Sellable plugin bundle into
|
|
34
|
-
`~/.sellable/codex-marketplace
|
|
34
|
+
`~/.sellable/codex-marketplace`, includes the Sellable skill entrypoints, and
|
|
35
|
+
enables it in `~/.codex/config.toml`.
|
|
35
36
|
|
|
36
37
|
If only one host is installed, `--host all` installs the available host and tells you how to add the other one later.
|
package/bin/sellable-install.mjs
CHANGED
|
@@ -9,7 +9,8 @@ import { createInterface } from "node:readline/promises";
|
|
|
9
9
|
const DEFAULT_API_URL = "https://app.sellable.dev";
|
|
10
10
|
const DEFAULT_SERVER_PACKAGE =
|
|
11
11
|
process.env.SELLABLE_MCP_PACKAGE || "@sellable/mcp";
|
|
12
|
-
const CODEX_PLUGIN_VERSION = "0.1.
|
|
12
|
+
const CODEX_PLUGIN_VERSION = "0.1.5";
|
|
13
|
+
const INSTALL_PACKAGE_SPEC = `@sellable/install@${CODEX_PLUGIN_VERSION}`;
|
|
13
14
|
|
|
14
15
|
function usage() {
|
|
15
16
|
return `Sellable agent installer
|
|
@@ -177,7 +178,7 @@ async function promptForMissingAuth(opts) {
|
|
|
177
178
|
[
|
|
178
179
|
"Missing Sellable token/workspace id.",
|
|
179
180
|
`Create a token at ${opts.apiUrl}/settings, then rerun:`,
|
|
180
|
-
|
|
181
|
+
` npx -y ${INSTALL_PACKAGE_SPEC} --host all --token <token> --workspace-id <workspace_id>`,
|
|
181
182
|
"",
|
|
182
183
|
"You can also use SELLABLE_TOKEN and SELLABLE_WORKSPACE_ID.",
|
|
183
184
|
].join("\n")
|
|
@@ -331,6 +332,227 @@ function codexPluginMcp(opts) {
|
|
|
331
332
|
};
|
|
332
333
|
}
|
|
333
334
|
|
|
335
|
+
const CREATE_CAMPAIGN_ALLOWED_TOOLS = [
|
|
336
|
+
"mcp__sellable__get_auth_status",
|
|
337
|
+
"mcp__sellable__bootstrap_create_campaign",
|
|
338
|
+
"mcp__sellable__get_subskill_prompt",
|
|
339
|
+
"mcp__sellable__search_subskill_prompts",
|
|
340
|
+
"mcp__sellable__get_provider_prompt",
|
|
341
|
+
"mcp__sellable__get_message_prompt",
|
|
342
|
+
"mcp__sellable__get_active_workspace",
|
|
343
|
+
"mcp__sellable__list_senders",
|
|
344
|
+
"mcp__sellable__get_sender",
|
|
345
|
+
"mcp__sellable__enrich_sender",
|
|
346
|
+
"mcp__sellable__complete_sender_research",
|
|
347
|
+
"mcp__sellable__fetch_linkedin_profile",
|
|
348
|
+
"mcp__sellable__fetch_linkedin_posts",
|
|
349
|
+
"mcp__sellable__get_linkedin_profile",
|
|
350
|
+
"mcp__sellable__fetch_company",
|
|
351
|
+
"mcp__sellable__fetch_company_posts",
|
|
352
|
+
"mcp__sellable__lookup_sales_nav_filter",
|
|
353
|
+
"mcp__sellable__search_sales_nav",
|
|
354
|
+
"mcp__sellable__search_prospeo",
|
|
355
|
+
"mcp__sellable__search_signals",
|
|
356
|
+
"mcp__sellable__fetch_post_engagers",
|
|
357
|
+
"mcp__sellable__enrich_with_prospeo",
|
|
358
|
+
"mcp__sellable__bulk_enrich_with_prospeo",
|
|
359
|
+
"mcp__sellable__save_domain_filters",
|
|
360
|
+
"mcp__sellable__add_rubric_item",
|
|
361
|
+
"mcp__sellable__upsert_rubric",
|
|
362
|
+
"mcp__sellable__set_headline_icp_criteria",
|
|
363
|
+
"mcp__sellable__check_rubric",
|
|
364
|
+
"mcp__sellable__create_campaign",
|
|
365
|
+
"mcp__sellable__save_rubrics",
|
|
366
|
+
"mcp__sellable__wait_for_rubric_results",
|
|
367
|
+
"mcp__sellable__update_campaign_brief",
|
|
368
|
+
"mcp__sellable__update_campaign",
|
|
369
|
+
"mcp__sellable__get_campaign",
|
|
370
|
+
"mcp__sellable__get_campaign_context",
|
|
371
|
+
"mcp__sellable__get_campaign_framework",
|
|
372
|
+
"mcp__sellable__get_campaign_navigation_state",
|
|
373
|
+
"mcp__sellable__confirm_lead_list",
|
|
374
|
+
"mcp__sellable__import_leads",
|
|
375
|
+
"mcp__sellable__wait_for_lead_list_ready",
|
|
376
|
+
"mcp__sellable__wait_for_campaign_table_ready",
|
|
377
|
+
"mcp__sellable__get_rows",
|
|
378
|
+
"mcp__sellable__get_rows_minimal",
|
|
379
|
+
"mcp__sellable__get_table_rows",
|
|
380
|
+
"mcp__sellable__load_csv_linkedin_leads",
|
|
381
|
+
"mcp__sellable__load_csv_domains",
|
|
382
|
+
"mcp__sellable__queue_cells",
|
|
383
|
+
"mcp__sellable__generate_messages",
|
|
384
|
+
"mcp__sellable__get_campaign_messages_preview",
|
|
385
|
+
"mcp__sellable__attach_sequence",
|
|
386
|
+
"mcp__sellable__attach_recommended_sequence",
|
|
387
|
+
"mcp__sellable__start_campaign",
|
|
388
|
+
];
|
|
389
|
+
|
|
390
|
+
function allowedToolsYaml(tools) {
|
|
391
|
+
return tools.map((tool) => ` - ${tool}`).join("\n");
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
function codexSkillOpenAiYaml(displayName, description) {
|
|
395
|
+
return `interface:
|
|
396
|
+
display_name: "${displayName.replaceAll('"', '\\"')}"
|
|
397
|
+
short_description: "${description.replaceAll('"', '\\"')}"
|
|
398
|
+
`;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
function createCampaignSkillMd() {
|
|
402
|
+
return `---
|
|
403
|
+
name: sellable:create-campaign
|
|
404
|
+
description: Create a Sellable campaign through the approval-gated workflow.
|
|
405
|
+
allowed-tools:
|
|
406
|
+
${allowedToolsYaml(CREATE_CAMPAIGN_ALLOWED_TOOLS)}
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
# Sellable Create Campaign
|
|
410
|
+
|
|
411
|
+
Use this as the customer-facing entrypoint for Sellable campaign creation.
|
|
412
|
+
|
|
413
|
+
## Bootstrap
|
|
414
|
+
|
|
415
|
+
MCP tool access is required. First call \`mcp__sellable__get_auth_status({})\`
|
|
416
|
+
directly. If that tool is unavailable, stop and say this is a Codex
|
|
417
|
+
install/reload problem, not a campaign problem. Tell the user to
|
|
418
|
+
run \`npx -y ${INSTALL_PACKAGE_SPEC} --host all\` so the packaged MCP server,
|
|
419
|
+
Codex Desktop plugin, and Sellable skill bundle are installed. If they want a
|
|
420
|
+
CLI verification, tell them to run \`sellable --verify-only --host all\`. After
|
|
421
|
+
that, they must fully quit and reopen Codex Desktop before starting a new
|
|
422
|
+
thread. Do not use \`scripts/mcp/sellable-tool-call.mjs\`, \`npm run\`,
|
|
423
|
+
\`node\`, or any local harness as a fallback for this interactive skill.
|
|
424
|
+
|
|
425
|
+
1. Call \`mcp__sellable__get_auth_status({})\`.
|
|
426
|
+
2. If auth is not OK, stop and show the returned guidance.
|
|
427
|
+
3. Detect optional campaign id in the user request (\`cmp_...\`).
|
|
428
|
+
4. If no campaign id is provided, stay in fresh-create mode and do not call campaign discovery/resume helpers to find one.
|
|
429
|
+
- Do not call \`mcp__sellable__get_campaigns\`.
|
|
430
|
+
- Do not call \`mcp__sellable__get_campaign\` to hunt for IDs.
|
|
431
|
+
- Do not call \`mcp__sellable__create_campaign({ campaignId: ... })\` unless the user supplied that id.
|
|
432
|
+
5. Call \`mcp__sellable__bootstrap_create_campaign({ flowVersion: "v2", campaignId? })\`.
|
|
433
|
+
6. If \`safeToProceed !== true\`, stop and show \`blockingErrors\` + \`nextStep\`.
|
|
434
|
+
|
|
435
|
+
## Execute Workflow
|
|
436
|
+
|
|
437
|
+
1. Load canonical prompt via
|
|
438
|
+
\`mcp__sellable__get_subskill_prompt({ subskillName: "create-campaign-v2" })\`.
|
|
439
|
+
2. Follow that prompt exactly.
|
|
440
|
+
3. For message generation, load the full \`generate-messages\` prompt in the
|
|
441
|
+
same run with chunked
|
|
442
|
+
\`mcp__sellable__get_subskill_prompt({ subskillName: "generate-messages", offset, limit })\`
|
|
443
|
+
calls until \`hasMore\` is false. Do not synthesize
|
|
444
|
+
\`message-validation.md\` from the brief, lead review, or general knowledge.
|
|
445
|
+
4. Treat message quality as the gate before minting. Do not create a campaign,
|
|
446
|
+
show a commit gate, or mint anything until \`message-validation.md\` proves
|
|
447
|
+
the full generate-messages workflow ran and \`message-review.md\` recommends
|
|
448
|
+
\`approve-message\` against the gold-standard rules.
|
|
449
|
+
5. Do not create or mutate the live campaign until the approval gate returns
|
|
450
|
+
\`approve\`.
|
|
451
|
+
6. Do not ask the user to run another command.
|
|
452
|
+
|
|
453
|
+
## Fallback
|
|
454
|
+
|
|
455
|
+
If subskill lookup fails, use
|
|
456
|
+
\`mcp__sellable__search_subskill_prompts({ query: "create-campaign-v2" })\`,
|
|
457
|
+
then retry \`get_subskill_prompt\`.
|
|
458
|
+
`;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
function genericSellableSkillMd({ name, title, description }) {
|
|
462
|
+
return `---
|
|
463
|
+
name: sellable:${name}
|
|
464
|
+
description: ${description}
|
|
465
|
+
allowed-tools:
|
|
466
|
+
- mcp__sellable__get_auth_status
|
|
467
|
+
- mcp__sellable__get_subskill_prompt
|
|
468
|
+
- mcp__sellable__search_subskill_prompts
|
|
469
|
+
---
|
|
470
|
+
|
|
471
|
+
# ${title}
|
|
472
|
+
|
|
473
|
+
Use this as the customer-facing entrypoint for the Sellable \`${name}\` workflow.
|
|
474
|
+
|
|
475
|
+
## Bootstrap
|
|
476
|
+
|
|
477
|
+
MCP tool access is required. First call \`mcp__sellable__get_auth_status({})\`
|
|
478
|
+
directly. Do not inspect repo files, run shell commands, use \`npm\`, \`node\`,
|
|
479
|
+
local harness scripts, or read local prompt files to emulate this workflow.
|
|
480
|
+
|
|
481
|
+
If the Sellable MCP tool is unavailable, stop and say this is a Codex
|
|
482
|
+
install/reload problem. Tell the user to run
|
|
483
|
+
\`npx -y ${INSTALL_PACKAGE_SPEC} --host all\`, fully quit and reopen Codex
|
|
484
|
+
Desktop, then start a new thread.
|
|
485
|
+
|
|
486
|
+
1. Call \`mcp__sellable__get_auth_status({})\`.
|
|
487
|
+
2. If auth is not OK, stop and show the returned guidance.
|
|
488
|
+
|
|
489
|
+
## Execute Workflow
|
|
490
|
+
|
|
491
|
+
1. Load canonical prompt via \`mcp__sellable__get_subskill_prompt({ subskillName: "${name}" })\`.
|
|
492
|
+
2. Follow that prompt exactly.
|
|
493
|
+
|
|
494
|
+
## MCP Prompt Fallback
|
|
495
|
+
|
|
496
|
+
If subskill lookup fails, use \`mcp__sellable__search_subskill_prompts({ query: "${name}" })\`, then retry \`get_subskill_prompt\`.
|
|
497
|
+
`;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
function codexPluginSkills() {
|
|
501
|
+
return [
|
|
502
|
+
{
|
|
503
|
+
dir: "sellable-create-campaign",
|
|
504
|
+
displayName: "Sellable Create Campaign",
|
|
505
|
+
description: "Create a Sellable campaign with approval gates",
|
|
506
|
+
skillMd: createCampaignSkillMd(),
|
|
507
|
+
},
|
|
508
|
+
{
|
|
509
|
+
dir: "sellable-engage",
|
|
510
|
+
displayName: "Sellable Engage",
|
|
511
|
+
description: "Discover posts and draft comments for a comment campaign",
|
|
512
|
+
skillMd: genericSellableSkillMd({
|
|
513
|
+
name: "engage",
|
|
514
|
+
title: "Sellable Engage",
|
|
515
|
+
description:
|
|
516
|
+
"Find high-signal LinkedIn posts and draft thoughtful engagement comments, then load approved comments into the sender's comment campaign.",
|
|
517
|
+
}),
|
|
518
|
+
},
|
|
519
|
+
{
|
|
520
|
+
dir: "sellable-interview",
|
|
521
|
+
displayName: "Sellable Interview",
|
|
522
|
+
description: "Build a commenting style guide and ICP profile",
|
|
523
|
+
skillMd: genericSellableSkillMd({
|
|
524
|
+
name: "interview",
|
|
525
|
+
title: "Sellable Interview",
|
|
526
|
+
description:
|
|
527
|
+
"Voice-first interview to build your commenting style guide and ICP profile.",
|
|
528
|
+
}),
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
dir: "sellable-workflow-sequences",
|
|
532
|
+
displayName: "Sellable Workflow Sequences",
|
|
533
|
+
description: "Create workflow tables and attach outbound sequences",
|
|
534
|
+
skillMd: genericSellableSkillMd({
|
|
535
|
+
name: "workflow-sequences",
|
|
536
|
+
title: "Sellable Workflow Sequences",
|
|
537
|
+
description:
|
|
538
|
+
"Create workflow tables via Sellable MCP, attach outbound sequence templates, and avoid manual sequence-column runCondition mistakes.",
|
|
539
|
+
}),
|
|
540
|
+
},
|
|
541
|
+
];
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
function writeCodexPluginSkills(pluginRoot, opts) {
|
|
545
|
+
for (const skill of codexPluginSkills()) {
|
|
546
|
+
const skillRoot = join(pluginRoot, "skills", skill.dir);
|
|
547
|
+
writeFile(join(skillRoot, "SKILL.md"), skill.skillMd, opts);
|
|
548
|
+
writeFile(
|
|
549
|
+
join(skillRoot, "agents", "openai.yaml"),
|
|
550
|
+
codexSkillOpenAiYaml(skill.displayName, skill.description),
|
|
551
|
+
opts
|
|
552
|
+
);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
|
|
334
556
|
function installCodexDesktopPlugin(opts) {
|
|
335
557
|
const home = codexHome();
|
|
336
558
|
const configPath = join(home, "config.toml");
|
|
@@ -371,6 +593,7 @@ function installCodexDesktopPlugin(opts) {
|
|
|
371
593
|
opts
|
|
372
594
|
);
|
|
373
595
|
writeFile(join(pluginRoot, ".mcp.json"), `${JSON.stringify(mcp, null, 2)}\n`, opts);
|
|
596
|
+
writeCodexPluginSkills(pluginRoot, opts);
|
|
374
597
|
|
|
375
598
|
if (!opts.dryRun) {
|
|
376
599
|
rmSync(cacheRoot, { recursive: true, force: true });
|
|
@@ -381,6 +604,7 @@ function installCodexDesktopPlugin(opts) {
|
|
|
381
604
|
opts
|
|
382
605
|
);
|
|
383
606
|
writeFile(join(pluginCache, ".mcp.json"), `${JSON.stringify(mcp, null, 2)}\n`, opts);
|
|
607
|
+
writeCodexPluginSkills(pluginCache, opts);
|
|
384
608
|
|
|
385
609
|
if (!opts.dryRun) {
|
|
386
610
|
mkdirSync(home, { recursive: true, mode: 0o700 });
|
|
@@ -527,7 +751,19 @@ function verify(opts) {
|
|
|
527
751
|
".codex-plugin",
|
|
528
752
|
"plugin.json"
|
|
529
753
|
);
|
|
754
|
+
const skillPath = join(
|
|
755
|
+
codexHome(),
|
|
756
|
+
"plugins",
|
|
757
|
+
"cache",
|
|
758
|
+
"sellable",
|
|
759
|
+
"sellable",
|
|
760
|
+
CODEX_PLUGIN_VERSION,
|
|
761
|
+
"skills",
|
|
762
|
+
"sellable-create-campaign",
|
|
763
|
+
"SKILL.md"
|
|
764
|
+
);
|
|
530
765
|
console.log(existsSync(pluginPath) ? "Codex Desktop plugin present" : "Codex Desktop plugin missing");
|
|
766
|
+
console.log(existsSync(skillPath) ? "Codex skill bundle present" : "Codex skill bundle missing");
|
|
531
767
|
}
|
|
532
768
|
}
|
|
533
769
|
|