@tiuxo/opencode-openrgb 0.0.0-stage → 0.1.1
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 +57 -0
- package/LICENSE +11 -0
- package/README.md +287 -2
- package/index.ts +9 -0
- package/package.json +54 -4
- package/src/client.ts +464 -0
- package/src/controller.ts +360 -0
- package/src/index.ts +109 -0
- package/src/options.ts +229 -0
- package/src/palette.ts +86 -0
- package/src/protocol.ts +611 -0
- package/src/state.ts +215 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.1] - 2026-11-10
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Opened one OpenRGB connection per location rather than one per machine, so a
|
|
15
|
+
single opencode server could run several controllers writing to the same
|
|
16
|
+
devices at once. The shared controller registry was module-level state, but
|
|
17
|
+
opencode gives each location its own module instance, making that scope
|
|
18
|
+
per-location rather than per-process. It now lives on a `globalThis` symbol,
|
|
19
|
+
which is the scope the hardware actually has.
|
|
20
|
+
|
|
21
|
+
0.1.0 was staged but never released, so no published version carries this bug.
|
|
22
|
+
|
|
23
|
+
## [0.1.0] - 2026-11-10
|
|
24
|
+
|
|
25
|
+
Initial release, targeting the opencode 2 plugin API.
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- Ambient status lighting driven by aggregate session state: amber while the
|
|
30
|
+
agent works, yellow on a retry, violet while a permission prompt waits, red
|
|
31
|
+
on failure. Idle restores the lighting captured at startup.
|
|
32
|
+
- State is aggregated across all sessions, so subagent and task work keeps the
|
|
33
|
+
lights busy until everything is genuinely finished. The highest priority
|
|
34
|
+
wins: `error` > `permission` > `retry` > `busy` > `idle`.
|
|
35
|
+
- `"baseline"` as a state color, breathing the device's *own* startup lighting
|
|
36
|
+
per LED, so an OpenRGB profile keeps its identity and only its intensity
|
|
37
|
+
changes.
|
|
38
|
+
- Device targeting by type or name glob, defaulting to interior and ambient
|
|
39
|
+
hardware. Keyboards, mice, keypads and accessories are left alone unless
|
|
40
|
+
explicitly included.
|
|
41
|
+
- An OpenRGB SDK client with no runtime dependencies, speaking protocol
|
|
42
|
+
versions 1-5 and negotiating `min(server, 5)`. If OpenRGB is absent,
|
|
43
|
+
restarted, or misbehaving, every operation degrades to a silent no-op and
|
|
44
|
+
the client reconnects in the background with backoff.
|
|
45
|
+
- Software brightness scaling, since `Direct` modes commonly report no
|
|
46
|
+
hardware brightness range.
|
|
47
|
+
- Configurable pulse, debounce and restore delay, plus a `debug` option and an
|
|
48
|
+
`OPENCODE_OPENRGB_DEBUG` kill switch read in the server process.
|
|
49
|
+
- `probe`, `selftest` and `simulate` scripts for inspecting hardware, verifying
|
|
50
|
+
the wire protocol against a real server, and previewing a palette.
|
|
51
|
+
- A warning at startup when the captured lighting is uniformly one of the
|
|
52
|
+
plugin's own status colors, which indicates a previous run exited without
|
|
53
|
+
restoring.
|
|
54
|
+
|
|
55
|
+
[Unreleased]: https://git.tiuxo.com/brian/opencode-openrgb/compare/v0.1.1...HEAD
|
|
56
|
+
[0.1.1]: https://git.tiuxo.com/brian/opencode-openrgb/releases/tag/v0.1.1
|
|
57
|
+
[0.1.0]: https://git.tiuxo.com/brian/opencode-openrgb/releases/tag/v0.1.0
|
package/LICENSE
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Copyright (c) 2026 Brian Clemens.
|
|
2
|
+
|
|
3
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
|
4
|
+
|
|
5
|
+
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
6
|
+
|
|
7
|
+
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
|
8
|
+
|
|
9
|
+
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
|
10
|
+
|
|
11
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,288 @@
|
|
|
1
|
-
#
|
|
1
|
+
# opencode-openrgb
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Ambient status lighting for [opencode](https://opencode.ai), driven by
|
|
4
|
+
[OpenRGB](https://openrgb.org).
|
|
5
|
+
|
|
6
|
+
Your RGB hardware mirrors what opencode is doing: amber while the agent works,
|
|
7
|
+
violet when it is waiting on a permission prompt, red when something fails. When
|
|
8
|
+
everything goes idle, your original lighting is restored exactly as it was.
|
|
9
|
+
|
|
10
|
+
There are no model-facing tools. The plugin never lets the LLM touch your
|
|
11
|
+
lights — it only reacts to session state.
|
|
12
|
+
|
|
13
|
+
| State | Meaning | Default |
|
|
14
|
+
| ------------ | ---------------------------------------- | --------- |
|
|
15
|
+
| `busy` | at least one session is working | `#ff8c00` |
|
|
16
|
+
| `retry` | a request is being retried | `#ffd000` |
|
|
17
|
+
| `permission` | a permission prompt is waiting for you | `#b400ff` |
|
|
18
|
+
| `error` | a session errored (decays after 10s) | `#ff0000` |
|
|
19
|
+
| `idle` | nothing running | restore |
|
|
20
|
+
|
|
21
|
+
Any state can instead be set to `"baseline"`, meaning *your own* lighting,
|
|
22
|
+
breathing. See [Pulsing your own color](#pulsing-your-own-color).
|
|
23
|
+
|
|
24
|
+
State is aggregated across **all** sessions, so subagent and task work keeps the
|
|
25
|
+
lights busy until everything is genuinely finished. When several conditions hold
|
|
26
|
+
at once, the highest priority wins: `error` > `permission` > `retry` > `busy` >
|
|
27
|
+
`idle`.
|
|
28
|
+
|
|
29
|
+
## Requirements
|
|
30
|
+
|
|
31
|
+
- OpenRGB running with its SDK server enabled (Settings → General → *Enable SDK
|
|
32
|
+
Server*), listening on `127.0.0.1:6742` by default
|
|
33
|
+
- opencode 2.0+
|
|
34
|
+
|
|
35
|
+
Protocol versions 1–5 are supported; the client negotiates `min(server, 5)`.
|
|
36
|
+
|
|
37
|
+
> This plugin targets the opencode 2 plugin API and does not load under 1.x.
|
|
38
|
+
|
|
39
|
+
## Install
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
opencode plugin add @tiuxo/opencode-openrgb
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The plugin only loads for projects whose config declares it. For ambient
|
|
46
|
+
lighting everywhere, declare it **globally** in
|
|
47
|
+
`~/.config/opencode/opencode.json`:
|
|
48
|
+
|
|
49
|
+
```jsonc
|
|
50
|
+
{
|
|
51
|
+
"$schema": "https://opencode.ai/config.json",
|
|
52
|
+
"plugins": ["@tiuxo/opencode-openrgb"]
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Config is hot-reloaded, so the plugin activates on save. Use `/reload` to force
|
|
57
|
+
it.
|
|
58
|
+
|
|
59
|
+
### From source
|
|
60
|
+
|
|
61
|
+
Clone the repository and point `package` at the directory, using an absolute
|
|
62
|
+
path — plugin paths resolve relative to the config file that declares them:
|
|
63
|
+
|
|
64
|
+
```jsonc
|
|
65
|
+
{
|
|
66
|
+
"$schema": "https://opencode.ai/config.json",
|
|
67
|
+
"plugins": [
|
|
68
|
+
{ "package": "/absolute/path/to/opencode-openrgb" }
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Point it at the repository directory, not a file inside it: opencode skips
|
|
74
|
+
configured plugin paths that are not directories.
|
|
75
|
+
|
|
76
|
+
To check what the plugin can see before enabling it:
|
|
77
|
+
|
|
78
|
+
```sh
|
|
79
|
+
bun run probe
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Options
|
|
83
|
+
|
|
84
|
+
Every field is optional. Invalid values log a warning and fall back to the
|
|
85
|
+
default rather than failing to load.
|
|
86
|
+
|
|
87
|
+
```jsonc
|
|
88
|
+
{
|
|
89
|
+
"package": "@tiuxo/opencode-openrgb",
|
|
90
|
+
"options": {
|
|
91
|
+
"enabled": true,
|
|
92
|
+
"host": "127.0.0.1",
|
|
93
|
+
"port": 6742,
|
|
94
|
+
|
|
95
|
+
"colors": {
|
|
96
|
+
// A hex/named color, or "baseline" to breathe your own lighting.
|
|
97
|
+
"busy": "#ff8c00",
|
|
98
|
+
"retry": "#ffd000",
|
|
99
|
+
"permission": "#b400ff",
|
|
100
|
+
"error": "#ff0000"
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
// "restore" puts back the lighting captured at startup.
|
|
104
|
+
// A color instead holds that color while idle. "off" goes dark.
|
|
105
|
+
"idle": "restore",
|
|
106
|
+
|
|
107
|
+
"brightness": 1.0, // 0..1, applied in software
|
|
108
|
+
"pulse": false, // breathing effect while busy
|
|
109
|
+
"pulseFps": 15,
|
|
110
|
+
|
|
111
|
+
"debounceMs": 120, // coalesce bursts of events
|
|
112
|
+
"restoreDelayMs": 400, // extra settle time before handing control back
|
|
113
|
+
|
|
114
|
+
"devices": {
|
|
115
|
+
"include": ["motherboard", "dram", "gpu", "cooler", "case", "ledstrip"],
|
|
116
|
+
"exclude": []
|
|
117
|
+
},
|
|
118
|
+
|
|
119
|
+
"debug": false
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Colors accept `#rgb`, `#rrggbb`, `rgb(r, g, b)`, and names like `amber`,
|
|
125
|
+
`violet`, `off`.
|
|
126
|
+
|
|
127
|
+
### Pulsing your own color
|
|
128
|
+
|
|
129
|
+
If you would rather not have a status color replace your carefully chosen
|
|
130
|
+
lighting, set a state to `"baseline"`:
|
|
131
|
+
|
|
132
|
+
```jsonc
|
|
133
|
+
{ "colors": { "busy": "baseline" } }
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
The device then breathes *its own* color while the agent works — whatever the
|
|
137
|
+
lighting was when the plugin connected — so your OpenRGB profile keeps its
|
|
138
|
+
identity and only its intensity changes. This is per LED, so a profile using
|
|
139
|
+
several colors keeps that pattern intact and simply pulses.
|
|
140
|
+
|
|
141
|
+
A `baseline` state always pulses, regardless of the `pulse` option: a static
|
|
142
|
+
baseline would be pixel-identical to idle and would tell you nothing.
|
|
143
|
+
|
|
144
|
+
`"current"` and `"profile"` are accepted as aliases. Note that `"gold"` is a
|
|
145
|
+
*named color*, not the baseline — use `"baseline"` if you mean "whatever is
|
|
146
|
+
already there".
|
|
147
|
+
|
|
148
|
+
### Device targeting
|
|
149
|
+
|
|
150
|
+
`include` and `exclude` entries match either a device **type**
|
|
151
|
+
(`motherboard`, `gpu`, `keyboard`, …) or a glob against the device **name**
|
|
152
|
+
(`ASUS*`, `*X670E*`, `*`). `exclude` wins over `include`.
|
|
153
|
+
|
|
154
|
+
The default targets interior/ambient hardware only. Keyboards, mice, keypads and
|
|
155
|
+
accessories are deliberately left alone: their lighting usually conveys
|
|
156
|
+
something already — an Elgato Stream Deck's button icons, for instance — and
|
|
157
|
+
hijacking it by default would be obnoxious. Opt in explicitly if you want it:
|
|
158
|
+
|
|
159
|
+
```jsonc
|
|
160
|
+
"devices": { "include": ["*"], "exclude": ["accessory"] }
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Scripts
|
|
164
|
+
|
|
165
|
+
| Command | What it does |
|
|
166
|
+
| ------------------- | ------------------------------------------------------------------------ |
|
|
167
|
+
| `bun run probe` | Read-only dump of devices, zones, modes; shows what would be targeted |
|
|
168
|
+
| `bun run selftest` | Writes colors, reads them back from the server, asserts, then restores |
|
|
169
|
+
| `bun run simulate` (`--pulse`, `--hold <ms>`) | Drives the real plugin through every state, so you can preview your palette |
|
|
170
|
+
| `bun test` | Tests for the codec, client, state machine and option parsing |
|
|
171
|
+
| `bun run typecheck` | `tsc --noEmit` over src, scripts and tests |
|
|
172
|
+
|
|
173
|
+
`selftest` and `simulate` change your lighting while they run and restore it
|
|
174
|
+
afterwards.
|
|
175
|
+
|
|
176
|
+
## How it works
|
|
177
|
+
|
|
178
|
+
The OpenRGB SDK is a binary TCP protocol. This plugin implements the parts it
|
|
179
|
+
needs directly, with no runtime dependencies.
|
|
180
|
+
|
|
181
|
+
A few details that are easy to get wrong, all verified against the OpenRGB
|
|
182
|
+
sources and confirmed against real hardware by `scripts/selftest.ts`:
|
|
183
|
+
|
|
184
|
+
- `RGBColor` is `0x00BBGGRR`, so the little-endian byte order is R, G, B, 0
|
|
185
|
+
- In `UPDATELEDS` and `UPDATEMODE`, the leading `data_size` field **counts
|
|
186
|
+
itself**, and equals the packet header's size field
|
|
187
|
+
- Below protocol 6, `mode.value` is a device-internal field that must be
|
|
188
|
+
round-tripped back to the server verbatim when updating a mode
|
|
189
|
+
- Protocol 5 has no ACK packets, so writes are fire-and-forget
|
|
190
|
+
|
|
191
|
+
Per-LED color only applies in a direct/custom mode, so the plugin switches the
|
|
192
|
+
device into its `Direct` mode if it is not already there, and switches back on
|
|
193
|
+
restore. Brightness is applied by scaling RGB in software, because `Direct`
|
|
194
|
+
modes commonly report no hardware brightness range at all.
|
|
195
|
+
|
|
196
|
+
Robustness is a hard requirement: the plugin must never break opencode. If
|
|
197
|
+
OpenRGB is not running, is restarted, or misbehaves, every operation degrades to
|
|
198
|
+
a silent no-op and the client reconnects in the background with backoff.
|
|
199
|
+
|
|
200
|
+
### Events
|
|
201
|
+
|
|
202
|
+
The plugin subscribes to exactly the events that can change the lighting, so it
|
|
203
|
+
stays off the firehose of streaming text and step events:
|
|
204
|
+
|
|
205
|
+
| Event | Effect |
|
|
206
|
+
| --------------------------- | --------------------------------- |
|
|
207
|
+
| `session.status` | `busy` / `retry` / `idle` |
|
|
208
|
+
| `session.idle` | session is finished |
|
|
209
|
+
| `session.retry.scheduled` | a retry is pending |
|
|
210
|
+
| `session.execution.failed` | raises the error state (10s hold) |
|
|
211
|
+
| `permission.asked` | a prompt is waiting for you |
|
|
212
|
+
| `permission.replied` | clears that prompt |
|
|
213
|
+
| `session.deleted` | forgets the session entirely |
|
|
214
|
+
|
|
215
|
+
### Restoring on exit
|
|
216
|
+
|
|
217
|
+
Under opencode 2 the plugin restores from the cleanup function returned by
|
|
218
|
+
`setup`, which runs when the plugin unloads. That is an ordinary async context,
|
|
219
|
+
so queued socket writes reach OpenRGB normally.
|
|
220
|
+
|
|
221
|
+
The synchronous write path remains for abrupt teardown. `socket.write` only
|
|
222
|
+
*enqueues* data, and if the event loop stops before it flushes, the restore
|
|
223
|
+
silently never reaches OpenRGB and the lights stay stuck on the status color —
|
|
224
|
+
and the next startup then snapshots that leftover color as the "baseline",
|
|
225
|
+
losing the real one. The restore path therefore writes straight to the socket's
|
|
226
|
+
file descriptor when it cannot rely on the loop running again. This reaches for
|
|
227
|
+
private API (`socket._handle.fd`), so every failure path falls back to a normal
|
|
228
|
+
queued write. The plugin also warns at startup if the lighting it captured is
|
|
229
|
+
uniformly one of its own status colors, a strong hint that a previous run died
|
|
230
|
+
without restoring.
|
|
231
|
+
|
|
232
|
+
## Limitations
|
|
233
|
+
|
|
234
|
+
- **Protocol 6 is not implemented.** It lands with OpenRGB 1.0 final and changes
|
|
235
|
+
device addressing to unique IDs. Decoders are version-guarded so the upgrade
|
|
236
|
+
is contained, but until then the client negotiates down to 5.
|
|
237
|
+
- **Restore is a startup snapshot.** If you change your lighting in the OpenRGB
|
|
238
|
+
GUI mid-session, the plugin will revert it at the next idle. Restart opencode
|
|
239
|
+
to re-snapshot.
|
|
240
|
+
- **A hard kill can still leave the last color showing.** `SIGKILL` or power
|
|
241
|
+
loss gives the plugin no chance to restore. Graceful exits are handled (see
|
|
242
|
+
below).
|
|
243
|
+
- **One instance per server.** opencode loads the plugin once per location, but
|
|
244
|
+
the hardware is global, so every instance shares one refcounted controller;
|
|
245
|
+
the last one to unload restores the lighting. Separate opencode *processes*
|
|
246
|
+
would still compete for the hardware.
|
|
247
|
+
|
|
248
|
+
## Development
|
|
249
|
+
|
|
250
|
+
```sh
|
|
251
|
+
bun install
|
|
252
|
+
bun test
|
|
253
|
+
bun run typecheck
|
|
254
|
+
bun run simulate # drive real hardware through every state
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
The plugin ships as TypeScript source and opencode loads it directly, so there
|
|
258
|
+
is no build step.
|
|
259
|
+
|
|
260
|
+
The repo's own `opencode.json` wires the plugin locally with `debug: true`, so
|
|
261
|
+
running opencode inside this directory loads the working copy.
|
|
262
|
+
|
|
263
|
+
The entry point (`src/index.ts`) stays thin: it defines the plugin, resolves
|
|
264
|
+
options, and pumps the event subscription. The logic lives in
|
|
265
|
+
`src/controller.ts` so it is directly importable and testable without a plugin
|
|
266
|
+
host — see `test/plugin.test.ts`, which drives the real entry point against a
|
|
267
|
+
mock OpenRGB server.
|
|
268
|
+
|
|
269
|
+
### The root index.ts
|
|
270
|
+
|
|
271
|
+
opencode resolves a local directory plugin by trying `<dir>/server` and
|
|
272
|
+
`<dir>/index`, without consulting `package.json` `main`/`exports`. A plugin
|
|
273
|
+
whose only entrypoint is `src/index.ts` resolves to nothing and is dropped
|
|
274
|
+
silently, with nothing logged.
|
|
275
|
+
|
|
276
|
+
Installs by package name do use `exports`, so the root `index.ts` is a
|
|
277
|
+
re-export and both resolution paths land on it.
|
|
278
|
+
|
|
279
|
+
`@opencode/plugin` is imported for types only, so the published package has no
|
|
280
|
+
runtime dependencies.
|
|
281
|
+
|
|
282
|
+
## Changelog
|
|
283
|
+
|
|
284
|
+
See [CHANGELOG.md](CHANGELOG.md).
|
|
285
|
+
|
|
286
|
+
## License
|
|
287
|
+
|
|
288
|
+
BSD-3-Clause
|
package/index.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// opencode resolves local directory plugins through <dir>/index, ignoring package.json
|
|
2
|
+
// main/exports, and drops the plugin silently when that fails. Package installs use
|
|
3
|
+
// exports, which points here too.
|
|
4
|
+
|
|
5
|
+
export { default } from "./src/index.js"
|
|
6
|
+
|
|
7
|
+
export type { ResolvedOptions, IdleBehaviour, ActiveState, StateColor } from "./src/options.js"
|
|
8
|
+
export type { LightingState, OpencodeEvent } from "./src/state.js"
|
|
9
|
+
export type { Device, Mode, Zone, Led } from "./src/protocol.js"
|
package/package.json
CHANGED
|
@@ -1,6 +1,56 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tiuxo/opencode-openrgb",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Ambient status lighting for opencode via OpenRGB. Mirrors session state onto your RGB hardware.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "BSD-3-Clause",
|
|
7
|
+
"author": "Brian Clemens <brian@tiuxo.com>",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://git.tiuxo.com/brian/opencode-openrgb.git"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://git.tiuxo.com/brian/opencode-openrgb",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://git.tiuxo.com/brian/opencode-openrgb/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"opencode",
|
|
18
|
+
"opencode-plugin",
|
|
19
|
+
"openrgb",
|
|
20
|
+
"rgb",
|
|
21
|
+
"lighting",
|
|
22
|
+
"ambient",
|
|
23
|
+
"status"
|
|
24
|
+
],
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public",
|
|
27
|
+
"registry": "https://registry.npmjs.org/"
|
|
28
|
+
},
|
|
29
|
+
"exports": {
|
|
30
|
+
".": "./index.ts"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"index.ts",
|
|
34
|
+
"src",
|
|
35
|
+
"README.md",
|
|
36
|
+
"LICENSE",
|
|
37
|
+
"CHANGELOG.md"
|
|
38
|
+
],
|
|
39
|
+
"scripts": {
|
|
40
|
+
"test": "bun test",
|
|
41
|
+
"typecheck": "tsc --noEmit && tsc -p tsconfig.scripts.json",
|
|
42
|
+
"check": "bun run typecheck && bun test",
|
|
43
|
+
"probe": "bun scripts/probe.ts",
|
|
44
|
+
"selftest": "bun scripts/selftest.ts",
|
|
45
|
+
"simulate": "bun scripts/simulate.ts"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@opencode/plugin": "^2.2.7",
|
|
49
|
+
"@types/bun": "^1.4.0",
|
|
50
|
+
"@types/node": "^24.12.2",
|
|
51
|
+
"typescript": "^5.8.2"
|
|
52
|
+
},
|
|
53
|
+
"engines": {
|
|
54
|
+
"opencode": ">=2.0.0"
|
|
55
|
+
}
|
|
56
|
+
}
|