@newrelic/preflight 1.0.1 → 1.0.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.
- package/README.md +107 -401
- package/dist/dashboard/live-event-bus.d.ts.map +1 -1
- package/dist/dashboard/live-event-bus.js.map +1 -1
- package/dist/dashboard/routes/api-handler.d.ts.map +1 -1
- package/dist/dashboard/routes/api-handler.js +7 -8
- package/dist/dashboard/routes/api-handler.js.map +1 -1
- package/dist/dashboard/routes/sse-handler.js +11 -11
- package/dist/dashboard/routes/sse-handler.js.map +1 -1
- package/dist/hooks/event-processor.d.ts +9 -2
- package/dist/hooks/event-processor.d.ts.map +1 -1
- package/dist/hooks/event-processor.js +12 -0
- package/dist/hooks/event-processor.js.map +1 -1
- package/dist/hooks/session-resolver.js +1 -1
- package/dist/hooks/session-resolver.js.map +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +304 -153
- package/dist/index.js.map +1 -1
- package/dist/install/cli.d.ts.map +1 -1
- package/dist/install/cli.js +84 -40
- package/dist/install/cli.js.map +1 -1
- package/dist/install/install-helper.d.ts +14 -6
- package/dist/install/install-helper.d.ts.map +1 -1
- package/dist/install/install-helper.js +41 -22
- package/dist/install/install-helper.js.map +1 -1
- package/dist/install/platform.d.ts +21 -0
- package/dist/install/platform.d.ts.map +1 -0
- package/dist/install/platform.js +95 -0
- package/dist/install/platform.js.map +1 -0
- package/dist/install/schedule.d.ts +7 -0
- package/dist/install/schedule.d.ts.map +1 -1
- package/dist/install/schedule.js +75 -0
- package/dist/install/schedule.js.map +1 -1
- package/dist/install/setup-wizard.d.ts.map +1 -1
- package/dist/install/setup-wizard.js +43 -1
- package/dist/install/setup-wizard.js.map +1 -1
- package/dist/metrics/live-session-registry.js +4 -4
- package/dist/metrics/live-session-registry.js.map +1 -1
- package/dist/metrics/session-tracker.d.ts +2 -0
- package/dist/metrics/session-tracker.d.ts.map +1 -1
- package/dist/metrics/session-tracker.js +9 -2
- package/dist/metrics/session-tracker.js.map +1 -1
- package/dist/storage/local-store.js +1 -1
- package/dist/storage/local-store.js.map +1 -1
- package/dist/transport/nr-ingest.js +1 -1
- package/dist/transport/nr-ingest.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,498 +1,204 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="demo/preflight-logo.svg" alt="Preflight" width="96" height="96" />
|
|
3
|
+
<h1>Preflight</h1>
|
|
4
|
+
<p><strong>Observability for AI Coding Assistants</strong></p>
|
|
2
5
|
|
|
3
|
-
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
[](.nvmrc)
|
|
8
|
+
[](#quick-start)
|
|
9
|
+
[](#dashboards)
|
|
4
10
|
|
|
5
|
-
|
|
11
|
+
[**Docs**](docs/ADVANCED.md) • [**Examples**](examples/) • [**Community**](https://support.newrelic.com/s/) • [**Contributing**](CONTRIBUTING.md)
|
|
6
12
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
- **Tracks every action** — sees every file the AI reads, every command it runs, every edit it makes
|
|
10
|
-
- **Tracks costs** — calculates USD spend per session, day, and week, broken down by model
|
|
11
|
-
- **Detects waste** — catches inefficiencies like re-reading the same file repeatedly, making edits without reading first, or running the same failing command in a loop
|
|
12
|
-
- **Measures efficiency** — computes a 0-100 score per task based on how directly the AI worked toward the goal
|
|
13
|
-
- **Sends to New Relic** — all data lands in your NR account as queryable events and metrics, ready for dashboards and alerts
|
|
13
|
+
</div>
|
|
14
14
|
|
|
15
15
|
---
|
|
16
16
|
|
|
17
|
-
##
|
|
17
|
+
## Why Your AI Tool Needs Observability
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
Your AI coding assistant makes hundreds of decisions every session — what to read, what to edit, when to run commands. But you can't see any of it. You know it was fast, but was it _efficient_? You got a PR merged, but how much did it cost? You fixed a bug, but did it get stuck in a loop first?
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
**Preflight is observability for agentic coding** — the actions, cost, and efficiency of your AI coding assistant as it works. See exactly what's happening, how much it costs, and where your AI is wasting time.
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
**Local-first by design.** Preflight runs entirely on your machine and sends your data nowhere by default. A live dashboard at `localhost:7777` shows your sessions in real time, fully offline. Connect a New Relic account only when you want more — team rollups, alerting, and cross-session history. You choose: **local-only**, **New Relic**, or **both**.
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
---
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
## Demo
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
node --version
|
|
31
|
-
```
|
|
29
|
+

|
|
32
30
|
|
|
33
|
-
|
|
31
|
+
See cost breakdown, efficiency scoring, anti-patterns, and live session tracking in action.
|
|
34
32
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## What You Get
|
|
36
|
+
|
|
37
|
+
### Visibility
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
- **Every action captured** — file reads, edits, commands, searches
|
|
40
|
+
- **Live session dashboard** — see what's happening right now
|
|
41
|
+
- **Historical trends** — analyze patterns over weeks and months
|
|
40
42
|
|
|
41
|
-
|
|
43
|
+
### Cost Control
|
|
42
44
|
|
|
43
|
-
|
|
45
|
+
- **USD spend tracking** — per session, day, and week
|
|
46
|
+
- **Per-model breakdown** — know which models cost most
|
|
47
|
+
- **Budget alerts** — get notified before you overspend
|
|
48
|
+
- **Forecasting** — project monthly burn rate
|
|
44
49
|
|
|
45
|
-
|
|
46
|
-
| ---------------- | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
|
47
|
-
| **License key** | Sends telemetry data _into_ NR (ingest) | NR One → top-right menu → API keys → create a key of type **License**. Long hex string ending in `NRAL`. Not `NRAK-`. |
|
|
48
|
-
| **User API key** | Deploys dashboards and alerts _into_ NR | NR One → top-right menu → API keys → create a key of type **User**. Starts with `NRAK-`. Only needed for the deploy commands. |
|
|
50
|
+
### Efficiency Insights
|
|
49
51
|
|
|
50
|
-
|
|
52
|
+
- **Efficiency score** — 0–100 score per task, based on how directly the AI worked
|
|
53
|
+
- **Anti-pattern detection** — catches re-reads, blind edits, stuck loops
|
|
54
|
+
- **Personalized recommendations** — optimize your AI workflow
|
|
55
|
+
- **Weekly coaching reports** — narrative analysis vs. your historical baseline
|
|
51
56
|
|
|
52
|
-
|
|
57
|
+
### Dashboards
|
|
58
|
+
|
|
59
|
+
- **Local dashboard** — live session view at `localhost:7777`, no account required
|
|
60
|
+
- **7 pre-built New Relic dashboards** — deploy in seconds _(New Relic mode)_:
|
|
61
|
+
- **Overview** — session stats, cost summary, top tools
|
|
62
|
+
- **Personal** — 30-day self-reflection scoped to you
|
|
63
|
+
- **Session Detail** — deep-dive into a single session's tool calls
|
|
64
|
+
- **Team View** — aggregated cost and efficiency across developers
|
|
65
|
+
- **Manager View** — high-level team metrics, no tool-call content
|
|
66
|
+
- **Platform Comparison** — Claude Code vs. Cursor vs. Windsurf, etc.
|
|
67
|
+
- **Security Audit** — audit trail of sensitive file access
|
|
53
68
|
|
|
54
69
|
---
|
|
55
70
|
|
|
56
71
|
## Quick Start
|
|
57
72
|
|
|
58
|
-
|
|
73
|
+
### 1. Install
|
|
59
74
|
|
|
60
75
|
```bash
|
|
61
76
|
npm install -g @newrelic/preflight
|
|
62
77
|
```
|
|
63
78
|
|
|
64
|
-
|
|
79
|
+
### 2. Run setup
|
|
65
80
|
|
|
66
81
|
```bash
|
|
67
82
|
preflight setup
|
|
68
83
|
```
|
|
69
84
|
|
|
70
|
-
The wizard
|
|
85
|
+
The wizard defaults to **local mode** — press Enter through the prompts and you're set. It wires Preflight into your AI tool (hooks + MCP server) and writes config to `~/.newrelic-preflight/`. Takes under a minute, no account required.
|
|
71
86
|
|
|
72
|
-
|
|
87
|
+
When prompted, pick a mode:
|
|
73
88
|
|
|
74
|
-
|
|
89
|
+
| Mode | What it does | New Relic account? |
|
|
90
|
+
| --------------------- | -------------------------------------------------------------------- | ------------------ |
|
|
91
|
+
| **local** _(default)_ | Everything stays on your machine; live dashboard at `localhost:7777` | Not needed |
|
|
92
|
+
| **cloud** | Ships telemetry to New Relic | Required |
|
|
93
|
+
| **both** | Local dashboard **and** New Relic | Required |
|
|
75
94
|
|
|
76
|
-
|
|
77
|
-
preflight install \
|
|
78
|
-
--license-key YOUR_LICENSE_KEY \
|
|
79
|
-
--account-id YOUR_ACCOUNT_ID
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
This installs the hook scripts in your Claude Code settings and registers the MCP server in `~/.mcp.json`, so every tool call is captured and the `nr_observe_*` tools are available in Claude Code. You only run this once.
|
|
95
|
+
### 3. Start coding
|
|
83
96
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
Replace `NRAK-...` with your user API key and `12345` with your account ID:
|
|
87
|
-
|
|
88
|
-
```bash
|
|
89
|
-
NEW_RELIC_API_KEY=NRAK-... NEW_RELIC_ACCOUNT_ID=12345 \
|
|
90
|
-
preflight deploy-dashboards --all
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
This creates 7 dashboards in your NR account. Find them under **Dashboards** → search "AI Coding". The deploy commands ship with the package — both `preflight deploy-dashboards` and `preflight deploy-alerts` are available immediately after `npm install -g`.
|
|
94
|
-
|
|
95
|
-
> **Region:** Use your account's license key and account ID for your environment. Add `--eu` for EU region accounts or `--gov` for FedRAMP accounts. Omit both flags for standard production (`one.newrelic.com`).
|
|
96
|
-
|
|
97
|
-
**Step 4 — Restart Claude Code and verify**
|
|
98
|
-
|
|
99
|
-
Restart Claude Code, then verify the MCP server connected:
|
|
100
|
-
|
|
101
|
-
> _Can you call the `nr_observe_health` tool and show me the result?_
|
|
102
|
-
|
|
103
|
-
You should see `"status": "ok"` with a version and uptime. Then make any request to Claude Code (triggering at least one tool call), and check session tracking:
|
|
104
|
-
|
|
105
|
-
> _Can you call the `nr_observe_get_session_stats` tool and show me the result?_
|
|
106
|
-
|
|
107
|
-
If you get back tool call counts and timing data, it's working.
|
|
108
|
-
|
|
109
|
-
---
|
|
110
|
-
|
|
111
|
-
## From source / contributing
|
|
112
|
-
|
|
113
|
-
This is also the current install path until the npm package is published. Use it to develop the project, deploy dashboards/alerts, or stay on the latest unreleased changes:
|
|
114
|
-
|
|
115
|
-
```bash
|
|
116
|
-
git clone https://github.com/newrelic-experimental/preflight
|
|
117
|
-
cd preflight
|
|
118
|
-
nvm use # Switch to the right Node version (24+)
|
|
119
|
-
npm install # Install all dependencies
|
|
120
|
-
npm run build # Compile TypeScript
|
|
121
|
-
npm link # Register preflight binary on PATH (required for hooks)
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
Then run `preflight setup` exactly as in the Quick Start.
|
|
125
|
-
|
|
126
|
-
> **`npm link` permission error?** If you see `EACCES: permission denied` pointing at `/usr/local/lib/node_modules`, your system Node.js is installed in a root-owned directory. Pick one fix:
|
|
127
|
-
>
|
|
128
|
-
> _Quick fix — set a user-writable npm prefix (keeps your existing Node.js):_
|
|
129
|
-
>
|
|
130
|
-
> ```bash
|
|
131
|
-
> npm config set prefix ~/.npm-global
|
|
132
|
-
> export PATH="$HOME/.npm-global/bin:$PATH" # also add to ~/.zshrc or ~/.bash_profile
|
|
133
|
-
> npm link
|
|
134
|
-
> ```
|
|
135
|
-
>
|
|
136
|
-
> _Recommended — use nvm (better if you switch Node versions):_
|
|
137
|
-
>
|
|
138
|
-
> ```bash
|
|
139
|
-
> curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
|
|
140
|
-
> # restart your shell, then:
|
|
141
|
-
> nvm install 24 && nvm use 24
|
|
142
|
-
> npm install && npm run build && npm link
|
|
143
|
-
> ```
|
|
144
|
-
>
|
|
145
|
-
> Do not use `sudo npm link` — it creates root-owned files that break future `npm install` runs.
|
|
97
|
+
Restart your AI tool — hooks and the MCP server load at session start. Every tool call is captured automatically. Open **http://localhost:7777** to watch your session live.
|
|
146
98
|
|
|
147
99
|
---
|
|
148
100
|
|
|
149
|
-
##
|
|
150
|
-
|
|
151
|
-
Once installed, Claude Code can query live session data on your behalf. Just ask it in plain English — or use the tool names directly:
|
|
101
|
+
## Works With
|
|
152
102
|
|
|
153
|
-
|
|
154
|
-
| --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
|
|
155
|
-
| _"Show me my session stats"_ → `nr_observe_get_session_stats` | Tool call counts, success rate, total duration |
|
|
156
|
-
| _"What's my efficiency score?"_ → `nr_observe_get_efficiency_score` | A 0-100 score with a breakdown of where points were lost |
|
|
157
|
-
| _"How much has this session cost?"_ → `nr_observe_get_cost_breakdown` | USD cost broken down by tool type and AI model |
|
|
158
|
-
| _"Any budget warnings?"_ → `nr_observe_get_budget_status` | Current spend vs. your configured caps (if set) |
|
|
159
|
-
| _"Any wasteful patterns?"_ → `nr_observe_get_anti_patterns` | Detected inefficiencies — repeated reads, blind edits, stuck loops |
|
|
160
|
-
| _"Any recommendations?"_ → `nr_observe_get_recommendations` | Personalized suggestions for this session |
|
|
161
|
-
| _"How am I doing this week?"_ → `nr_observe_get_personal_insights` | A narrative coaching report vs. your own historical baseline (requires 2+ weeks of history) |
|
|
162
|
-
|
|
163
|
-
Everything also flows into your New Relic dashboards automatically — you don't have to ask Claude to see it there.
|
|
103
|
+
**Claude Code** • **Cursor** • **Windsurf** • **GitHub Copilot** • **Zed** • **Continue.dev** • **Amazon Q Developer**
|
|
164
104
|
|
|
165
105
|
---
|
|
166
106
|
|
|
167
|
-
##
|
|
168
|
-
|
|
169
|
-
After deploying, you'll have seven dashboards in NR One:
|
|
107
|
+
## Connect New Relic (optional)
|
|
170
108
|
|
|
171
|
-
|
|
172
|
-
| ----------------------- | --------------------------------------------------------------- |
|
|
173
|
-
| **Overview** | Session stats, efficiency score, cost summary, top tools |
|
|
174
|
-
| **Session Detail** | Every tool call in a specific session, in order |
|
|
175
|
-
| **Personal** | 30-day self-reflection view scoped to one developer |
|
|
176
|
-
| **Team View** | Aggregated cost and efficiency across multiple developers |
|
|
177
|
-
| **Manager View** | Team-level cost by developer with no tool-call content visible |
|
|
178
|
-
| **Platform Comparison** | Side-by-side metrics across Claude Code, Cursor, Windsurf, etc. |
|
|
179
|
-
| **Security Audit** | Audit trail of sensitive file access and destructive commands |
|
|
109
|
+
Local mode is fully featured on its own. Connect a New Relic account to unlock:
|
|
180
110
|
|
|
181
|
-
|
|
111
|
+
- **Team & manager dashboards** across multiple developers
|
|
112
|
+
- **Alerting** on cost spikes, low efficiency, and stuck loops
|
|
113
|
+
- **Cross-session history**, trends, and weekly coaching reports
|
|
182
114
|
|
|
183
|
-
|
|
115
|
+
Re-run `preflight setup` and choose **cloud** or **both**, or configure it non-interactively:
|
|
184
116
|
|
|
185
117
|
```bash
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
### Updating or removing dashboards
|
|
192
|
-
|
|
193
|
-
To replace existing dashboards in place after pulling new fixes (preserves the dashboard's GUID and URL), add `--update`:
|
|
194
|
-
|
|
195
|
-
```bash
|
|
196
|
-
NEW_RELIC_API_KEY=NRAK-... NEW_RELIC_ACCOUNT_ID=12345 \
|
|
197
|
-
preflight deploy-dashboards --all --update
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
To delete the deployed dashboards, add `--teardown`. Dashboards are matched by name; missing ones are skipped:
|
|
201
|
-
|
|
202
|
-
```bash
|
|
203
|
-
NEW_RELIC_API_KEY=NRAK-... NEW_RELIC_ACCOUNT_ID=12345 \
|
|
204
|
-
preflight deploy-dashboards --all --teardown
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
### Terraform (IaC alternative)
|
|
208
|
-
|
|
209
|
-
A Terraform module in `terraform/` deploys all 7 dashboards and the full alert policy as an alternative to the deploy scripts — useful for GitOps workflows or when you want state tracking. See [ADVANCED.md — Terraform Deployment](./docs/ADVANCED.md#terraform-deployment) for usage.
|
|
210
|
-
|
|
211
|
-
---
|
|
212
|
-
|
|
213
|
-
## Alert Conditions
|
|
214
|
-
|
|
215
|
-
Optional: get notified in NR when something goes wrong.
|
|
216
|
-
|
|
217
|
-
```bash
|
|
218
|
-
NEW_RELIC_API_KEY=NRAK-... NEW_RELIC_ACCOUNT_ID=12345 \
|
|
219
|
-
preflight deploy-alerts
|
|
118
|
+
preflight install \
|
|
119
|
+
--mode cloud \
|
|
120
|
+
--license-key YOUR_LICENSE_KEY \
|
|
121
|
+
--account-id YOUR_ACCOUNT_ID
|
|
220
122
|
```
|
|
221
123
|
|
|
222
|
-
|
|
124
|
+
EU accounts add `--eu`. FedRAMP accounts add `--fedramp`.
|
|
223
125
|
|
|
224
|
-
|
|
126
|
+
Then deploy the prebuilt dashboards:
|
|
225
127
|
|
|
226
128
|
```bash
|
|
227
129
|
NEW_RELIC_API_KEY=NRAK-... NEW_RELIC_ACCOUNT_ID=12345 \
|
|
228
|
-
preflight deploy-
|
|
130
|
+
preflight deploy-dashboards --all
|
|
229
131
|
```
|
|
230
132
|
|
|
231
|
-
|
|
133
|
+
You'll need a **license key** (telemetry ingest) and your **account ID**, plus a **user API key** (`NRAK-…`) to deploy dashboards and alerts. See [ADVANCED.md](docs/ADVANCED.md) for alerts, OTLP export to other backends, and Terraform.
|
|
232
134
|
|
|
233
|
-
|
|
234
|
-
NEW_RELIC_API_KEY=NRAK-... NEW_RELIC_ACCOUNT_ID=12345 \
|
|
235
|
-
preflight deploy-alerts --developer your-name
|
|
236
|
-
```
|
|
135
|
+
> **Data ingest note:** Telemetry sent to New Relic counts against your account's data ingest. On paid plans, standard ingest rates apply. Monitor your usage under **NR One → Data Management → Data Ingestion**.
|
|
237
136
|
|
|
238
137
|
---
|
|
239
138
|
|
|
240
|
-
##
|
|
241
|
-
|
|
242
|
-
The easiest way to configure is through the setup wizard (`preflight setup`). To edit manually, open `~/.newrelic-preflight/config.json`:
|
|
243
|
-
|
|
244
|
-
```json
|
|
245
|
-
{
|
|
246
|
-
"licenseKey": "aabbccdd...",
|
|
247
|
-
"accountId": "12345",
|
|
248
|
-
"developer": "your-name",
|
|
249
|
-
"sessionBudgetUsd": 1.0,
|
|
250
|
-
"dailyBudgetUsd": 5.0,
|
|
251
|
-
"weeklyBudgetUsd": 20.0
|
|
252
|
-
}
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
### Key settings
|
|
256
|
-
|
|
257
|
-
| Setting | What it does | Default |
|
|
258
|
-
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
|
|
259
|
-
| `developer` | Your identifier on all NR events. Automatically normalized to lowercase with underscores — e.g., "John Doe" → "john_doe". Falls back to `$USER` or your git name if not set. | Inferred |
|
|
260
|
-
| `collectorHost` | Region override: `null` = US (default), `'eu'` = EU, `'gov'` = FedRAMP/GovCloud. The wizard auto-detects from your license key prefix and lets you confirm. | `null` (US) |
|
|
261
|
-
| `nrApiKey` | User API key (`NRAK-...`) for NerdGraph queries (team summaries, dashboard/alert deploy). The wizard prompts for it and validates it live. | Not set |
|
|
262
|
-
| `sessionBudgetUsd` | Emits a warning event at 50%, 80%, 100% of this amount per session | No limit |
|
|
263
|
-
| `dailyBudgetUsd` | Emits a warning event at 50%, 80%, 100% of this amount per day | No limit |
|
|
264
|
-
| `weeklyBudgetUsd` | Emits a warning event at 50%, 80%, 100% of this amount per week | No limit |
|
|
265
|
-
| `retainSessionsDays` | Auto-deletes local session files older than N days | Keep forever |
|
|
266
|
-
| `teamId` | A label **you define** (e.g. `"platform-eng"`, `"my-team"`) stamped on all NR events as `team_id`, enabling cross-developer queries like `WHERE team_id = 'platform-eng'`. This is **not** your NR account ID — it's a free-form slug you choose to identify your team. | Not set |
|
|
267
|
-
| `projectId` | Tags all events with a project name (auto-derived from your git remote URL if not set) | Auto-derived |
|
|
268
|
-
| `digestWebhookUrl` | Slack webhook URL for weekly cost and efficiency summaries | Not set |
|
|
269
|
-
|
|
270
|
-
All settings can also be set via environment variables — see [example.config.js](./example.config.js) for the full annotated reference.
|
|
271
|
-
|
|
272
|
-
### Validating your config
|
|
273
|
-
|
|
274
|
-
If the MCP server fails to connect, run:
|
|
275
|
-
|
|
276
|
-
```bash
|
|
277
|
-
preflight validate
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
This checks your config file for JSON syntax errors, invalid field types, and misspelled or unknown keys — and suggests corrections:
|
|
139
|
+
## Requirements
|
|
281
140
|
|
|
282
|
-
|
|
283
|
-
✗ Error: mode: Invalid enum value. Expected 'cloud' | 'local' | 'both', received 'clod'
|
|
284
|
-
⚠ Warning: Unknown key "licensekey" — did you mean "licenseKey"?
|
|
285
|
-
```
|
|
141
|
+
### Required
|
|
286
142
|
|
|
287
|
-
|
|
143
|
+
- **Node.js v22 or higher** ([get it](https://nodejs.org) or use [nvm](https://github.com/nvm-sh/nvm))
|
|
144
|
+
- **An AI coding tool** (Claude Code recommended for deepest integration)
|
|
288
145
|
|
|
289
|
-
###
|
|
146
|
+
### Optional
|
|
290
147
|
|
|
291
|
-
|
|
148
|
+
- **New Relic account** — only for `cloud`/`both` mode. Skip it to run local-only (the default).
|
|
149
|
+
- **User API key** (`NRAK-…`) — only needed to deploy dashboards and alerts
|
|
292
150
|
|
|
293
151
|
---
|
|
294
152
|
|
|
295
|
-
##
|
|
296
|
-
|
|
297
|
-
To pull the latest changes and rebuild in one step:
|
|
153
|
+
## Other Commands
|
|
298
154
|
|
|
299
155
|
```bash
|
|
300
|
-
preflight
|
|
156
|
+
preflight validate # Check config for syntax errors and unknown keys
|
|
157
|
+
preflight update # Pull latest version and rebuild
|
|
158
|
+
preflight uninstall # Remove hooks and MCP config from your AI tool
|
|
301
159
|
```
|
|
302
160
|
|
|
303
|
-
|
|
161
|
+
Add `--project` to `install`/`uninstall` to scope changes to the current directory only.
|
|
304
162
|
|
|
305
163
|
---
|
|
306
164
|
|
|
307
|
-
##
|
|
308
|
-
|
|
309
|
-
To remove the Preflight hooks and MCP server from Claude Code:
|
|
310
|
-
|
|
311
|
-
```bash
|
|
312
|
-
preflight uninstall
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
This removes the hooks from your user-level Claude Code settings and deregisters the MCP server. A timestamped backup of your settings is saved automatically before any changes are made.
|
|
316
|
-
|
|
317
|
-
If you installed at the project level, add `--project`:
|
|
318
|
-
|
|
319
|
-
```bash
|
|
320
|
-
preflight uninstall --project
|
|
321
|
-
```
|
|
322
|
-
|
|
323
|
-
Restart Claude Code after uninstalling for the changes to take effect.
|
|
324
|
-
|
|
325
|
-
### Removing dashboards and alerts
|
|
326
|
-
|
|
327
|
-
If you deployed dashboards or alerts, tear them down separately:
|
|
328
|
-
|
|
329
|
-
```bash
|
|
330
|
-
NEW_RELIC_API_KEY=NRAK-... NEW_RELIC_ACCOUNT_ID=12345 \
|
|
331
|
-
preflight deploy-dashboards --all --teardown
|
|
332
|
-
|
|
333
|
-
NEW_RELIC_API_KEY=NRAK-... NEW_RELIC_ACCOUNT_ID=12345 \
|
|
334
|
-
preflight deploy-alerts --teardown
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
### Removing local data
|
|
338
|
-
|
|
339
|
-
Session history and configuration are stored in `~/.newrelic-preflight/`. To remove everything:
|
|
340
|
-
|
|
341
|
-
```bash
|
|
342
|
-
rm -rf ~/.newrelic-preflight
|
|
343
|
-
```
|
|
344
|
-
|
|
345
|
-
### Unlinking the binary
|
|
346
|
-
|
|
347
|
-
If you registered the CLI globally via `npm link`, remove it with:
|
|
165
|
+
## Documentation
|
|
348
166
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
167
|
+
- [**ADVANCED.md**](docs/ADVANCED.md) — Configuration, dashboards, alerts, Terraform
|
|
168
|
+
- [**CONTRIBUTING.md**](CONTRIBUTING.md) — Development, testing, submitting PRs
|
|
169
|
+
- [**SECURITY.md**](docs/SECURITY.md) — Security guidelines and best practices
|
|
352
170
|
|
|
353
171
|
---
|
|
354
172
|
|
|
355
|
-
##
|
|
356
|
-
|
|
357
|
-
If you'd rather not ship telemetry to New Relic, set `mode: 'local'` in your config:
|
|
358
|
-
|
|
359
|
-
```json
|
|
360
|
-
{
|
|
361
|
-
"mode": "local"
|
|
362
|
-
}
|
|
363
|
-
```
|
|
364
|
-
|
|
365
|
-
In local mode:
|
|
366
|
-
|
|
367
|
-
- The MCP server does **not** construct `NrIngestManager` and never makes outbound HTTP calls to NR.
|
|
368
|
-
- An embedded dashboard boots at **http://127.0.0.1:7777** (configurable via `dashboard.port` or `NR_AI_DASHBOARD_PORT`).
|
|
369
|
-
- All telemetry stays in `~/.newrelic-preflight/` on your machine.
|
|
370
|
-
- `licenseKey` and `accountId` are not required.
|
|
173
|
+
## From Source
|
|
371
174
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
**Standalone** (no Claude Code required): pass `--local` to run the dashboard server directly, without an MCP transport. Use this to browse the dashboard when Claude Code isn't running, or to observe non-Claude-Code sources that hit the hooks (e.g. scripts using the Anthropic SDK). If the per-session MCP is also installed, only one process owns the dashboard at a time — whichever started first — and the other runs headless.
|
|
175
|
+
Develop, test, or run the latest unreleased version:
|
|
375
176
|
|
|
376
177
|
```bash
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
#
|
|
380
|
-
npm
|
|
381
|
-
npm run
|
|
382
|
-
npm
|
|
178
|
+
git clone https://github.com/newrelic-experimental/preflight
|
|
179
|
+
cd preflight
|
|
180
|
+
nvm use # Switch to Node v24
|
|
181
|
+
npm install # Install dependencies
|
|
182
|
+
npm run build # Compile TypeScript
|
|
183
|
+
npm link # Register preflight on PATH
|
|
383
184
|
```
|
|
384
185
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
The dashboard has six views:
|
|
388
|
-
|
|
389
|
-
- **Today** — live KPIs, sparkline of tool latencies, recent calls, anti-pattern alerts.
|
|
390
|
-
- **Sessions** — list of past sessions with a per-session timeline of every tool call.
|
|
391
|
-
- **History** — weekly efficiency and daily spend trends.
|
|
392
|
-
- **Audit** — every classified tool call (sensitive file access, destructive commands, external network), with a JSONL export button.
|
|
393
|
-
- **Settings** — edit developer name, team ID, budget caps, and session retention from the browser (no config file editing required).
|
|
394
|
-
- **Alerts** — live budget spend vs. caps, editable personal alert thresholds, and Slack digest configuration.
|
|
395
|
-
|
|
396
|
-
Run `preflight setup` to choose a mode interactively.
|
|
186
|
+
Then run `preflight setup` as usual.
|
|
397
187
|
|
|
398
188
|
---
|
|
399
189
|
|
|
400
|
-
##
|
|
401
|
-
|
|
402
|
-
Local-mode users get threshold alerting evaluated in-process — no New Relic dependency. Rules live at `~/.newrelic-preflight/alerts/rules.json`; a starter set is copied into place by the setup wizard.
|
|
403
|
-
|
|
404
|
-
For the full list of rule types, channel options, alert log configuration, and live reload behavior, see [ADVANCED.md](./docs/ADVANCED.md#local-alerts).
|
|
405
|
-
|
|
406
|
-
---
|
|
407
|
-
|
|
408
|
-
## Weekly Digest
|
|
409
|
-
|
|
410
|
-
Register a Slack webhook to receive a weekly summary every Monday morning:
|
|
411
|
-
|
|
412
|
-
In Claude Code, ask: _"Call `nr_observe_subscribe_digest` with this webhook URL: `https://hooks.slack.com/services/...`"_
|
|
190
|
+
## License
|
|
413
191
|
|
|
414
|
-
|
|
192
|
+
Preflight is open source under the [Apache License 2.0](LICENSE).
|
|
415
193
|
|
|
416
194
|
---
|
|
417
195
|
|
|
418
|
-
##
|
|
419
|
-
|
|
420
|
-
| Platform | How to enable |
|
|
421
|
-
| ------------------ | ------------------------------------------------------ |
|
|
422
|
-
| Claude Code | `preflight install` (automatic) |
|
|
423
|
-
| Cursor | Set `NEW_RELIC_AI_PLATFORM=cursor` in your environment |
|
|
424
|
-
| Windsurf | Set `NEW_RELIC_AI_PLATFORM=windsurf` |
|
|
425
|
-
| GitHub Copilot | Set `NEW_RELIC_AI_PLATFORM=copilot` |
|
|
426
|
-
| Zed | Set `NEW_RELIC_AI_PLATFORM=zed` |
|
|
427
|
-
| Continue.dev | Set `NEW_RELIC_AI_PLATFORM=continue` |
|
|
428
|
-
| Amazon Q Developer | Set `NEW_RELIC_AI_PLATFORM=amazonq` |
|
|
429
|
-
|
|
430
|
-
---
|
|
431
|
-
|
|
432
|
-
## Glossary
|
|
433
|
-
|
|
434
|
-
**MCP (Model Context Protocol)** — A standard that lets AI assistants like Claude Code discover and call external tools. Preflight registers itself as an MCP server so Claude Code can call it directly.
|
|
435
|
-
|
|
436
|
-
**License key** — A NR credential for _sending_ data into New Relic. Looks like a long hex string ending in `NRAL`. Found under API Keys in NR One.
|
|
437
|
-
|
|
438
|
-
**User API key** — A NR credential for _reading_ data and managing resources (dashboards, alerts). Starts with `NRAK-`. Create one under API Keys in NR One.
|
|
439
|
-
|
|
440
|
-
**Anti-pattern** — A detected waste pattern. Examples: re-reading the same file multiple times without making changes between reads (the AI lost context and is reloading it), making edits to a file without reading it first (blind edit), running the same failing command in a loop (stuck loop).
|
|
441
|
-
|
|
442
|
-
**Efficiency score** — A 0-100 number per task. High means the AI worked directly toward the goal. Low means wasted tool calls — repeated reads, blind edits, unnecessary backtracking.
|
|
443
|
-
|
|
444
|
-
**Token** — The unit AI models use to measure text length for billing. Roughly 3-4 characters per token. One page of text ≈ 500 tokens.
|
|
445
|
-
|
|
446
|
-
**Hook** — A script that Claude Code calls automatically before and after every tool call. Preflight uses this to capture tool call data without interrupting your workflow.
|
|
447
|
-
|
|
448
|
-
---
|
|
449
|
-
|
|
450
|
-
## Requirements
|
|
451
|
-
|
|
452
|
-
- **Node.js**: v22 or higher (`.nvmrc` pins v24 for development)
|
|
453
|
-
- **New Relic account**: free tier works; you need a license key (a user API key is optional — only needed for deploying dashboards and alerts)
|
|
454
|
-
- **An AI coding tool**: Claude Code, Cursor, Windsurf, GitHub Copilot, Zed, Continue.dev, or Amazon Q
|
|
455
|
-
|
|
456
|
-
---
|
|
457
|
-
|
|
458
|
-
## Documentation
|
|
459
|
-
|
|
460
|
-
- **[CONTRIBUTING.md](./CONTRIBUTING.md)** — Development setup, architecture, conventions, testing, and end-to-end verification
|
|
461
|
-
- **[ADVANCED.md](./docs/ADVANCED.md)** — OTLP export, local alerts, per-developer alerts, session backfill, Terraform deployment
|
|
462
|
-
- **[COMMANDS_TABLE.md](./docs/COMMANDS_TABLE.md)** — All MCP tools with parameters and return values
|
|
463
|
-
- **[METRICS_TABLE.md](./docs/METRICS_TABLE.md)** — Every event and metric sent to New Relic
|
|
464
|
-
- **[SECURITY.md](./docs/SECURITY.md)** — Security practices and audit trail
|
|
465
|
-
|
|
466
|
-
---
|
|
467
|
-
|
|
468
|
-
## For Contributors
|
|
469
|
-
|
|
470
|
-
### Development setup
|
|
471
|
-
|
|
472
|
-
```bash
|
|
473
|
-
nvm install && nvm use
|
|
474
|
-
npm install
|
|
475
|
-
npm run build
|
|
476
|
-
npm test
|
|
477
|
-
```
|
|
478
|
-
|
|
479
|
-
### Common tasks
|
|
480
|
-
|
|
481
|
-
| Command | Purpose |
|
|
482
|
-
| ---------------------- | ---------------------------------------------------------- |
|
|
483
|
-
| `npm run build` | Build TypeScript server + Vite web dashboard |
|
|
484
|
-
| `npm run build:server` | Build only the TypeScript server (`tsc --build`) |
|
|
485
|
-
| `npm run build:web` | Build only the Vite web dashboard (output: `dist/web/`) |
|
|
486
|
-
| `npm test` | Run all tests |
|
|
487
|
-
| `npm run lint` | Check code style |
|
|
488
|
-
| `npm run format` | Auto-format code |
|
|
489
|
-
| `npm run dev` | Start local dashboard (assumes pre-built `dist/`) |
|
|
490
|
-
| `npm run dev:all` | Build then start local dashboard |
|
|
491
|
-
| `npm run dev:full` | Build backend, then run backend + Vite dev server together |
|
|
492
|
-
| `npm run start:local` | Alias for `npm run dev` |
|
|
196
|
+
## Contributing
|
|
493
197
|
|
|
494
|
-
See [CONTRIBUTING.md](
|
|
198
|
+
We welcome contributions! See [CONTRIBUTING.md](CONTRIBUTING.md) for how to get started. Join the [New Relic Community](https://support.newrelic.com/s/) to share ideas, ask questions, or discuss features.
|
|
495
199
|
|
|
496
200
|
---
|
|
497
201
|
|
|
498
|
-
|
|
202
|
+
<div align="center">
|
|
203
|
+
<p><strong>Built by New Relic • Designed for developers who use AI</strong></p>
|
|
204
|
+
</div>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"live-event-bus.d.ts","sourceRoot":"","sources":["../../src/dashboard/live-event-bus.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"live-event-bus.d.ts","sourceRoot":"","sources":["../../src/dashboard/live-event-bus.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"live-event-bus.js","sourceRoot":"","sources":["../../src/dashboard/live-event-bus.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"live-event-bus.js","sourceRoot":"","sources":["../../src/dashboard/live-event-bus.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAgG3C,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAOhC,4EAA4E;AAC5E,0EAA0E;AAC1E,yEAAyE;AACzE,wEAAwE;AACxE,MAAM,UAAU,GAAG,UAAU,CAAC;AAE9B,MAAM,OAAO,YAAY;IACN,OAAO,GAAG,IAAI,YAAY,EAAE,CAAC;IAC7B,MAAM,GAAkB,EAAE,CAAC;IAC3B,UAAU,CAAS;IACpC,yEAAyE;IACzE,0EAA0E;IAC1E,2EAA2E;IAC3E,8DAA8D;IACtD,OAAO,GAAG,CAAC,CAAC;IAEpB,YAAY,OAA4B,EAAE;QACxC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,gBAAgB,IAAI,mBAAmB,CAAC;QAC/D,gEAAgE;QAChE,mEAAmE;QACnE,+DAA+D;QAC/D,gEAAgE;QAChE,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;IACpC,CAAC;IAED,EAAE,CAA0B,KAAQ,EAAE,OAA2C;QAC/E,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAuC,CAAC,CAAC;IAClE,CAAC;IAED,GAAG,CAA0B,KAAQ,EAAE,OAA2C;QAChF,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,OAAuC,CAAC,CAAC;IACnE,CAAC;IAED,yEAAyE;IACzE,0EAA0E;IAC1E,oEAAoE;IACpE,uBAAuB;IACvB,SAAS,CAA0B,KAAQ,EAAE,OAAqC;QAChF,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,GAAG,KAAK,EAAE,OAAuC,CAAC,CAAC;IAC/E,CAAC;IAED,UAAU,CAA0B,KAAQ,EAAE,OAAqC;QACjF,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,GAAG,KAAK,EAAE,OAAuC,CAAC,CAAC;IAChF,CAAC;IAED,IAAI,CAA0B,KAAQ,EAAE,OAAwB;QAC9D,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QAC3B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QAC1C,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,UAAU;YAAE,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAC9D,wEAAwE;QACxE,wEAAwE;QACxE,6CAA6C;QAC7C,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAClC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,OAAO,EAAwB,CAAC,CAAC;IAChF,CAAC;IAED,UAAU,CAAC,OAAe;QACxB,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,OAAO,CAAC,CAAC;IACpD,CAAC;CACF"}
|