@floomhq/floom 1.0.38 → 1.0.40
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 +67 -0
- package/dist/list.js +17 -3
- package/dist/package.js +1 -1
- package/dist/push-watch.js +1 -24
- package/dist/setup.js +2 -2
- package/dist/sync.js +2 -1
- package/package.json +1 -1
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
|
-
|
|
46
|
-
|
|
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("
|
|
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 =
|
|
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/push-watch.js
CHANGED
|
@@ -156,30 +156,7 @@ export async function pushWatchOnce(opts) {
|
|
|
156
156
|
const pushed = pushManifest.files[pushKey];
|
|
157
157
|
if (pushed?.hash === hash) {
|
|
158
158
|
if (!isUnchangedSyncedPackage(root, skillPackage, syncManifest)) {
|
|
159
|
-
|
|
160
|
-
try {
|
|
161
|
-
await publishSkillPath({ file: packagePath, update: true, updateSlug: pushed.slug, quiet: true });
|
|
162
|
-
updated += 1;
|
|
163
|
-
}
|
|
164
|
-
catch (err) {
|
|
165
|
-
if (err instanceof Error && /Skill not found/i.test(err.message)) {
|
|
166
|
-
const result = await publishSkillPath({ file: packagePath, visibility: "unlisted", quiet: true });
|
|
167
|
-
published += 1;
|
|
168
|
-
pushManifest.files[pushKey] = { hash, slug: result.data.slug, path: key, pushedAt: new Date().toISOString() };
|
|
169
|
-
markPackageSynced(root, skillPackage, syncManifest, result.data.slug);
|
|
170
|
-
await writeSyncManifest(syncManifest);
|
|
171
|
-
continue;
|
|
172
|
-
}
|
|
173
|
-
skipped += 1;
|
|
174
|
-
if (!opts.quiet) {
|
|
175
|
-
process.stderr.write(`[floom] skipped ${packagePath}: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
176
|
-
}
|
|
177
|
-
continue;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
else {
|
|
181
|
-
adopted += 1;
|
|
182
|
-
}
|
|
159
|
+
adopted += 1;
|
|
183
160
|
markPackageSynced(root, skillPackage, syncManifest, pushed.slug);
|
|
184
161
|
await writeSyncManifest(syncManifest);
|
|
185
162
|
}
|
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
|
|
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
|
@@ -449,7 +449,8 @@ async function loadSyncPayload(apiUrl, token) {
|
|
|
449
449
|
const seenCursors = new Set();
|
|
450
450
|
for (let page = 0; page < 1000; page += 1) {
|
|
451
451
|
const url = new URL(`${apiUrl}/api/v1/me/skills`);
|
|
452
|
-
url.searchParams.set("limit", "
|
|
452
|
+
url.searchParams.set("limit", "10");
|
|
453
|
+
url.searchParams.set("packages", "1");
|
|
453
454
|
if (cursor)
|
|
454
455
|
url.searchParams.set("cursor", cursor);
|
|
455
456
|
const payload = await getJson(url.toString(), "load your skills", token);
|