@sellable/install 0.1.285 → 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`
|
package/bin/sellable-install.mjs
CHANGED
|
@@ -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
|
@@ -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>
|