@hasna/skills 0.1.31 → 0.1.32

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
@@ -1910,7 +1910,7 @@ var package_default;
1910
1910
  var init_package = __esm(() => {
1911
1911
  package_default = {
1912
1912
  name: "@hasna/skills",
1913
- version: "0.1.31",
1913
+ version: "0.1.32",
1914
1914
  description: "Skills library for AI coding agents",
1915
1915
  type: "module",
1916
1916
  bin: {
@@ -6863,6 +6863,130 @@ var init_discovery = __esm(() => {
6863
6863
  vendorPattern = new RegExp(`\\b(${VENDOR_TERMS.map(escapeRegExp).join("|")})\\b`, "gi");
6864
6864
  });
6865
6865
 
6866
+ // src/lib/config.ts
6867
+ import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, copyFileSync } from "fs";
6868
+ import { join as join4, dirname as dirname2 } from "path";
6869
+ import { homedir as homedir3 } from "os";
6870
+ function validKeys() {
6871
+ return ["mode", ...Object.keys(ENUM_KEYS), ...STRING_KEYS];
6872
+ }
6873
+ function allowedValues(key) {
6874
+ if (key === "mode")
6875
+ return MODE_VALUES;
6876
+ return ENUM_KEYS[key];
6877
+ }
6878
+ function normalizeConfigValue(key, value) {
6879
+ if (typeof value !== "string")
6880
+ return;
6881
+ if (key === "mode")
6882
+ return MODE_ALIASES[value.trim().toLowerCase()];
6883
+ const allowed = allowedValues(key);
6884
+ if (allowed)
6885
+ return allowed.includes(value) ? value : undefined;
6886
+ if (key === "apiUrl") {
6887
+ try {
6888
+ const url = new URL(value);
6889
+ if (url.protocol !== "http:" && url.protocol !== "https:")
6890
+ return;
6891
+ return value.replace(/\/+$/, "");
6892
+ } catch {
6893
+ return;
6894
+ }
6895
+ }
6896
+ return;
6897
+ }
6898
+ function getDataDir() {
6899
+ const home = process.env["HOME"] || process.env["USERPROFILE"] || homedir3();
6900
+ const newDir = join4(home, ".hasna", "skills");
6901
+ const oldConfigFile = join4(home, ".skillsrc");
6902
+ if (existsSync4(oldConfigFile) && !existsSync4(join4(newDir, "config.json"))) {
6903
+ mkdirSync2(newDir, { recursive: true });
6904
+ try {
6905
+ copyFileSync(oldConfigFile, join4(newDir, "config.json"));
6906
+ } catch {}
6907
+ }
6908
+ mkdirSync2(newDir, { recursive: true });
6909
+ return newDir;
6910
+ }
6911
+ function getConfigPath(scope) {
6912
+ if (scope === "global") {
6913
+ return join4(getDataDir(), "config.json");
6914
+ }
6915
+ return join4(process.cwd(), "skills.config.json");
6916
+ }
6917
+ function readConfigFile(path) {
6918
+ if (!existsSync4(path))
6919
+ return {};
6920
+ try {
6921
+ const raw = readFileSync4(path, "utf-8");
6922
+ const parsed = JSON.parse(raw);
6923
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))
6924
+ return {};
6925
+ const config = {};
6926
+ for (const key of validKeys()) {
6927
+ const value = normalizeConfigValue(key, parsed[key]);
6928
+ if (value !== undefined)
6929
+ config[key] = value;
6930
+ }
6931
+ return config;
6932
+ } catch {
6933
+ return {};
6934
+ }
6935
+ }
6936
+ function loadConfig() {
6937
+ const globalConfig = readConfigFile(getConfigPath("global"));
6938
+ const projectConfig = readConfigFile(getConfigPath("project"));
6939
+ return { ...globalConfig, ...projectConfig };
6940
+ }
6941
+ function saveConfig(key, value, scope = "project") {
6942
+ if (!validKeys().includes(key)) {
6943
+ throw new Error(`Unknown config key: ${key}. Valid keys: ${validKeys().join(", ")}`);
6944
+ }
6945
+ const normalized = normalizeConfigValue(key, value);
6946
+ if (normalized === undefined) {
6947
+ const allowed = allowedValues(key);
6948
+ throw new Error(allowed ? `Invalid value '${value}' for ${key}. Allowed: ${allowed.join(", ")}` : `Invalid value '${value}' for ${key}. Expected an http(s) URL`);
6949
+ }
6950
+ const filePath = getConfigPath(scope);
6951
+ let existing = {};
6952
+ if (existsSync4(filePath)) {
6953
+ try {
6954
+ existing = JSON.parse(readFileSync4(filePath, "utf-8"));
6955
+ if (typeof existing !== "object" || existing === null || Array.isArray(existing)) {
6956
+ existing = {};
6957
+ }
6958
+ } catch {
6959
+ existing = {};
6960
+ }
6961
+ } else {
6962
+ const dir = dirname2(filePath);
6963
+ if (!existsSync4(dir)) {
6964
+ mkdirSync2(dir, { recursive: true });
6965
+ }
6966
+ }
6967
+ existing[key] = normalized;
6968
+ writeFileSync2(filePath, JSON.stringify(existing, null, 2) + `
6969
+ `);
6970
+ }
6971
+ var ENUM_KEYS, STRING_KEYS, MODE_VALUES, MODE_ALIASES;
6972
+ var init_config = __esm(() => {
6973
+ ENUM_KEYS = {
6974
+ defaultAgent: ["claude", "codex", "gemini", "pi", "opencode", "all"],
6975
+ defaultScope: ["global", "project"],
6976
+ format: ["compact", "json", "csv"]
6977
+ };
6978
+ STRING_KEYS = ["apiUrl"];
6979
+ MODE_VALUES = ["local", "hosted"];
6980
+ MODE_ALIASES = {
6981
+ local: "local",
6982
+ offline: "local",
6983
+ hosted: "hosted",
6984
+ remote: "hosted",
6985
+ "skills.md": "hosted",
6986
+ skillsmd: "hosted"
6987
+ };
6988
+ });
6989
+
6866
6990
  // node_modules/zod/v4/core/core.js
6867
6991
  function $constructor(name, initializer, params) {
6868
6992
  function init(inst, def) {
@@ -20729,115 +20853,6 @@ var init_zod = __esm(() => {
20729
20853
  init_external();
20730
20854
  });
20731
20855
 
20732
- // src/lib/config.ts
20733
- import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, copyFileSync } from "fs";
20734
- import { join as join4, dirname as dirname2 } from "path";
20735
- import { homedir as homedir3 } from "os";
20736
- function validKeys() {
20737
- return [...Object.keys(ENUM_KEYS), ...STRING_KEYS];
20738
- }
20739
- function normalizeConfigValue(key, value) {
20740
- if (typeof value !== "string")
20741
- return;
20742
- const allowed = ENUM_KEYS[key];
20743
- if (allowed)
20744
- return allowed.includes(value) ? value : undefined;
20745
- if (key === "apiUrl") {
20746
- try {
20747
- const url2 = new URL(value);
20748
- if (url2.protocol !== "http:" && url2.protocol !== "https:")
20749
- return;
20750
- return value.replace(/\/+$/, "");
20751
- } catch {
20752
- return;
20753
- }
20754
- }
20755
- return;
20756
- }
20757
- function getDataDir() {
20758
- const home = process.env["HOME"] || process.env["USERPROFILE"] || homedir3();
20759
- const newDir = join4(home, ".hasna", "skills");
20760
- const oldConfigFile = join4(home, ".skillsrc");
20761
- if (existsSync4(oldConfigFile) && !existsSync4(join4(newDir, "config.json"))) {
20762
- mkdirSync2(newDir, { recursive: true });
20763
- try {
20764
- copyFileSync(oldConfigFile, join4(newDir, "config.json"));
20765
- } catch {}
20766
- }
20767
- mkdirSync2(newDir, { recursive: true });
20768
- return newDir;
20769
- }
20770
- function getConfigPath(scope) {
20771
- if (scope === "global") {
20772
- return join4(getDataDir(), "config.json");
20773
- }
20774
- return join4(process.cwd(), "skills.config.json");
20775
- }
20776
- function readConfigFile(path) {
20777
- if (!existsSync4(path))
20778
- return {};
20779
- try {
20780
- const raw = readFileSync4(path, "utf-8");
20781
- const parsed = JSON.parse(raw);
20782
- if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))
20783
- return {};
20784
- const config2 = {};
20785
- for (const key of validKeys()) {
20786
- const value = normalizeConfigValue(key, parsed[key]);
20787
- if (value !== undefined)
20788
- config2[key] = value;
20789
- }
20790
- return config2;
20791
- } catch {
20792
- return {};
20793
- }
20794
- }
20795
- function loadConfig() {
20796
- const globalConfig2 = readConfigFile(getConfigPath("global"));
20797
- const projectConfig = readConfigFile(getConfigPath("project"));
20798
- return { ...globalConfig2, ...projectConfig };
20799
- }
20800
- function saveConfig(key, value, scope = "project") {
20801
- if (!validKeys().includes(key)) {
20802
- throw new Error(`Unknown config key: ${key}. Valid keys: ${validKeys().join(", ")}`);
20803
- }
20804
- const normalized = normalizeConfigValue(key, value);
20805
- if (normalized === undefined) {
20806
- const allowed = ENUM_KEYS[key];
20807
- throw new Error(allowed ? `Invalid value '${value}' for ${key}. Allowed: ${allowed.join(", ")}` : `Invalid value '${value}' for ${key}. Expected an http(s) URL`);
20808
- }
20809
- const filePath = getConfigPath(scope);
20810
- let existing = {};
20811
- if (existsSync4(filePath)) {
20812
- try {
20813
- existing = JSON.parse(readFileSync4(filePath, "utf-8"));
20814
- if (typeof existing !== "object" || existing === null || Array.isArray(existing)) {
20815
- existing = {};
20816
- }
20817
- } catch {
20818
- existing = {};
20819
- }
20820
- } else {
20821
- const dir = dirname2(filePath);
20822
- if (!existsSync4(dir)) {
20823
- mkdirSync2(dir, { recursive: true });
20824
- }
20825
- }
20826
- existing[key] = normalized;
20827
- writeFileSync2(filePath, JSON.stringify(existing, null, 2) + `
20828
- `);
20829
- }
20830
- var ENUM_KEYS, STRING_KEYS;
20831
- var init_config = __esm(() => {
20832
- ENUM_KEYS = {
20833
- mode: ["local", "skills.md"],
20834
- defaultAgent: ["claude", "codex", "gemini", "pi", "opencode", "all"],
20835
- defaultScope: ["global", "project"],
20836
- format: ["compact", "json", "csv"]
20837
- };
20838
- STRING_KEYS = ["apiUrl"];
20839
- });
20840
-
20841
20856
  // src/lib/auth-store.ts
20842
20857
  var exports_auth_store = {};
20843
20858
  __export(exports_auth_store, {
@@ -20848,14 +20863,14 @@ __export(exports_auth_store, {
20848
20863
  getApiKey: () => getApiKey,
20849
20864
  clearAuthConfig: () => clearAuthConfig
20850
20865
  });
20851
- import { mkdirSync as mkdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync3, unlinkSync } from "fs";
20866
+ import { existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync3, unlinkSync } from "fs";
20852
20867
  import { join as join5 } from "path";
20853
20868
  import { homedir as homedir4 } from "os";
20854
20869
  function getAuthConfig() {
20855
20870
  if (cachedConfig !== undefined)
20856
20871
  return cachedConfig;
20857
20872
  try {
20858
- const raw = readFileSync5(AUTH_FILE, "utf-8");
20873
+ const raw = readFileSync5(existsSync5(AUTH_FILE) ? AUTH_FILE : LEGACY_AUTH_FILE, "utf-8");
20859
20874
  const config2 = JSON.parse(raw);
20860
20875
  if (!config2.apiKey || !config2.email) {
20861
20876
  cachedConfig = null;
@@ -20869,7 +20884,7 @@ function getAuthConfig() {
20869
20884
  }
20870
20885
  }
20871
20886
  function saveAuthConfig(config2) {
20872
- mkdirSync3(AUTH_DIR, { recursive: true });
20887
+ mkdirSync3(AUTH_DIR, { recursive: true, mode: 448 });
20873
20888
  writeFileSync3(AUTH_FILE, JSON.stringify(config2, null, 2) + `
20874
20889
  `, { mode: 384 });
20875
20890
  cachedConfig = config2;
@@ -20878,6 +20893,9 @@ function clearAuthConfig() {
20878
20893
  try {
20879
20894
  unlinkSync(AUTH_FILE);
20880
20895
  } catch {}
20896
+ try {
20897
+ unlinkSync(LEGACY_AUTH_FILE);
20898
+ } catch {}
20881
20899
  cachedConfig = null;
20882
20900
  }
20883
20901
  function getApiKey() {
@@ -20900,11 +20918,12 @@ function normalizeSkillsApiOrigin(apiUrl) {
20900
20918
  function getApiUrl() {
20901
20919
  return normalizeSkillsApiOrigin(process.env.SKILLS_API_URL || loadConfig().apiUrl || "https://skills.md");
20902
20920
  }
20903
- var AUTH_DIR, AUTH_FILE, cachedConfig;
20921
+ var AUTH_DIR, AUTH_FILE, LEGACY_AUTH_FILE, cachedConfig;
20904
20922
  var init_auth_store = __esm(() => {
20905
20923
  init_config();
20906
- AUTH_DIR = join5(homedir4(), ".skills");
20924
+ AUTH_DIR = join5(homedir4(), ".hasna", "skills");
20907
20925
  AUTH_FILE = join5(AUTH_DIR, "auth.json");
20926
+ LEGACY_AUTH_FILE = join5(homedir4(), ".skills", "auth.json");
20908
20927
  });
20909
20928
 
20910
20929
  // src/lib/remote-registry.ts
@@ -21543,11 +21562,11 @@ __export(exports_skillinfo, {
21543
21562
  generateEnvExample: () => generateEnvExample,
21544
21563
  detectProjectSkills: () => detectProjectSkills
21545
21564
  });
21546
- import { existsSync as existsSync5, readFileSync as readFileSync6 } from "fs";
21565
+ import { existsSync as existsSync6, readFileSync as readFileSync6 } from "fs";
21547
21566
  import { join as join6 } from "path";
21548
21567
  function getSkillDocs(name) {
21549
21568
  const skillPath = getSkillPath(name);
21550
- if (!existsSync5(skillPath))
21569
+ if (!existsSync6(skillPath))
21551
21570
  return null;
21552
21571
  return {
21553
21572
  skillMd: readIfExists(join6(skillPath, "SKILL.md")),
@@ -21563,7 +21582,7 @@ function getSkillBestDoc(name) {
21563
21582
  }
21564
21583
  function getSkillRequirements(name) {
21565
21584
  const skillPath = getSkillPath(name);
21566
- if (!existsSync5(skillPath))
21585
+ if (!existsSync6(skillPath))
21567
21586
  return null;
21568
21587
  const texts = [];
21569
21588
  for (const file2 of ["SKILL.md", "README.md", "CLAUDE.md", ".env.example", ".env.local.example"]) {
@@ -21606,7 +21625,7 @@ function getSkillRequirements(name) {
21606
21625
  let cliCommand = `skills run ${skillName}`;
21607
21626
  let dependencies = {};
21608
21627
  const pkgPath = join6(skillPath, "package.json");
21609
- if (existsSync5(pkgPath)) {
21628
+ if (existsSync6(pkgPath)) {
21610
21629
  try {
21611
21630
  const pkg = JSON.parse(readFileSync6(pkgPath, "utf-8"));
21612
21631
  dependencies = pkg.dependencies || {};
@@ -21625,11 +21644,11 @@ function isHostedPremiumSkill(skillName, meta3) {
21625
21644
  async function runSkill(name, args, options = {}) {
21626
21645
  const canonicalName = getSkill(name)?.name ?? name;
21627
21646
  const skillPath = getSkillPath(canonicalName);
21628
- if (!existsSync5(skillPath)) {
21647
+ if (!existsSync6(skillPath)) {
21629
21648
  return { exitCode: 1, error: `Skill '${name}' not found` };
21630
21649
  }
21631
21650
  const pkgPath = join6(skillPath, "package.json");
21632
- if (!existsSync5(pkgPath)) {
21651
+ if (!existsSync6(pkgPath)) {
21633
21652
  return { exitCode: 1, error: `No package.json in skill '${name}'` };
21634
21653
  }
21635
21654
  let entryPoint;
@@ -21649,11 +21668,11 @@ async function runSkill(name, args, options = {}) {
21649
21668
  return { exitCode: 1, error: `Failed to parse package.json for skill '${name}'` };
21650
21669
  }
21651
21670
  const entryPath = join6(skillPath, entryPoint);
21652
- if (!existsSync5(entryPath)) {
21671
+ if (!existsSync6(entryPath)) {
21653
21672
  return { exitCode: 1, error: `Entry point '${entryPoint}' not found in skill '${name}'` };
21654
21673
  }
21655
21674
  const nodeModules = join6(skillPath, "node_modules");
21656
- if (!existsSync5(nodeModules)) {
21675
+ if (!existsSync6(nodeModules)) {
21657
21676
  const install = Bun.spawn(["bun", "install", "--no-save"], {
21658
21677
  cwd: skillPath,
21659
21678
  stdout: "pipe",
@@ -21681,7 +21700,7 @@ async function runSkill(name, args, options = {}) {
21681
21700
  }
21682
21701
  function detectProjectSkills(cwd = process.cwd()) {
21683
21702
  const pkgPath = join6(cwd, "package.json");
21684
- if (!existsSync5(pkgPath)) {
21703
+ if (!existsSync6(pkgPath)) {
21685
21704
  const alwaysRecommend = ["implementation-plan", "write", "deepresearch"];
21686
21705
  const recommended2 = alwaysRecommend.map((name) => loadRegistry().find((s) => s.name === name)).filter((s) => s !== undefined);
21687
21706
  return { detected: [], recommended: recommended2 };
@@ -21812,7 +21831,7 @@ function generateSkillMd(name) {
21812
21831
  if (!meta3)
21813
21832
  return null;
21814
21833
  const skillPath = getSkillPath(name);
21815
- if (!existsSync5(skillPath))
21834
+ if (!existsSync6(skillPath))
21816
21835
  return null;
21817
21836
  const frontmatter = [
21818
21837
  "---",
@@ -21825,7 +21844,7 @@ function generateSkillMd(name) {
21825
21844
  const claudeMd = readIfExists(join6(skillPath, "CLAUDE.md"));
21826
21845
  let cliCommand = null;
21827
21846
  const pkgPath = join6(skillPath, "package.json");
21828
- if (existsSync5(pkgPath)) {
21847
+ if (existsSync6(pkgPath)) {
21829
21848
  try {
21830
21849
  const pkg = JSON.parse(readFileSync6(pkgPath, "utf-8"));
21831
21850
  if (pkg.bin) {
@@ -21900,7 +21919,7 @@ function extractEnvVars(text) {
21900
21919
  }
21901
21920
  function readIfExists(path) {
21902
21921
  try {
21903
- if (existsSync5(path)) {
21922
+ if (existsSync6(path)) {
21904
21923
  return readFileSync6(path, "utf-8");
21905
21924
  }
21906
21925
  } catch {}
@@ -21932,7 +21951,7 @@ var init_skillinfo = __esm(() => {
21932
21951
  });
21933
21952
 
21934
21953
  // src/lib/skill-validation.ts
21935
- import { existsSync as existsSync6, lstatSync, readFileSync as readFileSync7, readdirSync as readdirSync2, statSync } from "fs";
21954
+ import { existsSync as existsSync7, lstatSync, readFileSync as readFileSync7, readdirSync as readdirSync2, statSync } from "fs";
21936
21955
  import { isAbsolute, join as join7, normalize } from "path";
21937
21956
  function add(target, code, message) {
21938
21957
  target.push({ code, message });
@@ -22005,7 +22024,7 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
22005
22024
  binCommands: [],
22006
22025
  docFiles: []
22007
22026
  };
22008
- if (!existsSync6(skillPath)) {
22027
+ if (!existsSync7(skillPath)) {
22009
22028
  add(issues, "skill.dir_missing", `Skill directory not found: ${skillPath}`);
22010
22029
  return {
22011
22030
  name: bareName,
@@ -22032,14 +22051,14 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
22032
22051
  }
22033
22052
  }
22034
22053
  for (const docFile of DOC_FILES) {
22035
- if (existsSync6(join7(skillPath, docFile)))
22054
+ if (existsSync7(join7(skillPath, docFile)))
22036
22055
  metadata.docFiles.push(docFile);
22037
22056
  }
22038
22057
  if (metadata.docFiles.length === 0) {
22039
22058
  add(issues, "skill.docs_missing", "Missing documentation file: expected SKILL.md, README.md, or CLAUDE.md");
22040
22059
  }
22041
22060
  const skillMdPath = join7(skillPath, "SKILL.md");
22042
- if (existsSync6(skillMdPath)) {
22061
+ if (existsSync7(skillMdPath)) {
22043
22062
  const frontmatter = parseSkillFrontmatter(readFileSync7(skillMdPath, "utf-8"));
22044
22063
  if (!frontmatter) {
22045
22064
  add(warnings, "skill.frontmatter_missing", "SKILL.md has no YAML frontmatter");
@@ -22074,7 +22093,7 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
22074
22093
  add(warnings, "skill.skill_md_missing", "Missing SKILL.md; registry docs may need generated agent-facing instructions");
22075
22094
  }
22076
22095
  const pkgPath = join7(skillPath, "package.json");
22077
- if (!existsSync6(pkgPath)) {
22096
+ if (!existsSync7(pkgPath)) {
22078
22097
  add(issues, "package.missing", "Missing package.json");
22079
22098
  } else {
22080
22099
  try {
@@ -22119,7 +22138,7 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
22119
22138
  continue;
22120
22139
  }
22121
22140
  const targetPath = join7(skillPath, target);
22122
- if (!existsSync6(targetPath)) {
22141
+ if (!existsSync7(targetPath)) {
22123
22142
  add(warnings, "package.bin_target_missing", `package.json bin '${command}' target '${target}' is not present before build`);
22124
22143
  } else if (statSync(targetPath).isDirectory()) {
22125
22144
  add(issues, "package.bin_target_directory", `package.json bin '${command}' target '${target}' must point to a file, not a directory`);
@@ -22132,12 +22151,12 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
22132
22151
  }
22133
22152
  }
22134
22153
  const srcDir = join7(skillPath, "src");
22135
- if (!existsSync6(srcDir)) {
22154
+ if (!existsSync7(srcDir)) {
22136
22155
  add(issues, "skill.src_missing", "Missing src/ directory");
22137
- } else if (!existsSync6(join7(srcDir, "index.ts")) && !existsSync6(join7(srcDir, "index.js"))) {
22156
+ } else if (!existsSync7(join7(srcDir, "index.ts")) && !existsSync7(join7(srcDir, "index.js"))) {
22138
22157
  add(issues, "skill.src_index_missing", "Missing src/index.ts or src/index.js");
22139
22158
  } else {
22140
- const indexPath = existsSync6(join7(srcDir, "index.ts")) ? join7(srcDir, "index.ts") : join7(srcDir, "index.js");
22159
+ const indexPath = existsSync7(join7(srcDir, "index.ts")) ? join7(srcDir, "index.ts") : join7(srcDir, "index.js");
22141
22160
  const size = statSync(indexPath).size;
22142
22161
  if (size < 50)
22143
22162
  add(warnings, "skill.src_index_minimal", `Source entry point is very small (${size}B)`);
@@ -22205,7 +22224,7 @@ __export(exports_introspect, {
22205
22224
  registerIntrospect: () => registerIntrospect
22206
22225
  });
22207
22226
  import chalk4 from "chalk";
22208
- import { existsSync as existsSync7, readFileSync as readFileSync8 } from "fs";
22227
+ import { existsSync as existsSync8, readFileSync as readFileSync8 } from "fs";
22209
22228
  import { join as join8 } from "path";
22210
22229
  import { execSync } from "child_process";
22211
22230
  function registerIntrospect(parent) {
@@ -22417,7 +22436,7 @@ function handleValidate(name, options) {
22417
22436
  function handleDiff(name, options) {
22418
22437
  const bare = name;
22419
22438
  const sourcePath = getSkillPath(bare);
22420
- if (!existsSync7(sourcePath)) {
22439
+ if (!existsSync8(sourcePath)) {
22421
22440
  if (options.json)
22422
22441
  console.log(JSON.stringify({ error: `Skill '${bare}' not found in registry` }));
22423
22442
  else
@@ -22436,7 +22455,7 @@ function handleDiff(name, options) {
22436
22455
  const installedVersion = installMeta.skills[bare]?.version ?? "unknown";
22437
22456
  const registryPkgPath = join8(sourcePath, "package.json");
22438
22457
  let registryVersion = "unknown";
22439
- if (existsSync7(registryPkgPath)) {
22458
+ if (existsSync8(registryPkgPath)) {
22440
22459
  try {
22441
22460
  registryVersion = JSON.parse(readFileSync8(registryPkgPath, "utf-8")).version || "unknown";
22442
22461
  } catch {}
@@ -22469,7 +22488,7 @@ __export(exports_init, {
22469
22488
  registerSetup: () => registerSetup
22470
22489
  });
22471
22490
  import chalk5 from "chalk";
22472
- import { existsSync as existsSync8, readFileSync as readFileSync9, writeFileSync as writeFileSync4, appendFileSync } from "fs";
22491
+ import { existsSync as existsSync9, readFileSync as readFileSync9, writeFileSync as writeFileSync4, appendFileSync } from "fs";
22473
22492
  import { join as join9 } from "path";
22474
22493
  function registerSetup(parent) {
22475
22494
  parent.command("init").option("--json", "Output as JSON", false).option("--for <agent>", "Detect project type and show MCP registration guidance for agent").option("--scope <scope>", "Deprecated; agent skill-folder installs are disabled", "global").description("Initialize project for pinned skills (.env.example, .gitignore)").action((options) => handleInit(options));
@@ -22564,7 +22583,7 @@ Use: skills mcp --register ${options.for}`));
22564
22583
  console.log(chalk5.dim(" No environment variables detected across pinned skills"));
22565
22584
  const gitignorePath = join9(cwd, ".gitignore");
22566
22585
  const gitignoreEntries = [".skills/runs/", ".skills/exports/", ".skills/tmp/"];
22567
- let gitignoreContent = existsSync8(gitignorePath) ? readFileSync9(gitignorePath, "utf-8") : "";
22586
+ let gitignoreContent = existsSync9(gitignorePath) ? readFileSync9(gitignorePath, "utf-8") : "";
22568
22587
  let gitignoreUpdated = false;
22569
22588
  const missingEntries = gitignoreEntries.filter((entry) => !gitignoreContent.includes(entry));
22570
22589
  if (missingEntries.length > 0) {
@@ -22610,7 +22629,7 @@ async function handleImport(file2, options) {
22610
22629
  if (file2 === "-")
22611
22630
  raw = await new Response(process.stdin).text();
22612
22631
  else {
22613
- if (!existsSync8(file2)) {
22632
+ if (!existsSync9(file2)) {
22614
22633
  const error48 = `File not found: ${file2}`;
22615
22634
  if (options.json)
22616
22635
  console.log(JSON.stringify({ imported: 0, error: error48 }));
@@ -22720,7 +22739,7 @@ __export(exports_diagnostic, {
22720
22739
  registerDiagnostic: () => registerDiagnostic
22721
22740
  });
22722
22741
  import chalk6 from "chalk";
22723
- import { existsSync as existsSync9, readFileSync as readFileSync10, readdirSync as readdirSync3, statSync as statSync2, writeFileSync as writeFileSync5 } from "fs";
22742
+ import { existsSync as existsSync10, readFileSync as readFileSync10, readdirSync as readdirSync3, statSync as statSync2, writeFileSync as writeFileSync5 } from "fs";
22724
22743
  import { join as join10 } from "path";
22725
22744
  import { execSync as execSync2 } from "child_process";
22726
22745
  function registerDiagnostic(parent) {
@@ -22856,7 +22875,7 @@ function handleAuth(name, options) {
22856
22875
  process.exitCode = 1;
22857
22876
  return;
22858
22877
  }
22859
- let existing = existsSync9(envFilePath) ? readFileSync10(envFilePath, "utf-8") : "";
22878
+ let existing = existsSync10(envFilePath) ? readFileSync10(envFilePath, "utf-8") : "";
22860
22879
  const keyPattern = new RegExp(`^${key}=.*$`, "m");
22861
22880
  const updated = keyPattern.test(existing) ? existing.replace(keyPattern, `${key}=${value}`) : existing.endsWith(`
22862
22881
  `) || existing === "" ? existing + `${key}=${value}
@@ -22922,7 +22941,7 @@ function handleWhoami(options) {
22922
22941
  const agentConfigs = [];
22923
22942
  for (const agent of AGENT_TARGETS) {
22924
22943
  const agentSkillsPath = getAgentSkillsDir(agent, "global");
22925
- const exists = existsSync9(agentSkillsPath);
22944
+ const exists = existsSync10(agentSkillsPath);
22926
22945
  let skillCount = 0;
22927
22946
  if (exists)
22928
22947
  try {
@@ -22967,7 +22986,7 @@ function handleOutdated(options) {
22967
22986
  const registryPath = getSkillPath(name);
22968
22987
  const registryPkgPath = join10(registryPath, "package.json");
22969
22988
  let registryVersion = "unknown";
22970
- if (existsSync9(registryPkgPath))
22989
+ if (existsSync10(registryPkgPath))
22971
22990
  try {
22972
22991
  registryVersion = JSON.parse(readFileSync10(registryPkgPath, "utf-8")).version || "unknown";
22973
22992
  } catch {}
@@ -23058,7 +23077,7 @@ var REMOTE_SKILL_RUN_CONTRACT_VERSION = 1;
23058
23077
 
23059
23078
  // src/lib/run-state.ts
23060
23079
  import { createHash, randomBytes } from "crypto";
23061
- import { existsSync as existsSync10, mkdirSync as mkdirSync4, readFileSync as readFileSync11, readdirSync as readdirSync4, statSync as statSync3, writeFileSync as writeFileSync6 } from "fs";
23080
+ import { existsSync as existsSync11, mkdirSync as mkdirSync4, readFileSync as readFileSync11, readdirSync as readdirSync4, statSync as statSync3, writeFileSync as writeFileSync6 } from "fs";
23062
23081
  import { extname, join as join11, relative } from "path";
23063
23082
  function createSkillRun(params, targetDir = process.cwd()) {
23064
23083
  const now = new Date;
@@ -23125,12 +23144,12 @@ function appendRunEvent(context, event, data = {}) {
23125
23144
  const line = JSON.stringify({ ts: new Date().toISOString(), event, ...data }) + `
23126
23145
  `;
23127
23146
  const path = join11(context.runDir, "events.ndjson");
23128
- const previous = existsSync10(path) ? readFileSync11(path, "utf-8") : "";
23147
+ const previous = existsSync11(path) ? readFileSync11(path, "utf-8") : "";
23129
23148
  writeFileSync6(path, previous + line);
23130
23149
  }
23131
23150
  function listSkillRuns(targetDir = process.cwd(), limit = 50) {
23132
23151
  const runsRoot = join11(getProjectStateDir(targetDir), "runs");
23133
- if (!existsSync10(runsRoot))
23152
+ if (!existsSync11(runsRoot))
23134
23153
  return [];
23135
23154
  const records = [];
23136
23155
  for (const day of readdirSync4(runsRoot).sort().reverse()) {
@@ -23149,7 +23168,7 @@ function listSkillRuns(targetDir = process.cwd(), limit = 50) {
23149
23168
  }
23150
23169
  function findSkillRun(runId, targetDir = process.cwd()) {
23151
23170
  const runsRoot = join11(getProjectStateDir(targetDir), "runs");
23152
- if (!existsSync10(runsRoot))
23171
+ if (!existsSync11(runsRoot))
23153
23172
  return null;
23154
23173
  for (const day of readdirSync4(runsRoot)) {
23155
23174
  const record2 = readRunRecord(join11(runsRoot, day, runId));
@@ -23170,7 +23189,7 @@ function writeArtifactsManifest(context, artifacts) {
23170
23189
  `);
23171
23190
  }
23172
23191
  function collectRunArtifacts(context) {
23173
- if (!existsSync10(context.exportDir))
23192
+ if (!existsSync11(context.exportDir))
23174
23193
  return [];
23175
23194
  const artifacts = [];
23176
23195
  for (const path of walkFiles(context.exportDir)) {
@@ -23187,7 +23206,7 @@ function collectRunArtifacts(context) {
23187
23206
  }
23188
23207
  function readRunRecord(runDir) {
23189
23208
  const path = join11(runDir, "run.json");
23190
- if (!existsSync10(path))
23209
+ if (!existsSync11(path))
23191
23210
  return null;
23192
23211
  try {
23193
23212
  return JSON.parse(readFileSync11(path, "utf-8"));
@@ -39276,7 +39295,7 @@ var init_remote_client = __esm(() => {
39276
39295
  });
39277
39296
 
39278
39297
  // src/mcp/operation-tools.ts
39279
- import { existsSync as existsSync11, readdirSync as readdirSync5, statSync as statSync4 } from "fs";
39298
+ import { existsSync as existsSync12, readdirSync as readdirSync5, statSync as statSync4 } from "fs";
39280
39299
  import { join as join12 } from "path";
39281
39300
  function registerOperationTools(server) {
39282
39301
  server.registerTool("pin_skill", {
@@ -39497,7 +39516,7 @@ function registerOperationTools(server) {
39497
39516
  });
39498
39517
  if (isPremiumSkill2(skillName) && !apiKey) {
39499
39518
  const cost = formatCost2(costCents ?? 0);
39500
- const error48 = `${skillName} is a hosted skill (${cost}). Run: skills setup --mode skills.md && skills auth login`;
39519
+ const error48 = `${skillName} is a hosted skill (${cost}). Run: skills setup --mode hosted && skills auth login`;
39501
39520
  writeRunLogs(runContext, "", error48 + `
39502
39521
  `);
39503
39522
  const run = completeSkillRun(runContext, { status: "failed", error: error48, costCents });
@@ -39533,9 +39552,9 @@ function registerOperationTools(server) {
39533
39552
  nextActions: remoteRunNextActions(remoteRunId)
39534
39553
  });
39535
39554
  } catch (err) {
39536
- console.error(`[skills] skills.md API failed for ${skillName}, falling back to local:`, err.message);
39555
+ console.error(`[skills] hosted API failed for ${skillName}, falling back to local:`, err.message);
39537
39556
  if (isPremiumSkill2(skillName)) {
39538
- const error48 = `Hosted skill ${skillName} requires skills.md access: ${err.message}`;
39557
+ const error48 = `Hosted skill ${skillName} requires hosted access: ${err.message}`;
39539
39558
  writeRunLogs(runContext, "", error48 + `
39540
39559
  `);
39541
39560
  const localRun2 = completeSkillRun(runContext, { status: "failed", error: error48 });
@@ -39576,7 +39595,7 @@ function registerOperationTools(server) {
39576
39595
  const { getApiKey: getApiKey2 } = await Promise.resolve().then(() => (init_auth_store(), exports_auth_store));
39577
39596
  const apiKey = getApiKey2();
39578
39597
  if (!apiKey) {
39579
- return mcpError("AUTH_REQUIRED", "Remote run status requires skills.md access. Run: skills auth login", ["skills auth login"]);
39598
+ return mcpError("AUTH_REQUIRED", "Remote run status requires hosted access. Run: skills auth login", ["skills auth login"]);
39580
39599
  }
39581
39600
  const localRun = findSkillRun(run_id);
39582
39601
  const remoteRunId = localRun?.remoteRunId || run_id;
@@ -39662,7 +39681,7 @@ function registerOperationTools(server) {
39662
39681
  const agents = [];
39663
39682
  for (const agent of AGENT_TARGETS) {
39664
39683
  const agentSkillsPath = getAgentSkillsDir(agent, "global");
39665
- const exists = existsSync11(agentSkillsPath);
39684
+ const exists = existsSync12(agentSkillsPath);
39666
39685
  let skillCount = 0;
39667
39686
  if (exists) {
39668
39687
  try {
@@ -39697,7 +39716,7 @@ var init_operation_tools = __esm(() => {
39697
39716
  });
39698
39717
 
39699
39718
  // src/lib/feedback.ts
39700
- import { existsSync as existsSync12, mkdirSync as mkdirSync5 } from "fs";
39719
+ import { existsSync as existsSync13, mkdirSync as mkdirSync5 } from "fs";
39701
39720
  import { homedir as homedir5 } from "os";
39702
39721
  import { dirname as dirname3, join as join13 } from "path";
39703
39722
  import { Database } from "bun:sqlite";
@@ -39707,7 +39726,7 @@ function getFeedbackDbPath() {
39707
39726
  function getFeedbackDb() {
39708
39727
  const dbPath = getFeedbackDbPath();
39709
39728
  const dir = dirname3(dbPath);
39710
- if (!existsSync12(dir))
39729
+ if (!existsSync13(dir))
39711
39730
  mkdirSync5(dir, { recursive: true });
39712
39731
  const db = new Database(dbPath);
39713
39732
  db.exec("PRAGMA journal_mode = WAL");
@@ -39868,14 +39887,14 @@ var init_resource_meta_tools = __esm(() => {
39868
39887
  });
39869
39888
 
39870
39889
  // src/lib/scheduler.ts
39871
- import { existsSync as existsSync13, readFileSync as readFileSync12, writeFileSync as writeFileSync7, mkdirSync as mkdirSync6 } from "fs";
39890
+ import { existsSync as existsSync14, readFileSync as readFileSync12, writeFileSync as writeFileSync7, mkdirSync as mkdirSync6 } from "fs";
39872
39891
  import { join as join14 } from "path";
39873
39892
  function getSchedulesPath(targetDir = process.cwd()) {
39874
39893
  return join14(targetDir, ".skills", "schedules.json");
39875
39894
  }
39876
39895
  function loadSchedules(targetDir = process.cwd()) {
39877
39896
  const path = getSchedulesPath(targetDir);
39878
- if (existsSync13(path)) {
39897
+ if (existsSync14(path)) {
39879
39898
  try {
39880
39899
  return JSON.parse(readFileSync12(path, "utf-8"));
39881
39900
  } catch {}
@@ -39885,7 +39904,7 @@ function loadSchedules(targetDir = process.cwd()) {
39885
39904
  function saveSchedules(data, targetDir = process.cwd()) {
39886
39905
  const path = getSchedulesPath(targetDir);
39887
39906
  const dir = join14(targetDir, ".skills");
39888
- if (!existsSync13(dir))
39907
+ if (!existsSync14(dir))
39889
39908
  mkdirSync6(dir, { recursive: true });
39890
39909
  writeFileSync7(path, JSON.stringify(data, null, 2));
39891
39910
  }
@@ -40430,7 +40449,7 @@ var init_mcp2 = __esm(() => {
40430
40449
 
40431
40450
  // src/cli/commands/runtime-mcp.ts
40432
40451
  import chalk7 from "chalk";
40433
- import { existsSync as existsSync14, mkdirSync as mkdirSync7, readFileSync as readFileSync13, writeFileSync as writeFileSync8 } from "fs";
40452
+ import { existsSync as existsSync15, mkdirSync as mkdirSync7, readFileSync as readFileSync13, writeFileSync as writeFileSync8 } from "fs";
40434
40453
  import { homedir as homedir6 } from "os";
40435
40454
  import { dirname as dirname4, join as join15 } from "path";
40436
40455
  async function handleMcp(options) {
@@ -40540,7 +40559,7 @@ function registerCodexMcp(command) {
40540
40559
  const config2 = `[mcp_servers.${MCP_SERVER_NAME}]
40541
40560
  command = ${JSON.stringify(command)}`;
40542
40561
  try {
40543
- const current = existsSync14(path) ? readFileSync13(path, "utf-8") : "";
40562
+ const current = existsSync15(path) ? readFileSync13(path, "utf-8") : "";
40544
40563
  writeTextFile(path, upsertTomlSection(current, `[mcp_servers.${MCP_SERVER_NAME}]`, `command = ${JSON.stringify(command)}`));
40545
40564
  return { agent: "codex", success: true, path, config: config2 };
40546
40565
  } catch (err) {
@@ -40590,7 +40609,7 @@ function registerJsonMcpServer(agent, path, containerKey, server2) {
40590
40609
  }
40591
40610
  }
40592
40611
  function readJsonObject(path) {
40593
- if (!existsSync14(path))
40612
+ if (!existsSync15(path))
40594
40613
  return {};
40595
40614
  const raw = readFileSync13(path, "utf-8").trim();
40596
40615
  if (!raw)
@@ -40637,7 +40656,7 @@ function findCommandOnPath(command) {
40637
40656
  if (!dir)
40638
40657
  continue;
40639
40658
  const candidate = join15(dir, command);
40640
- if (existsSync14(candidate))
40659
+ if (existsSync15(candidate))
40641
40660
  return candidate;
40642
40661
  }
40643
40662
  return command;
@@ -40670,7 +40689,7 @@ function registerRuntime(parent) {
40670
40689
  exportsCommand.command("open").argument("<run-id>", "Run id").option("--json", "Output as JSON", false).description("Open the export directory for a run").action((runId, options) => handleExportsOpen(runId, options));
40671
40690
  exportsCommand.command("download").argument("<run-id>", "Remote run id").option("--json", "Output as JSON", false).description("Download remote run artifacts into .skills/exports").action((runId, options) => handleExportsDownload(runId, options));
40672
40691
  parent.command("mcp").option("--register <agent>", "Register MCP server with agent").option("--json", "Output registration result as JSON", false).description("Start MCP server (stdio) or register with an agent").action(async (options) => handleMcp(options));
40673
- const setup = parent.command("setup").description("Choose local-only mode, skills.md mode, or agent integrations").option("--mode <mode>", "Runtime mode: local or skills.md").option("--api-url <url>", "skills.md-compatible API origin for hosted mode").option("--global", "Save setup choice globally", false).option("--json", "Output setup result as JSON", false).action(async (options) => handleSetup(options));
40692
+ const setup = parent.command("setup").description("Choose hosted mode, local-only mode, or agent integrations").option("--mode <mode>", "Runtime mode: hosted or local").option("--api-url <url>", "Hosted API origin").option("--global", "Save setup choice globally", false).option("--json", "Output setup result as JSON", false).action(async (options) => handleSetup(options));
40674
40693
  setup.command("agents").option("--json", "Output registration result as JSON", false).description("Register the Skills MCP server with all supported agents").action(async (options) => handleMcp({ register: "all", json: options.json }));
40675
40694
  parent.command("self-update").description("Update @hasna/skills to the latest version").option("--json", "Output result as JSON", false).action(async (options) => {
40676
40695
  if (process.env.SKILLS_TEST_MODE === "1") {
@@ -40719,15 +40738,15 @@ async function handleSetup(options) {
40719
40738
  const scope = options.global ? "global" : "project";
40720
40739
  let mode = normalizeSetupMode(options.mode);
40721
40740
  if (!mode && process.stdin.isTTY && process.stdout.isTTY) {
40722
- mode = normalizeSetupMode(await promptLine("Use Skills locally or with skills.md? [local/skills.md] "));
40741
+ mode = normalizeSetupMode(await promptLine("Use hosted Skills or local-only mode? [hosted/local] ")) ?? "hosted";
40723
40742
  }
40724
40743
  mode = mode ?? "local";
40725
40744
  saveConfig("mode", mode, scope);
40726
- if (mode === "skills.md") {
40745
+ if (mode === "hosted") {
40727
40746
  saveConfig("apiUrl", options.apiUrl || "https://skills.md", scope);
40728
40747
  }
40729
40748
  const config2 = loadConfig();
40730
- const next = mode === "skills.md" ? ["skills auth login", "skills list --remote"] : ["skills list", "skills run <skill>"];
40749
+ const next = mode === "hosted" ? ["skills auth login", "skills list --remote"] : ["skills list", "skills run <skill>"];
40731
40750
  const payload = {
40732
40751
  mode,
40733
40752
  scope,
@@ -40740,7 +40759,7 @@ async function handleSetup(options) {
40740
40759
  }
40741
40760
  console.log(chalk8.green(`Set Skills mode to ${mode}`));
40742
40761
  console.log(chalk8.dim(` Scope: ${scope}`));
40743
- if (mode === "skills.md") {
40762
+ if (mode === "hosted") {
40744
40763
  console.log(chalk8.dim(` API: ${config2.apiUrl || "https://skills.md"}`));
40745
40764
  console.log(chalk8.dim(" Next: skills auth login"));
40746
40765
  } else {
@@ -40755,8 +40774,8 @@ function normalizeSetupMode(value) {
40755
40774
  if (normalized === "local" || normalized === "offline")
40756
40775
  return "local";
40757
40776
  if (normalized === "skills.md" || normalized === "skillsmd" || normalized === "remote" || normalized === "hosted")
40758
- return "skills.md";
40759
- throw new Error("Invalid setup mode. Use local or skills.md.");
40777
+ return "hosted";
40778
+ throw new Error("Invalid setup mode. Use hosted or local.");
40760
40779
  }
40761
40780
  function promptLine(question) {
40762
40781
  const rl = createInterface({ input: process.stdin, output: process.stdout });
@@ -40845,7 +40864,7 @@ async function handleRun(name, args2, options) {
40845
40864
  const { getApiKey: getApiKey2 } = await Promise.resolve().then(() => (init_auth_store(), exports_auth_store));
40846
40865
  const apiKey = getApiKey2();
40847
40866
  if (!apiKey) {
40848
- const error48 = `${skill.name} is a hosted skill (${pricing.formatCost(costCents ?? 0)}). Run: skills setup --mode skills.md && skills auth login`;
40867
+ const error48 = `${skill.name} is a hosted skill (${pricing.formatCost(costCents ?? 0)}). Run: skills setup --mode hosted && skills auth login`;
40849
40868
  writeRunLogs(runContext, "", error48 + `
40850
40869
  `);
40851
40870
  const run = completeSkillRun(runContext, { status: "failed", error: error48, costCents });
@@ -40927,7 +40946,7 @@ async function handleRun(name, args2, options) {
40927
40946
  process.exitCode = exitCode;
40928
40947
  return;
40929
40948
  } catch (err) {
40930
- const error48 = `Hosted skill ${skill.name} requires skills.md access: ${err.message}`;
40949
+ const error48 = `Hosted skill ${skill.name} requires hosted access: ${err.message}`;
40931
40950
  writeRunLogs(runContext, "", error48 + `
40932
40951
  `);
40933
40952
  const run = completeSkillRun(runContext, { status: "failed", error: error48, costCents });
@@ -41033,7 +41052,7 @@ async function handleRunsStatus(runId, options) {
41033
41052
  const { getApiKey: getApiKey2 } = await Promise.resolve().then(() => (init_auth_store(), exports_auth_store));
41034
41053
  const apiKey = getApiKey2();
41035
41054
  if (!apiKey) {
41036
- const error48 = "Remote run status requires skills.md access. Run: skills auth login";
41055
+ const error48 = "Remote run status requires hosted access. Run: skills auth login";
41037
41056
  if (options.json)
41038
41057
  console.log(JSON.stringify({ contractVersion: REMOTE_SKILL_RUN_CONTRACT_VERSION, error: error48 }, null, 2));
41039
41058
  else
@@ -41134,7 +41153,7 @@ async function handleExportsDownload(runId, options) {
41134
41153
  const { getApiKey: getApiKey2 } = await Promise.resolve().then(() => (init_auth_store(), exports_auth_store));
41135
41154
  const apiKey = getApiKey2();
41136
41155
  if (!apiKey) {
41137
- const error48 = "Remote artifact downloads require skills.md access. Run: skills auth login";
41156
+ const error48 = "Remote artifact downloads require hosted access. Run: skills auth login";
41138
41157
  if (options.json)
41139
41158
  console.log(JSON.stringify({ error: error48 }, null, 2));
41140
41159
  else
@@ -41537,6 +41556,8 @@ var init_completion = __esm(() => {
41537
41556
  "import",
41538
41557
  "doctor",
41539
41558
  "auth",
41559
+ "billing",
41560
+ "credits",
41540
41561
  "env-check",
41541
41562
  "setup-info",
41542
41563
  "test",
@@ -41562,7 +41583,7 @@ __export(exports_create_sync_config, {
41562
41583
  registerCreateSync: () => registerCreateSync
41563
41584
  });
41564
41585
  import chalk9 from "chalk";
41565
- import { existsSync as existsSync15, writeFileSync as writeFileSync10, mkdirSync as mkdirSync9 } from "fs";
41586
+ import { existsSync as existsSync16, writeFileSync as writeFileSync10, mkdirSync as mkdirSync9 } from "fs";
41566
41587
  import { join as join17 } from "path";
41567
41588
  import { homedir as homedir7 } from "os";
41568
41589
  function registerCreateSync(parent) {
@@ -41612,13 +41633,13 @@ function registerCreateSync(parent) {
41612
41633
  const pp = getConfigPath("project");
41613
41634
  if (options.json) {
41614
41635
  console.log(JSON.stringify({
41615
- global: { path: gp, exists: existsSync15(gp) },
41616
- project: { path: pp, exists: existsSync15(pp) }
41636
+ global: { path: gp, exists: existsSync16(gp) },
41637
+ project: { path: pp, exists: existsSync16(pp) }
41617
41638
  }, null, 2));
41618
41639
  return;
41619
41640
  }
41620
- console.log(`${chalk9.cyan("global")}: ${gp}${existsSync15(gp) ? chalk9.green(" (exists)") : chalk9.dim(" (not found)")}`);
41621
- console.log(`${chalk9.cyan("project")}: ${pp}${existsSync15(pp) ? chalk9.green(" (exists)") : chalk9.dim(" (not found)")}`);
41641
+ console.log(`${chalk9.cyan("global")}: ${gp}${existsSync16(gp) ? chalk9.green(" (exists)") : chalk9.dim(" (not found)")}`);
41642
+ console.log(`${chalk9.cyan("project")}: ${pp}${existsSync16(pp) ? chalk9.green(" (exists)") : chalk9.dim(" (not found)")}`);
41622
41643
  });
41623
41644
  parent.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", "Deprecated; custom skills are always global", false).option("--json", "Output result as JSON", false).description("Scaffold a new custom skill directory").action((name, options) => handleCreate(name, options));
41624
41645
  parent.command("sync").option("--to <agent>", "Deprecated; use skills mcp --register <agent|all>").option("--from <agent>", "Deprecated; agent skill-folder sync is disabled").option("--register", "Deprecated; agent skill-folder imports are disabled", false).option("--scope <scope>", "Deprecated; ignored", "global").option("--json", "Output as JSON", false).description("Disabled legacy agent skill-folder sync").action((options) => handleSync(options));
@@ -41628,7 +41649,7 @@ function handleCreate(name, options) {
41628
41649
  const dirName = bare;
41629
41650
  const baseDir = join17(homedir7(), ".hasna", "skills", "custom");
41630
41651
  const skillDir = join17(baseDir, dirName);
41631
- if (existsSync15(skillDir)) {
41652
+ if (existsSync16(skillDir)) {
41632
41653
  console.log(options.json ? JSON.stringify({ error: `Skill '${bare}' already exists at ${skillDir}` }) : chalk9.red(`Skill '${bare}' already exists at ${skillDir}`));
41633
41654
  process.exitCode = 1;
41634
41655
  return;
@@ -41840,7 +41861,7 @@ async function executeScheduledSkill(skillName, args2) {
41840
41861
  const { getApiKey: getApiKey2 } = await Promise.resolve().then(() => (init_auth_store(), exports_auth_store));
41841
41862
  const apiKey = getApiKey2();
41842
41863
  if (!apiKey) {
41843
- throw new Error(`${skill.name} is a hosted skill. Run: skills setup --mode skills.md && skills auth login`);
41864
+ throw new Error(`${skill.name} is a hosted skill. Run: skills setup --mode hosted && skills auth login`);
41844
41865
  }
41845
41866
  const { RemoteSkillsClient: RemoteSkillsClient2 } = await Promise.resolve().then(() => (init_remote_client(), exports_remote_client));
41846
41867
  const client = new RemoteSkillsClient2(apiKey);
@@ -42004,6 +42025,66 @@ async function apiRequest(path, options) {
42004
42025
  });
42005
42026
  return res.json();
42006
42027
  }
42028
+ function sleep(ms) {
42029
+ return new Promise((resolve) => setTimeout(resolve, ms));
42030
+ }
42031
+ function browserCommand(url2) {
42032
+ if (process.platform === "darwin")
42033
+ return ["open", url2];
42034
+ if (process.platform === "win32")
42035
+ return ["cmd", "/c", "start", "", url2];
42036
+ return ["xdg-open", url2];
42037
+ }
42038
+ function openBrowser(url2) {
42039
+ const command = browserCommand(url2);
42040
+ if (!command)
42041
+ return;
42042
+ try {
42043
+ Bun.spawn(command, { stdout: "ignore", stderr: "ignore" });
42044
+ } catch {}
42045
+ }
42046
+ async function ensureApiKey(loginResult) {
42047
+ if (loginResult.apiKey)
42048
+ return loginResult.apiKey;
42049
+ if (!loginResult.token)
42050
+ return;
42051
+ const keyRes = await apiRequest("/api/auth/keys", {
42052
+ method: "POST",
42053
+ headers: { Authorization: `Bearer ${loginResult.token}` },
42054
+ body: JSON.stringify({ name: "cli" })
42055
+ });
42056
+ return keyRes.key;
42057
+ }
42058
+ async function persistLoginResult(loginResult) {
42059
+ const storedKey = await ensureApiKey(loginResult);
42060
+ if (!storedKey)
42061
+ return;
42062
+ saveAuthConfig({
42063
+ apiKey: storedKey,
42064
+ email: loginResult.user.email,
42065
+ orgId: loginResult.organization.id,
42066
+ orgSlug: loginResult.organization.slug,
42067
+ userId: loginResult.user.id
42068
+ });
42069
+ return storedKey;
42070
+ }
42071
+ function printLoginSuccess(loginResult, json2) {
42072
+ if (json2 || !isTTY) {
42073
+ console.log(JSON.stringify({
42074
+ status: "authenticated",
42075
+ email: loginResult.user.email,
42076
+ organization: loginResult.organization.slug,
42077
+ firstLogin: loginResult.firstLogin
42078
+ }));
42079
+ return;
42080
+ }
42081
+ console.log(chalk12.green(`
42082
+ \u2713 Signed in as ${loginResult.user.email}`));
42083
+ console.log(chalk12.dim(` Organization: ${loginResult.organization.name}`));
42084
+ if (loginResult.firstLogin) {
42085
+ console.log(chalk12.dim(` API key saved to ~/.hasna/skills/auth.json`));
42086
+ }
42087
+ }
42007
42088
  async function doLogin(email3, code) {
42008
42089
  if (!email3 || !email3.includes("@")) {
42009
42090
  console.error(chalk12.red("Invalid email"));
@@ -42037,41 +42118,99 @@ async function doLogin(email3, code) {
42037
42118
  process.exitCode = 1;
42038
42119
  return;
42039
42120
  }
42040
- let storedKey = verifyRes.apiKey;
42121
+ const storedKey = await persistLoginResult(verifyRes);
42041
42122
  if (!storedKey) {
42042
- const keyRes = await apiRequest("/api/auth/keys", {
42123
+ console.error(chalk12.red("Login succeeded but API key creation failed"));
42124
+ process.exitCode = 1;
42125
+ return;
42126
+ }
42127
+ printLoginSuccess(verifyRes, false);
42128
+ }
42129
+ async function doDeviceLogin(options) {
42130
+ const start = await apiRequest("/api/auth/device/start", {
42131
+ method: "POST",
42132
+ body: JSON.stringify({ client: "skills-cli" })
42133
+ });
42134
+ if (start.error) {
42135
+ console.error(chalk12.red(start.error));
42136
+ process.exitCode = 1;
42137
+ return;
42138
+ }
42139
+ const verificationUrl = start.verificationUriComplete || start.verificationUri;
42140
+ const shouldPoll = Boolean(options.poll || isTTY && !options.json);
42141
+ if (options.open !== false && isTTY && verificationUrl) {
42142
+ openBrowser(verificationUrl);
42143
+ }
42144
+ if (!shouldPoll) {
42145
+ const payload = {
42146
+ status: "pending",
42147
+ userCode: start.userCode,
42148
+ verificationUri: start.verificationUri,
42149
+ verificationUriComplete: start.verificationUriComplete,
42150
+ expiresIn: start.expiresIn,
42151
+ interval: start.interval,
42152
+ poll: "skills auth login --device --poll"
42153
+ };
42154
+ if (options.json || !isTTY)
42155
+ console.log(JSON.stringify(payload, null, 2));
42156
+ else {
42157
+ console.log(chalk12.bold(`
42158
+ Sign in in your browser
42159
+ `));
42160
+ console.log(`${chalk12.dim("Code:")} ${start.userCode}`);
42161
+ console.log(`${chalk12.dim("URL:")} ${verificationUrl}`);
42162
+ }
42163
+ return;
42164
+ }
42165
+ if (!options.json) {
42166
+ console.log(chalk12.bold(`
42167
+ Sign in in your browser
42168
+ `));
42169
+ console.log(`${chalk12.dim("Code:")} ${start.userCode}`);
42170
+ console.log(`${chalk12.dim("URL:")} ${verificationUrl}`);
42171
+ console.log(chalk12.dim(`
42172
+ Waiting for authentication...`));
42173
+ }
42174
+ const intervalMs = Math.max(1000, Number(start.interval || 5) * 1000);
42175
+ const timeoutMs = Number(options.pollTimeoutMs || DEFAULT_DEVICE_POLL_TIMEOUT_MS);
42176
+ const deadline = Date.now() + timeoutMs;
42177
+ while (Date.now() < deadline) {
42178
+ const tokenRes = await apiRequest("/api/auth/device/token", {
42043
42179
  method: "POST",
42044
- headers: { Authorization: `Bearer ${verifyRes.token}` },
42045
- body: JSON.stringify({ name: "cli" })
42180
+ body: JSON.stringify({ deviceCode: start.deviceCode })
42046
42181
  });
42047
- storedKey = keyRes.key;
42048
- }
42049
- saveAuthConfig({
42050
- apiKey: storedKey,
42051
- email: verifyRes.user.email,
42052
- orgId: verifyRes.organization.id,
42053
- orgSlug: verifyRes.organization.slug,
42054
- userId: verifyRes.user.id
42055
- });
42056
- if (isTTY) {
42057
- console.log(chalk12.green(`
42058
- \u2713 Signed in as ${verifyRes.user.email}`));
42059
- console.log(chalk12.dim(` Organization: ${verifyRes.organization.name}`));
42060
- if (verifyRes.firstLogin) {
42061
- console.log(chalk12.dim(` API key saved to ~/.skills/auth.json`));
42182
+ if (tokenRes.error === "authorization_pending" || tokenRes.status === "pending") {
42183
+ await sleep(intervalMs);
42184
+ continue;
42062
42185
  }
42063
- } else {
42064
- console.log(JSON.stringify({
42065
- status: "authenticated",
42066
- email: verifyRes.user.email,
42067
- organization: verifyRes.organization.slug,
42068
- firstLogin: verifyRes.firstLogin
42069
- }));
42186
+ if (tokenRes.error) {
42187
+ console.error(chalk12.red(tokenRes.detail || tokenRes.error));
42188
+ process.exitCode = 1;
42189
+ return;
42190
+ }
42191
+ const storedKey = await persistLoginResult(tokenRes);
42192
+ if (!storedKey) {
42193
+ console.error(chalk12.red("Login succeeded but API key creation failed"));
42194
+ process.exitCode = 1;
42195
+ return;
42196
+ }
42197
+ printLoginSuccess(tokenRes, Boolean(options.json));
42198
+ return;
42070
42199
  }
42200
+ const error48 = "Device login timed out before browser authentication completed";
42201
+ if (options.json || !isTTY)
42202
+ console.log(JSON.stringify({ status: "expired", error: error48 }));
42203
+ else
42204
+ console.error(chalk12.red(error48));
42205
+ process.exitCode = 1;
42071
42206
  }
42072
42207
  function registerAuth(parent) {
42073
- const auth = parent.command("auth").description("Manage your skills.md account");
42074
- auth.command("login").description("Sign in with your email (passwordless)").option("--email <email>", "Email address (non-interactive)").option("--code <code>", "Verification code (non-interactive)").action(async (options) => {
42208
+ const auth = parent.command("auth").description("Manage hosted account authentication");
42209
+ auth.command("login").description("Sign in with browser/device code or email code").option("--email <email>", "Email address (non-interactive)").option("--code <code>", "Verification code (non-interactive)").option("--device", "Use browser/device-code login", false).option("--no-open", "Do not open a browser for device-code login").option("--poll", "Poll until browser authentication completes in non-interactive mode", false).option("--poll-timeout-ms <ms>", "Maximum time to wait for device-code login").option("--json", "Output result as JSON", false).action(async (options) => {
42210
+ if (options.device || !options.email && !options.code) {
42211
+ await doDeviceLogin(options);
42212
+ return;
42213
+ }
42075
42214
  let email3 = options.email;
42076
42215
  if (!email3 && isTTY) {
42077
42216
  const existing = getAuthConfig();
@@ -42140,79 +42279,137 @@ function registerAuth(parent) {
42140
42279
  console.log(chalk12.dim("(offline \u2014 showing cached info)"));
42141
42280
  }
42142
42281
  });
42143
- auth.command("status").description("Show billing status and credits").action(async () => {
42144
- const config2 = getAuthConfig();
42145
- if (!config2) {
42146
- console.log(chalk12.dim("Not signed in. Run: skills auth login"));
42147
- return;
42148
- }
42149
- try {
42150
- const res = await apiRequest("/api/v1/billing/status", {
42151
- headers: { Authorization: `Bearer ${config2.apiKey}` }
42152
- });
42153
- console.log(chalk12.bold("Plan: ") + res.plan);
42154
- console.log(chalk12.bold("Balance: ") + res.balance);
42155
- } catch {
42156
- console.error(chalk12.red("Failed to fetch billing status"));
42157
- }
42158
- });
42159
- auth.command("checkout").description("Create a Pro checkout session").action(async () => {
42160
- const config2 = getAuthConfig();
42161
- if (!config2) {
42162
- console.log(chalk12.dim("Not signed in. Run: skills auth login"));
42163
- return;
42164
- }
42165
- const res = await apiRequest("/api/v1/billing/checkout", {
42166
- method: "POST",
42282
+ auth.command("status").description("Show hosted billing status").option("--json", "Output as JSON", false).action(handleBillingStatus);
42283
+ auth.command("checkout").description("Create a Pro checkout session").option("--json", "Output as JSON", false).action(handleCheckout);
42284
+ auth.command("portal").description("Create a customer portal session").option("--json", "Output as JSON", false).action(handlePortal);
42285
+ auth.command("buy-credits").description("Create a credit pack checkout session").argument("<amount>", "Credit pack amount: 1, 5, 20, 50, or 100").option("--json", "Output as JSON", false).action(handleBuyCredits);
42286
+ registerBilling(parent);
42287
+ registerCredits(parent);
42288
+ }
42289
+ function requireHostedAuth(json2) {
42290
+ const config2 = getAuthConfig();
42291
+ if (config2)
42292
+ return config2;
42293
+ const message = "Not signed in. Run: skills auth login";
42294
+ if (json2)
42295
+ console.log(JSON.stringify({ error: message }));
42296
+ else
42297
+ console.log(chalk12.dim(message));
42298
+ process.exitCode = 1;
42299
+ return null;
42300
+ }
42301
+ async function handleBillingStatus(options = {}) {
42302
+ const config2 = requireHostedAuth(options.json);
42303
+ if (!config2)
42304
+ return;
42305
+ try {
42306
+ const res = await apiRequest("/api/v1/billing/status", {
42167
42307
  headers: { Authorization: `Bearer ${config2.apiKey}` }
42168
42308
  });
42169
- if (res.error || !res.url) {
42170
- console.error(chalk12.red(res.detail || res.error || "Failed to create checkout session"));
42171
- process.exitCode = 1;
42309
+ if (options.json) {
42310
+ console.log(JSON.stringify(res, null, 2));
42172
42311
  return;
42173
42312
  }
42313
+ console.log(chalk12.bold("Plan: ") + res.plan);
42314
+ console.log(chalk12.bold("Balance: ") + res.balance);
42315
+ } catch {
42316
+ console.error(chalk12.red("Failed to fetch billing status"));
42317
+ process.exitCode = 1;
42318
+ }
42319
+ }
42320
+ async function handleCheckout(options = {}) {
42321
+ const config2 = requireHostedAuth(options.json);
42322
+ if (!config2)
42323
+ return;
42324
+ const res = await apiRequest("/api/v1/billing/checkout", {
42325
+ method: "POST",
42326
+ headers: { Authorization: `Bearer ${config2.apiKey}` }
42327
+ });
42328
+ if (res.error || !res.url) {
42329
+ console.error(chalk12.red(res.detail || res.error || "Failed to create checkout session"));
42330
+ process.exitCode = 1;
42331
+ return;
42332
+ }
42333
+ if (options.json)
42334
+ console.log(JSON.stringify(res, null, 2));
42335
+ else
42174
42336
  console.log(res.url);
42337
+ }
42338
+ async function handlePortal(options = {}) {
42339
+ const config2 = requireHostedAuth(options.json);
42340
+ if (!config2)
42341
+ return;
42342
+ const res = await apiRequest("/api/v1/billing/portal", {
42343
+ method: "POST",
42344
+ headers: { Authorization: `Bearer ${config2.apiKey}` }
42175
42345
  });
42176
- auth.command("portal").description("Create a customer portal session").action(async () => {
42177
- const config2 = getAuthConfig();
42178
- if (!config2) {
42179
- console.log(chalk12.dim("Not signed in. Run: skills auth login"));
42180
- return;
42181
- }
42182
- const res = await apiRequest("/api/v1/billing/portal", {
42183
- method: "POST",
42184
- headers: { Authorization: `Bearer ${config2.apiKey}` }
42185
- });
42186
- if (res.error || !res.url) {
42187
- console.error(chalk12.red(res.detail || res.error || "Failed to create customer portal session"));
42188
- process.exitCode = 1;
42189
- return;
42190
- }
42346
+ if (res.error || !res.url) {
42347
+ console.error(chalk12.red(res.detail || res.error || "Failed to create customer portal session"));
42348
+ process.exitCode = 1;
42349
+ return;
42350
+ }
42351
+ if (options.json)
42352
+ console.log(JSON.stringify(res, null, 2));
42353
+ else
42191
42354
  console.log(res.url);
42355
+ }
42356
+ async function handleBuyCredits(amount, options = {}) {
42357
+ const config2 = requireHostedAuth(options.json);
42358
+ if (!config2)
42359
+ return;
42360
+ const res = await apiRequest("/api/v1/billing/credits", {
42361
+ method: "POST",
42362
+ headers: { Authorization: `Bearer ${config2.apiKey}` },
42363
+ body: JSON.stringify({ amount })
42192
42364
  });
42193
- auth.command("buy-credits").description("Create a credit pack checkout session").argument("<amount>", "Credit pack amount: 1, 5, 20, 50, or 100").action(async (amount) => {
42194
- const config2 = getAuthConfig();
42195
- if (!config2) {
42196
- console.log(chalk12.dim("Not signed in. Run: skills auth login"));
42197
- return;
42198
- }
42199
- const res = await apiRequest("/api/v1/billing/credits", {
42200
- method: "POST",
42201
- headers: { Authorization: `Bearer ${config2.apiKey}` },
42202
- body: JSON.stringify({ amount })
42203
- });
42204
- if (res.error || !res.url) {
42205
- console.error(chalk12.red(res.detail || res.error || "Failed to create credit checkout session"));
42206
- process.exitCode = 1;
42207
- return;
42208
- }
42365
+ if (res.error || !res.url) {
42366
+ console.error(chalk12.red(res.detail || res.error || "Failed to create credit checkout session"));
42367
+ process.exitCode = 1;
42368
+ return;
42369
+ }
42370
+ if (options.json)
42371
+ console.log(JSON.stringify(res, null, 2));
42372
+ else
42209
42373
  console.log(res.url);
42374
+ }
42375
+ async function handleListCreditPacks(options = {}) {
42376
+ const config2 = requireHostedAuth(options.json);
42377
+ if (!config2)
42378
+ return;
42379
+ const res = await apiRequest("/api/v1/billing/credits", {
42380
+ headers: { Authorization: `Bearer ${config2.apiKey}` }
42210
42381
  });
42382
+ if (res.error) {
42383
+ console.error(chalk12.red(res.detail || res.error || "Failed to list credit packs"));
42384
+ process.exitCode = 1;
42385
+ return;
42386
+ }
42387
+ if (options.json) {
42388
+ console.log(JSON.stringify(res, null, 2));
42389
+ return;
42390
+ }
42391
+ const packs = Array.isArray(res) ? res : res.packs;
42392
+ for (const pack of packs ?? []) {
42393
+ console.log(`${pack.amount}: ${pack.amountCents ? `$${(pack.amountCents / 100).toFixed(2)}` : pack.label || ""}`);
42394
+ }
42395
+ }
42396
+ function registerBilling(parent) {
42397
+ const billing = parent.command("billing").description("Manage hosted billing");
42398
+ billing.command("status").description("Show billing status").option("--json", "Output as JSON", false).action(handleBillingStatus);
42399
+ billing.command("checkout").description("Create a Pro checkout session").option("--json", "Output as JSON", false).action(handleCheckout);
42400
+ billing.command("portal").description("Create a customer portal session").option("--json", "Output as JSON", false).action(handlePortal);
42401
+ billing.command("buy-credits").description("Create a credit pack checkout session").argument("<amount>", "Credit pack amount: 1, 5, 20, 50, or 100").option("--json", "Output as JSON", false).action(handleBuyCredits);
42211
42402
  }
42212
- var isTTY;
42403
+ function registerCredits(parent) {
42404
+ const credits = parent.command("credits").description("Manage hosted credit packs");
42405
+ credits.command("buy").description("Create a credit pack checkout session").argument("<amount>", "Credit pack amount: 1, 5, 20, 50, or 100").option("--json", "Output as JSON", false).action(handleBuyCredits);
42406
+ credits.command("packs").description("List available credit packs").option("--json", "Output as JSON", false).action(handleListCreditPacks);
42407
+ }
42408
+ var isTTY, DEFAULT_DEVICE_POLL_TIMEOUT_MS;
42213
42409
  var init_auth = __esm(() => {
42214
42410
  init_auth_store();
42215
42411
  isTTY = process.stdin.isTTY && process.stdout.isTTY;
42412
+ DEFAULT_DEVICE_POLL_TIMEOUT_MS = 10 * 60 * 1000;
42216
42413
  });
42217
42414
 
42218
42415
  // src/cli/commands/feedback.ts
@@ -43382,6 +43579,58 @@ function App({ initialSkills, overwrite = false }) {
43382
43579
  // src/cli/index.tsx
43383
43580
  init_registry();
43384
43581
  init_discovery();
43582
+
43583
+ // src/cli/onboarding.ts
43584
+ init_config();
43585
+ var SKIP_ONBOARDING_COMMANDS = new Set([
43586
+ "interactive",
43587
+ "setup",
43588
+ "config",
43589
+ "auth",
43590
+ "billing",
43591
+ "credits",
43592
+ "completion",
43593
+ "self-update"
43594
+ ]);
43595
+ function getRootCommandName(actionCommand) {
43596
+ let current = actionCommand;
43597
+ while (current.parent && current.parent.parent)
43598
+ current = current.parent;
43599
+ return current.name();
43600
+ }
43601
+ function shouldShowFirstRunOnboarding(input) {
43602
+ if (!input.isInteractive || input.testMode)
43603
+ return false;
43604
+ if (input.config.mode)
43605
+ return false;
43606
+ if (input.argv.some((arg) => arg === "--json" || arg === "--help" || arg === "-h" || arg === "--version" || arg === "-V")) {
43607
+ return false;
43608
+ }
43609
+ if (!input.commandName || SKIP_ONBOARDING_COMMANDS.has(input.commandName))
43610
+ return false;
43611
+ return input.argv.length > 0;
43612
+ }
43613
+ function getFirstRunOnboardingMessage() {
43614
+ return [
43615
+ "No Skills setup found.",
43616
+ " Hosted: skills setup --mode hosted && skills auth login",
43617
+ " Local: skills setup --mode local"
43618
+ ].join(`
43619
+ `);
43620
+ }
43621
+ function maybePrintFirstRunOnboarding(actionCommand, argv, isInteractive) {
43622
+ if (shouldShowFirstRunOnboarding({
43623
+ argv,
43624
+ commandName: getRootCommandName(actionCommand),
43625
+ config: loadConfig(),
43626
+ isInteractive,
43627
+ testMode: process.env.SKILLS_TEST_MODE === "1"
43628
+ })) {
43629
+ console.error(getFirstRunOnboardingMessage());
43630
+ }
43631
+ }
43632
+
43633
+ // src/cli/index.tsx
43385
43634
  import { jsxDEV as jsxDEV7 } from "react/jsx-dev-runtime";
43386
43635
  var isTTY2 = (process.stdout.isTTY ?? false) && (process.stdin.isTTY ?? false);
43387
43636
  if (process.argv.includes("--no-color")) {
@@ -43422,4 +43671,7 @@ var { registerAuth: registerAuth2 } = await Promise.resolve().then(() => (init_a
43422
43671
  registerAuth2(program2);
43423
43672
  var { registerFeedback: registerFeedback2 } = await Promise.resolve().then(() => (init_feedback2(), exports_feedback));
43424
43673
  registerFeedback2(program2);
43674
+ program2.hook("preAction", (_thisCommand, actionCommand) => {
43675
+ maybePrintFirstRunOnboarding(actionCommand, process.argv.slice(2), isTTY2);
43676
+ });
43425
43677
  await program2.parseAsync();