hawkeye-ai 0.1.2 → 0.1.3

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/README.md +682 -0
  2. package/package.json +2 -2
package/README.md ADDED
@@ -0,0 +1,682 @@
1
+ <p align="center">
2
+ <pre align="center">
3
+ ██╗ ██╗
4
+ ██║ ██║
5
+ ███████║ <b>Hawkeye</b>
6
+ ██╔══██║ The flight recorder for AI agents
7
+ ██║ ██║
8
+ ╚═╝ ╚═╝
9
+ </pre>
10
+ </p>
11
+
12
+ <p align="center">
13
+ <strong>Open-source observability & security for AI agents</strong><br/>
14
+ <em>Claude Code · Aider · AutoGPT · CrewAI · Open Interpreter · any LLM-powered agent</em>
15
+ </p>
16
+
17
+ <p align="center">
18
+ <a href="#installation">Install</a> •
19
+ <a href="#quick-start">Quick Start</a> •
20
+ <a href="#features">Features</a> •
21
+ <a href="#cli-commands">CLI</a> •
22
+ <a href="#dashboard">Dashboard</a> •
23
+ <a href="#driftdetect">DriftDetect</a> •
24
+ <a href="#guardrails">Guardrails</a> •
25
+ <a href="#security">Security</a> •
26
+ <a href="#architecture">Architecture</a>
27
+ </p>
28
+
29
+ ---
30
+
31
+ ## What is Hawkeye?
32
+
33
+ Hawkeye is a **flight recorder** for AI agents. It captures every action an agent performs — terminal commands, file operations, LLM calls, API requests — and provides:
34
+
35
+ - **Session recording & replay** — Full timeline of every agent action with costs and metadata
36
+ - **DriftDetect** — Real-time objective drift detection using heuristic + LLM scoring
37
+ - **Guardrails** — File protection, command blocking, cost limits, token limits, directory scoping
38
+ - **Visual dashboard** — Mobile-responsive web UI with session explorer, drift charts, and settings management
39
+ - **Remote tasks** — Submit prompts from your phone via dashboard, with image attachments, auto-approve, and persistent agent memory
40
+ - **Interactive TUI** — Terminal-responsive CLI with arrow-key navigation and slash commands
41
+ - **OpenTelemetry export** — Push traces to Grafana Tempo, Jaeger, Datadog, Honeycomb
42
+ - **Universal ingestion API** — Accept events from any source (MCP servers, custom tools)
43
+ - **Multi-agent support** — Claude Code (hooks), Aider, Open Interpreter, AutoGPT, CrewAI, or any custom command
44
+
45
+ ## Installation
46
+
47
+ ### npm (recommended)
48
+
49
+ ```bash
50
+ npm install -g @mklamine/hawkeye-cli
51
+ ```
52
+
53
+ ### npx (no install)
54
+
55
+ ```bash
56
+ npx @mklamine/hawkeye-cli
57
+ ```
58
+
59
+ ### Homebrew (macOS/Linux)
60
+
61
+ ```bash
62
+ brew tap mklamine/hawkeye
63
+ brew install hawkeye
64
+ ```
65
+
66
+ ### From source
67
+
68
+ ```bash
69
+ git clone https://github.com/lamine/hawkeye.git
70
+ cd hawkeye
71
+ pnpm install && pnpm build
72
+ cd packages/cli && npm link
73
+ ```
74
+
75
+ ## Quick Start
76
+
77
+ ```bash
78
+ # Initialize in your project
79
+ hawkeye init
80
+
81
+ # Record an agent session
82
+ hawkeye record -o "Build a REST API" -- claude chat
83
+
84
+ # Or launch the interactive TUI
85
+ hawkeye
86
+ ```
87
+
88
+ ## Features
89
+
90
+ ### Session Recording
91
+
92
+ Wrap any LLM-powered agent with `hawkeye record` to capture everything:
93
+
94
+ ```bash
95
+ hawkeye record -o "Refactor auth module" -- claude chat
96
+ hawkeye record -o "Fix bug #42" --agent cursor -- cursor .
97
+ hawkeye record -o "Deploy to staging" --no-drift -- node deploy.js
98
+ ```
99
+
100
+ Hawkeye automatically detects the agent (Claude Code, Aider, AutoGPT, CrewAI, Open Interpreter) and intercepts:
101
+
102
+ | Interceptor | What it captures |
103
+ | -------------- | ------------------------------------------------------ |
104
+ | **Terminal** | Commands executed, exit codes, stdout/stderr |
105
+ | **Filesystem** | File reads, writes, deletes, renames |
106
+ | **Network** | HTTP requests, LLM API calls with token counts & costs |
107
+
108
+ ### Claude Code Hooks
109
+
110
+ For agents with bundled Node.js runtimes (where `NODE_OPTIONS` injection doesn't work), Hawkeye integrates via **Claude Code hooks**:
111
+
112
+ ```bash
113
+ hawkeye hooks install # Install PreToolUse + PostToolUse hooks
114
+ hawkeye hooks install --guardrails-only # Only install guardrail enforcement
115
+ hawkeye hooks status # Check installation
116
+ hawkeye hooks uninstall # Remove hooks
117
+ ```
118
+
119
+ Hooks provide:
120
+
121
+ - **PreToolUse** — Guardrails enforcement (exit code 2 blocks the action)
122
+ - **PostToolUse** — Event recording to SQLite
123
+ - **Stop** — Drift score update (fires after every response, does not end session)
124
+ - Sessions auto-created per `session_id`
125
+
126
+ ### Interactive TUI
127
+
128
+ Launch the interactive mode by running `hawkeye` with no subcommand:
129
+
130
+ ```
131
+ ██╗ ██╗
132
+ ██║ ██║
133
+ ███████║ Hawkeye v0.1.0
134
+ ██╔══██║ The flight recorder for AI agents
135
+ ██║ ██║ /Users/you/project
136
+ ╚═╝ ╚═╝
137
+
138
+ ● Recording: "Build REST API" (5m 23s)
139
+
140
+ › /
141
+ ```
142
+
143
+ Type `/` to open the command picker with arrow-key navigation and live filtering:
144
+
145
+ | Command | Description |
146
+ | -------------- | ---------------------------------------------- |
147
+ | `/new` | New session — pick agent, model, objective |
148
+ | `/sessions` | List & manage recorded sessions |
149
+ | `/active` | Show current recording |
150
+ | `/stats` | Session statistics |
151
+ | `/end` | End active sessions |
152
+ | `/restart` | Restart a session (with picker) |
153
+ | `/delete` | Delete a session |
154
+ | `/tasks` | List, create, clear remote tasks |
155
+ | `/tasks journal` | View agent memory (task history) |
156
+ | `/remote` | Launch serve + daemon + Cloudflare tunnel |
157
+ | `/remote stop` | Stop tunnel + daemon |
158
+ | `/settings` | Configure DriftDetect, Guardrails, API keys |
159
+ | `/serve` | Open the web dashboard |
160
+ | `/mcp` | Show MCP server setup instructions |
161
+ | `/revert` | Revert file changes from a session |
162
+ | `/init` | Initialize Hawkeye |
163
+ | `/clear` | Clear screen |
164
+ | `/quit` | Exit |
165
+
166
+ ## CLI Commands
167
+
168
+ ### `hawkeye init`
169
+
170
+ Initialize Hawkeye in the current directory. Creates `.hawkeye/` directory and config files.
171
+
172
+ ### `hawkeye record`
173
+
174
+ ```bash
175
+ hawkeye record -o <objective> [options] -- <command...>
176
+ ```
177
+
178
+ | Option | Description |
179
+ | ----------------- | --------------------------------------- |
180
+ | `-o, --objective` | Session objective **(required)** |
181
+ | `-a, --agent` | Agent name (auto-detected from command) |
182
+ | `-m, --model` | Model name |
183
+ | `--no-drift` | Disable DriftDetect |
184
+ | `--no-guardrails` | Disable guardrails |
185
+
186
+ ### `hawkeye sessions`
187
+
188
+ ```bash
189
+ hawkeye sessions [-n 10] [-s recording|completed|aborted]
190
+ ```
191
+
192
+ ### `hawkeye stats <session-id>`
193
+
194
+ Display statistics for a session (accepts ID prefix).
195
+
196
+ ### `hawkeye replay <session-id>`
197
+
198
+ ```bash
199
+ hawkeye replay <session-id> [--speed 2] [--no-delay]
200
+ ```
201
+
202
+ Replay a session action-by-action with timing.
203
+
204
+ ### `hawkeye serve`
205
+
206
+ ```bash
207
+ hawkeye serve [-p 4242]
208
+ ```
209
+
210
+ Launch the web dashboard on `http://localhost:4242`. Auto-reloads after `pnpm build` — watches `dist/` and restarts the server when compiled files change.
211
+
212
+ ### `hawkeye daemon`
213
+
214
+ ```bash
215
+ hawkeye daemon [--agent claude] [--interval 30]
216
+ ```
217
+
218
+ Run the task daemon — polls `.hawkeye/tasks.json` for pending tasks and executes them. Features:
219
+
220
+ - **Persistent memory**: writes a task journal (`.hawkeye/task-journal.md`) after each task
221
+ - **Conversation continuity**: uses `claude --continue` within 30-min windows
222
+ - **Context injection**: enriches prompts with git status, recent commits, and task history
223
+ - Works with any agent CLI, not just Claude
224
+
225
+ ### `hawkeye export`
226
+
227
+ ```bash
228
+ hawkeye export <session-id> [-f json|html] [-o report.html]
229
+ ```
230
+
231
+ ### `hawkeye end`
232
+
233
+ ```bash
234
+ hawkeye end [-s <session-id>] [--all] [--status completed|aborted]
235
+ ```
236
+
237
+ ### `hawkeye restart`
238
+
239
+ ```bash
240
+ hawkeye restart [session-id] [-o <objective>] [-a <agent>] [-m <model>]
241
+ ```
242
+
243
+ Restart a session — inherits objective, agent, and model from the original if not overridden. Interactive picker when no ID is given.
244
+
245
+ ### `hawkeye otel-export`
246
+
247
+ ```bash
248
+ hawkeye otel-export <session-id> [-o traces.json]
249
+ hawkeye otel-export <session-id> --endpoint https://tempo.example.com/v1/traces
250
+ ```
251
+
252
+ Export as OTLP JSON traces. Compatible with Grafana Tempo, Jaeger, Datadog, Honeycomb.
253
+
254
+ ### `hawkeye hooks`
255
+
256
+ ```bash
257
+ hawkeye hooks install [--local] [--guardrails-only]
258
+ hawkeye hooks uninstall [--local]
259
+ hawkeye hooks status
260
+ ```
261
+
262
+ ### `hawkeye mcp`
263
+
264
+ Start the MCP (Model Context Protocol) server over stdio. Agents connect automatically.
265
+
266
+ ```bash
267
+ hawkeye mcp [--db <path>]
268
+ ```
269
+
270
+ Add to `.mcp.json` at project root for Claude Code:
271
+
272
+ ```json
273
+ {
274
+ "mcpServers": {
275
+ "hawkeye": {
276
+ "command": "node",
277
+ "args": ["path/to/hawkeye/packages/cli/dist/index.js", "mcp"]
278
+ }
279
+ }
280
+ }
281
+ ```
282
+
283
+ **27 tools** for agent self-awareness:
284
+
285
+ | Category | Tools |
286
+ |----------|-------|
287
+ | **Observability** (9) | `list_sessions`, `get_session`, `get_session_events`, `get_session_drift`, `get_session_stats`, `get_global_stats`, `compare_sessions`, `get_violations`, `get_cost_by_file` |
288
+ | **Self-awareness** (8) | `check_drift`, `get_objective`, `check_cost`, `check_guardrail`, `check_progress`, `log_event`, `list_changes`, `get_config` |
289
+ | **Intelligence** (4) | `get_session_timeline`, `get_error_summary`, `suggest_correction`, `post_mortem` |
290
+ | **Actions** (4) | `end_session`, `pause_session`, `resume_session`, `set_objective` |
291
+ | **Cross-session** (2) | `search_events`, `revert_file` |
292
+
293
+ ## Dashboard
294
+
295
+ The web dashboard (`hawkeye serve`) is fully **mobile responsive** and provides:
296
+
297
+ ### Sessions Page
298
+
299
+ - List all sessions with status filtering (recording / completed / aborted)
300
+ - Search by objective or agent name
301
+ - Auto-refresh every 5 seconds, module-level cache (no flash on page change)
302
+ - Shows costs, drift scores, action counts
303
+
304
+ ### Session Detail Page
305
+
306
+ - **Drift score chart** — Line chart with warning/critical reference zones
307
+ - **Event timeline** — Filterable, searchable list with type badges (CMD, FILE, LLM, GUARD, etc.)
308
+ - **Expandable details** — Full event payload for each action
309
+ - **Live mode** — Auto-refreshes every 3 seconds for active sessions
310
+ - **Export** — Download session as JSON
311
+
312
+ ### Tasks Page (Remote)
313
+
314
+ - Submit prompts remotely from your phone
315
+ - **Image attachments** — Upload photos to include with prompts
316
+ - **Auto-approve toggle** — Automatically approve all guardrail-blocked actions
317
+ - **Approve/Deny buttons** — Manually review dangerous actions
318
+ - **Agent memory** — View/clear the persistent task journal
319
+ - Status tracking: pending, running, completed, failed
320
+
321
+ ### Compare Page
322
+
323
+ - Select two sessions to compare side by side
324
+ - Stats comparison (actions, cost, tokens, drift)
325
+
326
+ ### Settings Page
327
+
328
+ - Configure DriftDetect (provider, model, thresholds, check frequency)
329
+ - Manage guardrail rules (enable/disable, toggle warn/block)
330
+ - Provider model selection with live lookup
331
+
332
+ ### REST API
333
+
334
+ | Endpoint | Method | Description |
335
+ | --------------------------------- | ------ | -------------------------------- |
336
+ | `/api/sessions` | GET | List sessions |
337
+ | `/api/sessions/:id` | GET | Session details |
338
+ | `/api/sessions/:id/events` | GET | Session events |
339
+ | `/api/sessions/:id/drift` | GET | Drift snapshots |
340
+ | `/api/sessions/:id/cost-by-file` | GET | Cost breakdown by file |
341
+ | `/api/sessions/:id/end` | POST | End a session |
342
+ | `/api/sessions/:id/pause` | POST | Pause a session |
343
+ | `/api/sessions/:id/resume` | POST | Resume a paused session |
344
+ | `/api/compare?ids=id1,id2` | GET | Compare sessions side by side |
345
+ | `/api/stats` | GET | Global statistics |
346
+ | `/api/settings` | GET | Get configuration |
347
+ | `/api/settings` | POST | Save configuration (Zod-validated) |
348
+ | `/api/providers` | GET | Available LLM providers & models |
349
+ | `/api/ingest` | POST | Universal event ingestion (Zod-validated) |
350
+ | `/api/revert` | POST | Revert a file change |
351
+ | `/api/tasks` | GET | List remote tasks |
352
+ | `/api/tasks` | POST | Create a task (with attachments) |
353
+ | `/api/tasks/:id/cancel` | POST | Cancel a pending task |
354
+ | `/api/tasks/journal` | GET | Read agent memory journal |
355
+ | `/api/tasks/journal/clear` | POST | Clear agent memory |
356
+ | `/api/tasks/attachments/:file` | GET | Serve task image attachments |
357
+ | `/api/pending-reviews` | GET | List pending review gate items |
358
+ | `/api/review-approve` | POST | Approve a review gate item |
359
+ | `/api/review-deny` | POST | Deny a review gate item |
360
+
361
+ ## DriftDetect
362
+
363
+ DriftDetect monitors agent behavior in real-time and assigns a **drift score** (0–100):
364
+
365
+ | Score | Status | Meaning |
366
+ | ------ | ----------- | --------------------------------- |
367
+ | 70–100 | ✅ OK | Agent is on track |
368
+ | 40–69 | ⚠️ Warning | Possible deviation from objective |
369
+ | 0–39 | 🔴 Critical | Significant drift detected |
370
+
371
+ ### Scoring Engines
372
+
373
+ **Heuristic scorer** (always active, zero-cost):
374
+
375
+ - Penalizes dangerous commands (`rm -rf`, `DROP TABLE`, `curl | bash`)
376
+ - Flags suspicious paths (`/etc`, `~/.ssh`, `/root`)
377
+ - Detects sensitive file extensions (`.pem`, `.key`, `.env`)
378
+ - Monitors error rates
379
+
380
+ **LLM scorer** (optional, configurable):
381
+
382
+ - Evaluates actions against the stated objective using an LLM
383
+ - Supports 6 providers:
384
+
385
+ | Provider | Models |
386
+ | --------- | ---------------------------------------------------------------------------------------------------- |
387
+ | Ollama | llama4, llama3.2, mistral, codellama, deepseek-coder, phi3 |
388
+ | Anthropic | claude-sonnet-4-6, claude-opus-4-6, claude-haiku-4-5, claude-sonnet-4-5, claude-opus-4-5 |
389
+ | OpenAI | gpt-4o, gpt-4o-mini, gpt-4.1, gpt-4.1-mini, gpt-4.1-nano, gpt-5, gpt-5-mini, o3, o3-mini, o4-mini |
390
+ | DeepSeek | deepseek-chat, deepseek-reasoner |
391
+ | Mistral | mistral-large-latest, mistral-medium-latest, mistral-small-latest, codestral-latest, devstral-latest |
392
+ | Google | gemini-2.5-pro, gemini-2.5-flash, gemini-2.5-flash-lite, gemini-2.0-flash |
393
+
394
+ ## Guardrails
395
+
396
+ Guardrails are evaluated **synchronously before** events are persisted. Violations can `warn` (log only) or `block` (prevent the action).
397
+
398
+ | Rule Type | Description | Config |
399
+ | ----------------- | -------------------------------------- | ------------------------------------- |
400
+ | `file_protect` | Protect files/dirs from modification | `paths: string[]` (glob patterns) |
401
+ | `command_block` | Block dangerous commands | `patterns: string[]` (regex patterns) |
402
+ | `cost_limit` | Limit spending per session/hour | `maxUsdPerSession`, `maxUsdPerHour` |
403
+ | `token_limit` | Limit token consumption | `maxTokensPerSession` |
404
+ | `directory_scope` | Restrict agent to specific directories | `allowedDirs`, `blockedDirs` |
405
+ | `network_lock` | Allow/block specific API hostnames | `allowedHosts`, `blockedHosts` |
406
+ | `review_gate` | Require human approval for commands | `patterns: string[]` (regex patterns) |
407
+
408
+ Example configuration (via `/settings` in TUI or dashboard):
409
+
410
+ ```json
411
+ {
412
+ "guardrails": [
413
+ {
414
+ "name": "Protect secrets",
415
+ "type": "file_protect",
416
+ "enabled": true,
417
+ "action": "block",
418
+ "config": { "paths": ["**/.env", "**/*.key", "**/*.pem"] }
419
+ },
420
+ {
421
+ "name": "No destructive commands",
422
+ "type": "command_block",
423
+ "enabled": true,
424
+ "action": "block",
425
+ "config": { "patterns": ["rm\\s+-rf\\s+/", "DROP\\s+TABLE", "curl.*\\|.*bash"] }
426
+ },
427
+ {
428
+ "name": "Budget limit",
429
+ "type": "cost_limit",
430
+ "enabled": true,
431
+ "action": "warn",
432
+ "config": { "maxUsdPerSession": 5.0, "maxUsdPerHour": 2.0 }
433
+ }
434
+ ]
435
+ }
436
+ ```
437
+
438
+ ## Configuration
439
+
440
+ Configuration is stored at `.hawkeye/config.json`:
441
+
442
+ ```json
443
+ {
444
+ "drift": {
445
+ "enabled": true,
446
+ "checkEvery": 5,
447
+ "provider": "ollama",
448
+ "model": "llama3.2",
449
+ "warningThreshold": 60,
450
+ "criticalThreshold": 30,
451
+ "contextWindow": 10
452
+ },
453
+ "guardrails": [],
454
+ "apiKeys": {
455
+ "anthropic": "sk-ant-...",
456
+ "openai": "sk-..."
457
+ }
458
+ }
459
+ ```
460
+
461
+ Manage settings via:
462
+
463
+ - **TUI**: `/settings` command with interactive sub-menus
464
+ - **Dashboard**: Settings page at `http://localhost:4242/settings`
465
+ - **Direct edit**: `.hawkeye/config.json`
466
+
467
+ ## Security
468
+
469
+ Hawkeye is designed to run locally. The dashboard server binds to `localhost` and includes multiple security layers:
470
+
471
+ | Protection | Description |
472
+ |---|---|
473
+ | **CORS** | Only `localhost` / `127.0.0.1` origins accepted |
474
+ | **WebSocket origin check** | Upgrade requests from cross-origin pages are rejected |
475
+ | **POST body limit** | 5 MB max — oversized requests are destroyed (prevents DoS) |
476
+ | **Path traversal** | Static file serving and attachment endpoints verify resolved paths stay within their root |
477
+ | **No command injection** | All git operations use `execFile()` with argument arrays, never shell strings |
478
+ | **Config file permissions** | `.hawkeye/config.json` written with `0o600` (owner-only) to protect API keys |
479
+ | **Concurrent write safety** | Hook handler uses exclusive lockfile for `hook-sessions.json` writes |
480
+
481
+ ### API Keys
482
+
483
+ API keys for LLM providers (Anthropic, OpenAI, etc.) are stored in `.hawkeye/config.json`. The file is created with restricted permissions (`0o600`), but you should also add `.hawkeye/` to your global `.gitignore` to avoid accidental commits.
484
+
485
+ ## Architecture
486
+
487
+ TypeScript monorepo using **pnpm workspaces** + **Turborepo**:
488
+
489
+ ```
490
+ packages/
491
+ ├── core/ Node.js SDK — recorder, interceptors, storage, DriftDetect, guardrails
492
+ ├── cli/ CLI (Commander.js + chalk) — commands, interactive TUI
493
+ └── dashboard/ React 19 + Vite + Tailwind CSS + Recharts — web UI
494
+ ```
495
+
496
+ ### Data Flow
497
+
498
+ ```
499
+ Agent ──► Interceptors ──► Recorder ──► Guardrails (sync) ──► SQLite
500
+
501
+ └──► DriftDetect (async)
502
+ ```
503
+
504
+ ### Network Interception
505
+
506
+ For child processes, Hawkeye injects a preload ESM script via `NODE_OPTIONS="--import ..."` that monkey-patches `http/https.request` and `globalThis.fetch`. It detects LLM API calls by hostname and path, parses SSE streaming responses, and sends captured events back to the parent via Node.js IPC.
507
+
508
+ ### Storage
509
+
510
+ SQLite via `better-sqlite3` with WAL mode. Four tables:
511
+
512
+ | Table | Purpose |
513
+ | ---------------------- | ------------------------------------------------------------- |
514
+ | `sessions` | Session metadata (objective, agent, status, timestamps) |
515
+ | `events` | Captured events (type, data, timestamps, token counts, costs) |
516
+ | `drift_snapshots` | Drift score history per session |
517
+ | `guardrail_violations` | Guardrail violation log |
518
+
519
+ ## Development
520
+
521
+ ```bash
522
+ pnpm install # Install all dependencies
523
+ pnpm build # Production build (all packages)
524
+ pnpm dev # Dev mode (Turborepo watch)
525
+ pnpm test # Run all tests (Vitest)
526
+ pnpm --filter @hawkeye/core test # Run only core tests
527
+ pnpm --filter @hawkeye/cli build # Build only CLI
528
+ ```
529
+
530
+ ### Requirements
531
+
532
+ - Node.js ≥ 20
533
+ - pnpm 9.x
534
+
535
+ ### Tech Stack
536
+
537
+ | Package | Stack |
538
+ | -------------------- | -------------------------------------- |
539
+ | `@hawkeye/core` | TypeScript, better-sqlite3, Vitest |
540
+ | `@hawkeye/cli` | TypeScript, Commander.js, chalk v5 |
541
+ | `@hawkeye/dashboard` | React 19, Vite, Tailwind CSS, Recharts |
542
+
543
+ ### Code Conventions
544
+
545
+ - TypeScript strict mode, ES2022 target, ESM modules
546
+ - File names in kebab-case
547
+ - Named exports only (no default exports except React components)
548
+ - `Result<T, E>` pattern for error handling (no throwing in core)
549
+ - Prettier: semi, singleQuote, trailingComma: all, printWidth: 100
550
+
551
+ ## Publishing
552
+
553
+ ### npm
554
+
555
+ Hawkeye is published as two packages on npm:
556
+
557
+ - [`@mklamine/hawkeye-core`](https://www.npmjs.com/package/@mklamine/hawkeye-core) — Core SDK
558
+ - [`@mklamine/hawkeye-cli`](https://www.npmjs.com/package/@mklamine/hawkeye-cli) — CLI with bundled dashboard
559
+
560
+ ```bash
561
+ # Build everything
562
+ pnpm build
563
+
564
+ # Publish (pnpm resolves workspace:* to real versions)
565
+ pnpm -r publish --access public --no-git-checks
566
+ ```
567
+
568
+ The CLI `prepack` script automatically copies the dashboard build into the CLI package so it ships as a single installable.
569
+
570
+ ### Homebrew
571
+
572
+ To distribute via Homebrew, create a tap repository (e.g. `homebrew-hawkeye`) with a formula:
573
+
574
+ ```ruby
575
+ # Formula/hawkeye.rb
576
+ class Hawkeye < Formula
577
+ desc "The flight recorder for AI agents"
578
+ homepage "https://github.com/mklamine/hawkeye"
579
+ url "https://registry.npmjs.org/@mklamine/hawkeye-cli/-/hawkeye-cli-0.1.1.tgz"
580
+ sha256 "SHA256_OF_TARBALL"
581
+
582
+ depends_on "node@20"
583
+
584
+ def install
585
+ system "npm", "install", *std_npm_args
586
+ bin.install_symlink libexec/"bin/hawkeye"
587
+ end
588
+
589
+ test do
590
+ assert_match "hawkeye", shell_output("#{bin}/hawkeye --version")
591
+ end
592
+ end
593
+ ```
594
+
595
+ Then:
596
+
597
+ ```bash
598
+ # Create the tap repo
599
+ gh repo create mklamine/homebrew-hawkeye --public
600
+
601
+ # Users install with:
602
+ brew tap mklamine/hawkeye
603
+ brew install hawkeye
604
+ ```
605
+
606
+ ### GitHub Releases
607
+
608
+ Automate releases with a GitHub Actions workflow:
609
+
610
+ ```bash
611
+ # Tag a release
612
+ git tag v0.1.0
613
+ git push origin v0.1.0
614
+ ```
615
+
616
+ Add a `.github/workflows/release.yml` to auto-publish to npm on tag push (see below).
617
+
618
+ ## CI/CD
619
+
620
+ <details>
621
+ <summary><code>.github/workflows/ci.yml</code> — Test & Build</summary>
622
+
623
+ ```yaml
624
+ name: CI
625
+ on: [push, pull_request]
626
+ jobs:
627
+ build:
628
+ runs-on: ubuntu-latest
629
+ steps:
630
+ - uses: actions/checkout@v4
631
+ - uses: pnpm/action-setup@v4
632
+ - uses: actions/setup-node@v4
633
+ with:
634
+ node-version: 20
635
+ cache: pnpm
636
+ - run: pnpm install --frozen-lockfile
637
+ - run: pnpm build
638
+ - run: pnpm test
639
+ ```
640
+
641
+ </details>
642
+
643
+ <details>
644
+ <summary><code>.github/workflows/release.yml</code> — Publish to npm on tag</summary>
645
+
646
+ ```yaml
647
+ name: Release
648
+ on:
649
+ push:
650
+ tags: ['v*']
651
+ jobs:
652
+ publish:
653
+ runs-on: ubuntu-latest
654
+ permissions:
655
+ contents: write
656
+ steps:
657
+ - uses: actions/checkout@v4
658
+ - uses: pnpm/action-setup@v4
659
+ - uses: actions/setup-node@v4
660
+ with:
661
+ node-version: 20
662
+ cache: pnpm
663
+ registry-url: https://registry.npmjs.org
664
+ - run: pnpm install --frozen-lockfile
665
+ - run: pnpm build
666
+ - run: pnpm -r publish --access public --no-git-checks
667
+ env:
668
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
669
+ - uses: softprops/action-gh-release@v2
670
+ with:
671
+ generate_release_notes: true
672
+ ```
673
+
674
+ </details>
675
+
676
+ ## Acknowledgments
677
+
678
+ Special thanks to **Lamine** for their contributions and support.
679
+
680
+ ## License
681
+
682
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hawkeye-ai",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "CLI for Hawkeye — the flight recorder for AI agents",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -34,7 +34,7 @@
34
34
  "dev": "tsc --watch",
35
35
  "test": "vitest run --passWithNoTests",
36
36
  "lint": "eslint src/",
37
- "prepack": "node -e \"const{cpSync,existsSync,mkdirSync}=require('fs');const{join}=require('path');const src=join(__dirname,'..','dashboard','dist');const dst=join(__dirname,'dashboard');if(existsSync(src)){mkdirSync(dst,{recursive:true});cpSync(src,dst,{recursive:true});console.log('Bundled dashboard dist into CLI package')}else{console.warn('Dashboard dist not found — run pnpm build first')}\""
37
+ "prepack": "node -e \"const{cpSync,existsSync,mkdirSync}=require('fs');const{join}=require('path');const src=join(__dirname,'..','dashboard','dist');const dst=join(__dirname,'dashboard');if(existsSync(src)){mkdirSync(dst,{recursive:true});cpSync(src,dst,{recursive:true});console.log('Bundled dashboard dist into CLI package')}else{console.warn('Dashboard dist not found — run pnpm build first')};const readme=join(__dirname,'..','..','README.md');if(existsSync(readme)){cpSync(readme,join(__dirname,'README.md'));console.log('Copied README.md')}\""
38
38
  },
39
39
  "dependencies": {
40
40
  "@mklamine/hawkeye-core": "^0.1.1",