@clix-so/clix-agent-skills 1.0.0 → 1.0.1

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/README.md CHANGED
@@ -60,7 +60,7 @@ configurations. See the "Configuration Locations" section below for details.
60
60
 
61
61
  ```bash
62
62
  # Install a specific skill (repo root - default)
63
- # Default install path (when --client is omitted): .agent/skills/<skill>
63
+ # Default install path (when --client is omitted): .agents/skills/<skill>
64
64
  npx @clix-so/clix-agent-skills@latest install <skill-name> --client <your-client>
65
65
  # For example, to install a skill on Cursor:
66
66
  npx @clix-so/clix-agent-skills@latest install integration --client cursor
@@ -80,20 +80,21 @@ npx @clix-so/clix-agent-skills@latest install --all --client cursor --global
80
80
 
81
81
  **Supported Clients:**
82
82
 
83
- | Client | Flag | Default Path |
84
- | ----------------------- | ------------------------------------ | ------------------ |
85
- | Default (no `--client`) | _n/a_ | `.agent/skills/` |
86
- | Amp | `--client amp` | `.agents/skills/` |
87
- | Claude Code | `--client claude` (or `claude-code`) | `.claude/skills/` |
88
- | Codex | `--client codex` | `.codex/skills/` |
89
- | Cursor | `--client cursor` | `.cursor/skills/` |
90
- | Gemini CLI | `--client gemini` | `.gemini/skills/` |
91
- | Google Antigravity | `--client antigravity` | `.agent/skills/` |
92
- | GitHub Copilot | `--client github` | `.github/skills/` |
93
- | Goose | `--client goose` | `.agents/skills/` |
94
- | Letta | `--client letta` | `.skills/` |
95
- | OpenCode | `--client opencode` | `.opencode/skill/` |
96
- | VS Code | `--client vscode` | `.vscode/skills/` |
83
+ | Client | Flag | Project Path | System Path |
84
+ | ----------------------- | ---------------------- | ------------------ | ------------------------------- |
85
+ | Default (no `--client`) | _n/a_ | `.agents/skills/` | `~/.agents/skills/` |
86
+ | Amp | `--client amp` | `.agents/skills/` | `~/.config/agents/skills/` |
87
+ | Claude Code | `--client claude` | `.claude/skills/` | `~/.claude/skills/` |
88
+ | Codex | `--client codex` | `.codex/skills/` | `~/.codex/skills/` |
89
+ | Cursor | `--client cursor` | `.cursor/skills/` | `~/.cursor/skills/` |
90
+ | Factory | `--client factory` | `.factory/skills/` | `~/.factory/skills/` |
91
+ | Gemini CLI | `--client gemini` | `.gemini/skills/` | `~/.gemini/skills/` |
92
+ | Google Antigravity | `--client antigravity` | `.agent/skills/` | `~/.gemini/antigravity/skills/` |
93
+ | GitHub Copilot | `--client github` | `.github/skills/` | `~/.github/skills/` |
94
+ | Goose | `--client goose` | `.agents/skills/` | `~/.config/agents/skills/` |
95
+ | Letta | `--client letta` | `.skills/` | `~/.skills/` |
96
+ | OpenCode | `--client opencode` | `.opencode/skill/` | `~/.opencode/skill/` |
97
+ | VS Code | `--client vscode` | `.vscode/skills/` | `~/.vscode/skills/` |
97
98
 
98
99
  ### Claude Code (Alternative setup via plugin marketplace)
99
100
 
package/dist/bin/cli.js CHANGED
@@ -7,16 +7,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
7
7
  const commander_1 = require("commander");
8
8
  const chalk_1 = __importDefault(require("chalk"));
9
9
  const install_1 = require("./commands/install");
10
+ const errors_1 = require("./utils/errors");
10
11
  const package_json_1 = require("../../package.json");
11
- /**
12
- * Extracts error message from unknown error type
13
- */
14
- function getErrorMessage(error) {
15
- if (error instanceof Error) {
16
- return error.message;
17
- }
18
- return String(error);
19
- }
20
12
  const program = new commander_1.Command();
21
13
  program
22
14
  .name("clix-agent-skills")
@@ -25,7 +17,7 @@ program
25
17
  program
26
18
  .command("install [skill]")
27
19
  .description("Install agent skill(s)")
28
- .option("-c, --client <client>", "Target AI client (amazonq, amp, antigravity, claude|claude-code, codex, copilot|github, cursor, gemini, goose, kiro, letta, opencode, vscode, manual)")
20
+ .option("-c, --client <client>", "Target AI client (amazonq, amp, antigravity, claude|claude-code, codex, copilot|github, cursor, factory, gemini, goose, kiro, letta, opencode, vscode, manual)")
29
21
  .option("-p, --path <path>", "Custom installation path (default: .agent/skills)")
30
22
  .option("-a, --all", "Install all available skills")
31
23
  .option("-g, --global", "Install globally to system root (default: installs to repo root)")
@@ -43,7 +35,7 @@ program
43
35
  }
44
36
  }
45
37
  catch (error) {
46
- console.error(chalk_1.default.red("Error installing skill(s):"), getErrorMessage(error));
38
+ console.error(chalk_1.default.red("Error installing skill(s):"), (0, errors_1.getErrorMessage)(error));
47
39
  process.exit(1);
48
40
  }
49
41
  });
@@ -11,15 +11,7 @@ const fs_extra_1 = __importDefault(require("fs-extra"));
11
11
  const chalk_1 = __importDefault(require("chalk"));
12
12
  const ora_1 = __importDefault(require("ora"));
13
13
  const mcp_1 = require("../utils/mcp");
14
- /**
15
- * Extracts error message from unknown error type
16
- */
17
- function getErrorMessage(error) {
18
- if (error instanceof Error) {
19
- return error.message;
20
- }
21
- return String(error);
22
- }
14
+ const errors_1 = require("../utils/errors");
23
15
  async function installSkill(skillName, options) {
24
16
  const spinner = (0, ora_1.default)(`Installing skill: ${chalk_1.default.bold(skillName)}`).start();
25
17
  // 1. Locate Skill in current package
@@ -57,7 +49,7 @@ async function installSkill(skillName, options) {
57
49
  return;
58
50
  }
59
51
  // 2. Determine Destination
60
- let relativeDest = ".agent/skills";
52
+ let relativeDest = ".agents/skills";
61
53
  if (options.path) {
62
54
  relativeDest = options.path;
63
55
  }
@@ -86,11 +78,16 @@ async function installSkill(skillName, options) {
86
78
  case "cursor":
87
79
  relativeDest = ".cursor/skills";
88
80
  break;
81
+ case "factory":
82
+ relativeDest = ".factory/skills";
83
+ break;
89
84
  case "gemini":
90
85
  // Gemini CLI discovers project skills in `.gemini/skills/` and user skills in `~/.gemini/skills/`
91
86
  relativeDest = ".gemini/skills";
92
87
  break;
93
88
  case "antigravity":
89
+ case "google-antigravity":
90
+ case "google_antigravity":
94
91
  // Google Antigravity uses `.agent/skills` for workspace installs and
95
92
  // `~/.gemini/antigravity/skills` for global installs.
96
93
  relativeDest = options.global ? ".gemini/antigravity/skills" : ".agent/skills";
@@ -117,7 +114,7 @@ async function installSkill(skillName, options) {
117
114
  default:
118
115
  relativeDest = options.client.startsWith(".")
119
116
  ? `${options.client}/skills`
120
- : `.agent/skills`;
117
+ : `.agents/skills`;
121
118
  }
122
119
  }
123
120
  // Determine installation root: repo root (cwd) or system root (home directory)
@@ -142,7 +139,7 @@ async function installSkill(skillName, options) {
142
139
  spinner.succeed(`Skill files installed to ${chalk_1.default.green(installLocation)}`);
143
140
  }
144
141
  catch (error) {
145
- spinner.fail(`Failed to copy skill files: ${getErrorMessage(error)}`);
142
+ spinner.fail(`Failed to copy skill files: ${(0, errors_1.getErrorMessage)(error)}`);
146
143
  throw error;
147
144
  }
148
145
  // 4. MCP Configuration (always global/system root)
@@ -151,7 +148,7 @@ async function installSkill(skillName, options) {
151
148
  await (0, mcp_1.configureMCP)(options.client);
152
149
  }
153
150
  catch (error) {
154
- console.warn(chalk_1.default.yellow(`MCP Configuration warning: ${getErrorMessage(error)}`));
151
+ console.warn(chalk_1.default.yellow(`MCP Configuration warning: ${(0, errors_1.getErrorMessage)(error)}`));
155
152
  }
156
153
  }
157
154
  console.log(`\n${chalk_1.default.green("✔")} Skill ${chalk_1.default.bold(skillName)} is ready to use!`);
@@ -203,7 +200,7 @@ async function installAllSkills(options) {
203
200
  successCount++;
204
201
  }
205
202
  catch (error) {
206
- console.error(chalk_1.default.red(`\n✗ Failed to install ${chalk_1.default.bold(skillName)}: ${getErrorMessage(error)}`));
203
+ console.error(chalk_1.default.red(`\n✗ Failed to install ${chalk_1.default.bold(skillName)}: ${(0, errors_1.getErrorMessage)(error)}`));
207
204
  failCount++;
208
205
  }
209
206
  }
@@ -213,7 +210,7 @@ async function installAllSkills(options) {
213
210
  await (0, mcp_1.configureMCP)(options.client);
214
211
  }
215
212
  catch (error) {
216
- console.warn(chalk_1.default.yellow(`MCP Configuration warning: ${getErrorMessage(error)}`));
213
+ console.warn(chalk_1.default.yellow(`MCP Configuration warning: ${(0, errors_1.getErrorMessage)(error)}`));
217
214
  }
218
215
  }
219
216
  console.log();
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getErrorMessage = getErrorMessage;
4
+ /**
5
+ * Extracts error message from unknown error type
6
+ */
7
+ function getErrorMessage(error) {
8
+ if (error instanceof Error) {
9
+ return error.message;
10
+ }
11
+ return String(error);
12
+ }
@@ -44,6 +44,7 @@ const chalk_1 = __importDefault(require("chalk"));
44
44
  const inquirer_1 = __importDefault(require("inquirer"));
45
45
  const TOML = __importStar(require("@iarna/toml"));
46
46
  const child_process_1 = require("child_process");
47
+ const errors_1 = require("./errors");
47
48
  // ============================================================================
48
49
  // Constants
49
50
  // ============================================================================
@@ -62,18 +63,6 @@ const CLAUDE_CODE_MCP_ADD_ARGS = [
62
63
  "-y",
63
64
  "@clix-so/clix-mcp-server@latest",
64
65
  ];
65
- // ============================================================================
66
- // Helper Functions
67
- // ============================================================================
68
- /**
69
- * Extracts error message from unknown error type
70
- */
71
- function getErrorMessage(error) {
72
- if (error instanceof Error) {
73
- return error.message;
74
- }
75
- return String(error);
76
- }
77
66
  function hasClixServerInClaudeMcpListOutput(output) {
78
67
  return output.toLowerCase().includes("clix-mcp-server");
79
68
  }
@@ -85,7 +74,7 @@ async function configureClaudeCode() {
85
74
  // Verify Claude CLI exists and supports MCP.
86
75
  const helpRes = (0, child_process_1.spawnSync)("claude", ["mcp", "--help"], { encoding: "utf8" });
87
76
  if (helpRes.error) {
88
- console.log(chalk_1.default.yellow(`Could not run Claude CLI (${getErrorMessage(helpRes.error)}). Skipping MCP configuration.`));
77
+ console.log(chalk_1.default.yellow(`Could not run Claude CLI (${(0, errors_1.getErrorMessage)(helpRes.error)}). Skipping MCP configuration.`));
89
78
  return;
90
79
  }
91
80
  if (helpRes.status !== 0) {
@@ -248,7 +237,7 @@ async function configureCodexTOML(configPath) {
248
237
  console.log(chalk_1.default.green(`✔ Created config file at ${nicePath}`));
249
238
  }
250
239
  catch (error) {
251
- console.log(chalk_1.default.red(`Failed to create config file: ${getErrorMessage(error)}`));
240
+ console.log(chalk_1.default.red(`Failed to create config file: ${(0, errors_1.getErrorMessage)(error)}`));
252
241
  return;
253
242
  }
254
243
  }
@@ -259,7 +248,7 @@ async function configureCodexTOML(configPath) {
259
248
  config = TOML.parse(content);
260
249
  }
261
250
  catch (error) {
262
- console.log(chalk_1.default.red(`Failed to parse existing config TOML: ${getErrorMessage(error)}`));
251
+ console.log(chalk_1.default.red(`Failed to parse existing config TOML: ${(0, errors_1.getErrorMessage)(error)}`));
263
252
  return;
264
253
  }
265
254
  }
@@ -315,7 +304,7 @@ async function configureOpenCode() {
315
304
  console.log(chalk_1.default.green(`✔ Created config file at ${nicePath}`));
316
305
  }
317
306
  catch (error) {
318
- console.log(chalk_1.default.red(`Failed to create config file: ${getErrorMessage(error)}`));
307
+ console.log(chalk_1.default.red(`Failed to create config file: ${(0, errors_1.getErrorMessage)(error)}`));
319
308
  return;
320
309
  }
321
310
  }
@@ -324,7 +313,7 @@ async function configureOpenCode() {
324
313
  config = await fs_extra_1.default.readJSON(configPath);
325
314
  }
326
315
  catch (error) {
327
- console.log(chalk_1.default.red(`Failed to parse existing config JSON: ${getErrorMessage(error)}`));
316
+ console.log(chalk_1.default.red(`Failed to parse existing config JSON: ${(0, errors_1.getErrorMessage)(error)}`));
328
317
  return;
329
318
  }
330
319
  }
@@ -356,6 +345,76 @@ async function configureOpenCode() {
356
345
  console.log(chalk_1.default.green(`✔ Added Clix MCP Server to configuration. Please restart opencode.`));
357
346
  }
358
347
  }
348
+ async function configureFactoryConfig(configTarget) {
349
+ const { scope, path: configPath } = configTarget;
350
+ const nicePath = scope === "project"
351
+ ? path_1.default.relative(process.cwd(), configPath) || configPath
352
+ : configPath.replace(os_1.default.homedir(), "~");
353
+ console.log(chalk_1.default.blue(`Checking MCP config at ${nicePath} (${scope} scope)...`));
354
+ if (!fs_extra_1.default.existsSync(configPath)) {
355
+ const { create } = await inquirer_1.default.prompt([
356
+ {
357
+ type: "confirm",
358
+ name: "create",
359
+ message: `Config file not found at ${nicePath}. Create it?`,
360
+ default: true,
361
+ },
362
+ ]);
363
+ if (!create) {
364
+ console.log(chalk_1.default.yellow(`Skipping MCP configuration for ${scope} scope.`));
365
+ return;
366
+ }
367
+ try {
368
+ await fs_extra_1.default.ensureDir(path_1.default.dirname(configPath));
369
+ await fs_extra_1.default.writeJSON(configPath, createEmptyConfig("mcpServers"), { spaces: 2 });
370
+ console.log(chalk_1.default.green(`✔ Created config file at ${nicePath}`));
371
+ }
372
+ catch (error) {
373
+ console.log(chalk_1.default.red(`Failed to create config file (${scope} scope): ${(0, errors_1.getErrorMessage)(error)}`));
374
+ return;
375
+ }
376
+ }
377
+ let config;
378
+ try {
379
+ config = await fs_extra_1.default.readJSON(configPath);
380
+ }
381
+ catch (error) {
382
+ console.log(chalk_1.default.red(`Failed to parse existing config JSON: ${(0, errors_1.getErrorMessage)(error)}`));
383
+ return;
384
+ }
385
+ let mcpServers = getMcpServersFromConfig(config, "mcpServers");
386
+ if (!mcpServers) {
387
+ mcpServers = {};
388
+ setMcpServersInConfig(config, "mcpServers", mcpServers);
389
+ }
390
+ if (mcpServers["clix-mcp-server"]) {
391
+ console.log(chalk_1.default.green(`✔ Clix MCP Server is already configured for ${scope} scope.`));
392
+ return;
393
+ }
394
+ const { inject } = await inquirer_1.default.prompt([
395
+ {
396
+ type: "confirm",
397
+ name: "inject",
398
+ message: `Add Clix MCP Server to ${nicePath}?`,
399
+ default: true,
400
+ },
401
+ ]);
402
+ if (inject) {
403
+ mcpServers["clix-mcp-server"] = CLIX_MCP_SERVER_ENTRY;
404
+ setMcpServersInConfig(config, "mcpServers", mcpServers);
405
+ await fs_extra_1.default.writeJSON(configPath, config, { spaces: 2 });
406
+ console.log(chalk_1.default.green(`✔ Added Clix MCP Server to configuration (${scope} scope).`));
407
+ }
408
+ }
409
+ async function configureFactory() {
410
+ const targets = [
411
+ { scope: "user", path: path_1.default.join(os_1.default.homedir(), ".factory", "mcp.json") },
412
+ { scope: "project", path: path_1.default.join(process.cwd(), ".factory", "mcp.json") },
413
+ ];
414
+ for (const target of targets) {
415
+ await configureFactoryConfig(target);
416
+ }
417
+ }
359
418
  // ============================================================================
360
419
  // Main Function
361
420
  // ============================================================================
@@ -374,6 +433,7 @@ async function configureMCP(client) {
374
433
  { name: "Claude Code", value: "claude" },
375
434
  { name: "Codex", value: "codex" },
376
435
  { name: "Cursor", value: "cursor" },
436
+ { name: "Factory", value: "factory" },
377
437
  { name: "Gemini CLI", value: "gemini" },
378
438
  { name: "GitHub", value: "github" },
379
439
  { name: "Goose", value: "goose" },
@@ -395,6 +455,11 @@ async function configureMCP(client) {
395
455
  console.log(chalk_1.default.blue("Skipping automatic MCP configuration."));
396
456
  return;
397
457
  }
458
+ // Factory supports user + project scoped config files; configure both.
459
+ if (targetClient === "factory") {
460
+ await configureFactory();
461
+ return;
462
+ }
398
463
  // Claude Code is configured via the `claude` CLI (no file editing).
399
464
  if (targetClient && isClaudeCodeClient(targetClient)) {
400
465
  await configureClaudeCode();
@@ -439,7 +504,7 @@ async function configureMCP(client) {
439
504
  console.log(chalk_1.default.green(`✔ Created config file at ${nicePath}`));
440
505
  }
441
506
  catch (error) {
442
- console.log(chalk_1.default.red(`Failed to create config file: ${getErrorMessage(error)}`));
507
+ console.log(chalk_1.default.red(`Failed to create config file: ${(0, errors_1.getErrorMessage)(error)}`));
443
508
  return;
444
509
  }
445
510
  }
@@ -449,7 +514,7 @@ async function configureMCP(client) {
449
514
  config = await fs_extra_1.default.readJSON(configPath);
450
515
  }
451
516
  catch (error) {
452
- console.log(chalk_1.default.red(`Failed to parse existing config JSON: ${getErrorMessage(error)}`));
517
+ console.log(chalk_1.default.red(`Failed to parse existing config JSON: ${(0, errors_1.getErrorMessage)(error)}`));
453
518
  return;
454
519
  }
455
520
  // Get or create mcpServers object
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clix-so/clix-agent-skills",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "An open collection of agent skills for Clix.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -20,10 +20,11 @@
20
20
  "lint": "prettier --check .",
21
21
  "lint:fix": "prettier --write .",
22
22
  "sync-version": "ts-node scripts/sync-version.ts",
23
+ "auto-version": "ts-node scripts/auto-version.ts",
23
24
  "generate-llms": "ts-node scripts/generate-llms.ts",
24
25
  "preversion": "npm run sync-version",
25
26
  "postversion": "npm run sync-version",
26
- "prepublishOnly": "npm run sync-version && npm run build && npm test && npm run generate-llms && npm run lint:fix"
27
+ "prepublishOnly": "npm install && npm run sync-version && npm run build && npm test && npm run generate-llms && npm run lint:fix"
27
28
  },
28
29
  "keywords": [
29
30
  "clix",