@merittdev/horus 0.1.17 → 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.
- package/dist/index.cjs +314 -30
- 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.
|
|
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
|
|
|
@@ -59087,7 +59087,7 @@ function sql(strings, ...params) {
|
|
|
59087
59087
|
return new SQL([new StringChunk(str)]);
|
|
59088
59088
|
}
|
|
59089
59089
|
sql2.raw = raw;
|
|
59090
|
-
function
|
|
59090
|
+
function join7(chunks, separator) {
|
|
59091
59091
|
const result = [];
|
|
59092
59092
|
for (const [i, chunk] of chunks.entries()) {
|
|
59093
59093
|
if (i > 0 && separator !== void 0) {
|
|
@@ -59097,7 +59097,7 @@ function sql(strings, ...params) {
|
|
|
59097
59097
|
}
|
|
59098
59098
|
return new SQL(result);
|
|
59099
59099
|
}
|
|
59100
|
-
sql2.join =
|
|
59100
|
+
sql2.join = join7;
|
|
59101
59101
|
function identifier(value) {
|
|
59102
59102
|
return new Name(value);
|
|
59103
59103
|
}
|
|
@@ -62688,7 +62688,7 @@ var PgSelectQueryBuilderBase = class extends TypedQueryBuilder {
|
|
|
62688
62688
|
return (table, on) => {
|
|
62689
62689
|
const baseTableName = this.tableName;
|
|
62690
62690
|
const tableName = getTableLikeName(table);
|
|
62691
|
-
if (typeof tableName === "string" && this.config.joins?.some((
|
|
62691
|
+
if (typeof tableName === "string" && this.config.joins?.some((join7) => join7.alias === tableName)) {
|
|
62692
62692
|
throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
62693
62693
|
}
|
|
62694
62694
|
if (!this.isPartialSelect) {
|
|
@@ -63700,7 +63700,7 @@ var PgUpdateBase = class extends QueryPromise {
|
|
|
63700
63700
|
createJoin(joinType) {
|
|
63701
63701
|
return (table, on) => {
|
|
63702
63702
|
const tableName = getTableLikeName(table);
|
|
63703
|
-
if (typeof tableName === "string" && this.config.joins.some((
|
|
63703
|
+
if (typeof tableName === "string" && this.config.joins.some((join7) => join7.alias === tableName)) {
|
|
63704
63704
|
throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
63705
63705
|
}
|
|
63706
63706
|
if (typeof on === "function") {
|
|
@@ -63796,10 +63796,10 @@ var PgUpdateBase = class extends QueryPromise {
|
|
|
63796
63796
|
const fromFields = this.getTableLikeFields(this.config.from);
|
|
63797
63797
|
fields[tableName] = fromFields;
|
|
63798
63798
|
}
|
|
63799
|
-
for (const
|
|
63800
|
-
const tableName2 = getTableLikeName(
|
|
63801
|
-
if (typeof tableName2 === "string" && !is(
|
|
63802
|
-
const fromFields = this.getTableLikeFields(
|
|
63799
|
+
for (const join7 of this.config.joins) {
|
|
63800
|
+
const tableName2 = getTableLikeName(join7.table);
|
|
63801
|
+
if (typeof tableName2 === "string" && !is(join7.table, SQL)) {
|
|
63802
|
+
const fromFields = this.getTableLikeFields(join7.table);
|
|
63803
63803
|
fields[tableName2] = fromFields;
|
|
63804
63804
|
}
|
|
63805
63805
|
}
|
|
@@ -72938,22 +72938,22 @@ function extractQueueGraph(input) {
|
|
|
72938
72938
|
}
|
|
72939
72939
|
}
|
|
72940
72940
|
const producers = [];
|
|
72941
|
-
for (const
|
|
72942
|
-
for (const m of
|
|
72941
|
+
for (const pc37 of input.producerClasses) {
|
|
72942
|
+
for (const m of pc37.content.matchAll(INJECT_QUEUE_RE)) {
|
|
72943
72943
|
const queue = m[1] ?? "";
|
|
72944
|
-
if (queue) producers.push({ queue, symbol:
|
|
72944
|
+
if (queue) producers.push({ queue, symbol: pc37.name, file: pc37.filePath });
|
|
72945
72945
|
}
|
|
72946
|
-
for (const m of
|
|
72946
|
+
for (const m of pc37.content.matchAll(NEW_BULL_RE)) {
|
|
72947
72947
|
if (m[2] !== "Queue") continue;
|
|
72948
72948
|
const queue = resolveArg(m[3] ?? "", constMap);
|
|
72949
72949
|
if (queue) {
|
|
72950
|
-
producers.push({ queue, symbol: (m[1] ??
|
|
72950
|
+
producers.push({ queue, symbol: (m[1] ?? pc37.name) || baseName(pc37.filePath), file: pc37.filePath });
|
|
72951
72951
|
}
|
|
72952
72952
|
}
|
|
72953
|
-
for (const m of
|
|
72953
|
+
for (const m of pc37.content.matchAll(QUEUE_NAME_CONST_RE)) {
|
|
72954
72954
|
const ident = m[1] ?? "";
|
|
72955
72955
|
const queue = m[2] ?? "";
|
|
72956
|
-
if (queue) producers.push({ queue, symbol: ident || baseName(
|
|
72956
|
+
if (queue) producers.push({ queue, symbol: ident || baseName(pc37.filePath), file: pc37.filePath });
|
|
72957
72957
|
}
|
|
72958
72958
|
}
|
|
72959
72959
|
const workers = [];
|
|
@@ -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
|
-
|
|
77915
|
-
|
|
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
|
-
|
|
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
|
+
---
|
|
77983
78005
|
|
|
77984
|
-
|
|
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
|
|
78021
|
+
|
|
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
|
-
|
|
77993
|
-
|
|
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
|
}
|
|
@@ -78046,6 +78150,178 @@ async function runSkillPath(target, opts) {
|
|
|
78046
78150
|
return 0;
|
|
78047
78151
|
}
|
|
78048
78152
|
|
|
78153
|
+
// ../../packages/cli/src/commands/update.ts
|
|
78154
|
+
init_cjs_shims();
|
|
78155
|
+
var import_node_fs10 = require("fs");
|
|
78156
|
+
var import_node_path12 = require("path");
|
|
78157
|
+
var import_node_os3 = require("os");
|
|
78158
|
+
var import_node_crypto2 = require("crypto");
|
|
78159
|
+
var import_picocolors36 = __toESM(require_picocolors(), 1);
|
|
78160
|
+
var RELEASES_API = "https://api.github.com/repos/meritt-dev/horus/releases/latest";
|
|
78161
|
+
function parseVersion(v) {
|
|
78162
|
+
const m = v.replace(/^v/, "").match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
78163
|
+
if (!m) throw new Error(`Cannot parse version: ${v}`);
|
|
78164
|
+
return [+m[1], +m[2], +m[3]];
|
|
78165
|
+
}
|
|
78166
|
+
function isNewer(candidate, current) {
|
|
78167
|
+
const [cam, can, cap] = parseVersion(candidate);
|
|
78168
|
+
const [cum, cun, cup] = parseVersion(current);
|
|
78169
|
+
if (cam !== cum) return cam > cum;
|
|
78170
|
+
if (can !== cun) return can > cun;
|
|
78171
|
+
return cap > cup;
|
|
78172
|
+
}
|
|
78173
|
+
async function fetchLatestRelease(_fetch = fetch) {
|
|
78174
|
+
const res = await _fetch(RELEASES_API, {
|
|
78175
|
+
headers: {
|
|
78176
|
+
"User-Agent": `horus/${HORUS_VERSION}`,
|
|
78177
|
+
Accept: "application/vnd.github.v3+json"
|
|
78178
|
+
}
|
|
78179
|
+
});
|
|
78180
|
+
if (!res.ok) throw new Error(`GitHub API responded ${res.status}`);
|
|
78181
|
+
return res.json();
|
|
78182
|
+
}
|
|
78183
|
+
function sha256hex(buf) {
|
|
78184
|
+
return (0, import_node_crypto2.createHash)("sha256").update(buf).digest("hex");
|
|
78185
|
+
}
|
|
78186
|
+
function resolveBinaryPath() {
|
|
78187
|
+
const raw = process.argv[1];
|
|
78188
|
+
if (!raw) throw new Error("Cannot determine binary path from process.argv[1]");
|
|
78189
|
+
try {
|
|
78190
|
+
return (0, import_node_fs10.realpathSync)(raw);
|
|
78191
|
+
} catch {
|
|
78192
|
+
return raw;
|
|
78193
|
+
}
|
|
78194
|
+
}
|
|
78195
|
+
async function runUpdate(opts) {
|
|
78196
|
+
const write = opts.write ?? ((l) => console.log(l));
|
|
78197
|
+
const _fetch = opts._fetch ?? fetch;
|
|
78198
|
+
const currentVersion = opts._currentVersion ?? HORUS_VERSION;
|
|
78199
|
+
write(`
|
|
78200
|
+
${import_picocolors36.default.bold("Horus update")}
|
|
78201
|
+
`);
|
|
78202
|
+
write(` Current version: ${import_picocolors36.default.cyan(currentVersion)}`);
|
|
78203
|
+
let release;
|
|
78204
|
+
try {
|
|
78205
|
+
release = await fetchLatestRelease(_fetch);
|
|
78206
|
+
} catch (e) {
|
|
78207
|
+
write(` ${import_picocolors36.default.red("\u2717")} Could not reach GitHub: ${e.message}`);
|
|
78208
|
+
return 1;
|
|
78209
|
+
}
|
|
78210
|
+
const latest = release.tag_name.replace(/^v/, "");
|
|
78211
|
+
write(` Latest version: ${import_picocolors36.default.cyan(latest)}`);
|
|
78212
|
+
const newer = isNewer(latest, currentVersion);
|
|
78213
|
+
if (opts.check) {
|
|
78214
|
+
if (newer) {
|
|
78215
|
+
write(`
|
|
78216
|
+
${import_picocolors36.default.yellow("\u2192")} ${import_picocolors36.default.bold(latest)} is available.`);
|
|
78217
|
+
write(` Run ${import_picocolors36.default.bold("horus update")} to upgrade.`);
|
|
78218
|
+
} else {
|
|
78219
|
+
write(`
|
|
78220
|
+
${import_picocolors36.default.green("\u2713")} Already on the latest version.`);
|
|
78221
|
+
}
|
|
78222
|
+
return 0;
|
|
78223
|
+
}
|
|
78224
|
+
if (!newer && !opts.force) {
|
|
78225
|
+
write(`
|
|
78226
|
+
${import_picocolors36.default.green("\u2713")} Already on the latest version.`);
|
|
78227
|
+
return 0;
|
|
78228
|
+
}
|
|
78229
|
+
const tag = release.tag_name;
|
|
78230
|
+
const assetName = `horus-${tag}`;
|
|
78231
|
+
const checksumName = `${assetName}.sha256`;
|
|
78232
|
+
const binaryAsset = release.assets.find((a) => a.name === assetName);
|
|
78233
|
+
const checksumAsset = release.assets.find((a) => a.name === checksumName);
|
|
78234
|
+
if (!binaryAsset) {
|
|
78235
|
+
write(` ${import_picocolors36.default.red("\u2717")} Release ${tag} has no binary asset named '${assetName}'.`);
|
|
78236
|
+
write(` Fallback: ${import_picocolors36.default.dim("curl -fsSL https://horus.sh/install.sh | bash")}`);
|
|
78237
|
+
return 1;
|
|
78238
|
+
}
|
|
78239
|
+
write(`
|
|
78240
|
+
Downloading ${assetName}...`);
|
|
78241
|
+
const binRes = await _fetch(binaryAsset.browser_download_url, {
|
|
78242
|
+
headers: { "User-Agent": `horus/${HORUS_VERSION}` },
|
|
78243
|
+
redirect: "follow"
|
|
78244
|
+
});
|
|
78245
|
+
if (!binRes.ok || !binRes.body) {
|
|
78246
|
+
write(` ${import_picocolors36.default.red("\u2717")} Download failed: ${binRes.status}`);
|
|
78247
|
+
return 1;
|
|
78248
|
+
}
|
|
78249
|
+
const binBuf = Buffer.from(await binRes.arrayBuffer());
|
|
78250
|
+
if (checksumAsset) {
|
|
78251
|
+
const csRes = await _fetch(checksumAsset.browser_download_url, {
|
|
78252
|
+
headers: { "User-Agent": `horus/${HORUS_VERSION}` },
|
|
78253
|
+
redirect: "follow"
|
|
78254
|
+
});
|
|
78255
|
+
if (csRes.ok) {
|
|
78256
|
+
const csText = await csRes.text();
|
|
78257
|
+
const expectedHash = csText.trim().split(/\s+/)[0];
|
|
78258
|
+
const actualHash = sha256hex(binBuf);
|
|
78259
|
+
if (expectedHash !== actualHash) {
|
|
78260
|
+
write(` ${import_picocolors36.default.red("\u2717")} Checksum mismatch \u2014 download may be corrupt.`);
|
|
78261
|
+
write(` Expected: ${expectedHash}`);
|
|
78262
|
+
write(` Got: ${actualHash}`);
|
|
78263
|
+
return 1;
|
|
78264
|
+
}
|
|
78265
|
+
write(` ${import_picocolors36.default.green("\u2713")} Checksum verified.`);
|
|
78266
|
+
}
|
|
78267
|
+
}
|
|
78268
|
+
let binaryPath;
|
|
78269
|
+
try {
|
|
78270
|
+
binaryPath = resolveBinaryPath();
|
|
78271
|
+
} catch (e) {
|
|
78272
|
+
write(` ${import_picocolors36.default.red("\u2717")} ${e.message}`);
|
|
78273
|
+
return 1;
|
|
78274
|
+
}
|
|
78275
|
+
if (!(0, import_node_fs10.existsSync)(binaryPath)) {
|
|
78276
|
+
write(` ${import_picocolors36.default.red("\u2717")} Binary not found at ${binaryPath}`);
|
|
78277
|
+
return 1;
|
|
78278
|
+
}
|
|
78279
|
+
const tmpPath = (0, import_node_path12.join)((0, import_node_os3.tmpdir)(), `horus-update-${tag}-${process.pid}`);
|
|
78280
|
+
const backupPath = `${binaryPath}.bak`;
|
|
78281
|
+
try {
|
|
78282
|
+
(0, import_node_fs10.writeFileSync)(tmpPath, binBuf, { mode: 493 });
|
|
78283
|
+
} catch (e) {
|
|
78284
|
+
write(` ${import_picocolors36.default.red("\u2717")} Could not write to temp dir: ${e.message}`);
|
|
78285
|
+
return 1;
|
|
78286
|
+
}
|
|
78287
|
+
try {
|
|
78288
|
+
(0, import_node_fs10.renameSync)(binaryPath, backupPath);
|
|
78289
|
+
try {
|
|
78290
|
+
(0, import_node_fs10.renameSync)(tmpPath, binaryPath);
|
|
78291
|
+
(0, import_node_fs10.chmodSync)(binaryPath, 493);
|
|
78292
|
+
} catch (e) {
|
|
78293
|
+
try {
|
|
78294
|
+
(0, import_node_fs10.renameSync)(backupPath, binaryPath);
|
|
78295
|
+
} catch {
|
|
78296
|
+
}
|
|
78297
|
+
throw e;
|
|
78298
|
+
}
|
|
78299
|
+
try {
|
|
78300
|
+
(0, import_node_fs10.unlinkSync)(backupPath);
|
|
78301
|
+
} catch {
|
|
78302
|
+
}
|
|
78303
|
+
} catch (e) {
|
|
78304
|
+
try {
|
|
78305
|
+
(0, import_node_fs10.unlinkSync)(tmpPath);
|
|
78306
|
+
} catch {
|
|
78307
|
+
}
|
|
78308
|
+
const msg = e.message ?? String(e);
|
|
78309
|
+
const needsSudo = e.code === "EACCES" || e.code === "EPERM";
|
|
78310
|
+
write(` ${import_picocolors36.default.red("\u2717")} Could not replace binary at ${binaryPath}: ${msg}`);
|
|
78311
|
+
if (needsSudo) {
|
|
78312
|
+
write(`
|
|
78313
|
+
Try with sudo:`);
|
|
78314
|
+
write(
|
|
78315
|
+
` ${import_picocolors36.default.dim(`sudo curl -fsSL https://github.com/meritt-dev/horus/releases/download/${tag}/${assetName} -o ${binaryPath} && sudo chmod +x ${binaryPath}`)}`
|
|
78316
|
+
);
|
|
78317
|
+
}
|
|
78318
|
+
return 1;
|
|
78319
|
+
}
|
|
78320
|
+
write(` ${import_picocolors36.default.green("\u2713")} Updated: ${import_picocolors36.default.bold(currentVersion)} \u2192 ${import_picocolors36.default.bold(latest)}`);
|
|
78321
|
+
write(` ${import_picocolors36.default.dim(binaryPath)}`);
|
|
78322
|
+
return 0;
|
|
78323
|
+
}
|
|
78324
|
+
|
|
78049
78325
|
// ../../packages/cli/src/index.ts
|
|
78050
78326
|
function buildProgram() {
|
|
78051
78327
|
const program2 = new Command();
|
|
@@ -78363,11 +78639,11 @@ Examples:
|
|
|
78363
78639
|
process.exitCode = await runSkillInstall(target, { force: opts.force, global: opts.global });
|
|
78364
78640
|
}).addHelpText("after", `
|
|
78365
78641
|
Targets:
|
|
78366
|
-
claude \u2192 .claude/skills/horus.md (Claude Code
|
|
78367
|
-
codex \u2192 .
|
|
78368
|
-
gemini \u2192 .
|
|
78369
|
-
cursor \u2192 .
|
|
78370
|
-
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)
|
|
78371
78647
|
|
|
78372
78648
|
Examples:
|
|
78373
78649
|
horus skill install claude
|
|
@@ -78387,6 +78663,14 @@ Examples:
|
|
|
78387
78663
|
Examples:
|
|
78388
78664
|
horus skill path claude
|
|
78389
78665
|
horus skill path generic --global
|
|
78666
|
+
`);
|
|
78667
|
+
program2.command("update").description("Update Horus to the latest release from GitHub").option("--check", "check for a newer version without downloading").option("--force", "re-download even if already on the latest version").action(async (opts) => {
|
|
78668
|
+
process.exitCode = await runUpdate({ check: opts.check, force: opts.force });
|
|
78669
|
+
}).addHelpText("after", `
|
|
78670
|
+
Examples:
|
|
78671
|
+
horus update # update to latest
|
|
78672
|
+
horus update --check # check without installing
|
|
78673
|
+
horus update --force # re-download current version
|
|
78390
78674
|
`);
|
|
78391
78675
|
return program2;
|
|
78392
78676
|
}
|