feat(cli): claudemesh skill prints bundled SKILL.md (v1.18.0)
Some checks failed
CI / Docker build (linux/amd64) (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Broker tests (Postgres) (push) Has been cancelled

Zero-install access to the protocol reference: a fresh `npm i -g
claudemesh-cli` user (or someone running the prebuilt binary) can
now `claudemesh skill | claude --skill-add -` without copying any
files into ~/.claude/skills. The skill markdown is embedded into
the CLI bundle at build time via Bun's text-import attribute.

Also replaces two `<> ALL(...)` raw SQL fragments in the dashboard
unread-count queries with drizzle's notInArray() helper — matches
the same fix already applied to /v1/me/topics in the API package.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alejandro Gutiérrez
2026-05-03 12:24:45 +01:00
parent 50b2ae97c2
commit f9ed3fa286
6 changed files with 42 additions and 7 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "claudemesh-cli",
"version": "1.17.0",
"version": "1.18.0",
"description": "Peer mesh for Claude Code sessions — CLI + MCP server.",
"keywords": [
"claude-code",

View File

@@ -0,0 +1,21 @@
/**
* `claudemesh skill` — print the bundled SKILL.md to stdout.
*
* Zero-install access: the skill is embedded into the binary at build
* time via Bun's text-import attribute, so a fresh `npm i -g` user
* (or someone running the prebuilt binary) can pipe the contents into
* Claude Code (or anywhere else) without copying files into
* ~/.claude/skills.
*
* claudemesh skill | claude --skill-add -
* claudemesh skill > /tmp/cm.md
*/
import skillContent from "../../skills/claudemesh/SKILL.md" with { type: "text" };
import { EXIT } from "~/constants/exit-codes.js";
export async function runSkill(): Promise<number> {
process.stdout.write(skillContent);
if (!skillContent.endsWith("\n")) process.stdout.write("\n");
return EXIT.SUCCESS;
}

View File

@@ -123,6 +123,7 @@ Topic (conversation scope, v0.2.0)
claudemesh topic tail <topic> live SSE tail [--limit --forward-only]
claudemesh topic post <t> <msg> encrypted REST post (v0.3.0 v2) [--reply-to <id>]
claudemesh send "#topic" "msg" send to a topic (WS path, v1 plaintext)
claudemesh skill print the bundled SKILL.md to stdout
claudemesh me cross-mesh workspace overview (v0.4.0)
claudemesh me topics cross-mesh topic list [--unread]
claudemesh me notifications cross-mesh @-mentions [--all] [--since=ISO]
@@ -538,10 +539,14 @@ async function main(): Promise<void> {
case "skill": {
const sub = positionals[0];
const f = { mesh: flags.mesh as string, json: !!flags.json };
if (sub === "list") { const { runSkillList } = await import("~/commands/platform-actions.js"); process.exit(await runSkillList({ ...f, query: positionals[1] })); }
// No subcommand → print the bundled SKILL.md to stdout. Lets a
// fresh user pipe `claudemesh skill | claude --skill-add -`
// without copying anything into ~/.claude/skills (v1.18.0).
if (!sub) { const { runSkill } = await import("~/commands/skill.js"); process.exit(await runSkill()); }
else if (sub === "list") { const { runSkillList } = await import("~/commands/platform-actions.js"); process.exit(await runSkillList({ ...f, query: positionals[1] })); }
else if (sub === "get") { const { runSkillGet } = await import("~/commands/platform-actions.js"); process.exit(await runSkillGet(positionals[1] ?? "", f)); }
else if (sub === "remove") { const { runSkillRemove } = await import("~/commands/platform-actions.js"); process.exit(await runSkillRemove(positionals[1] ?? "", f)); }
else { console.error("Usage: claudemesh skill <list|get|remove>"); process.exit(EXIT.INVALID_ARGS); }
else { console.error("Usage: claudemesh skill (print bundled SKILL.md)\n claudemesh skill <list|get|remove>"); process.exit(EXIT.INVALID_ARGS); }
break;
}
case "vault": {