@sellable/install 0.1.284 → 0.1.286

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
@@ -100,6 +100,7 @@ Use the same public entrypoints in both hosts:
100
100
  - Claude Code: `/sellable:foundation`
101
101
  - Claude Code: `/sellable:content`
102
102
  - Claude Code: `/sellable:create-post`
103
+ - Claude Code: `/sellable:refresh-sender-engagement`
103
104
  - Claude Code: `/sellable:refill-sends`
104
105
  - Codex: `$sellable:create-campaign`
105
106
  - Codex: `$sellable:create-ab-test`
@@ -107,6 +108,7 @@ Use the same public entrypoints in both hosts:
107
108
  - Codex: `$sellable:foundation`
108
109
  - Codex: `$sellable:content`
109
110
  - Codex: `$sellable:create-post`
111
+ - Codex: `$sellable:refresh-sender-engagement`
110
112
  - Codex: `$sellable:refill-sends`
111
113
  - Codex Desktop plugin: `sellable@sellable`
112
114
  - Codex visible skill: `Sellable Create Campaign`
@@ -115,6 +117,7 @@ Use the same public entrypoints in both hosts:
115
117
  - Codex visible skill: `Sellable Foundation`
116
118
  - Codex visible skill: `Sellable Content`
117
119
  - Codex visible skill: `Sellable Create Post`
120
+ - Codex visible skill: `Sellable Refresh Sender Engagement`
118
121
  - Codex visible skill: `Sellable Refill Sends`
119
122
  - Internal MCP workflow prompt: `create-campaign-v2`
120
123
  - Internal MCP workflow prompt: `refill-sends-workflow`
@@ -190,7 +190,7 @@ Auth:
190
190
  Install is auth-free by default. Sign in happens on the first run of
191
191
  /sellable:create-campaign, /sellable:create-evergreen-campaigns,
192
192
  /sellable:foundation, /sellable:content, /sellable:create-post, or
193
- /sellable:refill-sends in Claude Code or Codex,
193
+ /sellable:refresh-sender-engagement, or /sellable:refill-sends in Claude Code or Codex,
194
194
  where the agent walks you through signup or sign-in and stores credentials
195
195
  in ~/.sellable/config.json.
196
196
 
@@ -220,6 +220,7 @@ function printCreateCommandHint() {
220
220
  { label: "Foundation", command: "/sellable:foundation" },
221
221
  { label: "Content", command: "/sellable:content" },
222
222
  { label: "Post", command: "/sellable:create-post" },
223
+ { label: "Refresh", command: "/sellable:refresh-sender-engagement" },
223
224
  { label: "Refill", command: "/sellable:refill-sends" },
224
225
  ]);
225
226
  console.log("");
@@ -231,6 +232,7 @@ function printCreateCommandHint() {
231
232
  { label: "Foundation", command: "$sellable:foundation" },
232
233
  { label: "Content", command: "$sellable:content" },
233
234
  { label: "Post", command: "$sellable:create-post" },
235
+ { label: "Refresh", command: "$sellable:refresh-sender-engagement" },
234
236
  { label: "Refill", command: "$sellable:refill-sends" },
235
237
  ]);
236
238
  console.log("");
@@ -1094,6 +1096,29 @@ const REFILL_SENDS_ALLOWED_TOOLS = [
1094
1096
  "mcp__sellable__get_sender",
1095
1097
  ];
1096
1098
 
1099
+ const REFRESH_SENDER_ENGAGEMENT_ALLOWED_TOOLS = [
1100
+ "mcp__sellable__get_auth_status",
1101
+ "mcp__sellable__start_cli_login",
1102
+ "mcp__sellable__wait_for_cli_login",
1103
+ "mcp__sellable__get_active_workspace",
1104
+ "mcp__sellable__list_workspaces",
1105
+ "mcp__sellable__set_active_workspace",
1106
+ "mcp__sellable__get_subskill_prompt",
1107
+ "mcp__sellable__search_subskill_prompts",
1108
+ "mcp__sellable__list_senders",
1109
+ "mcp__sellable__get_sender",
1110
+ "mcp__sellable__get_campaigns",
1111
+ "mcp__sellable__get_campaign",
1112
+ "mcp__sellable__get_campaign_context",
1113
+ "mcp__sellable__get_campaign_table_schema",
1114
+ "mcp__sellable__list_tables",
1115
+ "mcp__sellable__get_rows_minimal",
1116
+ "mcp__sellable__fetch_linkedin_posts",
1117
+ "mcp__sellable__select_promising_posts",
1118
+ "mcp__sellable__fetch_post_engagers",
1119
+ "mcp__sellable__add_on_demand_leads",
1120
+ ];
1121
+
1097
1122
  function allowedToolsYaml(tools) {
1098
1123
  return [...new Set(tools)].map((tool) => ` - ${tool}`).join("\n");
1099
1124
  }
@@ -1977,6 +2002,75 @@ then retry \`get_subskill_prompt\`.
1977
2002
  `, host, "refill-sends");
1978
2003
  }
1979
2004
 
2005
+ function refreshSenderEngagementSkillMd(host = "shared") {
2006
+ try {
2007
+ const here = dirname(fileURLToPath(import.meta.url));
2008
+ const templatePath = join(
2009
+ here,
2010
+ "..",
2011
+ "skill-templates",
2012
+ "refresh-sender-engagement.md"
2013
+ );
2014
+ if (existsSync(templatePath)) {
2015
+ return stampInstalledHost(
2016
+ addOrReplaceAllowedTools(
2017
+ readFileSync(templatePath, "utf8"),
2018
+ REFRESH_SENDER_ENGAGEMENT_ALLOWED_TOOLS
2019
+ ),
2020
+ host,
2021
+ "refresh-sender-engagement"
2022
+ );
2023
+ }
2024
+ } catch {
2025
+ // fall through to hardcoded fallback below
2026
+ }
2027
+ return stampInstalledHost(`---
2028
+ name: refresh-sender-engagement
2029
+ description: Refresh sender-owned Post Engagers campaigns by finding active Signal Discovery campaigns, fetching recent sender-authored posts, and adding net-new engagers without sending.
2030
+ visibility: public
2031
+ allowed-tools:
2032
+ ${allowedToolsYaml(REFRESH_SENDER_ENGAGEMENT_ALLOWED_TOOLS)}
2033
+ ---
2034
+
2035
+ # Sellable Refresh Sender Engagement
2036
+
2037
+ Use this as the customer-facing entrypoint for the Sellable
2038
+ \`refresh-sender-engagement\` workflow. It finds active sender-owned Post
2039
+ Engagers / Signal Discovery campaigns, fetches recent sender-authored LinkedIn
2040
+ posts, pulls latest engagers, filters to ICP, and adds net-new leads with
2041
+ dedupe. It never creates messages, approves rows, schedules sends, or launches
2042
+ campaigns.
2043
+
2044
+ ## Bootstrap
2045
+
2046
+ MCP prompt and command access are required. Do not inspect repo files, run shell
2047
+ commands, use \`npm\`, \`node\`, local harness scripts, or read local prompt
2048
+ files to emulate this workflow.
2049
+
2050
+ If the Sellable MCP prompt tools are unavailable, stop and say this is a Codex
2051
+ install/reload problem. Tell the user to run
2052
+ \`curl -fsSL "https://app.sellable.dev/api/v2/cli/install" | sh\`, fully quit and reopen Codex
2053
+ Desktop, then start a new thread.
2054
+
2055
+ ## Execute Workflow
2056
+
2057
+ 1. Call \`mcp__sellable__get_auth_status({})\`.
2058
+ 2. Load the canonical prompt via
2059
+ \`mcp__sellable__get_subskill_prompt({ subskillName: "refresh-sender-engagement" })\`.
2060
+ If the response has \`hasMore=true\`, continue with \`nextOffset\` until
2061
+ \`hasMore=false\`.
2062
+ 3. Follow the canonical prompt exactly. Target active/paused sender-owned Post
2063
+ Engagers campaigns backed by Signal Discovery, and do not touch shared lanes
2064
+ or send-state tools.
2065
+
2066
+ ## MCP Prompt Fallback
2067
+
2068
+ If exact subskill lookup fails, use
2069
+ \`mcp__sellable__search_subskill_prompts({ query: "refresh-sender-engagement", includePublic: true, includeInternal: true })\`,
2070
+ then retry \`get_subskill_prompt\`.
2071
+ `, host, "refresh-sender-engagement");
2072
+ }
2073
+
1980
2074
  function genericSellableSkillMd({ name, title, description, host = "shared" }) {
1981
2075
  return stampInstalledHost(`---
1982
2076
  name: ${name}
@@ -2450,6 +2544,12 @@ function codexPluginSkills() {
2450
2544
  description: "Capture ideas and draft LinkedIn posts in your voice",
2451
2545
  skillMd: createPostSkillMd(),
2452
2546
  },
2547
+ {
2548
+ dir: "sellable-refresh-sender-engagement",
2549
+ displayName: "Sellable Refresh Sender Engagement",
2550
+ description: "Refresh post-engager campaigns from recent sender posts",
2551
+ skillMd: refreshSenderEngagementSkillMd("codex"),
2552
+ },
2453
2553
  {
2454
2554
  dir: "sellable-refill-sends",
2455
2555
  displayName: "Sellable Refill Sends",
@@ -2681,6 +2781,19 @@ function claudeCommands() {
2681
2781
  argumentHint: "[post idea or source material]",
2682
2782
  skillMd: createPostSkillMd(),
2683
2783
  },
2784
+ {
2785
+ name: "refresh-sender-engagement",
2786
+ title: "Refresh Sender Engagement",
2787
+ filename: join("sellable", "refresh-sender-engagement.md"),
2788
+ description:
2789
+ "Refresh sender-owned Post Engagers campaigns from recent sender posts.",
2790
+ argumentHint: "[--sender name-or-id ...] [lookback window]",
2791
+ skillMd: refreshSenderEngagementSkillMd("claude"),
2792
+ allowedTools: [
2793
+ "AskUserQuestion",
2794
+ ...REFRESH_SENDER_ENGAGEMENT_ALLOWED_TOOLS,
2795
+ ],
2796
+ },
2684
2797
  {
2685
2798
  name: "refill-sends",
2686
2799
  title: "Refill Sends",
@@ -3988,6 +4101,7 @@ function printNextSteps(installedHosts, authReused) {
3988
4101
  { label: "Foundation", command: "/sellable:foundation" },
3989
4102
  { label: "Content", command: "/sellable:content" },
3990
4103
  { label: "Post", command: "/sellable:create-post" },
4104
+ { label: "Refresh", command: "/sellable:refresh-sender-engagement" },
3991
4105
  { label: "Refill", command: "/sellable:refill-sends" },
3992
4106
  ]);
3993
4107
  console.log("");
@@ -4000,6 +4114,7 @@ function printNextSteps(installedHosts, authReused) {
4000
4114
  { label: "Foundation", command: "$sellable:foundation" },
4001
4115
  { label: "Content", command: "$sellable:content" },
4002
4116
  { label: "Post", command: "$sellable:create-post" },
4117
+ { label: "Refresh", command: "$sellable:refresh-sender-engagement" },
4003
4118
  { label: "Refill", command: "$sellable:refill-sends" },
4004
4119
  ]);
4005
4120
  console.log("");
@@ -4291,12 +4406,14 @@ async function main() {
4291
4406
  console.log(` Claude Code: /sellable:foundation`);
4292
4407
  console.log(` Claude Code: /sellable:content`);
4293
4408
  console.log(` Claude Code: /sellable:create-post`);
4409
+ console.log(` Claude Code: /sellable:refresh-sender-engagement`);
4294
4410
  console.log(` Claude Code: /sellable:refill-sends`);
4295
4411
  console.log(` Codex: $sellable:create-campaign`);
4296
4412
  console.log(` Codex: $sellable:create-evergreen-campaigns`);
4297
4413
  console.log(` Codex: $sellable:foundation`);
4298
4414
  console.log(` Codex: $sellable:content`);
4299
4415
  console.log(` Codex: $sellable:create-post`);
4416
+ console.log(` Codex: $sellable:refresh-sender-engagement`);
4300
4417
  console.log(` Codex: $sellable:refill-sends`);
4301
4418
  process.exit(0);
4302
4419
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/install",
3
- "version": "0.1.284",
3
+ "version": "0.1.286",
4
4
  "type": "module",
5
5
  "description": "One-command installer for Sellable MCP in Claude Code and Codex",
6
6
  "bin": {
@@ -1358,9 +1358,11 @@ Message, and verify current-revision sample messages before final completion.
1358
1358
  senders, the copy must be safe for every attached sender to send. Do not
1359
1359
  use founder-only first person such as "I'm building", "my company", "my
1360
1360
  team", or "I have a framework" unless every attached sender can credibly
1361
- say it. Prefer sender-agnostic company/team language such as "we're
1362
- helping CX teams..." or "at cxconnect.ai, we help..." and one clear
1363
- problem question.
1361
+ say it. Prefer sender-agnostic company/team language grounded in the
1362
+ current workspace's verified company, offer, buyer, and proof, plus one
1363
+ clear problem question. Do not reuse unrelated fixture/example customer
1364
+ names, domains, verticals, product categories, use cases, or proof points
1365
+ unless the current workspace/company research independently supports them.
1364
1366
  Before Message Drafting runs, the campaign brief must already include
1365
1367
  these shared-lane hard avoids and source-use rules. Do not rely on a
1366
1368
  failed first generation batch to discover that self-intros, generic
@@ -1370,7 +1372,10 @@ Message, and verify current-revision sample messages before final completion.
1370
1372
  Shared Signal Discovery samples may use a supported topic bridge such as
1371
1373
  "saw you around conversations about [high-level topic], so hope this is
1372
1374
  relevant" when the topic is grounded in source evidence and not
1373
- activity-log phrasing. Translate source/tool terms into prospect-facing
1375
+ activity-log phrasing. Signal Discovery is only a lead-source provider;
1376
+ do not infer a product category, buyer pain, offer, asset, CTA, or
1377
+ provider-themed message direction from the lane/provider name.
1378
+ Translate source/tool terms into prospect-facing
1374
1379
  business language; do not put internal workflow vocabulary such as
1375
1380
  "Codex-style workflow", "MCP", "agent workflows",
1376
1381
  "Claude Code", or "Claude-style agent workflows" in customer-facing
@@ -1535,7 +1540,10 @@ Message, and verify current-revision sample messages before final completion.
1535
1540
  `issues`.
1536
1541
  Shared Signal Discovery samples may use `"saw you around conversations
1537
1542
  about [high-level topic], so hope this is relevant"` when the topic is
1538
- supported by source evidence and not activity-log phrasing. Shared Cold
1543
+ supported by source evidence and not activity-log phrasing. Signal
1544
+ Discovery is only a lead-source provider; reject provider-themed campaign
1545
+ copy unless that language is independently supported by the current
1546
+ workspace/company research. Shared Cold
1539
1547
  Fallback samples must still reject source/conversation hedges such as
1540
1548
  `"hope this is relevant"`, `"might be interested"`, or `"saw you in a few
1541
1549
  conversations"`.
@@ -0,0 +1,98 @@
1
+ ---
2
+ name: refresh-sender-engagement
3
+ description: Top up a sender's post-engager pipeline — fetch their recent LinkedIn posts, pull new engagers, filter by headline ICP criteria, and add net-new leads to their post-engagers campaign with dedupe. Schedule-automation friendly ("refresh sender engagement for these people"). Read-only on LinkedIn; never sends.
4
+ visibility: public
5
+ allowed-tools:
6
+ - mcp__sellable__get_auth_status
7
+ - mcp__sellable__start_cli_login
8
+ - mcp__sellable__wait_for_cli_login
9
+ - mcp__sellable__get_active_workspace
10
+ - mcp__sellable__list_workspaces
11
+ - mcp__sellable__set_active_workspace
12
+ - mcp__sellable__get_subskill_prompt
13
+ - mcp__sellable__search_subskill_prompts
14
+ - mcp__sellable__list_senders
15
+ - mcp__sellable__get_sender
16
+ - mcp__sellable__get_campaigns
17
+ - mcp__sellable__get_campaign
18
+ - mcp__sellable__get_campaign_context
19
+ - mcp__sellable__get_campaign_table_schema
20
+ - mcp__sellable__list_tables
21
+ - mcp__sellable__get_rows_minimal
22
+ - mcp__sellable__fetch_linkedin_posts
23
+ - mcp__sellable__select_promising_posts
24
+ - mcp__sellable__fetch_post_engagers
25
+ - mcp__sellable__add_on_demand_leads
26
+ ---
27
+
28
+ # Refresh Sender Engagement
29
+
30
+ <role>
31
+ You are a pipeline supply agent. People who engage with a sender's LinkedIn posts are their warmest prospects; your job is to capture them into the sender's post-engagers campaign before they go cold — with zero duplicates and zero sends.
32
+ </role>
33
+
34
+ <inputs>
35
+ The invoking prompt names the senders ("refresh sender engagement for csreyes92 and thomas"). Resolve each via `list_senders` (match name/handle/LinkedIn URL). With no names given, inspect the active workspace and refresh every connected sender that has an active/paused sender-owned Post Engagers campaign backed by Signal Discovery.
36
+
37
+ Optional: lookback window (default: posts from the last 30 days), engagement sources (default `both` reactions+comments), target sender names/ids, maximum posts per sender (default 5, hard cap 5 unless the user explicitly asks for more), and target campaign ids/names when the user wants to force a specific campaign.
38
+ </inputs>
39
+
40
+ <entrypoint>
41
+ This is a public Sellable command:
42
+
43
+ - Claude Code: `/sellable:refresh-sender-engagement`
44
+ - Codex: `$sellable:refresh-sender-engagement`
45
+
46
+ Use this command when the user asks to refresh recent engagers, top up tracked
47
+ campaign post engagers, pull latest engagers from sender posts, or refill warm
48
+ post-engager source rows. It is not a send-refill command; if the user asks to
49
+ prepare/schedule sends after adding rows, finish this refresh first and then
50
+ suggest `refill-sends`.
51
+ </entrypoint>
52
+
53
+ <objective>
54
+ For each target sender/campaign:
55
+
56
+ 1. **Find active Signal Discovery/Post Engagers campaigns first**:
57
+ - Call `get_auth_status` and confirm the active workspace.
58
+ - Call `get_campaigns` and, when needed, `list_tables`/`get_campaign` to find candidate campaigns.
59
+ - Keep only active or paused campaign-backed sender-owned Post Engagers campaigns. Strong signals include campaign/table names like `<Sender> - Post Engagers`, `sourceProvider:"signal-discovery"`, sender attachment to exactly one sender, and source/list/table readback indicating post engagers.
60
+ - Exclude shared Signal Discovery lanes, Shared Cold Fallback lanes, archived/completed campaigns, non-campaign tables, direct/on-demand-only campaigns, and any campaign attached to multiple senders unless the user explicitly selected it and the readback proves it is sender-owned.
61
+ - If no matching campaign exists for a sender, report "no active Post Engagers Signal Discovery campaign — create one first" and skip; do not silently create campaigns.
62
+ 2. **Resolve the sender and source boundary**:
63
+ - Match each candidate campaign to its sender from `list_senders`/`get_sender`.
64
+ - Use the sender's own LinkedIn profile URL/handle as the only source author boundary.
65
+ - Never scrape third-party authors into a sender-owned Post Engagers campaign.
66
+ 3. **Find relevant sender-authored posts to refresh**:
67
+ - Call `fetch_linkedin_posts({ linkedinUrl: sender profile, limit: 25 })`.
68
+ - Keep original posts authored by that exact sender, not reposts, from the lookback window.
69
+ - Rank posts by recency, engagement count, and fit to the campaign's buyer/problem/topic. Prefer posts likely to attract the target buyer over generic company updates.
70
+ - If the campaign has an existing Signal Discovery/source state that names tracked/selected posts, prefer refreshing those posts when they are still inside the lookback window and relevant; otherwise choose the strongest recent sender-authored posts.
71
+ - When the product flow expects selected posts to be visible, call `select_promising_posts` before scraping.
72
+ 4. **Pull latest engagers**:
73
+ - For the top posts (up to 5 per sender per run), call `fetch_post_engagers({ postUrl, sources })`.
74
+ - Default `sources` to `"both"` unless the user requested reactions-only or comments-only.
75
+ 5. **Filter to ICP** using the campaign's existing headline ICP criteria (from `get_campaign` brief/rubrics/table schema). Judge each engager's headline against those criteria; exclude obvious non-fits, the sender's own colleagues, existing employees, students/job-seekers, competitors, and anyone with no usable headline. When the campaign has no criteria, keep likely decision-makers/operators and exclude weak-fit profiles.
76
+ 6. **Add net-new leads only**:
77
+ - Use `add_on_demand_leads({ tableId, leads, skipDuplicates: true })` with name, headline-derived title, profile URL, and source/post context where the tool accepts it.
78
+ - Dedupe is mandatory. Never disable dedupe on a scheduled run.
79
+ - Do not generate, approve, schedule, or send messages.
80
+ 7. **Report**: campaigns inspected, target campaigns selected, posts scanned, engagers found, ICP-passing, net-new added per sender/campaign. If a sender posted nothing in the window, say "no recent posts — nothing to refresh" (that is a truthful no-op, not a failure).
81
+ </objective>
82
+
83
+ <safety>
84
+ - LinkedIn operations here are read-only fetches plus adding rows to a campaign table. **No messages are generated, approved, or sent by this skill.**
85
+ - Respect workspace boundaries: only add leads to campaigns in the active workspace, and only for senders that belong to it.
86
+ - Respect campaign boundaries: only add engagers to the matched sender-owned Post Engagers campaign/table. Do not mix shared-lane engagers into sender-owned campaigns or sender-owned engagers into shared lanes.
87
+ - Cap provider usage per run: at most 5 posts × `fetch_post_engagers` per sender. If the invoking automation wants more, it must say so explicitly.
88
+ - Never call `start_campaign`, `attach_sequence`, `queue_campaign_cells`, `start_campaign_message_preparation`, approval tools, or any send/schedule tool.
89
+ </safety>
90
+
91
+ <output>
92
+ ```
93
+ Sender Engagement Refresh — {date}
94
+ • csreyes92: 3 recent posts → 142 engagers → 38 ICP-fit → 15 net-new added to "Christian Reyes - Post Engagers"
95
+ • thomas: no posts in last 30 days — nothing to refresh (consider /engage or /create-post to restart supply)
96
+ Follow with fill-send-horizon to prepare messages for the new leads.
97
+ ```
98
+ </output>