@floomhq/floom 1.0.19 → 1.0.20
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 +108 -3
- package/dist/sync.js +12 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -129,6 +129,112 @@ function commandUsage() {
|
|
|
129
129
|
`;
|
|
130
130
|
process.stdout.write(out);
|
|
131
131
|
}
|
|
132
|
+
function subcommandUsage(cmd) {
|
|
133
|
+
const key = cmd === "install" ? "add" : cmd === "rm" ? "delete" : cmd === "connect" ? "setup" : cmd === "paste" ? "agent-prompt" : cmd;
|
|
134
|
+
const usageByCommand = {
|
|
135
|
+
add: `${c.bold("Usage:")} ${c.cyan(`${CLI_COMMAND} add`)} ${c.dim("<url-or-slug> [flags]")}
|
|
136
|
+
|
|
137
|
+
Install a Floom skill into a local agent skills folder.
|
|
138
|
+
|
|
139
|
+
${c.bold("Flags")}
|
|
140
|
+
${c.cyan("--target")} ${c.dim("claude|codex")} Install for Claude Code or Codex. Default: claude.
|
|
141
|
+
${c.cyan("--setup")} Add Floom guidance to the matching agent instructions file.
|
|
142
|
+
${c.cyan("--force")} Replace the local copy when remote content differs.
|
|
143
|
+
${c.cyan("--json")} Print machine-readable install output.
|
|
144
|
+
|
|
145
|
+
${c.bold("Examples")}
|
|
146
|
+
${c.cyan(`${CLI_COMMAND} add https://floom.dev/s/ffas93ud --setup`)}
|
|
147
|
+
${c.cyan(`${CLI_COMMAND} add ffas93ud --target codex --json`)}
|
|
148
|
+
`,
|
|
149
|
+
update: `${c.bold("Usage:")} ${c.cyan(`${CLI_COMMAND} update`)} ${c.dim("<url-or-slug> [flags]")}
|
|
150
|
+
|
|
151
|
+
Refresh or migrate one local skill through the same installer as add.
|
|
152
|
+
|
|
153
|
+
${c.bold("Flags")}
|
|
154
|
+
${c.cyan("--target")} ${c.dim("claude|codex")} Update Claude Code or Codex local skills. Default: claude.
|
|
155
|
+
${c.cyan("--setup")} Also refresh agent setup instructions.
|
|
156
|
+
${c.cyan("--json")} Print machine-readable install output.
|
|
157
|
+
`,
|
|
158
|
+
doctor: `${c.bold("Usage:")} ${c.cyan(`${CLI_COMMAND} doctor`)} ${c.dim("[flags]")}
|
|
159
|
+
|
|
160
|
+
Diagnose auth, API reachability, PATH collisions, MCP setup, and local skills folders.
|
|
161
|
+
|
|
162
|
+
${c.bold("Flags")}
|
|
163
|
+
${c.cyan("--target")} ${c.dim("claude|codex")} Check Claude Code or Codex paths. Default: claude.
|
|
164
|
+
${c.cyan("--json")} Print structured checks for scripts.
|
|
165
|
+
`,
|
|
166
|
+
publish: `${c.bold("Usage:")} ${c.cyan(`${CLI_COMMAND} publish`)} ${c.dim("<path> [flags]")}
|
|
167
|
+
|
|
168
|
+
Scan and publish a Markdown skill file or skill folder. Prints a Floom share URL.
|
|
169
|
+
|
|
170
|
+
${c.bold("Flags")}
|
|
171
|
+
${c.cyan("--public")} | ${c.cyan("--private")} | ${c.cyan("--unlisted")} Set visibility. Default: unlisted.
|
|
172
|
+
${c.cyan("--type")} ${c.dim("knowledge|instruction|workflow|skill")}
|
|
173
|
+
${c.cyan("--installs-as")} ${c.dim("claude_skill|memory|rule|codex_instruction|opencode_instruction|cursor_rule|other")}
|
|
174
|
+
${c.cyan("--skill-version")} ${c.dim("<label>")}
|
|
175
|
+
`,
|
|
176
|
+
init: `${c.bold("Usage:")} ${c.cyan(`${CLI_COMMAND} init`)} ${c.dim("[path] [flags]")}
|
|
177
|
+
|
|
178
|
+
Create a starter skill folder with SKILL.md.
|
|
179
|
+
|
|
180
|
+
${c.bold("Flags")}
|
|
181
|
+
${c.cyan("--template")} ${c.dim(`generic|${INIT_TEMPLATES.filter((t) => t !== "generic").join("|")}`)}
|
|
182
|
+
`,
|
|
183
|
+
sync: `${c.bold("Usage:")} ${c.cyan(`${CLI_COMMAND} sync`)} ${c.dim("[flags]")}
|
|
184
|
+
|
|
185
|
+
Preview pull of published, saved, and subscribed library skills.
|
|
186
|
+
|
|
187
|
+
${c.bold("Flags")}
|
|
188
|
+
${c.cyan("--target")} ${c.dim("claude|codex")} Sync into Claude Code or Codex skills. Default: claude.
|
|
189
|
+
`,
|
|
190
|
+
watch: `${c.bold("Usage:")} ${c.cyan(`${CLI_COMMAND} watch`)} ${c.dim("[flags]")}
|
|
191
|
+
|
|
192
|
+
Poll sync on an interval. Preview behavior.
|
|
193
|
+
|
|
194
|
+
${c.bold("Flags")}
|
|
195
|
+
${c.cyan("--target")} ${c.dim("claude|codex")} Watch Claude Code or Codex skills. Default: claude.
|
|
196
|
+
${c.cyan("--interval")} ${c.dim("<seconds>")} Poll interval. Minimum: 10.
|
|
197
|
+
`,
|
|
198
|
+
setup: `${c.bold("Usage:")} ${c.cyan(`${CLI_COMMAND} setup`)} ${c.dim("[flags]")}
|
|
199
|
+
|
|
200
|
+
Add Floom guidance to CLAUDE.md or AGENTS.md.
|
|
201
|
+
|
|
202
|
+
${c.bold("Flags")}
|
|
203
|
+
${c.cyan("--target")} ${c.dim("claude|codex")} Configure Claude Code or Codex.
|
|
204
|
+
${c.cyan("--file")} ${c.dim("<path>")} Write a specific instructions file.
|
|
205
|
+
${c.cyan("--yes")} Write without prompting.
|
|
206
|
+
${c.cyan("--dry-run")} Preview the change only.
|
|
207
|
+
`,
|
|
208
|
+
search: `${c.bold("Usage:")} ${c.cyan(`${CLI_COMMAND} search`)} ${c.dim("<query> [flags]")}
|
|
209
|
+
|
|
210
|
+
Find public skills and libraries.
|
|
211
|
+
|
|
212
|
+
${c.bold("Flags")}
|
|
213
|
+
${c.cyan("--library")} ${c.dim("<slug>")} Limit search to one library.
|
|
214
|
+
${c.cyan("--type")} ${c.dim("knowledge|instruction|workflow|skill")}
|
|
215
|
+
${c.cyan("--json")} Print machine-readable results.
|
|
216
|
+
`,
|
|
217
|
+
info: `${c.bold("Usage:")} ${c.cyan(`${CLI_COMMAND} info`)} ${c.dim("<url-or-slug> [flags]")}
|
|
218
|
+
|
|
219
|
+
Show public skill metadata.
|
|
220
|
+
|
|
221
|
+
${c.bold("Flags")}
|
|
222
|
+
${c.cyan("--json")} Print machine-readable metadata.
|
|
223
|
+
`,
|
|
224
|
+
"agent-prompt": `${c.bold("Usage:")} ${c.cyan(`${CLI_COMMAND} agent-prompt`)} ${c.dim("[flags]")}
|
|
225
|
+
|
|
226
|
+
Print the one-line instruction to paste into your agent.
|
|
227
|
+
|
|
228
|
+
${c.bold("Flags")}
|
|
229
|
+
${c.cyan("--target")} ${c.dim("claude|codex")} Print the right local skills path. Default: claude.
|
|
230
|
+
`,
|
|
231
|
+
};
|
|
232
|
+
const body = key ? usageByCommand[key] : undefined;
|
|
233
|
+
if (!body)
|
|
234
|
+
return false;
|
|
235
|
+
process.stdout.write(`${body}\n`);
|
|
236
|
+
return true;
|
|
237
|
+
}
|
|
132
238
|
const ASSET_TYPES = new Set(["knowledge", "instruction", "workflow", "skill"]);
|
|
133
239
|
const INSTALL_TARGETS = new Set([
|
|
134
240
|
"claude_skill",
|
|
@@ -722,10 +828,9 @@ async function main() {
|
|
|
722
828
|
// never block on update-notifier
|
|
723
829
|
}
|
|
724
830
|
}
|
|
725
|
-
// Subcommand --help: any rest arg = --help/-h/help → show the command reference.
|
|
726
|
-
// Subcommands are simple enough that one reference screen is fine for Version 1.
|
|
727
831
|
if (rest.includes("--help") || rest.includes("-h") || rest.includes("help")) {
|
|
728
|
-
|
|
832
|
+
if (!subcommandUsage(cmd))
|
|
833
|
+
commandUsage();
|
|
729
834
|
return;
|
|
730
835
|
}
|
|
731
836
|
try {
|
package/dist/sync.js
CHANGED
|
@@ -79,6 +79,17 @@ function skillPath(skill, targetAgent) {
|
|
|
79
79
|
function syncKey(skill) {
|
|
80
80
|
return `${skill.library_slug ?? ""}\0${skill.folder ?? ""}\0${skill.slug}`;
|
|
81
81
|
}
|
|
82
|
+
function hasStructuredPath(skill) {
|
|
83
|
+
return Boolean(skill.library_slug || skill.folder);
|
|
84
|
+
}
|
|
85
|
+
function dedupeSyncSkills(skills) {
|
|
86
|
+
const structuredSlugs = new Set();
|
|
87
|
+
for (const skill of skills) {
|
|
88
|
+
if (hasStructuredPath(skill))
|
|
89
|
+
structuredSlugs.add(skill.slug);
|
|
90
|
+
}
|
|
91
|
+
return skills.filter((skill) => !structuredSlugs.has(skill.slug) || hasStructuredPath(skill));
|
|
92
|
+
}
|
|
82
93
|
function validateSyncSkillShape(skill) {
|
|
83
94
|
if (!skill || typeof skill !== "object")
|
|
84
95
|
throw new FloomError("Invalid sync response.");
|
|
@@ -288,7 +299,7 @@ export async function sync(opts = {}) {
|
|
|
288
299
|
for (const skill of payload.skills)
|
|
289
300
|
validateSyncSkillShape(skill);
|
|
290
301
|
// Version 1 preview syncs published, saved, and subscribed library skills.
|
|
291
|
-
const all = payload.skills;
|
|
302
|
+
const all = dedupeSyncSkills(payload.skills);
|
|
292
303
|
const seen = new Set();
|
|
293
304
|
let unchanged = 0;
|
|
294
305
|
let updated = 0;
|