@merittdev/horus 0.22.0 → 0.24.0

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/horus.js ADDED
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env node
2
+ // Launcher for the native Horus binary (esbuild/biome pattern). npm installs exactly one
3
+ // platform package through optionalDependencies; this shim runs its `bin/horus`, inheriting
4
+ // stdio and forwarding signals and the exit status. No postinstall, no download.
5
+ 'use strict';
6
+ const { spawn } = require('node:child_process');
7
+ const fs = require('node:fs');
8
+ const path = require('node:path');
9
+
10
+ const launcher = require('../package.json').name;
11
+ const pkg = `${launcher}-${process.platform}-${process.arch}`;
12
+
13
+ let binary;
14
+ try {
15
+ binary = path.join(path.dirname(require.resolve(`${pkg}/package.json`)), 'bin', 'horus');
16
+ } catch {
17
+ const supported = Object.keys(require('../package.json').optionalDependencies || {}).join(', ');
18
+ console.error(
19
+ `horus: no native binary for ${process.platform}-${process.arch} (expected the optional package ${pkg}).\n` +
20
+ `Supported: ${supported}.\n` +
21
+ 'If you installed with --omit=optional or --no-optional, reinstall without it.',
22
+ );
23
+ process.exit(1);
24
+ }
25
+
26
+ // Some npm versions drop the executable bit from non-`bin` files.
27
+ try {
28
+ fs.accessSync(binary, fs.constants.X_OK);
29
+ } catch {
30
+ fs.chmodSync(binary, 0o755);
31
+ }
32
+
33
+ const child = spawn(binary, process.argv.slice(2), { stdio: 'inherit' });
34
+ const forward = (signal) => child.kill(signal);
35
+ const signals = ['SIGINT', 'SIGTERM', 'SIGHUP', 'SIGQUIT'];
36
+ for (const s of signals) process.on(s, forward);
37
+ child.on('error', (err) => {
38
+ console.error(`horus: failed to start ${binary}: ${err.message}`);
39
+ process.exit(1);
40
+ });
41
+ child.on('exit', (code, signal) => {
42
+ for (const s of signals) process.off(s, forward);
43
+ if (signal) process.kill(process.pid, signal);
44
+ else process.exit(code ?? 1);
45
+ });
package/package.json CHANGED
@@ -1,59 +1,28 @@
1
1
  {
2
2
  "name": "@merittdev/horus",
3
- "version": "0.22.0",
3
+ "version": "0.24.0",
4
4
  "description": "Local-first, source-aware production-incident investigation engine",
5
- "type": "module",
5
+ "license": "MIT",
6
+ "homepage": "https://horus.sh",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/meritt-dev/horus"
10
+ },
6
11
  "bin": {
7
- "horus": "./dist/index.cjs"
12
+ "horus": "bin/horus.js"
8
13
  },
9
14
  "files": [
10
- "dist"
15
+ "bin"
11
16
  ],
12
- "scripts": {
13
- "build": "tsup",
14
- "typecheck": "tsc --noEmit",
15
- "test": "tsup && vitest run --passWithNoTests",
16
- "prepublishOnly": "tsup",
17
- "prepack": "cp ../../README.md README.md"
18
- },
19
17
  "engines": {
20
- "node": ">=22"
21
- },
22
- "devDependencies": {
23
- "@electric-sql/pglite": "^0.5.3",
24
- "@horus/ai": "workspace:*",
25
- "@horus/cli": "workspace:*",
26
- "@horus/connectors": "workspace:*",
27
- "@horus/core": "workspace:*",
28
- "@horus/db": "workspace:*",
29
- "@horus/engine": "workspace:*",
30
- "@horus/eval": "workspace:*",
31
- "@horus/stitcher": "workspace:*",
32
- "@types/node": "^22.10.2",
33
- "tsup": "^8.3.5",
34
- "typescript": "^5.7.2",
35
- "vitest": "^2.1.8"
18
+ "node": ">=18"
36
19
  },
37
- "keywords": [
38
- "incident-investigation",
39
- "observability",
40
- "sre",
41
- "debugging",
42
- "cli"
43
- ],
44
- "license": "MIT",
45
- "author": {
46
- "name": "Meritt Dev",
47
- "url": "https://horus.sh"
48
- },
49
- "repository": {
50
- "type": "git",
51
- "url": "https://github.com/meritt-dev/horus"
20
+ "optionalDependencies": {
21
+ "@merittdev/horus-darwin-arm64": "0.24.0",
22
+ "@merittdev/horus-darwin-x64": "0.24.0",
23
+ "@merittdev/horus-linux-arm64": "0.24.0",
24
+ "@merittdev/horus-linux-x64": "0.24.0"
52
25
  },
53
- "bugs": {
54
- "url": "https://github.com/meritt-dev/horus/issues"
55
- },
56
- "homepage": "https://horus.sh",
57
26
  "publishConfig": {
58
27
  "access": "public"
59
28
  }
package/README.md DELETED
@@ -1,375 +0,0 @@
1
- <p align="center">
2
- <img src="https://meritt-dev-assets.s3.eu-central-1.amazonaws.com/public/horus-logo-dark-20260614171147.svg" width="72" alt="Horus" />
3
- </p>
4
-
5
- # Horus
6
-
7
- **Understand what happened.**
8
-
9
- Open-source incident investigation. Horus connects Elasticsearch, Sentry, Grafana, MongoDB, Postgres, Redis (incl. BullMQ queues), Axiom logs, Shopify Admin, and source intelligence into deterministic reports — installable today.
10
-
11
- CLI-only. Read-only against production systems. Horus never writes to your infrastructure.
12
-
13
- **Website:** [horus.sh](https://horus.sh) · **Source:** [github.com/meritt-dev/horus](https://github.com/meritt-dev/horus)
14
-
15
- ```bash
16
- curl -fsSL https://horus.sh/install.sh | bash
17
- npm install -g @merittdev/horus
18
- brew install meritt-dev/tap/horus
19
- ```
20
-
21
- Homebrew tap is live through meritt-dev/tap.
22
-
23
- ---
24
-
25
- ## What Horus does
26
-
27
- Horus reads from your existing systems and reconstructs the incident through evidence, correlation, and ranked hypotheses.
28
-
29
- It does not dump thousands of logs. It connects runtime signals to source context and returns a **deterministic report** — suspected causes (ranked), hypotheses, evidence, gaps, and next actions. Evidence before inference. Optional `--ai` adds an Anthropic narrative on top.
30
-
31
- Every incident leaves evidence.
32
-
33
- ## What Horus is not
34
-
35
- | | |
36
- |---|---|
37
- | **Monitoring** | Detects problems |
38
- | **Observability** | Shows signals |
39
- | **Horus** | Reconstructs what happened |
40
-
41
- Horus is not another dashboard, alerting tool, or log viewer. It sits on top of the systems you already use.
42
-
43
- > Monitoring detects. Observability shows. Horus reconstructs.
44
-
45
- ## Getting started
46
-
47
- ```bash
48
- horus init
49
- horus connect elasticsearch # optional runtime connectors
50
- horus investigate "checkout latency spike"
51
- horus investigations # list saved IDs
52
- horus replay <id>
53
- horus postmortem <id>
54
- ```
55
-
56
- Horus source intelligence requires a local code-graph host (the curl installer attempts to install it). Postgres is required for the audit store.
57
-
58
- ## How it works
59
-
60
- **Evidence in. Explanation out.**
61
-
62
- | Runtime + Source | Investigation Engine | Investigation Report |
63
- |---|---|---|
64
- | Elasticsearch · Axiom logs · Sentry errors | Correlation | Suspected causes (ranked) |
65
- | Grafana metrics | Timeline | Hypotheses + confidence |
66
- | MongoDB · Postgres · Redis state | Cause ranking | Evidence + gaps |
67
- | BullMQ queue runtime | | Next actions |
68
- | Source graph + git | | |
69
-
70
- Pipeline: **Evidence → Correlation → Hypotheses → Timeline → Report**
71
-
72
- ## Sources Horus investigates
73
-
74
- Elasticsearch · Sentry · Grafana · MongoDB · Postgres · Redis · BullMQ · Axiom · Git changes · Source graph · Queue map · Ownership
75
-
76
- Trace reconstruction is not shipped yet. Connectors are read-only and project-scoped.
77
-
78
- ## Example output (illustrative)
79
-
80
- ```bash
81
- cd ~/code/atlas-payments
82
- horus investigate --env production "checkout latency spike"
83
- ```
84
-
85
- ```text
86
- # Investigation inv-347
87
- Hint: checkout latency spike
88
-
89
- ## Suspected causes (ranked)
90
- 1. [0.82 / high] Redis connection pool exhaustion [↑ queue]
91
-
92
- ## Hypotheses
93
- [supported] [0.78] queue: backlog growth preceded latency spike
94
-
95
- ## Evidence gaps
96
- - queue runtime state: worker heartbeat unavailable
97
-
98
- ## Evidence
99
- - ev-01 [elasticsearch/error] Request timeout increase
100
- - ev-04 [bullmq/queue] checkout-jobs backlog growth
101
-
102
- ## Next actions
103
- - Inspect worker concurrency changes in deploy #784
104
- ```
105
-
106
- ## Principles
107
-
108
- **Read-only** — Horus never writes to your production systems.
109
-
110
- **Deterministic first** — The engine is deterministic; optional `--ai` adds an Anthropic narrative.
111
-
112
- **Local-first** — Connectors read from your own clusters, not a hosted black box.
113
-
114
- **Project-scoped** — The repo you run in (its `.horus/config.json`) is the project identity; `--config <path>` targets another repo.
115
-
116
- **Agent-ready** — Every investigation/analysis command takes `--json` (compact by default, `--full` for the raw structure) with a `nextSteps` array to chain from. `horus packet` builds a compact, honesty-framed briefing sized for an agent's context window.
117
-
118
- ## Capabilities
119
-
120
- Installable today. More connectors and AI providers are in progress.
121
-
122
- **Today**
123
-
124
- - Elasticsearch logs
125
- - Axiom logs
126
- - Sentry errors
127
- - Grafana metrics
128
- - MongoDB / Postgres / Redis state
129
- - BullMQ queue evidence
130
- - Shopify Admin (GraphQL — queries you supply)
131
- - Source intelligence (code graph)
132
- - Timeline generation
133
- - Evidence correlation
134
- - Investigation replay
135
- - Postmortem drafts
136
-
137
- **Coming next**
138
-
139
- - Kubernetes evidence
140
- - Distributed trace reconstruction
141
- - Slack evidence ingestion
142
- - Local AI provider execution
143
-
144
- ---
145
-
146
- ## Architecture
147
-
148
- Horus is organized in four layers:
149
-
150
- **Source Intelligence**
151
-
152
- - Horus source intelligence backend (`packages/source-py`, ships inside the bundle) — code graph, semantic search, impact analysis, ownership across TypeScript/JavaScript, Python, Go, Java, and Rust (tree-sitter).
153
-
154
- **Runtime Evidence**
155
-
156
- - **Elasticsearch** — logs → synthesized error-signature evidence
157
- - **Axiom** — structured logs (APL) → synthesized error-signature evidence, same path as Elasticsearch
158
- - **Sentry** — grouped exceptions (issues) → same error-signature / direct-seed path as logs
159
- - **MongoDB / Postgres** — application/operational state
160
- - **Grafana** — metrics via its datasource proxy
161
- - **Redis / BullMQ** — cache & queue runtime state
162
- - **Shopify Admin** — application state via GraphQL queries you supply at investigation time (`--shopify-query`) or declare in config; the connector embeds none. Read-only, Client-Credentials auth.
163
- - **Git** — change history, ownership signals
164
-
165
- **Investigation** (deterministic)
166
-
167
- - **Queue Stitcher** — connects producer `queue.add(...)` to consumer `@Processor` handlers
168
- - **Timeline Engine** — orders evidence into a sequence of events
169
- - **Correlation Engine** — connects evidence across sources into incident threads
170
-
171
- **Presentation**
172
-
173
- - **Deterministic investigation report** — evidence, timeline, hypotheses, gap analysis, next actions
174
- - **Optional AI narrative** — a later layer on top of the deterministic report
175
-
176
- ### Source intelligence is built into Horus
177
-
178
- **Source intelligence is the expected intelligence layer used by Horus** — not an optional integration. Semantic search, impact analysis, ownership signals, change detection, and the process graph live in the Horus source intelligence backend; Horus does not duplicate them.
179
-
180
- The **only** code-intelligence gap Horus owns is **queue-boundary stitching**: the source graph terminates around `queue.add(...)` and doesn't connect a producer to the consumer's `@Processor`. The stitcher synthesizes those producer → queue → worker edges.
181
-
182
- > If the Horus source intelligence backend is unavailable, Horus can still collect runtime evidence, but source context, impact analysis, change analysis, and queue stitching become degraded.
183
-
184
- Horus talks to the source intelligence backend over **HTTP/MCP only** (no CLI shell-outs for queries). Run `horus init` in a repository to start and register its source intelligence host.
185
-
186
- ## Configuration
187
-
188
- The config model separates **code** from **runtime**:
189
-
190
- - **Code belongs to the project** — `repositories[]`, each served by its own source intelligence host.
191
- - **Runtime belongs to the environment** — `environments[].connectors` (Elasticsearch, Sentry, MongoDB, Postgres, Grafana, Redis/BullMQ, Axiom).
192
-
193
- ```ts
194
- // config/horus.config.ts
195
- export default defineConfig({
196
- projects: [
197
- {
198
- name: 'atlas-payments',
199
- repositories: [
200
- {
201
- name: 'atlas-payments',
202
- path: '/repos/atlas-payments',
203
- source: { hostUrl: 'http://127.0.0.1:8420' },
204
- },
205
- ],
206
- environments: [
207
- {
208
- name: 'production',
209
- readOnly: true,
210
- connectors: {
211
- elasticsearch: {
212
- indexPattern: 'atlas-payments-prod-*',
213
- serviceName: 'atlas-payments-prod',
214
- },
215
- mongodb: {
216
- database: 'atlas_payments_prod',
217
- collections: ['orders', 'payments', 'workers'],
218
- },
219
- grafana: {},
220
- },
221
- },
222
- ],
223
- },
224
- ],
225
- });
226
- ```
227
-
228
- Local persistence is **embedded** (a bundled pglite database at `~/.horus/horus.db`) — no database to run or configure. Teams that need shared state use **Horus Cloud** (an API mirror), not a self-run Postgres.
229
-
230
- **No connector runs without an explicit project/env scope** — there are no global connector defaults.
231
-
232
- **Secrets are never committed.** `horus connect` encrypts connector credentials at rest into `.horus/secrets.local.json` (AES-256-GCM, never `config.json`) and auto-adds `.horus/` to `.gitignore`; environment variables are also supported at runtime. For the full secrets and gitignore model, see **[horus.sh/docs/security](https://horus.sh/docs/security)**.
233
-
234
- ## Install
235
-
236
- See **[horus.sh/docs/installation](https://horus.sh/docs/installation)** for full install, update, and uninstall instructions.
237
-
238
- ```bash
239
- curl -fsSL https://horus.sh/install.sh | bash
240
- npm install -g @merittdev/horus
241
- brew install meritt-dev/tap/horus
242
- horus --version
243
- horus init
244
- ```
245
-
246
- The curl installer downloads the Horus CLI from GitHub Releases and installs the source intelligence backend from the wheel **bundled in the same release** — one bundle, one version, nothing on PyPI. All three channels ship the same `horus` binary with the backend wheel alongside it; `horus init` installs the backend automatically when it's missing.
247
-
248
- ### What the installer installs
249
-
250
- | Component | Role | Required |
251
- | --- | --- | --- |
252
- | **Horus CLI** | The `horus` command | Yes |
253
- | **Horus source intelligence backend** | Enables `horus init`, `horus explain`, `horus changes`, `horus architecture` | Optional |
254
-
255
- ### Prerequisites
256
-
257
- | Requirement | Role |
258
- | --- | --- |
259
- | Node.js 22+ | Horus CLI runtime (the installed binary needs Node.js) |
260
- | Python 3.11+ + uv/pip | Required only for the Horus source intelligence backend |
261
-
262
- The investigation audit store is **embedded** (bundled pglite, zero setup) — there is no Postgres to install. Teams that need shared state use **Horus Cloud**.
263
-
264
- The installer **does not** configure Elasticsearch, MongoDB, Grafana, Redis, or any production system. Runtime connectors are added per-project after install via `horus connect`.
265
-
266
- ### Direct download (without the curl installer)
267
-
268
- ```bash
269
- # Replace vX.Y.Z with the current release tag (see github.com/meritt-dev/horus/releases)
270
- curl -fsSL https://github.com/meritt-dev/horus/releases/download/vX.Y.Z/horus-vX.Y.Z -o horus
271
- chmod +x horus
272
- sudo mv horus /usr/local/bin/horus
273
- horus --version
274
- ```
275
-
276
- To **update** to a newer version, re-run the installer — it overwrites the binary and leaves your config untouched. To **uninstall**, see **[horus.sh/docs/installation#uninstall](https://horus.sh/docs/installation#uninstall)**.
277
-
278
- If something goes wrong after install, run `horus doctor` and see **[horus.sh/docs/installation#troubleshooting](https://horus.sh/docs/installation#troubleshooting)**.
279
-
280
- ## Local development
281
-
282
- ```bash
283
- pnpm install
284
- pnpm build # builds apps/horus/dist/index.cjs
285
-
286
- # Per repository: start the source intelligence host and stitch queue boundaries
287
- horus init
288
-
289
- source ~/.horus.env
290
-
291
- node apps/horus/dist/index.cjs status
292
- ```
293
-
294
- **Verify the full v0.1 user path (init → investigate → replay → postmortem):**
295
-
296
- ```bash
297
- # No-services startup check (version, help, doctor):
298
- ./scripts/smoke-test.sh apps/horus/dist/index.cjs
299
-
300
- # Full end-to-end flow (uses the embedded pglite store — no services to start):
301
- ./scripts/e2e-smoke.sh apps/horus/dist/index.cjs
302
- ```
303
-
304
- ```bash
305
- horus --help
306
- horus help <command>
307
- horus investigate --help
308
- ```
309
-
310
- ### Core commands
311
-
312
- | Command | What it does |
313
- | --- | --- |
314
- | `horus status [--env]` | Per-project/env connector-health matrix |
315
- | `horus connect <type>` | Add/update a runtime connector — `elasticsearch` / `mongodb` / `postgres` / `sentry` / `axiom` / `grafana` / `redis` (plus `ai` to configure an AI provider) |
316
- | `horus init [--env <e>]` | Set up the current repo: config, source-intelligence host, index, queue map |
317
- | `horus hosts [--reap]` | List source-intelligence hosts and live status; `--reap` stops orphaned hosts |
318
- | `horus stop [--all]` | Stop this repo's source-intelligence host (`--all` stops every host) |
319
- | `horus investigate --env <e> "<hint>"` | Full deterministic investigation report (`--format json` for agents) |
320
- | `horus packet <hint\|savedId> [--for claude] [--json]` | Compact, honesty-framed briefing for a coding-agent context window |
321
- | `horus logs [service] --env <e>` | Error-signature evidence (`--raw` for lines) |
322
- | `horus state --env <e>` | MongoDB application-state evidence (read-only) |
323
- | `horus metrics [hint] --env <e>` | Grafana metrics evidence |
324
- | `horus queues [name] [--live]` | Queue topology from source intelligence; `--live` reads real-time Redis/BullMQ state |
325
- | `horus search <query>` · `explain <symbol>` · `blast-radius` · `architecture` · `what-changed` | Source-aware code intelligence — one canonical resolver, so a query resolves to the same symbol across commands (qualified `Class.method` supported) |
326
- | `horus memory <show\|add\|list\|link\|...>` | Inspect/author deterministic incident memory; `memory link` adds `supersedes` / `contradicts` / `recurs-with` edges |
327
- | `horus feedback <id> [--resolved] [--note] [--cause]` | Record outcome feedback on an investigation (improves Horus) |
328
- | `horus report [hint] [--title --body --labels]` | File a Horus bug or capability gap — opens a pre-filled GitHub issue (no auth, nothing sent automatically) |
329
-
330
- ## Local project workflow (git-style)
331
-
332
- A repo carries a `.horus/config.json` (discovered by walking up from the working directory, like `.git`) — the repo's config IS the project identity. Work from inside the repo, or pass `--config <path>` to target another repo explicitly.
333
-
334
- ```bash
335
- cd /repos/atlas-payments
336
- horus init
337
-
338
- horus investigate "checkout latency spike"
339
- horus investigate --config /repos/atlas-payments/.horus/config.json "checkout latency spike" # from anywhere
340
- horus projects # list registered repos (informational)
341
- ```
342
-
343
- `horus init` reuses an already-running source intelligence host when one is healthy. Runtime connectors are added to the env block of `.horus/config.json` afterwards.
344
-
345
- ## For coding agents
346
-
347
- Horus is built to be an agent's evidence layer. Install a skill that teaches your agent to reach for Horus before guessing:
348
-
349
- ```bash
350
- horus skill install claude # .claude/skills/horus/SKILL.md (also: codex · gemini · cursor · generic)
351
- horus mcp # expose the local knowledge index to agents over MCP (stdio)
352
- ```
353
-
354
- Every investigation/analysis command takes `--json` (`--format json` for `investigate`/`replay`) — compact by default, `--full` for the raw structure — and each result carries a deterministic `nextSteps` array. `horus packet "<hint>" --json` returns a compact briefing sized for a context window.
355
-
356
- ## Layout
357
-
358
- ```
359
- packages/
360
- core/ evidence model, config schema + project/env resolution, version pins
361
- connectors/ provider contracts + source intelligence (HTTP/MCP) · Elasticsearch · Sentry · Axiom · Grafana · MongoDB · Postgres · Redis · BullMQ · application-state · Git
362
- stitcher/ queue-boundary stitcher
363
- db/ Drizzle schema + migrations (plain Postgres, no pgvector)
364
- engine/ deterministic investigation pipeline (timeline, correlation, hypotheses, gaps)
365
- cli/ commander CLI
366
- apps/horus/ composition root (bundled bin)
367
- config/ horus.config.ts
368
- ```
369
-
370
- ## Foundation
371
-
372
- - TypeScript monorepo (pnpm + Turborepo)
373
- - Postgres + Drizzle — semantic search delegated to source intelligence backend
374
- - Built-in **Horus source intelligence backend**, over HTTP/MCP only
375
- - Project/environment-scoped connectors; read-only against production
Binary file