@merittdev/horus 0.23.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.23.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,377 +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, Azure Monitor, CloudWatch Logs, Google Cloud Logging, Prometheus, Azure Service Bus, Kafka, Firestore, SQL Server, 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
- [Set up the eight new connectors](docs/connectors.md): cloud logs, direct Prometheus, broker snapshots, Firestore and SQL Server.
77
-
78
- Trace reconstruction is not shipped yet. Connectors are read-only and project-scoped.
79
-
80
- ## Example output (illustrative)
81
-
82
- ```bash
83
- cd ~/code/atlas-payments
84
- horus investigate --env production "checkout latency spike"
85
- ```
86
-
87
- ```text
88
- # Investigation inv-347
89
- Hint: checkout latency spike
90
-
91
- ## Suspected causes (ranked)
92
- 1. [0.82 / high] Redis connection pool exhaustion [↑ queue]
93
-
94
- ## Hypotheses
95
- [supported] [0.78] queue: backlog growth preceded latency spike
96
-
97
- ## Evidence gaps
98
- - queue runtime state: worker heartbeat unavailable
99
-
100
- ## Evidence
101
- - ev-01 [elasticsearch/error] Request timeout increase
102
- - ev-04 [bullmq/queue] checkout-jobs backlog growth
103
-
104
- ## Next actions
105
- - Inspect worker concurrency changes in deploy #784
106
- ```
107
-
108
- ## Principles
109
-
110
- **Read-only** — Horus never writes to your production systems.
111
-
112
- **Deterministic first** — The engine is deterministic; optional `--ai` adds an Anthropic narrative.
113
-
114
- **Local-first** — Connectors read from your own clusters, not a hosted black box.
115
-
116
- **Project-scoped** — The repo you run in (its `.horus/config.json`) is the project identity; `--config <path>` targets another repo.
117
-
118
- **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.
119
-
120
- ## Capabilities
121
-
122
- Installable today. More connectors and AI providers are in progress.
123
-
124
- **Today**
125
-
126
- - Elasticsearch logs
127
- - Axiom logs
128
- - Sentry errors
129
- - Grafana metrics
130
- - MongoDB / Postgres / Redis state
131
- - BullMQ queue evidence
132
- - Shopify Admin (GraphQL — queries you supply)
133
- - Source intelligence (code graph)
134
- - Timeline generation
135
- - Evidence correlation
136
- - Investigation replay
137
- - Postmortem drafts
138
-
139
- **Coming next**
140
-
141
- - Kubernetes evidence
142
- - Distributed trace reconstruction
143
- - Slack evidence ingestion
144
- - Local AI provider execution
145
-
146
- ---
147
-
148
- ## Architecture
149
-
150
- Horus is organized in four layers:
151
-
152
- **Source Intelligence**
153
-
154
- - 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).
155
-
156
- **Runtime Evidence**
157
-
158
- - **Elasticsearch** — logs → synthesized error-signature evidence
159
- - **Axiom** — structured logs (APL) → synthesized error-signature evidence, same path as Elasticsearch
160
- - **Sentry** — grouped exceptions (issues) → same error-signature / direct-seed path as logs
161
- - **MongoDB / Postgres** — application/operational state
162
- - **Grafana** — metrics via its datasource proxy
163
- - **Redis / BullMQ** — cache & queue runtime state
164
- - **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.
165
- - **Git** — change history, ownership signals
166
-
167
- **Investigation** (deterministic)
168
-
169
- - **Queue Stitcher** — connects producer `queue.add(...)` to consumer `@Processor` handlers
170
- - **Timeline Engine** — orders evidence into a sequence of events
171
- - **Correlation Engine** — connects evidence across sources into incident threads
172
-
173
- **Presentation**
174
-
175
- - **Deterministic investigation report** — evidence, timeline, hypotheses, gap analysis, next actions
176
- - **Optional AI narrative** — a later layer on top of the deterministic report
177
-
178
- ### Source intelligence is built into Horus
179
-
180
- **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.
181
-
182
- 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.
183
-
184
- > 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.
185
-
186
- 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.
187
-
188
- ## Configuration
189
-
190
- The config model separates **code** from **runtime**:
191
-
192
- - **Code belongs to the project** — `repositories[]`, each served by its own source intelligence host.
193
- - **Runtime belongs to the environment** — `environments[].connectors` (Elasticsearch, Sentry, MongoDB, Postgres, Grafana, Redis/BullMQ, Axiom).
194
-
195
- ```ts
196
- // config/horus.config.ts
197
- export default defineConfig({
198
- projects: [
199
- {
200
- name: 'atlas-payments',
201
- repositories: [
202
- {
203
- name: 'atlas-payments',
204
- path: '/repos/atlas-payments',
205
- source: { hostUrl: 'http://127.0.0.1:8420' },
206
- },
207
- ],
208
- environments: [
209
- {
210
- name: 'production',
211
- readOnly: true,
212
- connectors: {
213
- elasticsearch: {
214
- indexPattern: 'atlas-payments-prod-*',
215
- serviceName: 'atlas-payments-prod',
216
- },
217
- mongodb: {
218
- database: 'atlas_payments_prod',
219
- collections: ['orders', 'payments', 'workers'],
220
- },
221
- grafana: {},
222
- },
223
- },
224
- ],
225
- },
226
- ],
227
- });
228
- ```
229
-
230
- 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.
231
-
232
- **No connector runs without an explicit project/env scope** — there are no global connector defaults.
233
-
234
- **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)**.
235
-
236
- ## Install
237
-
238
- See **[horus.sh/docs/installation](https://horus.sh/docs/installation)** for full install, update, and uninstall instructions.
239
-
240
- ```bash
241
- curl -fsSL https://horus.sh/install.sh | bash
242
- npm install -g @merittdev/horus
243
- brew install meritt-dev/tap/horus
244
- horus --version
245
- horus init
246
- ```
247
-
248
- 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.
249
-
250
- ### What the installer installs
251
-
252
- | Component | Role | Required |
253
- | --- | --- | --- |
254
- | **Horus CLI** | The `horus` command | Yes |
255
- | **Horus source intelligence backend** | Enables `horus init`, `horus explain`, `horus changes`, `horus architecture` | Optional |
256
-
257
- ### Prerequisites
258
-
259
- | Requirement | Role |
260
- | --- | --- |
261
- | Node.js 22+ | Horus CLI runtime (the installed binary needs Node.js) |
262
- | Python 3.11+ + uv/pip | Required only for the Horus source intelligence backend |
263
-
264
- The investigation audit store is **embedded** (bundled pglite, zero setup) — there is no Postgres to install. Teams that need shared state use **Horus Cloud**.
265
-
266
- The installer **does not** configure Elasticsearch, MongoDB, Grafana, Redis, or any production system. Runtime connectors are added per-project after install via `horus connect`.
267
-
268
- ### Direct download (without the curl installer)
269
-
270
- ```bash
271
- # Replace vX.Y.Z with the current release tag (see github.com/meritt-dev/horus/releases)
272
- curl -fsSL https://github.com/meritt-dev/horus/releases/download/vX.Y.Z/horus-vX.Y.Z -o horus
273
- chmod +x horus
274
- sudo mv horus /usr/local/bin/horus
275
- horus --version
276
- ```
277
-
278
- 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)**.
279
-
280
- If something goes wrong after install, run `horus doctor` and see **[horus.sh/docs/installation#troubleshooting](https://horus.sh/docs/installation#troubleshooting)**.
281
-
282
- ## Local development
283
-
284
- ```bash
285
- pnpm install
286
- pnpm build # builds apps/horus/dist/index.cjs
287
-
288
- # Per repository: start the source intelligence host and stitch queue boundaries
289
- horus init
290
-
291
- source ~/.horus.env
292
-
293
- node apps/horus/dist/index.cjs status
294
- ```
295
-
296
- **Verify the full v0.1 user path (init → investigate → replay → postmortem):**
297
-
298
- ```bash
299
- # No-services startup check (version, help, doctor):
300
- ./scripts/smoke-test.sh apps/horus/dist/index.cjs
301
-
302
- # Full end-to-end flow (uses the embedded pglite store — no services to start):
303
- ./scripts/e2e-smoke.sh apps/horus/dist/index.cjs
304
- ```
305
-
306
- ```bash
307
- horus --help
308
- horus help <command>
309
- horus investigate --help
310
- ```
311
-
312
- ### Core commands
313
-
314
- | Command | What it does |
315
- | --- | --- |
316
- | `horus status [--env]` | Per-project/env connector-health matrix |
317
- | `horus connect <type>` | Add/update a runtime connector — `elasticsearch` / `mongodb` / `postgres` / `sentry` / `axiom` / `grafana` / `redis` (plus `ai` to configure an AI provider) |
318
- | `horus init [--env <e>]` | Set up the current repo: config, source-intelligence host, index, queue map |
319
- | `horus hosts [--reap]` | List source-intelligence hosts and live status; `--reap` stops orphaned hosts |
320
- | `horus stop [--all]` | Stop this repo's source-intelligence host (`--all` stops every host) |
321
- | `horus investigate --env <e> "<hint>"` | Full deterministic investigation report (`--format json` for agents) |
322
- | `horus packet <hint\|savedId> [--for claude] [--json]` | Compact, honesty-framed briefing for a coding-agent context window |
323
- | `horus logs [service] --env <e>` | Error-signature evidence (`--raw` for lines) |
324
- | `horus state --env <e>` | MongoDB application-state evidence (read-only) |
325
- | `horus metrics [hint] --env <e>` | Grafana metrics evidence |
326
- | `horus queues [name] [--live]` | Queue topology from source intelligence; `--live` reads real-time Redis/BullMQ state |
327
- | `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) |
328
- | `horus memory <show\|add\|list\|link\|...>` | Inspect/author deterministic incident memory; `memory link` adds `supersedes` / `contradicts` / `recurs-with` edges |
329
- | `horus feedback <id> [--resolved] [--note] [--cause]` | Record outcome feedback on an investigation (improves Horus) |
330
- | `horus report [hint] [--title --body --labels]` | File a Horus bug or capability gap — opens a pre-filled GitHub issue (no auth, nothing sent automatically) |
331
-
332
- ## Local project workflow (git-style)
333
-
334
- 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.
335
-
336
- ```bash
337
- cd /repos/atlas-payments
338
- horus init
339
-
340
- horus investigate "checkout latency spike"
341
- horus investigate --config /repos/atlas-payments/.horus/config.json "checkout latency spike" # from anywhere
342
- horus projects # list registered repos (informational)
343
- ```
344
-
345
- `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.
346
-
347
- ## For coding agents
348
-
349
- Horus is built to be an agent's evidence layer. Install a skill that teaches your agent to reach for Horus before guessing:
350
-
351
- ```bash
352
- horus skill install claude # .claude/skills/horus/SKILL.md (also: codex · gemini · cursor · generic)
353
- horus mcp # expose the local knowledge index to agents over MCP (stdio)
354
- ```
355
-
356
- 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.
357
-
358
- ## Layout
359
-
360
- ```
361
- packages/
362
- core/ evidence model, config schema + project/env resolution, version pins
363
- connectors/ provider contracts + source intelligence (HTTP/MCP) · Elasticsearch · Sentry · Axiom · Grafana · MongoDB · Postgres · Redis · BullMQ · application-state · Git
364
- stitcher/ queue-boundary stitcher
365
- db/ Drizzle schema + migrations (plain Postgres, no pgvector)
366
- engine/ deterministic investigation pipeline (timeline, correlation, hypotheses, gaps)
367
- cli/ commander CLI
368
- apps/horus/ composition root (bundled bin)
369
- config/ horus.config.ts
370
- ```
371
-
372
- ## Foundation
373
-
374
- - TypeScript monorepo (pnpm + Turborepo)
375
- - Postgres + Drizzle — semantic search delegated to source intelligence backend
376
- - Built-in **Horus source intelligence backend**, over HTTP/MCP only
377
- - Project/environment-scoped connectors; read-only against production
Binary file