mb-run 0.0.3-dev-20260705-2f3e02d → 0.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/CHANGELOG.md CHANGED
@@ -21,12 +21,12 @@ If you like this project and find it useful, please consider giving it a star on
21
21
 
22
22
  <a href="https://www.buymeacoffee.com/luligugithub"><img src="https://matterbridge.io/assets/bmc-button.svg" alt="Buy me a coffee" width="120"></a>
23
23
 
24
- ## [0.0.3] - Dev branch
24
+ ## [0.0.3] - 2026-07-06
25
25
 
26
26
  ### Added
27
27
 
28
- - [copilot]: Update VS Code settings to version 1.0.6 and add terminal auto-approve configurations.
29
- - [claude]: Update Claude settings to version 1.0.3 and add terminal auto-approve configurations.
28
+ - [copilot]: Update VS Code settings to version 1.0.7 and add terminal auto-approve configurations.
29
+ - [claude]: Update Claude settings to version 1.0.4 and add terminal auto-approve configurations.
30
30
  - [package]: Apply style.
31
31
 
32
32
  ### Changed
package/dist/upgrade.js CHANGED
@@ -116,7 +116,11 @@ export async function runPackageJsonUpgrade(opts, pkgPath, pkgJson, isMonorepo =
116
116
  removeDirSafe(path.join(dstDir, '.claude', 'rules', 'matterbridge'));
117
117
  }
118
118
  if (!isWorkspace) {
119
+ copyRecursive('.agents', '.agents');
119
120
  copyRecursive('.codex', '.codex');
121
+ copyRecursive('AGENTS.md', 'AGENTS.md');
122
+ if (!isPlugin)
123
+ unlinkSafe(path.join(dstDir, '.agents', 'matterbridge.md'));
120
124
  if (!isPlugin)
121
125
  removeDirSafe(path.join(dstDir, '.codex', 'rules', 'matterbridge'));
122
126
  }
@@ -339,6 +343,8 @@ export async function runPackageJsonUpgrade(opts, pkgPath, pkgJson, isMonorepo =
339
343
  fileReplace('CHANGELOG.md', '(https://github.com/prettier/prettier)', '(https://prettier.io/)');
340
344
  fileReplace('CHANGELOG.md', '(https://github.com/eslint/eslint)', '(https://eslint.org/)');
341
345
  fileReplace('CHANGELOG.md', '(https://nodejs.org/api/esm.html)', '(https://nodejs.org/)');
346
+ if (isMonorepo)
347
+ return;
342
348
  const scripts = pkgJson.scripts;
343
349
  const startScript = scripts?.start ?? `node ${pkgJson.main ?? 'dist/module.js'}`;
344
350
  log(magenta(`Start script: ${cyan(startScript)}`));
@@ -482,7 +488,7 @@ export async function runPackageJsonUpgrade(opts, pkgPath, pkgJson, isMonorepo =
482
488
  log(green('Installing devDependencies...'));
483
489
  const commands = [
484
490
  `npm pkg delete overrides`,
485
- `npm install --no-fund --no-audit --save-dev --save-exact typescript @types/node @typescript/native-preview oxlint oxlint-tsgolint oxfmt`,
491
+ `npm install --no-fund --no-audit --save-dev --save-exact typescript ${opts.useNode ? '@types/node' : ''} ${opts.useBun ? '@types/bun' : ''} @typescript/native-preview oxlint oxlint-tsgolint oxfmt`,
486
492
  opts.enableJest ? `npm install --no-fund --no-audit --save-dev --save-exact jest ts-jest @types/jest @jest/globals cross-env` : null,
487
493
  opts.enableVitest ? `npm install --no-fund --no-audit --save-dev --save-exact vitest @vitest/coverage-v8` : null,
488
494
  opts.enableBundle ? 'npm install --no-fund --no-audit --save-dev --save-exact esbuild' : null,
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "mb-run",
3
- "version": "0.0.3-dev-20260705-2f3e02d",
3
+ "version": "0.0.3",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "mb-run",
9
- "version": "0.0.3-dev-20260705-2f3e02d",
9
+ "version": "0.0.3",
10
10
  "license": "Apache-2.0",
11
11
  "dependencies": {
12
12
  "cross-spawn": "7.0.6",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mb-run",
3
- "version": "0.0.3-dev-20260705-2f3e02d",
3
+ "version": "0.0.3",
4
4
  "description": "Matterbridge command line executor",
5
5
  "author": "https://github.com/Luligu",
6
6
  "license": "Apache-2.0",
@@ -0,0 +1,319 @@
1
+ # Matterbridge Endpoint Guide
2
+
3
+ Use this guide when writing Matterbridge code in this repository or when authoring a plugin that consumes Matterbridge.
4
+
5
+ ## Public imports
6
+
7
+ - Import core classes, endpoint helpers, and device type definitions from `matterbridge`.
8
+ - Import single-class devices from `matterbridge/devices`.
9
+
10
+ ```ts
11
+ import {
12
+ MatterbridgeAccessoryPlatform,
13
+ MatterbridgeDynamicPlatform,
14
+ MatterbridgeEndpoint,
15
+ addFixedLabel,
16
+ addUserLabel,
17
+ contactSensor,
18
+ getAttribute,
19
+ onOffLight,
20
+ powerSource,
21
+ setAttribute,
22
+ subscribeAttribute,
23
+ updateAttribute,
24
+ } from 'matterbridge';
25
+
26
+ import { LaundryWasher, RoboticVacuumCleaner } from 'matterbridge/devices';
27
+ ```
28
+
29
+ ## Create a MatterbridgeEndpoint
30
+
31
+ `MatterbridgeEndpoint` is the low-level building block for custom Matterbridge devices.
32
+
33
+ Constructor:
34
+
35
+ ```ts
36
+ new MatterbridgeEndpoint(
37
+ definition: DeviceTypeDefinition | AtLeastOne<DeviceTypeDefinition>,
38
+ options: MatterbridgeEndpointOptions = {},
39
+ debug = false,
40
+ )
41
+ ```
42
+
43
+ Recommended pattern:
44
+
45
+ ```ts
46
+ const device = new MatterbridgeEndpoint([contactSensor, powerSource], { id: 'EntryDoor' })
47
+ .createDefaultIdentifyClusterServer()
48
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Entry Door', 'ENTRY-DOOR-001', 0xfff1, 'Matterbridge', 'Entry Door Sensor')
49
+ .createDefaultBooleanStateClusterServer(false)
50
+ .createDefaultPowerSourceReplaceableBatteryClusterServer(75)
51
+ .addRequiredClusters();
52
+ ```
53
+
54
+ Rules that matter:
55
+
56
+ - `definition` can be a single device type or an array of device types.
57
+ - Use multiple device types when the endpoint needs more than one role, for example `[contactSensor, powerSource]`.
58
+ - Call one of the Basic Information helpers before `registerDevice()`. Without `deviceName`, `serialNumber`, and `uniqueId`, registration fails.
59
+ - Call `addRequiredClusters()` at the end of the chain so any required clusters (server or client) that you did not explicitly create are added automatically.
60
+ - Use `addOptionalClusterServers()` only when you really want the optional clusters defined by the selected device type(s).
61
+
62
+ ## MatterbridgeEndpointOptions
63
+
64
+ `MatterbridgeEndpointOptions` supports:
65
+
66
+ - `id`: stable storage key for the endpoint.
67
+ - `number`: explicit endpoint number when you need one.
68
+ - `tagList`: semantic tags used for disambiguation, especially for composed devices or `mode: 'matter'` endpoints.
69
+ - `mode`: `undefined`, `'server'`, or `'matter'`.
70
+
71
+ Mode selection:
72
+
73
+ - `undefined`: normal bridged endpoint. This is the default for most DynamicPlatform devices.
74
+ - `'server'`: create an independent Matter device with its own server node.
75
+ - `'matter'`: add the endpoint directly to the Matterbridge server node alongside the aggregator.
76
+
77
+ Practical guidance:
78
+
79
+ - Use `mode: undefined` for normal bridged devices shown as children of the bridge.
80
+ - Use `mode: 'server'` when the device must be paired independently.
81
+ - Use `mode: 'matter'` when the device should be a native Matter endpoint on the server node.
82
+ - When using `mode: 'matter'`, respect Matter disambiguation rules and supply a `tagList` when sibling endpoints could be ambiguous.
83
+
84
+ Implementation details worth remembering:
85
+
86
+ - Spaces and `.` are removed from the internal endpoint id. The original value is retained as `originalId`.
87
+ - Non-Latin ids are normalized to a generated unique id.
88
+ - `id` should remain stable across restarts.
89
+
90
+ ## Choose the right Basic Information helper
91
+
92
+ Use the helper that matches how the endpoint is exposed:
93
+
94
+ - `createDefaultBasicInformationClusterServer(...)`
95
+ Use for `mode: 'server'`, `mode: 'matter'`, and AccessoryPlatform devices.
96
+ - `createDefaultBridgedDeviceBasicInformationClusterServer(...)`
97
+ Use for bridged DynamicPlatform endpoints.
98
+
99
+ Important behavior:
100
+
101
+ - `createDefaultBasicInformationClusterServer(...)` sets the metadata on the endpoint.
102
+ - For bridged endpoints, `registerDevice()` can add the `BridgedDeviceBasicInformation` cluster automatically when the device is running as a bridged endpoint in bridge mode, or in childbridge mode on a `DynamicPlatform`.
103
+ - Explicitly calling `createDefaultBridgedDeviceBasicInformationClusterServer(...)` is clearer for bridged devices and matches the repo examples.
104
+
105
+ ## Register the endpoint from a plugin
106
+
107
+ In plugin code, call `this.registerDevice(device)`.
108
+
109
+ DynamicPlatform bridged device:
110
+
111
+ ```ts
112
+ import { MatterbridgeDynamicPlatform, MatterbridgeEndpoint, onOffLight } from 'matterbridge';
113
+
114
+ export default function initializePlugin(matterbridge, log, config) {
115
+ return new ExamplePlatform(matterbridge, log, config);
116
+ }
117
+
118
+ class ExamplePlatform extends MatterbridgeDynamicPlatform {
119
+ async onStart(reason) {
120
+ await this.ready;
121
+
122
+ const device = new MatterbridgeEndpoint(onOffLight, { id: 'OnOffLightPlugin' })
123
+ .createDefaultBridgedDeviceBasicInformationClusterServer('Kitchen Light', 'LIGHT-001', 0xfff1, 'Matterbridge', 'Matterbridge OnOffLight')
124
+ .addRequiredClusters();
125
+
126
+ await this.registerDevice(device);
127
+ }
128
+ }
129
+ ```
130
+
131
+ AccessoryPlatform device:
132
+
133
+ ```ts
134
+ import { MatterbridgeAccessoryPlatform, MatterbridgeEndpoint, temperatureSensor } from 'matterbridge';
135
+
136
+ export default function initializePlugin(matterbridge, log, config) {
137
+ return new ExamplePlatform(matterbridge, log, config);
138
+ }
139
+
140
+ class ExamplePlatform extends MatterbridgeAccessoryPlatform {
141
+ async onStart(reason) {
142
+ await this.ready;
143
+
144
+ const device = new MatterbridgeEndpoint(temperatureSensor, { id: 'TemperatureSensorPlugin' })
145
+ .createDefaultBasicInformationClusterServer('Temperature Sensor', 'TEMP-001', 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Temperature Sensor')
146
+ .addRequiredClusters();
147
+
148
+ await this.registerDevice(device);
149
+ }
150
+ }
151
+ ```
152
+
153
+ Standalone Matter device from a plugin:
154
+
155
+ ```ts
156
+ const device = new MatterbridgeEndpoint(pressureSensor, { id: 'ServerNodeDevice', mode: 'server' })
157
+ .createDefaultBasicInformationClusterServer('Server Node Device', 'SERVER-001', 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Server Node Device')
158
+ .addRequiredClusters();
159
+
160
+ await this.registerDevice(device);
161
+ ```
162
+
163
+ Native Matter endpoint on the server node:
164
+
165
+ ```ts
166
+ const device = new MatterbridgeEndpoint(pressureSensor, { id: 'MatterNodeDevice', mode: 'matter' })
167
+ .createDefaultBasicInformationClusterServer('Matter Node Device', 'MATTER-001', 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Matter Node Device')
168
+ .addRequiredClusters();
169
+
170
+ await this.registerDevice(device);
171
+ ```
172
+
173
+ Plugin rules:
174
+
175
+ - Use `await this.ready` before creating or registering devices.
176
+ - Always call `this.registerDevice(device)` from the platform.
177
+ - Use `this.unregisterDevice(device)` or `this.unregisterAllDevices()` during shutdown or development resets.
178
+ - AccessoryPlatform plugins can only expose one normal accessory device. If you need multiple bridged devices, use `MatterbridgeDynamicPlatform`.
179
+ - Use stable names and serial numbers so the derived `uniqueId` stays stable.
180
+
181
+ ## Useful MatterbridgeEndpoint helpers
182
+
183
+ Common helpers on the endpoint instance:
184
+
185
+ - `hasClusterServer(cluster)`
186
+ - `hasAttributeServer(cluster, attribute)`
187
+ - `getAttribute(cluster, attribute)`
188
+ - `setAttribute(cluster, attribute, value)`
189
+ - `updateAttribute(cluster, attribute, value)`
190
+ - `subscribeAttribute(cluster, attribute, listener)`
191
+ - `addRequiredClusterServers()`
192
+ - `addOptionalClusterServers()`
193
+ - `addRequiredClusters()`
194
+
195
+ Example:
196
+
197
+ ```ts
198
+ await device.updateAttribute('OnOff', 'onOff', true);
199
+ ```
200
+
201
+ Cluster references can be passed in several ways:
202
+
203
+ - behavior type
204
+ - cluster type
205
+ - cluster id
206
+ - cluster name string such as `'OnOff'`
207
+
208
+ Behavior type and cluster type are preferred because they are type-safe and avoid typos.
209
+
210
+ Using the cluster name string is useful in plugins because it avoids importing every cluster type.
211
+
212
+ ## When to use a raw endpoint vs a single-class device
213
+
214
+ Use a raw `MatterbridgeEndpoint` when:
215
+
216
+ - you are building a custom combination of device types and clusters
217
+ - you want full control over which default cluster servers are created
218
+ - you are implementing a plugin-specific device model
219
+
220
+ Use a single-class device when:
221
+
222
+ - Matterbridge already ships a class for the device category you need
223
+ - you want a working device with sensible default clusters and behaviors
224
+ - you prefer a higher-level constructor over manual endpoint assembly
225
+
226
+ ## Single-class devices
227
+
228
+ Single-class devices are exported from `matterbridge/devices`.
229
+
230
+ These classes already extend `MatterbridgeEndpoint` and usually do all of the following internally:
231
+
232
+ - create the correct device type combination
233
+ - create Basic Information
234
+ - create Power Source when needed
235
+ - create the default cluster servers and behavior wiring required by the device
236
+
237
+ Current exported single-class devices:
238
+
239
+ - Media: `BasicVideoPlayer`, `CastingVideoPlayer`, `Speaker`
240
+ - Matter 1.5 additions: `Closure`, `ClosurePanel`, `IrrigationSystem`, `SoilSensor`
241
+ - Robotic: `RoboticVacuumCleaner`
242
+ - Appliances: `AirConditioner`, `Cooktop`, `Dishwasher`, `ExtractorHood`, `LaundryDryer`, `LaundryWasher`, `MicrowaveOven`, `Oven`, `Refrigerator`
243
+ - Energy: `BatteryStorage`, `Evse`, `HeatPump`, `SolarPower`, `WaterHeater`
244
+
245
+ ### Basic single-class example
246
+
247
+ ```ts
248
+ import { LaundryWasher } from 'matterbridge/devices';
249
+
250
+ const washer = new LaundryWasher('Laundry Washer', 'LW-001');
251
+ await this.registerDevice(washer);
252
+ ```
253
+
254
+ This is enough because the class constructor already creates the required device types, basic information, power source, and default cluster servers.
255
+
256
+ ### Single-class example with explicit mode
257
+
258
+ Some single-class devices expose `mode` directly in their constructor. For example:
259
+
260
+ ```ts
261
+ import { RoboticVacuumCleaner } from 'matterbridge/devices';
262
+
263
+ const robot = new RoboticVacuumCleaner('Robot Vacuum', 'RVC-001', 'server');
264
+ await this.registerDevice(robot);
265
+ ```
266
+
267
+ Use this when the class supports it and you want a standalone or native Matter device instead of a bridged endpoint.
268
+
269
+ ### Composed single-class devices
270
+
271
+ Some single-class devices are composed devices and need child endpoints added after construction:
272
+
273
+ - `Oven`: create the oven, then call `addCabinet(...)`
274
+ - `Cooktop`: create the cooktop, then call `addSurface(...)`
275
+ - `Refrigerator`: create the refrigerator, then call `addCabinet(...)`
276
+
277
+ Example:
278
+
279
+ ```ts
280
+ import { PositionTag } from '@matter/node';
281
+ import { Cooktop } from 'matterbridge/devices';
282
+
283
+ const cooktop = new Cooktop('Cooktop', 'CT-001');
284
+ cooktop.addSurface('Surface Top Left', [
285
+ { mfgCode: null, namespaceId: PositionTag.Top.namespaceId, tag: PositionTag.Top.tag, label: PositionTag.Top.label },
286
+ { mfgCode: null, namespaceId: PositionTag.Left.namespaceId, tag: PositionTag.Left.tag, label: PositionTag.Left.label },
287
+ ]);
288
+
289
+ await this.registerDevice(cooktop);
290
+ ```
291
+
292
+ For composed devices and for `mode: 'matter'`, use semantic tags carefully. `tagList` exists to satisfy Matter endpoint disambiguation rules.
293
+
294
+ ## Recommended plugin workflow
295
+
296
+ For most plugins, follow this order:
297
+
298
+ 1. Wait for `this.ready`.
299
+ 2. Create the endpoint or single-class device.
300
+ 3. Set device identity with one of the Basic Information helpers if you are using a raw `MatterbridgeEndpoint`.
301
+ 4. Add explicit cluster servers you need.
302
+ 5. Call `addRequiredClusterServers()` last.
303
+ 6. Register the device with `await this.registerDevice(device)`.
304
+ 7. Optionally add UI metadata with `setSelectDevice()` and `setSelectEntity()`.
305
+
306
+ ## Avoid these mistakes
307
+
308
+ - Do not register a raw `MatterbridgeEndpoint` before assigning basic identity metadata.
309
+ - Do not use `MatterbridgeAccessoryPlatform` for multiple normal bridged accessories.
310
+ - Do not forget that some bridged endpoints need semantic tags for disambiguation.
311
+ - Do not assume single-class devices all share the same constructor shape. Check the device class when you need custom defaults or a mode argument.
312
+ - Do not call Matterbridge internals directly from plugin code when `registerDevice()` already handles validation and mode-specific setup.
313
+
314
+ ## Short decision guide
315
+
316
+ - Need a custom sensor, switch, or actuator with a few clusters: use `MatterbridgeEndpoint`.
317
+ - Need a supported appliance, robotic, media, energy, closure, irrigation, or soil device: start with `matterbridge/devices`.
318
+ - Need one standalone accessory with its own server node: use `mode: 'server'` or a single-class device that exposes it.
319
+ - Need multiple bridged devices in a plugin: use `MatterbridgeDynamicPlatform`.
@@ -0,0 +1,56 @@
1
+ # Testing Standards for Unit Tests
2
+
3
+ ## 1. Test Framework
4
+
5
+ - Jest is available in the repository when the file `jest.config.js` exists.
6
+ - Vitest is available in the repository when the file `vite.config.ts` exists.
7
+ - Bun test is available in the repository when the file `bunfig.toml` exists.
8
+ - Jest tests live in `test` folders. Follow the existing convention in the repository for test file placement.
9
+ - Vitest tests live in `vitest` folders. Follow the existing convention in the repository for test file placement.
10
+ - Bun test tests live in `buntest` folders. Follow the existing convention in the repository for test file placement.
11
+ - Ensure that tests are written in TypeScript and follow the ESM module format.
12
+
13
+ ## 2. Test Structure
14
+
15
+ - Organize tests in file name `*.test.ts` in the `test`, `vitest`, or `buntest` folders.
16
+ - Use `describe` blocks to group related tests and `test` blocks for individual test cases.
17
+
18
+ ## 3. Test Naming
19
+
20
+ - Use descriptive test names that clearly indicate the behavior being tested.
21
+ - Follow the format: `should [expected behavior] when [condition]`.
22
+
23
+ ## 4. Test Data
24
+
25
+ - Use small, deterministic test data to ensure tests are reliable and easy to understand.
26
+
27
+ ## 5. Test Coverage
28
+
29
+ - Aim for high test coverage, but prioritize meaningful tests over achieving 100% coverage.
30
+
31
+ ## 6. Mocking with Jest
32
+
33
+ - If using Jest, use `jest.unstable_mockModule` for mocking dependencies in ESM modules.
34
+ - If using Jest, avoid using `jest.mock` as it is not compatible with ESM modules.
35
+
36
+ ## 7. Running Tests
37
+
38
+ - Run the relevant full test unit from start to finish rather than assuming isolated single-test execution is reliable.
39
+ - If only one test framework is installed, use `npm run test -- yourTest.test.ts` or `npm run test:coverage -- yourTest.test.ts` when the touched area can be validated by running the full relevant test file.
40
+ - When both Jest and Vitest are installed, use `npm run test -- yourTest.test.ts` for Jest or `npm run test:vitest -- yourTest.test.ts` for Vitest.
41
+ - When Bun test is installed, use `bun test yourTest.test.ts`.
42
+ - Use the existing `tasks.json` test tasks for areas that require grouped test files, custom coverage targets, or custom ignore-pattern handling.
43
+ - Avoid running all tests unnecessarily to save time and tokens.
44
+
45
+ ## 8. Test Assertions
46
+
47
+ - Use appropriate Jest, Vitest, or Bun test matchers for assertions (e.g., `toBe`, `toEqual`, `toThrow`).
48
+ - Ensure that assertions are clear and directly related to the behavior being tested.
49
+
50
+ ## 9. Performance
51
+
52
+ - Avoid optimization in tests; focus on correctness and clarity.
53
+ - Use simple loops and structures in tests to maintain readability and performance.
54
+ - Avoid complex setups that may slow down test execution unless necessary for the behavior being tested.
55
+ - Prefer simple test cases that are easy to understand and maintain over complex ones that may be difficult to debug.
56
+ - Some tests in this repo are intentionally structured as multi-step flows, where state persists across successive steps within a single test unit. Run those test units in full, and keep each test unit isolated from other test units.
@@ -114,7 +114,7 @@ Important behavior:
114
114
 
115
115
  ## Register the endpoint from a plugin
116
116
 
117
- In plugin code, prefer `this.registerDevice(device)` instead of calling Matterbridge internals directly.
117
+ In plugin code, call `this.registerDevice(device)`.
118
118
 
119
119
  DynamicPlatform bridged device:
120
120
 
@@ -137,7 +137,7 @@ class ExamplePlatform extends MatterbridgeDynamicPlatform {
137
137
  'Matterbridge',
138
138
  'Matterbridge OnOffLight',
139
139
  )
140
- .addRequiredClusterServers();
140
+ .addRequiredClusters();
141
141
 
142
142
  await this.registerDevice(device);
143
143
  }
@@ -166,7 +166,7 @@ class ExamplePlatform extends MatterbridgeAccessoryPlatform {
166
166
  0x8000,
167
167
  'Matterbridge Temperature Sensor',
168
168
  )
169
- .addRequiredClusterServers();
169
+ .addRequiredClusters();
170
170
 
171
171
  await this.registerDevice(device);
172
172
  }
@@ -185,7 +185,7 @@ const device = new MatterbridgeEndpoint(pressureSensor, { id: 'ServerNodeDevice'
185
185
  0x8000,
186
186
  'Matterbridge Server Node Device',
187
187
  )
188
- .addRequiredClusterServers();
188
+ .addRequiredClusters();
189
189
 
190
190
  await this.registerDevice(device);
191
191
  ```
@@ -202,14 +202,14 @@ const device = new MatterbridgeEndpoint(pressureSensor, { id: 'MatterNodeDevice'
202
202
  0x8000,
203
203
  'Matterbridge Matter Node Device',
204
204
  )
205
- .addRequiredClusterServers();
205
+ .addRequiredClusters();
206
206
 
207
207
  await this.registerDevice(device);
208
208
  ```
209
209
 
210
210
  Plugin rules:
211
211
 
212
- - `await this.ready` before creating or registering devices.
212
+ - Use `await this.ready` before creating or registering devices.
213
213
  - Always call `this.registerDevice(device)` from the platform.
214
214
  - Use `this.unregisterDevice(device)` or `this.unregisterAllDevices()` during shutdown or development resets.
215
215
  - AccessoryPlatform plugins can only expose one normal accessory device. If you need multiple bridged devices, use `MatterbridgeDynamicPlatform`.
@@ -49,6 +49,7 @@
49
49
  "Bash(tsc:*)",
50
50
  "Bash(npx tsgo:*)",
51
51
  "Bash(tsgo:*)",
52
+ "Bash(cd:*)",
52
53
  "Bash(tail:*)"
53
54
  ]
54
55
  }
@@ -115,7 +115,7 @@ Important behavior:
115
115
 
116
116
  ## Register the endpoint from a plugin
117
117
 
118
- In plugin code, prefer `this.registerDevice(device)` instead of calling Matterbridge internals directly.
118
+ In plugin code, call `this.registerDevice(device)`.
119
119
 
120
120
  DynamicPlatform bridged device:
121
121
 
@@ -138,7 +138,7 @@ class ExamplePlatform extends MatterbridgeDynamicPlatform {
138
138
  'Matterbridge',
139
139
  'Matterbridge OnOffLight',
140
140
  )
141
- .addRequiredClusterServers();
141
+ .addRequiredClusters();
142
142
 
143
143
  await this.registerDevice(device);
144
144
  }
@@ -167,7 +167,7 @@ class ExamplePlatform extends MatterbridgeAccessoryPlatform {
167
167
  0x8000,
168
168
  'Matterbridge Temperature Sensor',
169
169
  )
170
- .addRequiredClusterServers();
170
+ .addRequiredClusters();
171
171
 
172
172
  await this.registerDevice(device);
173
173
  }
@@ -186,7 +186,7 @@ const device = new MatterbridgeEndpoint(pressureSensor, { id: 'ServerNodeDevice'
186
186
  0x8000,
187
187
  'Matterbridge Server Node Device',
188
188
  )
189
- .addRequiredClusterServers();
189
+ .addRequiredClusters();
190
190
 
191
191
  await this.registerDevice(device);
192
192
  ```
@@ -203,14 +203,14 @@ const device = new MatterbridgeEndpoint(pressureSensor, { id: 'MatterNodeDevice'
203
203
  0x8000,
204
204
  'Matterbridge Matter Node Device',
205
205
  )
206
- .addRequiredClusterServers();
206
+ .addRequiredClusters();
207
207
 
208
208
  await this.registerDevice(device);
209
209
  ```
210
210
 
211
211
  Plugin rules:
212
212
 
213
- - `await this.ready` before creating or registering devices.
213
+ - Use `await this.ready` before creating or registering devices.
214
214
  - Always call `this.registerDevice(device)` from the platform.
215
215
  - Use `this.unregisterDevice(device)` or `this.unregisterAllDevices()` during shutdown or development resets.
216
216
  - AccessoryPlatform plugins can only expose one normal accessory device. If you need multiple bridged devices, use `MatterbridgeDynamicPlatform`.
@@ -1,4 +1,4 @@
1
- // VS Code settings native v. 1.0.6
1
+ // VS Code settings native v. 1.0.7
2
2
  {
3
3
  "npm.packageManager": "npm",
4
4
  "eslint.enable": false,
@@ -44,20 +44,29 @@
44
44
  "git.autofetch": true,
45
45
  "git.autoRepositoryDetection": false,
46
46
  // VS Code's Copilot Chat extension settings
47
- "chat.useCustomizationsInParentRepositories": true,
48
- "chat.useAgentsMdFile": true,
49
- "chat.useClaudeMdFile": true,
50
- "chat.instructionsFilesLocations": {
51
- ".github/instructions": true,
52
- ".claude/rules": true,
53
- "~/.copilot/instructions": true,
54
- "~/.claude/rules": true
55
- },
47
+ "chat.useCustomizationsInParentRepositories": true, // Default false.
56
48
  "chat.tools.terminal.autoApprove": {
57
49
  "npx tsc": true,
58
50
  "npx tsgo": true,
59
51
  "npx oxlint": true,
60
52
  "npx oxfmt": true,
61
- "npx vitest": true
53
+ "npx vitest": true,
54
+ "npm run build": true,
55
+ "npm run typecheck": true,
56
+ "npm run lint": true,
57
+ "npm run format:check": true,
58
+ "npm run test": true,
59
+ "npm run test:coverage": true,
60
+ "npm run update-htmls": true,
61
+ "git status": true,
62
+ "git diff": true,
63
+ "git diff --check": true,
64
+ "git diff --stat": true,
65
+ "git log": true,
66
+ "git show": true,
67
+ "git branch -vv": true,
68
+ "git ls-files": true,
69
+ "git --no-pager diff --stat": true,
70
+ "git --no-pager diff --check": true
62
71
  }
63
72
  }
package/vendor/AGENTS.md CHANGED
@@ -3,24 +3,24 @@
3
3
  ## Style And Formatting
4
4
 
5
5
  - Follow [STYLEGUIDE.md](./STYLEGUIDE.md) for code style, naming, JSDoc, validation, logging, and formatting expectations.
6
- - JSDoc requirements are enforced by oxlint. Treat missing or incomplete JSDoc on required APIs as a real lint issue, not optional documentation.
7
- - Import and export ordering are enforced by oxlint/oxfmt. Preserve the existing grouped and sorted order unless a change requires updating it.
8
- - Formatting is enforced by oxfmt. Follow the existing formatting and do not fight the formatter.
6
+ - JSDoc requirements are enforced by the linter. Treat missing or incomplete JSDoc on required APIs as a real lint issue, not optional documentation.
7
+ - Import and export ordering are enforced by the linter or by theformater. Preserve the existing grouped and sorted order unless a change requires updating it.
8
+ - Follow the existing formatting and do not fight the formatter.
9
9
 
10
10
  ## Scope And Safety
11
11
 
12
12
  - Keep changes minimal and scoped to the request. Avoid unrelated refactors or broad cleanup.
13
13
  - Do not modify production code only to make a test pass. If a failing test points to a likely source issue, explain the issue and change behavior only when required by the task.
14
14
  - Preserve cross-platform behavior. Changes must work on Windows, macOS, and Linux, especially for paths, shell commands, environment variables, and networking behavior.
15
- - Maintain compatibility with the supported Node.js versions in this repository: 20, 22, 24 and 26.
15
+ - Maintain compatibility with the supported Node.js versions in this repository: 20.19, 22.13, 24.0 and 26.0.
16
16
 
17
17
  ## Project Architecture
18
18
 
19
- - This repository is a TypeScript ESM monorepo. Follow existing project patterns for imports, exports, build configuration, and test setup.
19
+ - This repository is a TypeScript ESM repo. Follow existing project patterns for imports, exports, build configuration, and test setup.
20
20
 
21
21
  ## Testing And Validation
22
22
 
23
- - Prefer the existing npm scripts in [package.json](./package.json) and the repository test/build tasks when validating changes.
23
+ - Prefer the existing npm scripts in [package.json](./package.json) and the VS Code tasks in [tasks.json](./.vscode/tasks.json) when validating changes.
24
24
  - Keep tests deterministic and simple. Prefer small data sets and straightforward setup.
25
25
  - Some tests are intentionally multi-step flows. State may persist across successive steps within a single test flow, but each test unit must remain isolated from other tests.
26
26
  - For validation, run the relevant full test file or the matching suite/task for the touched area rather than assuming arbitrary isolated single-test execution is reliable.
@@ -28,3 +28,10 @@
28
28
  ## Documentation
29
29
 
30
30
  - When behavior changes, update the relevant tests and documentation.
31
+
32
+ ## Additional Agent Guidance
33
+
34
+ For task-specific guidance, read relevant files in `.agents/`:
35
+
36
+ - `.agents/testing.md` for testing and validation expectations
37
+ - `.agents/matterbridge.md` for instruction about using matterbridge in a plugin
@@ -51,13 +51,6 @@
51
51
  {
52
52
  "type": "update"
53
53
  },
54
- {
55
- "type": "copilot_code_review",
56
- "parameters": {
57
- "review_on_push": true,
58
- "review_draft_pull_requests": true
59
- }
60
- },
61
54
  {
62
55
  "type": "code_scanning",
63
56
  "parameters": {