@merittdev/horus 0.1.18 → 0.1.19

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.
Files changed (2) hide show
  1. package/dist/index.cjs +119 -15
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -50314,7 +50314,7 @@ init_cjs_shims();
50314
50314
 
50315
50315
  // ../../packages/core/src/version.ts
50316
50316
  init_cjs_shims();
50317
- var HORUS_VERSION = true ? "0.1.18" : "dev";
50317
+ var HORUS_VERSION = true ? "0.1.19" : "dev";
50318
50318
  var PINNED_AXON_VERSION = "1.0.7";
50319
50319
  var PINNED_SOURCE_VERSION = PINNED_AXON_VERSION;
50320
50320
 
@@ -77904,17 +77904,31 @@ init_cjs_shims();
77904
77904
  var import_node_fs9 = require("fs");
77905
77905
  var import_node_path11 = require("path");
77906
77906
  var import_node_os2 = require("os");
77907
+ var import_promises = require("readline/promises");
77907
77908
  var import_picocolors35 = __toESM(require_picocolors(), 1);
77908
77909
  var SUPPORTED_TARGETS = ["claude", "codex", "gemini", "cursor", "generic"];
77909
77910
  function isValidTarget(target) {
77910
77911
  return SUPPORTED_TARGETS.includes(target);
77911
77912
  }
77913
+ function getLegacyClaudeSkillPath(opts) {
77914
+ const base2 = opts.global ? (0, import_node_os2.homedir)() : opts.cwd ?? process.cwd();
77915
+ return (0, import_node_path11.join)(base2, ".claude", "skills", "horus.md");
77916
+ }
77912
77917
  function getSkillInstallPath(target, opts) {
77913
77918
  const base2 = opts.global ? (0, import_node_os2.homedir)() : opts.cwd ?? process.cwd();
77914
- if (target === "claude") {
77915
- return (0, import_node_path11.join)(base2, ".claude", "skills", "horus.md");
77919
+ switch (target) {
77920
+ case "claude":
77921
+ return (0, import_node_path11.join)(base2, ".claude", "skills", "horus", "SKILL.md");
77922
+ case "gemini":
77923
+ return (0, import_node_path11.join)(base2, ".gemini", "skills", "horus", "SKILL.md");
77924
+ case "cursor":
77925
+ return opts.global ? (0, import_node_path11.join)(base2, ".cursorrules") : (0, import_node_path11.join)(base2, ".cursor", "rules", "horus.mdc");
77926
+ case "codex":
77927
+ return opts.global ? (0, import_node_path11.join)(base2, ".codex", "AGENTS.md") : (0, import_node_path11.join)(base2, "AGENTS.md");
77928
+ case "generic":
77929
+ default:
77930
+ return (0, import_node_path11.join)(base2, ".horus", "skills", `horus-${target}.md`);
77916
77931
  }
77917
- return (0, import_node_path11.join)(base2, ".horus", "skills", `horus-${target}.md`);
77918
77932
  }
77919
77933
  var BASE_SKILL = `# Horus Incident Investigation Skill
77920
77934
 
@@ -77979,20 +77993,82 @@ horus score <id>
77979
77993
  - Horus is read-only evidence collection \u2014 never use Horus to mutate production systems.
77980
77994
  - Do not hallucinate evidence. If Horus returns nothing, say so explicitly.
77981
77995
  `;
77982
- var CLAUDE_SUFFIX = `## Claude Code notes
77996
+ function skillFrontmatter(target) {
77997
+ const description = "Use Horus as the grounded evidence layer for production incident investigation.";
77998
+ switch (target) {
77999
+ case "claude":
78000
+ case "gemini":
78001
+ return `---
78002
+ name: horus
78003
+ description: ${description}
78004
+ ---
78005
+
78006
+ `;
78007
+ case "cursor":
78008
+ return `---
78009
+ description: ${description}
78010
+ globs: *
78011
+ alwaysApply: true
78012
+ ---
78013
+
78014
+ `;
78015
+ default:
78016
+ return "";
78017
+ }
78018
+ }
78019
+ var PROVIDER_NOTES = {
78020
+ claude: `## Claude Code notes
77983
78021
 
77984
- This skill is loaded automatically when present at \`.claude/skills/horus.md\`.
78022
+ This skill is loaded automatically when present at \`.claude/skills/horus/SKILL.md\`.
77985
78023
 
77986
78024
  Useful starting points:
77987
78025
  - \`horus investigations\` \u2014 list saved investigation IDs
77988
78026
  - \`horus doctor\` \u2014 check system health
77989
78027
  - \`horus onboard [area]\` \u2014 get oriented in a new codebase area
77990
- `;
78028
+ `,
78029
+ gemini: `## Gemini CLI notes
78030
+
78031
+ This skill is loaded automatically when present at \`.gemini/skills/horus/SKILL.md\`.
78032
+
78033
+ Useful starting points:
78034
+ - \`horus investigations\` \u2014 list saved investigation IDs
78035
+ - \`horus doctor\` \u2014 check system health
78036
+ - \`horus onboard [area]\` \u2014 get oriented in a new codebase area
78037
+ `,
78038
+ cursor: `## Cursor notes
78039
+
78040
+ This rule is loaded automatically when present at \`.cursor/rules/horus.mdc\`.
78041
+
78042
+ Useful starting points:
78043
+ - \`horus investigations\` \u2014 list saved investigation IDs
78044
+ - \`horus doctor\` \u2014 check system health
78045
+ - \`horus onboard [area]\` \u2014 get oriented in a new codebase area
78046
+ `,
78047
+ codex: `## Codex notes
78048
+
78049
+ This file is loaded automatically by Codex CLI as project instructions.
78050
+
78051
+ Useful starting points:
78052
+ - \`horus investigations\` \u2014 list saved investigation IDs
78053
+ - \`horus doctor\` \u2014 check system health
78054
+ - \`horus onboard [area]\` \u2014 get oriented in a new codebase area
78055
+ `,
78056
+ generic: ""
78057
+ };
77991
78058
  function generateSkillContent(target) {
77992
- if (target === "claude") {
77993
- return BASE_SKILL + "\n" + CLAUDE_SUFFIX;
78059
+ return skillFrontmatter(target) + BASE_SKILL + "\n" + PROVIDER_NOTES[target];
78060
+ }
78061
+ async function confirm(message) {
78062
+ if (!process.stdin.isTTY) {
78063
+ return false;
78064
+ }
78065
+ const rl = (0, import_promises.createInterface)({ input: process.stdin, output: process.stdout });
78066
+ try {
78067
+ const answer = await rl.question(`${message} [y/N] `);
78068
+ return /^y(es)?$/i.test(answer.trim());
78069
+ } finally {
78070
+ rl.close();
77994
78071
  }
77995
- return BASE_SKILL;
77996
78072
  }
77997
78073
  async function runSkillInstall(target, opts) {
77998
78074
  const log = opts.write ?? ((line2) => console.log(line2));
@@ -78003,6 +78079,28 @@ async function runSkillInstall(target, opts) {
78003
78079
  }
78004
78080
  const outPath = getSkillInstallPath(target, { global: opts.global, cwd: opts.cwd });
78005
78081
  const content = generateSkillContent(target);
78082
+ if (target === "claude") {
78083
+ const legacyPath = getLegacyClaudeSkillPath({ global: opts.global, cwd: opts.cwd });
78084
+ if ((0, import_node_fs9.existsSync)(legacyPath)) {
78085
+ if (!opts.force) {
78086
+ const confirmed = await (opts.confirm ?? confirm)(
78087
+ `Found old flat skill file at ${legacyPath}. Replace it with the new directory layout?`
78088
+ );
78089
+ if (!confirmed) {
78090
+ log(`${import_picocolors35.default.yellow("!")} Migration cancelled; existing skill left untouched.`);
78091
+ log(import_picocolors35.default.dim(" Pass --force to replace without prompting."));
78092
+ return 1;
78093
+ }
78094
+ }
78095
+ try {
78096
+ (0, import_node_fs9.rmSync)(legacyPath);
78097
+ log(`${import_picocolors35.default.yellow("!")} Replaced old flat skill file: ${legacyPath}`);
78098
+ } catch (err) {
78099
+ log(`${import_picocolors35.default.red("\u2717")} Could not remove legacy skill file ${legacyPath}: ${err.message}`);
78100
+ return 1;
78101
+ }
78102
+ }
78103
+ }
78006
78104
  if ((0, import_node_fs9.existsSync)(outPath) && !opts.force) {
78007
78105
  log(`${import_picocolors35.default.red("\u2717")} ${outPath} already exists`);
78008
78106
  log(import_picocolors35.default.dim(" pass --force to overwrite"));
@@ -78019,6 +78117,12 @@ async function runSkillInstall(target, opts) {
78019
78117
  if (target === "claude") {
78020
78118
  log(import_picocolors35.default.dim(" Claude Code will load this skill automatically."));
78021
78119
  log(import_picocolors35.default.dim(" Invoke it with: /horus"));
78120
+ } else if (target === "gemini") {
78121
+ log(import_picocolors35.default.dim(" Gemini CLI will load this skill automatically."));
78122
+ } else if (target === "cursor") {
78123
+ log(import_picocolors35.default.dim(" Cursor will load this rule automatically."));
78124
+ } else if (target === "codex") {
78125
+ log(import_picocolors35.default.dim(" Codex CLI will load this file automatically."));
78022
78126
  } else {
78023
78127
  log(import_picocolors35.default.dim(` Copy or reference this file in your ${target} agent instructions.`));
78024
78128
  }
@@ -78535,11 +78639,11 @@ Examples:
78535
78639
  process.exitCode = await runSkillInstall(target, { force: opts.force, global: opts.global });
78536
78640
  }).addHelpText("after", `
78537
78641
  Targets:
78538
- claude \u2192 .claude/skills/horus.md (Claude Code \u2014 loaded automatically)
78539
- codex \u2192 .horus/skills/horus-codex.md
78540
- gemini \u2192 .horus/skills/horus-gemini.md
78541
- cursor \u2192 .horus/skills/horus-cursor.md
78542
- generic \u2192 .horus/skills/horus-generic.md
78642
+ claude \u2192 .claude/skills/horus/SKILL.md (Claude Code skill)
78643
+ codex \u2192 AGENTS.md (Codex CLI project instructions)
78644
+ gemini \u2192 .gemini/skills/horus/SKILL.md (Gemini CLI skill)
78645
+ cursor \u2192 .cursor/rules/horus.mdc (Cursor project rule)
78646
+ generic \u2192 .horus/skills/horus-generic.md (plain Markdown)
78543
78647
 
78544
78648
  Examples:
78545
78649
  horus skill install claude
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@merittdev/horus",
3
- "version": "0.1.18",
3
+ "version": "0.1.19",
4
4
  "description": "Local-first, source-aware production-incident investigation engine",
5
5
  "type": "module",
6
6
  "bin": {