@hasna/skills 0.1.15 → 0.1.16

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/bin/index.js CHANGED
@@ -1914,7 +1914,7 @@ var package_default;
1914
1914
  var init_package = __esm(() => {
1915
1915
  package_default = {
1916
1916
  name: "@hasna/skills",
1917
- version: "0.1.15",
1917
+ version: "0.1.16",
1918
1918
  description: "Skills library for AI coding agents",
1919
1919
  type: "module",
1920
1920
  bin: {
@@ -1974,6 +1974,7 @@ var init_package = __esm(() => {
1974
1974
  typescript: "^5"
1975
1975
  },
1976
1976
  dependencies: {
1977
+ "@hasna/cloud": "^0.1.0",
1977
1978
  "@modelcontextprotocol/sdk": "^1.26.0",
1978
1979
  chalk: "^5.3.0",
1979
1980
  commander: "^12.1.0",
@@ -2070,7 +2071,10 @@ function loadRegistry(cwd) {
2070
2071
  return _registryCache;
2071
2072
  }
2072
2073
  const official = SKILLS.map((s) => ({ ...s, source: "official" }));
2073
- const globalCustom = discoverSkillsInDir(join(homedir(), ".skills"));
2074
+ const globalCustomNew = discoverSkillsInDir(join(homedir(), ".hasna", "skills", "custom"));
2075
+ const globalCustomOld = discoverSkillsInDir(join(homedir(), ".skills"));
2076
+ const oldNames = new Set(globalCustomNew.map((s) => s.name));
2077
+ const globalCustom = [...globalCustomNew, ...globalCustomOld.filter((s) => !oldNames.has(s.name))];
2074
2078
  const projectCustom = discoverSkillsInDir(join(cwd || process.cwd(), ".skills", "custom-skills"));
2075
2079
  const customNames = new Set([...globalCustom, ...projectCustom].map((s) => s.name));
2076
2080
  const filtered = official.filter((s) => !customNames.has(s.name));
@@ -37366,7 +37370,7 @@ init_installer();
37366
37370
  init_skillinfo();
37367
37371
 
37368
37372
  // src/lib/config.ts
37369
- import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
37373
+ import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, copyFileSync } from "fs";
37370
37374
  import { join as join4, dirname as dirname2 } from "path";
37371
37375
  import { homedir as homedir3 } from "os";
37372
37376
  var VALID_KEYS = {
@@ -37374,9 +37378,22 @@ var VALID_KEYS = {
37374
37378
  defaultScope: ["global", "project"],
37375
37379
  format: ["compact", "json", "csv"]
37376
37380
  };
37381
+ function getDataDir() {
37382
+ const home = process.env["HOME"] || process.env["USERPROFILE"] || homedir3();
37383
+ const newDir = join4(home, ".hasna", "skills");
37384
+ const oldConfigFile = join4(home, ".skillsrc");
37385
+ if (existsSync4(oldConfigFile) && !existsSync4(join4(newDir, "config.json"))) {
37386
+ mkdirSync2(newDir, { recursive: true });
37387
+ try {
37388
+ copyFileSync(oldConfigFile, join4(newDir, "config.json"));
37389
+ } catch {}
37390
+ }
37391
+ mkdirSync2(newDir, { recursive: true });
37392
+ return newDir;
37393
+ }
37377
37394
  function getConfigPath(scope) {
37378
37395
  if (scope === "global") {
37379
- return join4(homedir3(), ".skillsrc");
37396
+ return join4(getDataDir(), "config.json");
37380
37397
  }
37381
37398
  return join4(process.cwd(), "skills.config.json");
37382
37399
  }
@@ -39028,11 +39045,11 @@ configCmd.command("path").description("Show configuration file paths").action(()
39028
39045
  console.log(`${chalk2.cyan("global")}: ${globalPath}${existsSync8(globalPath) ? chalk2.green(" (exists)") : chalk2.dim(" (not found)")}`);
39029
39046
  console.log(`${chalk2.cyan("project")}: ${projectPath}${existsSync8(projectPath) ? chalk2.green(" (exists)") : chalk2.dim(" (not found)")}`);
39030
39047
  });
39031
- program2.command("create").argument("<name>", "Skill name (e.g. my-tool)").option("--category <category>", "Skill category", "Development Tools").option("--description <description>", "Short description of what the skill does").option("--tags <tags>", "Comma-separated tags (e.g. api,testing,automation)").option("--global", "Create in ~/.skills/ instead of .skills/custom-skills/", false).option("--json", "Output result as JSON", false).description("Scaffold a new custom skill directory").action((name, options) => {
39048
+ program2.command("create").argument("<name>", "Skill name (e.g. my-tool)").option("--category <category>", "Skill category", "Development Tools").option("--description <description>", "Short description of what the skill does").option("--tags <tags>", "Comma-separated tags (e.g. api,testing,automation)").option("--global", "Create in ~/.hasna/skills/custom/ instead of .skills/custom-skills/", false).option("--json", "Output result as JSON", false).description("Scaffold a new custom skill directory").action((name, options) => {
39032
39049
  const { homedir: homedir4 } = __require("os");
39033
39050
  const bare = name.replace(/^skill-/, "");
39034
39051
  const dirName = `skill-${bare}`;
39035
- const baseDir = options.global ? join8(homedir4(), ".skills") : join8(process.cwd(), ".skills", "custom-skills");
39052
+ const baseDir = options.global ? join8(homedir4(), ".hasna", "skills", "custom") : join8(process.cwd(), ".skills", "custom-skills");
39036
39053
  const skillDir = join8(baseDir, dirName);
39037
39054
  if (existsSync8(skillDir)) {
39038
39055
  if (options.json) {
@@ -39112,7 +39129,7 @@ program2.command("create").argument("<name>", "Skill name (e.g. my-tool)").optio
39112
39129
  console.log(` ${chalk2.cyan("Docs:")} ${join8(skillDir, "SKILL.md")}`);
39113
39130
  }
39114
39131
  });
39115
- program2.command("sync").option("--to <agent>", "Push custom skills to agent: claude, codex, gemini, pi, opencode, or all").option("--from <agent>", "List agent skills and show which are unknown to the registry").option("--register", "With --from: copy unknown agent skills into ~/.skills/ to add them to the registry", false).option("--scope <scope>", "Agent install scope: global or project", "global").option("--json", "Output as JSON", false).description("Sync custom skills with agent directories (--to or --from)").action((options) => {
39132
+ program2.command("sync").option("--to <agent>", "Push custom skills to agent: claude, codex, gemini, pi, opencode, or all").option("--from <agent>", "List agent skills and show which are unknown to the registry").option("--register", "With --from: copy unknown agent skills into ~/.hasna/skills/custom/ to add them to the registry", false).option("--scope <scope>", "Agent install scope: global or project", "global").option("--json", "Output as JSON", false).description("Sync custom skills with agent directories (--to or --from)").action((options) => {
39116
39133
  const { homedir: homedir4 } = __require("os");
39117
39134
  if (!options.to && !options.from) {
39118
39135
  console.error(chalk2.red("Specify --to <agent> or --from <agent>"));
@@ -39150,7 +39167,7 @@ program2.command("sync").option("--to <agent>", "Push custom skills to agent: cl
39150
39167
  }
39151
39168
  const unknown3 = found.filter((s) => !s.inRegistry);
39152
39169
  if (options.register && unknown3.length > 0) {
39153
- const globalSkillsDir = join8(homedir4(), ".skills");
39170
+ const globalSkillsDir = join8(homedir4(), ".hasna", "skills", "custom");
39154
39171
  const registered = [];
39155
39172
  for (const s of unknown3) {
39156
39173
  const srcSkillMd = join8(s.path, "SKILL.md");
@@ -39168,7 +39185,7 @@ program2.command("sync").option("--to <agent>", "Push custom skills to agent: cl
39168
39185
  console.log(JSON.stringify({ agentDir, skills: found, registered }));
39169
39186
  } else {
39170
39187
  for (const name of registered) {
39171
- console.log(chalk2.green(`\u2713 Registered '${name}' into ~/.skills/ (global custom)`));
39188
+ console.log(chalk2.green(`\u2713 Registered '${name}' into ~/.hasna/skills/custom/ (global custom)`));
39172
39189
  }
39173
39190
  if (registered.length === 0)
39174
39191
  console.log(chalk2.dim("No new skills to register (all SKILL.md files missing)"));
@@ -39187,7 +39204,7 @@ Agent skills in ~/.${agentName}/skills/ (${found.length} found):
39187
39204
  }
39188
39205
  if (unknown3.length > 0) {
39189
39206
  console.log("");
39190
- console.log(chalk2.dim(`Tip: ${unknown3.length} skill(s) not in registry. Run with --register to add them to ~/.skills/.`));
39207
+ console.log(chalk2.dim(`Tip: ${unknown3.length} skill(s) not in registry. Run with --register to add them to ~/.hasna/skills/custom/.`));
39191
39208
  }
39192
39209
  }
39193
39210
  return;
package/bin/mcp.js CHANGED
@@ -28566,7 +28566,7 @@ import { join as join5 } from "path";
28566
28566
  // package.json
28567
28567
  var package_default = {
28568
28568
  name: "@hasna/skills",
28569
- version: "0.1.15",
28569
+ version: "0.1.16",
28570
28570
  description: "Skills library for AI coding agents",
28571
28571
  type: "module",
28572
28572
  bin: {
@@ -28626,6 +28626,7 @@ var package_default = {
28626
28626
  typescript: "^5"
28627
28627
  },
28628
28628
  dependencies: {
28629
+ "@hasna/cloud": "^0.1.0",
28629
28630
  "@modelcontextprotocol/sdk": "^1.26.0",
28630
28631
  chalk: "^5.3.0",
28631
28632
  commander: "^12.1.0",
@@ -30174,7 +30175,10 @@ function loadRegistry(cwd) {
30174
30175
  return _registryCache;
30175
30176
  }
30176
30177
  const official = SKILLS.map((s) => ({ ...s, source: "official" }));
30177
- const globalCustom = discoverSkillsInDir(join(homedir(), ".skills"));
30178
+ const globalCustomNew = discoverSkillsInDir(join(homedir(), ".hasna", "skills", "custom"));
30179
+ const globalCustomOld = discoverSkillsInDir(join(homedir(), ".skills"));
30180
+ const oldNames = new Set(globalCustomNew.map((s) => s.name));
30181
+ const globalCustom = [...globalCustomNew, ...globalCustomOld.filter((s) => !oldNames.has(s.name))];
30178
30182
  const projectCustom = discoverSkillsInDir(join(cwd || process.cwd(), ".skills", "custom-skills"));
30179
30183
  const customNames = new Set([...globalCustom, ...projectCustom].map((s) => s.name));
30180
30184
  const filtered = official.filter((s) => !customNames.has(s.name));
package/dist/index.js CHANGED
@@ -1524,7 +1524,10 @@ function loadRegistry(cwd) {
1524
1524
  return _registryCache;
1525
1525
  }
1526
1526
  const official = SKILLS.map((s) => ({ ...s, source: "official" }));
1527
- const globalCustom = discoverSkillsInDir(join(homedir(), ".skills"));
1527
+ const globalCustomNew = discoverSkillsInDir(join(homedir(), ".hasna", "skills", "custom"));
1528
+ const globalCustomOld = discoverSkillsInDir(join(homedir(), ".skills"));
1529
+ const oldNames = new Set(globalCustomNew.map((s) => s.name));
1530
+ const globalCustom = [...globalCustomNew, ...globalCustomOld.filter((s) => !oldNames.has(s.name))];
1528
1531
  const projectCustom = discoverSkillsInDir(join(cwd || process.cwd(), ".skills", "custom-skills"));
1529
1532
  const customNames = new Set([...globalCustom, ...projectCustom].map((s) => s.name));
1530
1533
  const filtered = official.filter((s) => !customNames.has(s.name));
@@ -2216,7 +2219,7 @@ function readIfExists(path) {
2216
2219
  return null;
2217
2220
  }
2218
2221
  // src/lib/config.ts
2219
- import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
2222
+ import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, copyFileSync } from "fs";
2220
2223
  import { join as join4, dirname as dirname2 } from "path";
2221
2224
  import { homedir as homedir3 } from "os";
2222
2225
  var VALID_KEYS = {
@@ -2224,9 +2227,22 @@ var VALID_KEYS = {
2224
2227
  defaultScope: ["global", "project"],
2225
2228
  format: ["compact", "json", "csv"]
2226
2229
  };
2230
+ function getDataDir() {
2231
+ const home = process.env["HOME"] || process.env["USERPROFILE"] || homedir3();
2232
+ const newDir = join4(home, ".hasna", "skills");
2233
+ const oldConfigFile = join4(home, ".skillsrc");
2234
+ if (existsSync4(oldConfigFile) && !existsSync4(join4(newDir, "config.json"))) {
2235
+ mkdirSync2(newDir, { recursive: true });
2236
+ try {
2237
+ copyFileSync(oldConfigFile, join4(newDir, "config.json"));
2238
+ } catch {}
2239
+ }
2240
+ mkdirSync2(newDir, { recursive: true });
2241
+ return newDir;
2242
+ }
2227
2243
  function getConfigPath(scope) {
2228
2244
  if (scope === "global") {
2229
- return join4(homedir3(), ".skillsrc");
2245
+ return join4(getDataDir(), "config.json");
2230
2246
  }
2231
2247
  return join4(process.cwd(), "skills.config.json");
2232
2248
  }
@@ -3,7 +3,8 @@
3
3
  *
4
4
  * Loads configuration from:
5
5
  * 1. Project-local: ./skills.config.json (highest priority)
6
- * 2. Global: ~/.skillsrc (JSON format, lowest priority)
6
+ * 2. Global: ~/.hasna/skills/config.json (JSON format, lowest priority)
7
+ * (backward compat: also checks ~/.skillsrc)
7
8
  *
8
9
  * Values from the project config override global config.
9
10
  */
@@ -13,6 +14,12 @@ export interface SkillsConfig {
13
14
  format?: "compact" | "json" | "csv";
14
15
  }
15
16
  export type ConfigScope = "global" | "project";
17
+ /**
18
+ * Get the data directory for skills global config/data.
19
+ * New default: ~/.hasna/skills/
20
+ * Auto-migrates from ~/.skillsrc if the new config doesn't exist yet.
21
+ */
22
+ export declare function getDataDir(): string;
16
23
  /**
17
24
  * Get the config file path for a given scope
18
25
  */
@@ -15,7 +15,8 @@ export type Category = (typeof CATEGORIES)[number];
15
15
  export declare const SKILLS: SkillMeta[];
16
16
  /**
17
17
  * Load the full registry: official skills merged with custom skills from:
18
- * - ~/.skills/ (global custom)
18
+ * - ~/.hasna/skills/custom/ (global custom, new path)
19
+ * - ~/.skills/ (global custom, legacy path)
19
20
  * - ./.custom-skills/ (project-level custom, relative to cwd)
20
21
  *
21
22
  * Custom skills with the same name as official skills take precedence.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/skills",
3
- "version": "0.1.15",
3
+ "version": "0.1.16",
4
4
  "description": "Skills library for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
@@ -60,6 +60,7 @@
60
60
  "typescript": "^5"
61
61
  },
62
62
  "dependencies": {
63
+ "@hasna/cloud": "^0.1.0",
63
64
  "@modelcontextprotocol/sdk": "^1.26.0",
64
65
  "chalk": "^5.3.0",
65
66
  "commander": "^12.1.0",