@floomhq/signaldash 0.2.0 → 0.3.0

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/bin/sd.mjs CHANGED
@@ -141,6 +141,21 @@ export async function runMcp(dependencies = {}) {
141
141
  }
142
142
  }
143
143
 
144
+
145
+ export async function cmdSkill(dependencies = {}) {
146
+ const log = dependencies.log || console.log;
147
+ const { mkdirSync: mk, writeFileSync: wf, readFileSync: rf, existsSync: ex } = await import("node:fs");
148
+ const { dirname, join } = await import("node:path");
149
+ const here = dirname(fileURLToPath(import.meta.url));
150
+ const src = join(here, "..", "skills", "signaldash", "SKILL.md");
151
+ if (!ex(src)) { log("skill file not found in package"); process.exitCode = 1; return; }
152
+ const dest = join(homedir(), ".claude", "skills", "signaldash");
153
+ mk(dest, { recursive: true });
154
+ wf(join(dest, "SKILL.md"), rf(src, "utf8"));
155
+ log(`Installed the SignalDash skill to ${dest}/SKILL.md`);
156
+ log("Your agent now knows how to use LinkedIn + WhatsApp safely through SignalDash.");
157
+ }
158
+
144
159
  export async function main(argv = process.argv.slice(2), dependencies = {}) {
145
160
  const [cmd, a, b, c] = argv;
146
161
  const log = dependencies.log || console.log;
@@ -148,7 +163,8 @@ export async function main(argv = process.argv.slice(2), dependencies = {}) {
148
163
  else if (cmd === "connect" && b === "claim") await cmdClaim(a, c, dependencies);
149
164
  else if (cmd === "connect") await cmdConnect(a, dependencies);
150
165
  else if (cmd === "mcp") await runMcp(dependencies);
151
- else log(`SignalDash secure LinkedIn + WhatsApp access for your agent.\n\n signaldash login <invite-code> [--backend URL]\n signaldash connect linkedin|whatsapp\n signaldash connect linkedin|whatsapp claim <account_id>\n signaldash mcp\n\nThe agent reaches channels only through SignalDash. No keys on your machine.`);
166
+ else if (cmd === "skill") await cmdSkill(dependencies);
167
+ else log(`SignalDash — secure LinkedIn + WhatsApp access for your agent.\n\n signaldash login <invite-code> [--backend URL]\n signaldash connect linkedin|whatsapp\n signaldash connect linkedin|whatsapp claim <account_id>\n signaldash mcp\n signaldash skill install the agent skill\n\nThe agent reaches channels only through SignalDash. No keys on your machine.`);
152
168
  }
153
169
 
154
170
  if (
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@floomhq/signaldash",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Secure LinkedIn and WhatsApp MCP access for AI agents",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,68 @@
1
+ ---
2
+ name: signaldash
3
+ description: Give this agent secure access to the user's LinkedIn and WhatsApp — list chats, read threads, and send messages — through SignalDash. Use whenever the user asks to check, read, triage, reply to, or send LinkedIn/WhatsApp messages. Also covers first-time setup.
4
+ ---
5
+
6
+ # SignalDash — LinkedIn + WhatsApp for this agent
7
+
8
+ SignalDash is the gate between you and the user's real messaging accounts. The
9
+ user's channel credentials live on the SignalDash server, never on their machine
10
+ and never in your context. You act through SignalDash tools only.
11
+
12
+ ## Setup (only if the tools are not available yet)
13
+
14
+ The user needs an invite code from Federico, then:
15
+
16
+ ```bash
17
+ npx @floomhq/signaldash login <invite-code>
18
+ npx @floomhq/signaldash connect linkedin # opens a link; user authenticates; auto-detects
19
+ npx @floomhq/signaldash connect whatsapp # same, QR scan from WhatsApp > Linked Devices
20
+ claude mcp add signaldash -- npx -y @floomhq/signaldash mcp
21
+ ```
22
+
23
+ Cursor: add to `.cursor/mcp.json` →
24
+ `{"mcpServers":{"signaldash":{"command":"npx","args":["-y","@floomhq/signaldash","mcp"]}}}`
25
+
26
+ ## Tools
27
+
28
+ | Tool | What it does |
29
+ |---|---|
30
+ | `li_list_chats` | list the user's LinkedIn chats |
31
+ | `li_read_messages` | read a LinkedIn thread (`chat_id`) |
32
+ | `li_send_message` | send a LinkedIn message (`chat_id`, `text`) |
33
+ | `wa_list_chats` | list the user's WhatsApp chats |
34
+ | `wa_read_messages` | read a WhatsApp thread (`chat_id`) |
35
+ | `wa_send_message` | send a WhatsApp message (`chat_id`, `text`) |
36
+
37
+ ## The rules you MUST follow
38
+
39
+ These protect the user's accounts from being restricted or banned, and protect
40
+ them from you sending something wrong. They are not optional.
41
+
42
+ 1. **Never send without the user's explicit approval of the exact recipient and
43
+ exact text.** Draft it, show it, wait. Discussion is not approval.
44
+ 2. **Read the thread before you send.** Always `*_read_messages` on that exact
45
+ chat first: check who it is, what they last said, and whether this was
46
+ already sent. Never send blind. Never double-send.
47
+ 3. **Never bulk.** No mass messaging, no "message everyone who…", no bulk
48
+ profile fetching. LinkedIn restricts accounts for exactly this. Hard ceiling
49
+ is roughly 15-20 LinkedIn sends per day; the server enforces a daily cap and
50
+ spacing, do not try to work around it or parallelize sends.
51
+ 4. **One message at a time, human pace.** Let the server's pacing do its work.
52
+ 5. **Stop on any warning.** A checkpoint, restriction, "unusual activity"
53
+ prompt, 403 or 429 means halt all activity on that account and tell the user.
54
+ Do not retry.
55
+ 6. **Personalize.** Read the thread and write a specific reply. Templated
56
+ identical messages get reported as spam.
57
+
58
+ ## Good vs bad requests
59
+
60
+ Good: "list my unread LinkedIn chats and draft replies for my approval" ·
61
+ "read the thread with Mircea and suggest an answer" · "what came in on WhatsApp
62
+ from people I've spoken to before?"
63
+
64
+ Bad (refuse or push back): "connection-request everyone who liked my post" ·
65
+ "message all my connections about X" · "pull every profile in my network".
66
+
67
+ Rule of thumb: if a human could not plausibly do it by hand in a day, do not do
68
+ it. Account health beats throughput.