@floomhq/floom 1.0.37 → 1.0.39

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/dist/cli.js CHANGED
@@ -175,11 +175,78 @@ function moveUsage() {
175
175
  ${c.cyan("--tags a,b")} Add comma-separated tags
176
176
  `);
177
177
  }
178
+ function addUsage() {
179
+ process.stdout.write(`
180
+ ${c.bold("Usage:")} ${c.cyan(`${CLI_COMMAND} add`)} ${c.dim("<slug-or-url> [flags]")}
181
+
182
+ ${c.bold("Install a shared skill locally.")}
183
+ ${c.cyan(`${CLI_COMMAND} add https://floom.dev/s/ffas93ud --target claude --setup`)}
184
+ ${c.cyan(`${CLI_COMMAND} add support-tone --target codex --force`)}
185
+
186
+ ${c.bold("Flags")}
187
+ ${c.cyan(`--target ${TARGET_HINT}`)} Agent target, default claude
188
+ ${c.cyan("--setup")} Add Floom instructions for the target agent
189
+ ${c.cyan("--force")} Replace an existing tracked install
190
+ `);
191
+ }
192
+ function syncUsage() {
193
+ process.stdout.write(`
194
+ ${c.bold("Usage:")} ${c.cyan(`${CLI_COMMAND} sync`)} ${c.dim("[flags]")}
195
+
196
+ ${c.bold("Pull published, saved, and subscribed library skills into one target.")}
197
+ ${c.cyan(`${CLI_COMMAND} sync --target claude`)}
198
+ ${c.cyan(`${CLI_COMMAND} sync --target codex`)}
199
+
200
+ ${c.bold("Flags")}
201
+ ${c.cyan(`--target ${TARGET_HINT}`)} Agent target, default claude
202
+ `);
203
+ }
204
+ function watchUsage() {
205
+ process.stdout.write(`
206
+ ${c.bold("Usage:")} ${c.cyan(`${CLI_COMMAND} watch`)} ${c.dim("[flags]")}
207
+
208
+ ${c.bold("Run a polling loop for one target.")}
209
+ ${c.cyan(`${CLI_COMMAND} watch --target claude`)}
210
+ ${c.cyan(`${CLI_COMMAND} watch --push --target codex`)}
211
+
212
+ ${c.bold("Flags")}
213
+ ${c.cyan("--push")} Publish/update local skill changes
214
+ ${c.cyan("--no-yolo")} Adopt local skills without auto-publishing new ones
215
+ ${c.cyan("--once")} Run one cycle and exit
216
+ ${c.cyan("--interval <seconds>")} Poll interval, minimum 10
217
+ ${c.cyan(`--target ${TARGET_HINT}`)} Agent target, default claude
218
+ `);
219
+ }
220
+ function doctorUsage() {
221
+ process.stdout.write(`
222
+ ${c.bold("Usage:")} ${c.cyan(`${CLI_COMMAND} doctor`)} ${c.dim("[flags]")}
223
+
224
+ ${c.bold("Check auth, MCP registration, local folders, and CLI freshness.")}
225
+ ${c.cyan(`${CLI_COMMAND} doctor --target claude`)}
226
+ ${c.cyan(`${CLI_COMMAND} doctor --target opencode`)}
227
+
228
+ ${c.bold("Flags")}
229
+ ${c.cyan(`--target ${TARGET_HINT}`)} Agent target, default claude
230
+ `);
231
+ }
178
232
  function isHelpArg(value) {
179
233
  return value === "--help" || value === "-h" || value === "help";
180
234
  }
181
235
  function subcommandUsage(cmd) {
182
236
  switch (cmd) {
237
+ case "add":
238
+ case "install":
239
+ addUsage();
240
+ return true;
241
+ case "sync":
242
+ syncUsage();
243
+ return true;
244
+ case "watch":
245
+ watchUsage();
246
+ return true;
247
+ case "doctor":
248
+ doctorUsage();
249
+ return true;
183
250
  case "share":
184
251
  shareUsage();
185
252
  return true;
package/dist/list.js CHANGED
@@ -42,8 +42,22 @@ export async function list(opts) {
42
42
  const spinner = opts.json ? null : ora({ text: c.dim("Loading skills..."), color: "yellow" }).start();
43
43
  let published = [];
44
44
  try {
45
- const mine = await getJson(`${apiUrl}/api/v1/me/skills`, "load your skills", cfg.accessToken);
46
- published = mine.skills ?? [];
45
+ let cursor;
46
+ const seenCursors = new Set();
47
+ for (let page = 0; page < 1000; page += 1) {
48
+ const url = new URL(`${apiUrl}/api/v1/me/skills`);
49
+ url.searchParams.set("limit", "100");
50
+ if (cursor)
51
+ url.searchParams.set("cursor", cursor);
52
+ const mine = await getJson(url.toString(), "load your skills", cfg.accessToken);
53
+ published.push(...(mine.skills ?? []));
54
+ if (!mine.next_cursor)
55
+ break;
56
+ if (seenCursors.has(mine.next_cursor))
57
+ throw new FloomError("Invalid skills response.");
58
+ seenCursors.add(mine.next_cursor);
59
+ cursor = mine.next_cursor;
60
+ }
47
61
  }
48
62
  finally {
49
63
  spinner?.stop();
@@ -52,7 +66,7 @@ export async function list(opts) {
52
66
  process.stdout.write(`${JSON.stringify({ published }, null, 2)}\n`);
53
67
  return;
54
68
  }
55
- process.stdout.write(`\n${symbols.dot} ${c.bold("Published")} ${c.dim(`(${published.length})`)}\n\n`);
69
+ process.stdout.write(`\n${symbols.dot} ${c.bold("Skills")} ${c.dim(`(${published.length})`)}\n\n`);
56
70
  if (published.length === 0) {
57
71
  process.stdout.write(` ${c.dim("Nothing published yet. Try `npx -y @floomhq/floom publish my-skill`.")}\n`);
58
72
  }
package/dist/package.js CHANGED
@@ -115,7 +115,7 @@ const GENERATED_PACKAGE_DIRS = new Set([
115
115
  ]);
116
116
  const GENERATED_PACKAGE_FILES = new Set([".DS_Store"]);
117
117
  const GENERATED_PACKAGE_FILE_SUFFIXES = [".icns", ".log", ".mov", ".mp3", ".mp4", ".pyc", ".pyo", ".wav", ".webm"];
118
- const PACKAGE_FILE_LIMIT = 1000;
118
+ const PACKAGE_FILE_LIMIT = 100;
119
119
  const PACKAGE_TOTAL_BYTES_LIMIT = 8_000_000;
120
120
  const PACKAGE_FILE_BYTES_LIMIT = 500_000;
121
121
  const PACKAGE_SEGMENT_RE = /^[A-Za-z0-9._-]{1,128}$/;
package/dist/setup.js CHANGED
@@ -21,8 +21,8 @@ function floomAgentInstructions(target) {
21
21
  - Before recreating agent behavior from scratch, check Floom for reusable skills.
22
22
  - Search or inspect skills with \`${CLI_COMMAND} search <query>\`, \`${CLI_COMMAND} info <slug-or-url>\`, and \`${CLI_COMMAND} list\`.
23
23
  - Add shared skills with \`${addCommand}\`; public and unlisted links do not require a Floom account.
24
- - Use installed Markdown skills from the local skills folder when they match the task.
25
- - \`${CLI_COMMAND} sync --target ${target}\`, \`${CLI_COMMAND} watch --push --target ${target}\`, and \`@floomhq/floom-mcp-sync\` keep saved, published, and subscribed library skills current; review conflicts before relying on synced output.
24
+ - Use the installed \`floom-find-skills\` router skill, Floom search, or MCP lookup before loading local files. Do not enumerate every cached skill into model context.
25
+ - \`${CLI_COMMAND} sync --target ${target}\`, \`${CLI_COMMAND} watch --push --target ${target}\`, and \`@floomhq/floom-mcp-sync\` keep saved, published, and subscribed library skills current in the Floom cache; review conflicts before relying on synced output.
26
26
  ${END_MARKER}`;
27
27
  }
28
28
  async function fileExists(path) {
package/dist/sync.js CHANGED
@@ -270,7 +270,7 @@ export async function sync(opts = {}) {
270
270
  const spinner = opts.spinner === false ? null : ora({ text: c.dim("Syncing skills..."), color: "yellow" }).start();
271
271
  let payload;
272
272
  try {
273
- payload = await getJson(`${apiUrl}/api/v1/me/skills`, "load your skills", cfg.accessToken);
273
+ payload = await loadSyncPayload(apiUrl, cfg.accessToken);
274
274
  }
275
275
  catch (err) {
276
276
  spinner?.stop();
@@ -442,3 +442,29 @@ export async function sync(opts = {}) {
442
442
  throw err;
443
443
  }
444
444
  }
445
+ async function loadSyncPayload(apiUrl, token) {
446
+ const all = [];
447
+ let fullSync = false;
448
+ let cursor;
449
+ const seenCursors = new Set();
450
+ for (let page = 0; page < 1000; page += 1) {
451
+ const url = new URL(`${apiUrl}/api/v1/me/skills`);
452
+ url.searchParams.set("limit", "10");
453
+ url.searchParams.set("packages", "1");
454
+ if (cursor)
455
+ url.searchParams.set("cursor", cursor);
456
+ const payload = await getJson(url.toString(), "load your skills", token);
457
+ if (!Array.isArray(payload.skills))
458
+ throw new FloomError("Invalid sync response.");
459
+ all.push(...payload.skills);
460
+ fullSync = payload.full_sync === true;
461
+ if (!payload.next_cursor) {
462
+ return { skills: all, full_sync: fullSync };
463
+ }
464
+ if (seenCursors.has(payload.next_cursor))
465
+ throw new FloomError("Invalid sync response.");
466
+ seenCursors.add(payload.next_cursor);
467
+ cursor = payload.next_cursor;
468
+ }
469
+ throw new FloomError("Invalid sync response.");
470
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@floomhq/floom",
3
- "version": "1.0.37",
3
+ "version": "1.0.39",
4
4
  "description": "Sync AI skills across agents and machines.",
5
5
  "license": "MIT",
6
6
  "type": "module",