slashvibe-mcp 0.8.5 → 0.8.6

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/index.js CHANGED
@@ -241,7 +241,10 @@ async function getPresenceFooter() {
241
241
 
242
242
  // The status line. Counts only — no mood inference, no nudges.
243
243
  const parts = ['vibe'];
244
- if (onlineCount > 0) parts.push(`${onlineCount} online`);
244
+ // "2 online" under a board showing three rows — one of them you — reads as a
245
+ // contradiction, even though both numbers are right. The footer counts the room
246
+ // AROUND you, so it should say so.
247
+ if (onlineCount > 0) parts.push(`${onlineCount} other${onlineCount === 1 ? '' : 's'}`);
245
248
  if (unreadCount > 0) parts.push(`**${unreadCount} unread**`);
246
249
  if (liveCount > 0) parts.push(`${liveCount} live`);
247
250
  let footer = `\n\n────────────────────────\n${parts.join(' · ')}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slashvibe-mcp",
3
- "version": "0.8.5",
3
+ "version": "0.8.6",
4
4
  "mcpName": "io.github.vibecodinginc/vibe",
5
5
  "description": "Presence + messaging for terminal coding agents (Claude Code, Codex, Cursor) \u2014 the /vibe kernel",
6
6
  "main": "index.js",
package/setup.js CHANGED
@@ -39,7 +39,7 @@ const API_BASE = 'https://www.slashvibe.dev';
39
39
  function printBanner() {
40
40
  console.log(`
41
41
  ${colors.green} █░█ █ █▄▄ █▀▀${colors.reset}
42
- ${colors.green} ▀▄▀ █ █▄█ ██▄${colors.reset} ${colors.dim}ship together${colors.reset}
42
+ ${colors.green} ▀▄▀ █ █▄█ ██▄${colors.reset} ${colors.dim}ask here · answer there${colors.reset}
43
43
  ──────────────────────────────────────────────────
44
44
  `);
45
45
  }
package/tools/dm.js CHANGED
@@ -110,10 +110,27 @@ async function handler(args) {
110
110
  origin: origin || 'composed',
111
111
  });
112
112
 
113
- // Check for errors
113
+ // Check for errors.
114
+ //
115
+ // The generic tail — "please try again, check your connection" — used to be appended
116
+ // to EVERY failure, including the ones that already name their own fix. An expired
117
+ // session then read as: run `vibe init`, and also try again, and also check your
118
+ // connection. Three instructions, two of them wrong, at the moment someone's first
119
+ // message failed. docs/ROOM-TONE.md: an error names the fix in the same sentence as
120
+ // the problem — which means not adding a second, contradictory one after it.
121
+ //
122
+ // Errors carrying a specific remedy (auth_expired, not_signed_in, handle_not_found)
123
+ // are shown as-is. Only genuinely unknown failures get the retry hint.
114
124
  if (result && result.error) {
125
+ const REMEDY_CARRYING = new Set([
126
+ 'auth_expired', 'not_signed_in', 'auth_failed',
127
+ 'handle_not_found', 'self_dm', 'storage_error',
128
+ ]);
129
+ const detail = result.message || 'the message did not send.';
115
130
  return {
116
- display: `❌ **Failed to send message**\n\n${result.message}\n\n_Please try again. If the problem persists, check your connection._`
131
+ display: REMEDY_CARRYING.has(result.error)
132
+ ? detail
133
+ : `${detail}\n\n_worth one retry — if it keeps failing, say_ \`vibe doctor\`_._`,
117
134
  };
118
135
  }
119
136
 
package/tools/inbox.js CHANGED
@@ -183,7 +183,7 @@ async function handler(args) {
183
183
  // If there are guest messages but no DMs, show guest messages
184
184
  if (guestSection) {
185
185
  return {
186
- display: guestSection + '📭 No DM threads yet. Say "dm @someone" to start.',
186
+ display: guestSection + '📭 no messages yet — say "dm @someone" to start one.',
187
187
  actions: formatActions(actions.recommendedConnections([]))
188
188
  };
189
189
  }
@@ -197,6 +197,9 @@ async function handler(args) {
197
197
  'All caught up!',
198
198
  'No messages yet.'
199
199
  );
200
+ // NOTE: reachable only with VIBE_EXTRAS — the suggestion block is off by
201
+ // default (private fabric: no proposing strangers). The default empty inbox
202
+ // is the branch below.
200
203
  return {
201
204
  display,
202
205
  actions: recommendations.actions
@@ -206,20 +209,17 @@ async function handler(args) {
206
209
  console.log('[inbox] recommendations error:', e.message);
207
210
  }
208
211
 
209
- // Fallback: Check onboarding status to customize CTA
210
- let cta = 'Say "dm @someone" to start';
211
- try {
212
- const checklist = await store.getChecklistStatus(myHandle);
213
- if (checklist.success && checklist.tasks) {
214
- const repliedToSeth = checklist.tasks.find(t => t.id === 'reply_seth')?.done;
215
- if (!repliedToSeth) {
216
- cta = 'Reply to @vibe to get started!';
217
- }
218
- }
219
- } catch (e) {}
220
-
212
+ // THE FIRST SCREEN A NEW INVITEE SEES. Designed, not apologised for: an empty
213
+ // room should say what to do next in the same breath as being empty.
214
+ //
215
+ // The old copy pointed at "@vibe" — a system account — as the thing to reply to.
216
+ // Under docs/PRIVATE-FABRIC.md you are here because a PERSON invited you, and the
217
+ // useful first move is answering them, not a bot.
221
218
  return {
222
- display: `📭 No messages yet. ${cta}`,
219
+ display:
220
+ '📭 no messages yet.\n\n' +
221
+ '_whoever invited you is the place to start:_ `dm @them`\n' +
222
+ "_they'll get it in their next session — neither of you has to be online._",
223
223
  actions: formatActions(actions.recommendedConnections([]))
224
224
  };
225
225
  }
@@ -284,10 +284,15 @@ async function handler(args) {
284
284
  console.log('[inbox] recommendations error:', e.message);
285
285
  }
286
286
 
287
- // Fallback: show recent threads
288
- const recentHandles = sorted.slice(0, 3).map(t => `@${t.handle}`).join(', ');
287
+ // Caught up, WITH history — a different state from "you just arrived", and they
288
+ // were rendering as the same sentence. "Recent: @a, @b, @c" also named the
289
+ // handles without saying what they were: recent conversations, recent arrivals,
290
+ // or a suggestion? Naming the relationship costs three words.
291
+ const recentHandles = sorted.slice(0, 3).map((th) => `@${th.handle}`).join(', ');
289
292
  return {
290
- display: `📭 All caught up! Recent: ${recentHandles}`,
293
+ display: recentHandles
294
+ ? `📭 nothing unread.\n\n_your recent threads:_ ${recentHandles}\n_open one with_ \`vibe inbox @handle\``
295
+ : '📭 nothing unread.',
291
296
  actions: formatActions(actions.recommendedConnections([]))
292
297
  };
293
298
  }
package/tools/init.js CHANGED
@@ -59,7 +59,7 @@ function generatePreAuthBanner(presence) {
59
59
  const label = formatPresenceLabel(presence);
60
60
  const onlineText = label ? `🟢 ${label}` : '🟢 join the crew';
61
61
  return `
62
- █░█ █ █▄▄ █▀▀ 🚀 ship together
62
+ █░█ █ █▄▄ █▀▀ ask here · answer there
63
63
  ▀▄▀ █ █▄█ ██▄ ${onlineText}
64
64
  ──────────────────────────────────────────────────
65
65
  `;
@@ -75,7 +75,7 @@ function generateAuthBanner(handle, unreadCount, presence) {
75
75
  const unreadCol = unreadCount > 0 ? `📬 ${unreadCount} unread`.padEnd(14) : `📬 0 messages`.padEnd(14);
76
76
  const onlineText = formatPresenceLabel(presence) || 'just you so far';
77
77
 
78
- return ` █░█ █ █▄▄ █▀▀ ${handleCol} 🚀 ship together
78
+ return ` █░█ █ █▄▄ █▀▀ ${handleCol} ask here · answer there
79
79
  ▀▄▀ █ █▄█ ██▄ ${unreadCol} 🟢 ${onlineText}
80
80
  ──────────────────────────────────────────────────`;
81
81
  }
package/tools/start.js CHANGED
@@ -167,7 +167,7 @@ function generateWelcomeCard({ handle, onlineCount, unreadCount, versionInfo })
167
167
  versionSuffix = ' ⬆️';
168
168
  }
169
169
 
170
- return ` █░█ █ █▄▄ █▀▀ ${handleCol} 🚀 ship together
170
+ return ` █░█ █ █▄▄ █▀▀ ${handleCol} ask here · answer there
171
171
  ▀▄▀ █ █▄█ ██▄ ${unreadCol} 🟢 ${onlineCount} online${versionSuffix}
172
172
  ──────────────────────────────────────────────────`;
173
173
  }
package/tools/who.js CHANGED
@@ -312,16 +312,20 @@ say hi to **@vibe** (the platform account, always around), or send
312
312
  }
313
313
  }
314
314
 
315
- // Fun quick actions - randomize suggestions
316
- const quickActions = [
317
- `say "message @handle" to reach someone`,
318
- `"play with @handle" if you'd rather build something together`,
319
- `"status shipping" so others see what you're on`,
320
- ];
321
- const randomAction = quickActions[Math.floor(Math.random() * quickActions.length)];
322
-
315
+ // One line, and it must name a tool that is ACTUALLY REGISTERED.
316
+ //
317
+ // This rotated three suggestions at random, one of which advertised `play` — a
318
+ // culture-layer tool that 0.8.0 moved behind VIBE_EXTRAS. So the default board
319
+ // routinely told people to use something their session does not have. That is the
320
+ // help-drift class we already have a guard for on `vibe_help`; the board escaped it.
321
+ //
322
+ // Randomness went too: a board that says something different every time reads as
323
+ // decoration. The hint now follows from state — if you have not set a status,
324
+ // that is the useful thing to say.
323
325
  display += `---\n`;
324
- display += randomAction;
326
+ display += config.getOneLiner()
327
+ ? `say "dm @handle" to reach someone`
328
+ : `say "status <what you're on>" so others see what you're building`;
325
329
 
326
330
  // Check for unread to add urgency
327
331
  try {
@@ -336,17 +340,15 @@ say hi to **@vibe** (the platform account, always around), or send
336
340
 
337
341
  }
338
342
 
339
- // Genesis spots remaining
340
- try {
341
- const stats = await store.getStats();
342
- if (stats.genesis && stats.genesis.genesis_remaining > 0) {
343
- display += `\n\n_${stats.genesis.genesis_remaining} genesis spots left of ${stats.genesis.genesis_cap}_`;
344
- } else if (stats.genesis && stats.genesis.genesis_remaining === 0) {
345
- display += `\n\n_genesis is full — ${stats.genesis.total} builders_`;
346
- }
347
- } catch (e) {
348
- // Silent fail — genesis display is nice-to-have
349
- }
343
+ // The scarcity line is gone.
344
+ //
345
+ // "genesis is full — 282 builders" was a growth-era artifact on two counts. It sold
346
+ // scarcity, which docs/PRIVATE-FABRIC.md removed from scope; and the number was a
347
+ // handle count, not people — 282 "builders" on a network where a handful of humans
348
+ // are actually active reads as a claim the room immediately contradicts. Nobody
349
+ // invited into a private fabric needs to be told the list is closed.
350
+ //
351
+ // What the board says about who is here is now only what it can see: the rows above.
350
352
 
351
353
  // If not initialized, append join prompt instead of actions/unread
352
354
  if (!isInit) {
package/version.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
- "version": "0.8.5",
2
+ "version": "0.8.6",
3
3
  "updated": "2026-07-31",
4
- "changelog": "Identity is one thing now. Whoever your credential says you are is who the client shows, routes and self-checks as \u2014 previously a saved handle could name one account while requests went out as another. Presence waits for the server to confirm you before it turns green, so a stale or forged session no longer announces itself. Changing your handle is turned off for now: your messages and tasks are still tied to it, and both rename paths are closed rather than one. A suggested first message no longer contains anyone else's words.",
4
+ "changelog": "Who is here is no longer public. Counts are; handles are not \u2014 sign in to see names, which every normal install already does. The rest is the first ninety minutes: an empty inbox now says what to do next instead of 'all caught up' to someone who never had a message, the board stops advertising tools your session does not have, and a failed message names one fix instead of three contradictory ones.",
5
5
  "features": [
6
- "The credential names you everywhere the client asks who you are",
7
- "Presence turns green only after the server confirms the session",
8
- "Handle changes are off \u2014 both routes, not one \u2014 until ownership moves off handles",
9
- "Suggested messages contain only our words; what someone shipped is shown as data"
6
+ "Presence names require a credential; counts stay public",
7
+ "Empty inbox tells you what to do next, and knows arriving from caught-up",
8
+ "The board only suggests commands your session actually has",
9
+ "Errors name one fix and stop"
10
10
  ],
11
11
  "deprecated": [],
12
12
  "breaking": false,