@funstack/skill-installer 1.0.0-alpha.0 → 1.0.0-alpha.2

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
@@ -1,6 +1,6 @@
1
1
  # @funstack/skill-installer
2
2
 
3
- A CLI tool to install AI Agent skills by copying skill files to the appropriate location.
3
+ A CLI tool and library to install AI Agent skills by copying skill files to the appropriate location.
4
4
 
5
5
  ## Installation
6
6
 
@@ -46,6 +46,20 @@ For CI/CD pipelines or scripted installations, set the `SKILL_INSTALL_PATH` envi
46
46
  SKILL_INSTALL_PATH=./.claude/skills skill-installer ./path/to/my-skill
47
47
  ```
48
48
 
49
+ ### Programmatic Usage
50
+
51
+ You can also use this package as a library:
52
+
53
+ ```typescript
54
+ import { install } from '@funstack/skill-installer';
55
+
56
+ // Prompts the user to select an agent and installs the skill
57
+ const installedPath = await install('./path/to/my-skill');
58
+ console.log(`Installed to: ${installedPath}`);
59
+ ```
60
+
61
+ The `install` function returns a promise that resolves to the final installation path.
62
+
49
63
  ## Supported AI Agents
50
64
 
51
65
  | Agent | Installation Path |
package/package.json CHANGED
@@ -1,15 +1,18 @@
1
1
  {
2
2
  "name": "@funstack/skill-installer",
3
- "version": "1.0.0-alpha.0",
4
- "description": "CLI tool to install Agent Skills",
3
+ "version": "1.0.0-alpha.2",
4
+ "description": "CLI tool and library to install Agent Skills",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/uhyo/funstack-skill-installer.git"
8
8
  },
9
9
  "type": "module",
10
- "main": "index.js",
10
+ "main": "src/index.ts",
11
11
  "bin": {
12
- "skill-installer": "./src/index.ts"
12
+ "skill-installer": "./src/cli.ts"
13
+ },
14
+ "exports": {
15
+ ".": "./src/index.ts"
13
16
  },
14
17
  "keywords": [],
15
18
  "author": "uhyo <uhyo@uhy.ooo>",
package/src/cli.ts ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { install } from "./index.ts";
4
+
5
+ async function main() {
6
+ const skillPath = process.argv[2];
7
+ if (!skillPath) {
8
+ console.error("Usage: skill-installer <skill-path>");
9
+ console.error(" <skill-path> Path to the skill directory to install");
10
+ process.exit(1);
11
+ }
12
+
13
+ await install(skillPath);
14
+ }
15
+
16
+ main().catch((error) => {
17
+ console.error("Error:", error.message);
18
+ process.exit(1);
19
+ });
package/src/index.ts CHANGED
@@ -1,5 +1,3 @@
1
- #!/usr/bin/env node
2
-
3
1
  import * as readline from "node:readline/promises";
4
2
  import * as fs from "node:fs/promises";
5
3
  import * as path from "node:path";
@@ -100,45 +98,40 @@ async function selectOption(
100
98
  });
101
99
  }
102
100
 
103
- async function main() {
104
- // 1. Parse CLI arguments
105
- const skillPath = process.argv[2];
106
- if (!skillPath) {
107
- console.error("Usage: skill-installer <skill-path>");
108
- console.error(" <skill-path> Path to the skill directory to install");
109
- process.exit(1);
110
- }
111
-
101
+ /**
102
+ * Install a skill to the appropriate AI agent directory.
103
+ * In TTY mode, prompts the user to select an agent.
104
+ * In non-TTY mode, uses the SKILL_INSTALL_PATH environment variable.
105
+ *
106
+ * @param skillPath - Path to the skill directory to install
107
+ * @returns The path where the skill was installed
108
+ */
109
+ export async function install(skillPath: string): Promise<string> {
112
110
  // Validate that the skill path exists and is a directory
113
111
  try {
114
112
  const stats = await fs.stat(skillPath);
115
113
  if (!stats.isDirectory()) {
116
- console.error(`Error: ${skillPath} is not a directory`);
117
- process.exit(1);
114
+ throw new Error(`${skillPath} is not a directory`);
115
+ }
116
+ } catch (error) {
117
+ if (error instanceof Error && error.message.includes("is not a directory")) {
118
+ throw error;
118
119
  }
119
- } catch {
120
- console.error(`Error: ${skillPath} does not exist`);
121
- process.exit(1);
120
+ throw new Error(`${skillPath} does not exist`);
122
121
  }
123
122
 
124
- // 2. Determine installation path
123
+ // Determine installation path
125
124
  let destinationPath: string;
126
125
 
127
126
  if (!stdin.isTTY) {
128
127
  // Non-TTY mode: read from environment variable
129
128
  const envPath = process.env.SKILL_INSTALL_PATH;
130
129
  if (!envPath) {
131
- console.error(
132
- "Error: stdin is not a TTY and SKILL_INSTALL_PATH is not set.",
130
+ throw new Error(
131
+ "stdin is not a TTY and SKILL_INSTALL_PATH is not set.\n\n" +
132
+ "In non-interactive mode, set the SKILL_INSTALL_PATH environment variable:\n" +
133
+ " SKILL_INSTALL_PATH=./.claude/skills skill-installer <skill-path>",
133
134
  );
134
- console.error("");
135
- console.error(
136
- "In non-interactive mode, set the SKILL_INSTALL_PATH environment variable:",
137
- );
138
- console.error(
139
- " SKILL_INSTALL_PATH=./.claude/skills skill-installer <skill-path>",
140
- );
141
- process.exit(1);
142
135
  }
143
136
  destinationPath = envPath;
144
137
  } else {
@@ -174,8 +167,7 @@ async function main() {
174
167
  "\nEnter custom installation path: ",
175
168
  );
176
169
  if (!customPath.trim()) {
177
- console.error("Error: Installation path cannot be empty");
178
- process.exit(1);
170
+ throw new Error("Installation path cannot be empty");
179
171
  }
180
172
  destinationPath = customPath.trim();
181
173
  } finally {
@@ -184,7 +176,7 @@ async function main() {
184
176
  }
185
177
  }
186
178
 
187
- // 4. Copy skill files
179
+ // Copy skill files
188
180
  // Create destination directory if it doesn't exist
189
181
  await fs.mkdir(destinationPath, { recursive: true });
190
182
 
@@ -200,9 +192,6 @@ async function main() {
200
192
  " Skill installed successfully to: " +
201
193
  styleText("bold", finalDestination),
202
194
  );
203
- }
204
195
 
205
- main().catch((error) => {
206
- console.error("Error:", error.message);
207
- process.exit(1);
208
- });
196
+ return finalDestination;
197
+ }