@sirenodeck/sirenodeck 0.1.1-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (485) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +69 -0
  3. package/bin/_wrapper-shared.js +42 -0
  4. package/bin/dev.js +95 -0
  5. package/bin/sirenodeck.js +42 -0
  6. package/config/default-config.yml +117 -0
  7. package/config/starter-config.yml +54 -0
  8. package/dist/main.mjs +64702 -0
  9. package/package.json +140 -0
  10. package/src/action/executor.ts +156 -0
  11. package/src/action/index.ts +7 -0
  12. package/src/addon/api-types.ts +15 -0
  13. package/src/addon/api.ts +461 -0
  14. package/src/addon/check-runner.ts +84 -0
  15. package/src/addon/index.ts +5 -0
  16. package/src/addon/loader.ts +441 -0
  17. package/src/addon/registry.ts +230 -0
  18. package/src/addon/spec.ts +69 -0
  19. package/src/api/addon.ts +33 -0
  20. package/src/api/asset-url.ts +24 -0
  21. package/src/api/index.ts +50 -0
  22. package/src/api/protocol-internal.ts +656 -0
  23. package/src/api/protocol.ts +2 -0
  24. package/src/api/react/index.ts +11 -0
  25. package/src/api/react/registry.ts +91 -0
  26. package/src/api/react/use-addon-channel.ts +26 -0
  27. package/src/api/react/use-button-state.tsx +23 -0
  28. package/src/api/react/use-deck.ts +24 -0
  29. package/src/assets/logo.png +0 -0
  30. package/src/assets/logo72x72.png +0 -0
  31. package/src/assets/logoFull.png +0 -0
  32. package/src/builtin-addons/brightness/README.md +51 -0
  33. package/src/builtin-addons/brightness/buttons/brightness/backend.ts +13 -0
  34. package/src/builtin-addons/brightness/buttons/brightness/config.ts +10 -0
  35. package/src/builtin-addons/brightness/buttons/brightness/frontend.tsx +50 -0
  36. package/src/builtin-addons/brightness/domain/macos.ts +46 -0
  37. package/src/builtin-addons/brightness/index.d.ts +5 -0
  38. package/src/builtin-addons/brightness/index.ts +20 -0
  39. package/src/builtin-addons/brightness/poller.ts +27 -0
  40. package/src/builtin-addons/brightness/providers/darwin.ts +107 -0
  41. package/src/builtin-addons/brightness/providers/index.ts +81 -0
  42. package/src/builtin-addons/brightness/providers/linux.ts +108 -0
  43. package/src/builtin-addons/brightness/providers/windows.ts +77 -0
  44. package/src/builtin-addons/brightness/sirenodeck.json +6 -0
  45. package/src/builtin-addons/coding-agents/assets/claude-code.svg +1 -0
  46. package/src/builtin-addons/coding-agents/assets/opencode-dark-square.svg +1 -0
  47. package/src/builtin-addons/coding-agents/buttons/agent/backend.ts +82 -0
  48. package/src/builtin-addons/coding-agents/buttons/agent/config.ts +13 -0
  49. package/src/builtin-addons/coding-agents/buttons/agent/frontend.tsx +130 -0
  50. package/src/builtin-addons/coding-agents/buttons/agent/pages.tsx +150 -0
  51. package/src/builtin-addons/coding-agents/buttons/summary/backend.ts +48 -0
  52. package/src/builtin-addons/coding-agents/buttons/summary/config.ts +11 -0
  53. package/src/builtin-addons/coding-agents/buttons/summary/frontend.tsx +254 -0
  54. package/src/builtin-addons/coding-agents/decks/agents.ts +69 -0
  55. package/src/builtin-addons/coding-agents/global/backend.ts +402 -0
  56. package/src/builtin-addons/coding-agents/global-entry.ts +7 -0
  57. package/src/builtin-addons/coding-agents/hook/script.ts +123 -0
  58. package/src/builtin-addons/coding-agents/index.ts +15 -0
  59. package/src/builtin-addons/coding-agents/manifest.ts +115 -0
  60. package/src/builtin-addons/coding-agents/providers/claude-code.ts +470 -0
  61. package/src/builtin-addons/coding-agents/providers/claude-instances.ts +184 -0
  62. package/src/builtin-addons/coding-agents/providers/opencode-instances.ts +108 -0
  63. package/src/builtin-addons/coding-agents/providers/opencode.ts +636 -0
  64. package/src/builtin-addons/coding-agents/providers/registry.ts +120 -0
  65. package/src/builtin-addons/coding-agents/providers/spawn.ts +112 -0
  66. package/src/builtin-addons/coding-agents/shared/claude-hook-events.ts +55 -0
  67. package/src/builtin-addons/coding-agents/shared/claude-status.ts +236 -0
  68. package/src/builtin-addons/coding-agents/shared/live-count.ts +39 -0
  69. package/src/builtin-addons/coding-agents/shared/notifier.ts +58 -0
  70. package/src/builtin-addons/coding-agents/shared/opencode-status.ts +82 -0
  71. package/src/builtin-addons/coding-agents/shared/snapshot.ts +66 -0
  72. package/src/builtin-addons/coding-agents/shared/state.ts +72 -0
  73. package/src/builtin-addons/coding-agents/sirenodeck.json +6 -0
  74. package/src/builtin-addons/coding-agents/types/types.ts +33 -0
  75. package/src/builtin-addons/core/README.md +89 -0
  76. package/src/builtin-addons/core/buttons/action/backend.ts +7 -0
  77. package/src/builtin-addons/core/buttons/action/config.ts +13 -0
  78. package/src/builtin-addons/core/buttons/action/frontend.tsx +16 -0
  79. package/src/builtin-addons/core/buttons/change-deck/backend.ts +18 -0
  80. package/src/builtin-addons/core/buttons/change-deck/config.ts +15 -0
  81. package/src/builtin-addons/core/buttons/change-deck/frontend.tsx +18 -0
  82. package/src/builtin-addons/core/buttons/media-sample/backend.ts +8 -0
  83. package/src/builtin-addons/core/buttons/media-sample/config.ts +7 -0
  84. package/src/builtin-addons/core/buttons/media-sample/frontend.tsx +2 -0
  85. package/src/builtin-addons/core/buttons/page-nav/backend.ts +28 -0
  86. package/src/builtin-addons/core/buttons/page-nav/config.ts +9 -0
  87. package/src/builtin-addons/core/buttons/page-nav/frontend.tsx +68 -0
  88. package/src/builtin-addons/core/buttons/toggle/backend.ts +119 -0
  89. package/src/builtin-addons/core/buttons/toggle/config.ts +57 -0
  90. package/src/builtin-addons/core/buttons/toggle/frontend.tsx +57 -0
  91. package/src/builtin-addons/core/buttons/toggle/global-service.ts +174 -0
  92. package/src/builtin-addons/core/index.ts +120 -0
  93. package/src/builtin-addons/core/sirenodeck.json +6 -0
  94. package/src/builtin-addons/date-time/README.md +73 -0
  95. package/src/builtin-addons/date-time/buttons/analog-clock/backend.ts +10 -0
  96. package/src/builtin-addons/date-time/buttons/analog-clock/config.ts +4 -0
  97. package/src/builtin-addons/date-time/buttons/analog-clock/frontend.tsx +88 -0
  98. package/src/builtin-addons/date-time/buttons/custom/backend.ts +10 -0
  99. package/src/builtin-addons/date-time/buttons/custom/config.ts +9 -0
  100. package/src/builtin-addons/date-time/buttons/custom/frontend.tsx +26 -0
  101. package/src/builtin-addons/date-time/buttons/date/backend.ts +10 -0
  102. package/src/builtin-addons/date-time/buttons/date/config.ts +10 -0
  103. package/src/builtin-addons/date-time/buttons/date/frontend.tsx +42 -0
  104. package/src/builtin-addons/date-time/buttons/time/backend.ts +10 -0
  105. package/src/builtin-addons/date-time/buttons/time/config.ts +9 -0
  106. package/src/builtin-addons/date-time/buttons/time/frontend.tsx +29 -0
  107. package/src/builtin-addons/date-time/index.d.ts +5 -0
  108. package/src/builtin-addons/date-time/index.ts +30 -0
  109. package/src/builtin-addons/date-time/poller.ts +11 -0
  110. package/src/builtin-addons/date-time/shared/format-date.ts +36 -0
  111. package/src/builtin-addons/date-time/shared/format.ts +105 -0
  112. package/src/builtin-addons/date-time/shared/use-now.ts +10 -0
  113. package/src/builtin-addons/date-time/sirenodeck.json +6 -0
  114. package/src/builtin-addons/emoji-selector/README.md +45 -0
  115. package/src/builtin-addons/emoji-selector/assets/launcher.svg +10 -0
  116. package/src/builtin-addons/emoji-selector/assets/smileys.svg +8 -0
  117. package/src/builtin-addons/emoji-selector/buttons/category/backend.ts +14 -0
  118. package/src/builtin-addons/emoji-selector/buttons/category/config.ts +8 -0
  119. package/src/builtin-addons/emoji-selector/buttons/category/frontend.tsx +19 -0
  120. package/src/builtin-addons/emoji-selector/buttons/emoji/backend.ts +7 -0
  121. package/src/builtin-addons/emoji-selector/buttons/emoji/config.ts +9 -0
  122. package/src/builtin-addons/emoji-selector/buttons/emoji/frontend.tsx +11 -0
  123. package/src/builtin-addons/emoji-selector/buttons/launcher/backend.ts +13 -0
  124. package/src/builtin-addons/emoji-selector/buttons/launcher/config.ts +6 -0
  125. package/src/builtin-addons/emoji-selector/buttons/launcher/frontend.tsx +31 -0
  126. package/src/builtin-addons/emoji-selector/data/categories.ts +1084 -0
  127. package/src/builtin-addons/emoji-selector/decks/index.ts +137 -0
  128. package/src/builtin-addons/emoji-selector/index.d.ts +5 -0
  129. package/src/builtin-addons/emoji-selector/index.ts +29 -0
  130. package/src/builtin-addons/emoji-selector/sirenodeck.json +6 -0
  131. package/src/builtin-addons/emoji-selector/support.ts +49 -0
  132. package/src/builtin-addons/index.ts +13 -0
  133. package/src/builtin-addons/internal-settings/README.md +26 -0
  134. package/src/builtin-addons/internal-settings/backend.ts +58 -0
  135. package/src/builtin-addons/internal-settings/buttons/app-info/backend.ts +7 -0
  136. package/src/builtin-addons/internal-settings/buttons/app-info/config.ts +13 -0
  137. package/src/builtin-addons/internal-settings/buttons/app-info/frontend.tsx +18 -0
  138. package/src/builtin-addons/internal-settings/buttons/brightness/common/frontend.tsx +50 -0
  139. package/src/builtin-addons/internal-settings/buttons/brightness-down/backend.ts +16 -0
  140. package/src/builtin-addons/internal-settings/buttons/brightness-down/config.ts +6 -0
  141. package/src/builtin-addons/internal-settings/buttons/brightness-down/frontend.tsx +8 -0
  142. package/src/builtin-addons/internal-settings/buttons/brightness-up/backend.ts +16 -0
  143. package/src/builtin-addons/internal-settings/buttons/brightness-up/config.ts +6 -0
  144. package/src/builtin-addons/internal-settings/buttons/brightness-up/frontend.tsx +8 -0
  145. package/src/builtin-addons/internal-settings/decks/settings.ts +25 -0
  146. package/src/builtin-addons/internal-settings/index.d.ts +4 -0
  147. package/src/builtin-addons/internal-settings/index.ts +53 -0
  148. package/src/builtin-addons/internal-settings/logo72x72.png +0 -0
  149. package/src/builtin-addons/internal-settings/sirenodeck.json +6 -0
  150. package/src/builtin-addons/media/README.md +45 -0
  151. package/src/builtin-addons/media/backend.ts +143 -0
  152. package/src/builtin-addons/media/buttons/media-player/backend.ts +19 -0
  153. package/src/builtin-addons/media/buttons/media-player/components/MediaStatus.tsx +25 -0
  154. package/src/builtin-addons/media/buttons/media-player/components/MediaSurface.tsx +52 -0
  155. package/src/builtin-addons/media/buttons/media-player/components/ProgressBar.tsx +21 -0
  156. package/src/builtin-addons/media/buttons/media-player/components/status-meta.ts +36 -0
  157. package/src/builtin-addons/media/buttons/media-player/config.ts +4 -0
  158. package/src/builtin-addons/media/buttons/media-player/frontend.tsx +29 -0
  159. package/src/builtin-addons/media/buttons/volume/common/frontend.tsx +52 -0
  160. package/src/builtin-addons/media/buttons/volume/mute/backend.ts +13 -0
  161. package/src/builtin-addons/media/buttons/volume/mute/config.ts +4 -0
  162. package/src/builtin-addons/media/buttons/volume/mute/frontend.tsx +26 -0
  163. package/src/builtin-addons/media/buttons/volume/volume-down/backend.ts +14 -0
  164. package/src/builtin-addons/media/buttons/volume/volume-down/config.ts +6 -0
  165. package/src/builtin-addons/media/buttons/volume/volume-down/frontend.tsx +10 -0
  166. package/src/builtin-addons/media/buttons/volume/volume-up/backend.ts +14 -0
  167. package/src/builtin-addons/media/buttons/volume/volume-up/config.ts +6 -0
  168. package/src/builtin-addons/media/buttons/volume/volume-up/frontend.tsx +8 -0
  169. package/src/builtin-addons/media/checks.ts +104 -0
  170. package/src/builtin-addons/media/executor.ts +36 -0
  171. package/src/builtin-addons/media/index.d.ts +5 -0
  172. package/src/builtin-addons/media/index.ts +53 -0
  173. package/src/builtin-addons/media/progress.ts +16 -0
  174. package/src/builtin-addons/media/providers/darwin.ts +391 -0
  175. package/src/builtin-addons/media/providers/index.ts +27 -0
  176. package/src/builtin-addons/media/providers/linux.ts +196 -0
  177. package/src/builtin-addons/media/providers/types.ts +48 -0
  178. package/src/builtin-addons/media/providers/windows.ts +121 -0
  179. package/src/builtin-addons/media/sirenodeck.json +6 -0
  180. package/src/builtin-addons/media/state.ts +19 -0
  181. package/src/builtin-addons/register-builtins.ts +65 -0
  182. package/src/builtin-addons/session/README.md +14 -0
  183. package/src/builtin-addons/session/buttons/session-info/backend.ts +8 -0
  184. package/src/builtin-addons/session/buttons/session-info/config.ts +4 -0
  185. package/src/builtin-addons/session/buttons/session-info/frontend.tsx +2 -0
  186. package/src/builtin-addons/session/buttons/time/backend.ts +7 -0
  187. package/src/builtin-addons/session/buttons/time/config.ts +6 -0
  188. package/src/builtin-addons/session/buttons/time/frontend.tsx +2 -0
  189. package/src/builtin-addons/session/index.d.ts +5 -0
  190. package/src/builtin-addons/session/index.ts +18 -0
  191. package/src/builtin-addons/session/sirenodeck.json +6 -0
  192. package/src/builtin-addons/system-status/README.md +169 -0
  193. package/src/builtin-addons/system-status/buttons/_shared.ts +131 -0
  194. package/src/builtin-addons/system-status/buttons/system-status/frontend.tsx +224 -0
  195. package/src/builtin-addons/system-status/buttons/system-status/schemas.ts +67 -0
  196. package/src/builtin-addons/system-status/domain/catalog.ts +53 -0
  197. package/src/builtin-addons/system-status/domain/chart-sampler.ts +58 -0
  198. package/src/builtin-addons/system-status/domain/display-metrics.ts +128 -0
  199. package/src/builtin-addons/system-status/domain/index.ts +10 -0
  200. package/src/builtin-addons/system-status/domain/live-metrics.ts +1021 -0
  201. package/src/builtin-addons/system-status/domain/metric-ids.ts +0 -0
  202. package/src/builtin-addons/system-status/index.ts +16 -0
  203. package/src/builtin-addons/system-status/manifest.ts +105 -0
  204. package/src/builtin-addons/system-status/shared/metrics-catalog.ts +316 -0
  205. package/src/builtin-addons/system-status/sirenodeck.json +6 -0
  206. package/src/builtin-addons/test-buildin/decks/action-buttons-test.ts +56 -0
  207. package/src/builtin-addons/test-buildin/index.d.ts +5 -0
  208. package/src/builtin-addons/test-buildin/index.ts +16 -0
  209. package/src/builtin-addons/value-display/README.md +59 -0
  210. package/src/builtin-addons/value-display/backend.ts +86 -0
  211. package/src/builtin-addons/value-display/buttons/value-display/backend.ts +17 -0
  212. package/src/builtin-addons/value-display/buttons/value-display/config.ts +36 -0
  213. package/src/builtin-addons/value-display/buttons/value-display/frontend.tsx +54 -0
  214. package/src/builtin-addons/value-display/index.d.ts +5 -0
  215. package/src/builtin-addons/value-display/index.ts +23 -0
  216. package/src/builtin-addons/value-display/sirenodeck.json +6 -0
  217. package/src/builtin-addons/weather/README.md +46 -0
  218. package/src/builtin-addons/weather/backend.ts +121 -0
  219. package/src/builtin-addons/weather/buttons/weather/backend.ts +27 -0
  220. package/src/builtin-addons/weather/buttons/weather/config.ts +29 -0
  221. package/src/builtin-addons/weather/buttons/weather/frontend.tsx +63 -0
  222. package/src/builtin-addons/weather/buttons/weather/icons.tsx +88 -0
  223. package/src/builtin-addons/weather/buttons/weather/pages.tsx +109 -0
  224. package/src/builtin-addons/weather/domain/codes.ts +35 -0
  225. package/src/builtin-addons/weather/domain/fetch.ts +47 -0
  226. package/src/builtin-addons/weather/index.d.ts +5 -0
  227. package/src/builtin-addons/weather/index.ts +23 -0
  228. package/src/builtin-addons/weather/poller.ts +70 -0
  229. package/src/builtin-addons/weather/provider/city-key.ts +9 -0
  230. package/src/builtin-addons/weather/provider/codes.ts +35 -0
  231. package/src/builtin-addons/weather/provider/fetch.ts +97 -0
  232. package/src/builtin-addons/weather/provider/geocode.ts +67 -0
  233. package/src/builtin-addons/weather/provider/types.ts +42 -0
  234. package/src/builtin-addons/weather/sirenodeck.json +6 -0
  235. package/src/cli/coding-agents-onboarding.ts +434 -0
  236. package/src/cli/commands/addon-decks.ts +441 -0
  237. package/src/cli/commands/addon-registry.ts +639 -0
  238. package/src/cli/commands/emulator-mode.ts +289 -0
  239. package/src/cli/commands/install.ts +128 -0
  240. package/src/cli/commands/logs.ts +74 -0
  241. package/src/cli/commands/network-bind.ts +111 -0
  242. package/src/cli/commands/pipeline/helpers.ts +75 -0
  243. package/src/cli/commands/pipeline/preflight.ts +20 -0
  244. package/src/cli/commands/port-identity.ts +152 -0
  245. package/src/cli/commands/reload.ts +37 -0
  246. package/src/cli/commands/restart.ts +139 -0
  247. package/src/cli/commands/run.ts +2270 -0
  248. package/src/cli/commands/service/install.ts +121 -0
  249. package/src/cli/commands/service/render-template.ts +158 -0
  250. package/src/cli/commands/service-manager.ts +184 -0
  251. package/src/cli/commands/spawn-daemon.ts +251 -0
  252. package/src/cli/commands/start.ts +1061 -0
  253. package/src/cli/commands/status.ts +110 -0
  254. package/src/cli/commands/stop.ts +121 -0
  255. package/src/cli/commands/subprocess-supervisor.ts +203 -0
  256. package/src/cli/commands/system-requirements.ts +699 -0
  257. package/src/cli/cwd.ts +28 -0
  258. package/src/cli/first-run.ts +149 -0
  259. package/src/cli/http-server.ts +244 -0
  260. package/src/cli/index.ts +355 -0
  261. package/src/cli/install-root.ts +26 -0
  262. package/src/cli/main.ts +194 -0
  263. package/src/cli/package-manager.ts +175 -0
  264. package/src/cli/probe-deps.ts +45 -0
  265. package/src/cli/prompt.ts +22 -0
  266. package/src/cli/startup-display.ts +452 -0
  267. package/src/config/builtin-icons.ts +57 -0
  268. package/src/config/config-diff.ts +54 -0
  269. package/src/config/discovery.ts +64 -0
  270. package/src/config/icon-resolver.ts +90 -0
  271. package/src/config/include-resolver.ts +202 -0
  272. package/src/config/index.ts +9 -0
  273. package/src/config/loader.ts +187 -0
  274. package/src/config/mutation.ts +514 -0
  275. package/src/config/reference-expander.ts +84 -0
  276. package/src/config/schemas.ts +223 -0
  277. package/src/config/validation.ts +254 -0
  278. package/src/core/asset-id.ts +21 -0
  279. package/src/core/gesture-state.ts +344 -0
  280. package/src/core/icon-asset-registry.ts +127 -0
  281. package/src/core/icon-source.ts +86 -0
  282. package/src/core/index.ts +30 -0
  283. package/src/core/mime.ts +16 -0
  284. package/src/core/pagination.ts +90 -0
  285. package/src/core/pub-sub.ts +126 -0
  286. package/src/core/settings.ts +153 -0
  287. package/src/core/store.ts +88 -0
  288. package/src/core/watcher.ts +73 -0
  289. package/src/deck/addon-handler-bridge.ts +516 -0
  290. package/src/deck/deck-config.ts +271 -0
  291. package/src/deck/editor-surfaces.ts +87 -0
  292. package/src/deck/host-context.ts +18 -0
  293. package/src/deck/index.ts +102 -0
  294. package/src/deck/macro-parse.ts +182 -0
  295. package/src/deck/methods.ts +348 -0
  296. package/src/deck/paginate-deck.ts +98 -0
  297. package/src/deck/position-buttons.ts +57 -0
  298. package/src/deck/runtime/index.ts +5 -0
  299. package/src/deck/runtime/runtime.ts +1060 -0
  300. package/src/deck/runtime-subscriptions.ts +45 -0
  301. package/src/deck/system-back-injection.ts +62 -0
  302. package/src/deck/system-buttons/registry.tsx +97 -0
  303. package/src/deck/system-buttons/types.ts +14 -0
  304. package/src/device/black-frame.ts +73 -0
  305. package/src/device/index.ts +13 -0
  306. package/src/device/linux-udev.ts +36 -0
  307. package/src/device/models.ts +89 -0
  308. package/src/device/reconnecting.ts +193 -0
  309. package/src/device/registry.ts +38 -0
  310. package/src/device/stream-deck.ts +155 -0
  311. package/src/index.ts +74 -0
  312. package/src/outputClient/emulator.ts +357 -0
  313. package/src/outputClient/index.ts +26 -0
  314. package/src/outputClient/open-browser.ts +26 -0
  315. package/src/outputClient/real.ts +393 -0
  316. package/src/outputClient/types.ts +83 -0
  317. package/src/render/browser-renderer.ts +240 -0
  318. package/src/render/buffer-hash.ts +20 -0
  319. package/src/render/editor-handler.ts +197 -0
  320. package/src/render/emulator-server.ts +128 -0
  321. package/src/render/icon-source-resolver.ts +69 -0
  322. package/src/render/index.ts +16 -0
  323. package/src/render/protocol.ts +61 -0
  324. package/src/render/push-raw-image.ts +100 -0
  325. package/src/render/screenshot-cadence.ts +87 -0
  326. package/src/render/state-publisher.ts +110 -0
  327. package/src/render/vite-server.ts +138 -0
  328. package/src/render/ws-bridge.ts +315 -0
  329. package/src/system/device-selection.ts +80 -0
  330. package/src/system/glob-match.ts +74 -0
  331. package/src/system/providers/active-app/darwin.ts +117 -0
  332. package/src/system/providers/active-app/linux.ts +245 -0
  333. package/src/system/providers/active-app/wayland-gnome.ts +303 -0
  334. package/src/system/providers/active-app/windows.ts +94 -0
  335. package/src/system/providers/active-app.ts +97 -0
  336. package/src/system/providers/clipboard/darwin.ts +65 -0
  337. package/src/system/providers/clipboard/linux.ts +163 -0
  338. package/src/system/providers/clipboard/windows.ts +94 -0
  339. package/src/system/providers/clipboard.ts +84 -0
  340. package/src/system/providers/error.ts +16 -0
  341. package/src/system/providers/key-macro/darwin.ts +221 -0
  342. package/src/system/providers/key-macro/linux.ts +651 -0
  343. package/src/system/providers/key-macro/parser.ts +215 -0
  344. package/src/system/providers/key-macro/windows.ts +476 -0
  345. package/src/system/providers/key-macro.ts +79 -0
  346. package/src/system/providers/notification/darwin.ts +36 -0
  347. package/src/system/providers/notification/linux.ts +115 -0
  348. package/src/system/providers/notification/windows.ts +72 -0
  349. package/src/system/providers/notification.ts +75 -0
  350. package/src/system/providers/session/darwin.ts +82 -0
  351. package/src/system/providers/session/linux.ts +175 -0
  352. package/src/system/providers/session/windows.ts +73 -0
  353. package/src/system/providers/session.ts +89 -0
  354. package/src/system/providers/shared.ts +65 -0
  355. package/src/system/requirements.ts +235 -0
  356. package/src/system/setup-wizard/config-seed.ts +30 -0
  357. package/src/system/setup-wizard/format.ts +275 -0
  358. package/src/system/setup-wizard/index.ts +45 -0
  359. package/src/system/setup-wizard/open-settings.ts +26 -0
  360. package/src/system/setup-wizard/plan.ts +230 -0
  361. package/src/system/setup-wizard/probe-cache.ts +34 -0
  362. package/src/system/setup-wizard/probe.ts +486 -0
  363. package/src/system/setup-wizard/runtime-features.ts +85 -0
  364. package/src/system/setup-wizard/sudo.ts +178 -0
  365. package/src/system/setup-wizard/types.ts +133 -0
  366. package/src/system/virtual-stream-deck.ts +67 -0
  367. package/src/themes/css.ts +210 -0
  368. package/src/themes/default/assets/IBMPlexSans-Italic-VariableFont_wdth,wght.ttf +0 -0
  369. package/src/themes/default/assets/IBMPlexSans-VariableFont_wdth,wght.ttf +0 -0
  370. package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-Bold.ttf +0 -0
  371. package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-BoldItalic.ttf +0 -0
  372. package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-ExtraLight.ttf +0 -0
  373. package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-ExtraLightItalic.ttf +0 -0
  374. package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-Italic.ttf +0 -0
  375. package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-Light.ttf +0 -0
  376. package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-LightItalic.ttf +0 -0
  377. package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-Medium.ttf +0 -0
  378. package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-MediumItalic.ttf +0 -0
  379. package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-Regular.ttf +0 -0
  380. package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-SemiBold.ttf +0 -0
  381. package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-SemiBoldItalic.ttf +0 -0
  382. package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-Thin.ttf +0 -0
  383. package/src/themes/default/assets/IBM_Plex_Mono/IBMPlexMono-ThinItalic.ttf +0 -0
  384. package/src/themes/default/assets/IBM_Plex_Mono/OFL.txt +93 -0
  385. package/src/themes/default/assets/OFL.txt +93 -0
  386. package/src/themes/default/assets/README.txt +106 -0
  387. package/src/themes/default/assets/static/IBMPlexSans-Bold.ttf +0 -0
  388. package/src/themes/default/assets/static/IBMPlexSans-BoldItalic.ttf +0 -0
  389. package/src/themes/default/assets/static/IBMPlexSans-ExtraLight.ttf +0 -0
  390. package/src/themes/default/assets/static/IBMPlexSans-ExtraLightItalic.ttf +0 -0
  391. package/src/themes/default/assets/static/IBMPlexSans-Italic.ttf +0 -0
  392. package/src/themes/default/assets/static/IBMPlexSans-Light.ttf +0 -0
  393. package/src/themes/default/assets/static/IBMPlexSans-LightItalic.ttf +0 -0
  394. package/src/themes/default/assets/static/IBMPlexSans-Medium.ttf +0 -0
  395. package/src/themes/default/assets/static/IBMPlexSans-MediumItalic.ttf +0 -0
  396. package/src/themes/default/assets/static/IBMPlexSans-Regular.ttf +0 -0
  397. package/src/themes/default/assets/static/IBMPlexSans-SemiBold.ttf +0 -0
  398. package/src/themes/default/assets/static/IBMPlexSans-SemiBoldItalic.ttf +0 -0
  399. package/src/themes/default/assets/static/IBMPlexSans-Thin.ttf +0 -0
  400. package/src/themes/default/assets/static/IBMPlexSans-ThinItalic.ttf +0 -0
  401. package/src/themes/default/assets/static/IBMPlexSans_Condensed-Bold.ttf +0 -0
  402. package/src/themes/default/assets/static/IBMPlexSans_Condensed-BoldItalic.ttf +0 -0
  403. package/src/themes/default/assets/static/IBMPlexSans_Condensed-ExtraLight.ttf +0 -0
  404. package/src/themes/default/assets/static/IBMPlexSans_Condensed-ExtraLightItalic.ttf +0 -0
  405. package/src/themes/default/assets/static/IBMPlexSans_Condensed-Italic.ttf +0 -0
  406. package/src/themes/default/assets/static/IBMPlexSans_Condensed-Light.ttf +0 -0
  407. package/src/themes/default/assets/static/IBMPlexSans_Condensed-LightItalic.ttf +0 -0
  408. package/src/themes/default/assets/static/IBMPlexSans_Condensed-Medium.ttf +0 -0
  409. package/src/themes/default/assets/static/IBMPlexSans_Condensed-MediumItalic.ttf +0 -0
  410. package/src/themes/default/assets/static/IBMPlexSans_Condensed-Regular.ttf +0 -0
  411. package/src/themes/default/assets/static/IBMPlexSans_Condensed-SemiBold.ttf +0 -0
  412. package/src/themes/default/assets/static/IBMPlexSans_Condensed-SemiBoldItalic.ttf +0 -0
  413. package/src/themes/default/assets/static/IBMPlexSans_Condensed-Thin.ttf +0 -0
  414. package/src/themes/default/assets/static/IBMPlexSans_Condensed-ThinItalic.ttf +0 -0
  415. package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-Bold.ttf +0 -0
  416. package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-BoldItalic.ttf +0 -0
  417. package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-ExtraLight.ttf +0 -0
  418. package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-ExtraLightItalic.ttf +0 -0
  419. package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-Italic.ttf +0 -0
  420. package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-Light.ttf +0 -0
  421. package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-LightItalic.ttf +0 -0
  422. package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-Medium.ttf +0 -0
  423. package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-MediumItalic.ttf +0 -0
  424. package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-Regular.ttf +0 -0
  425. package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-SemiBold.ttf +0 -0
  426. package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-SemiBoldItalic.ttf +0 -0
  427. package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-Thin.ttf +0 -0
  428. package/src/themes/default/assets/static/IBMPlexSans_SemiCondensed-ThinItalic.ttf +0 -0
  429. package/src/themes/default/components.css +81 -0
  430. package/src/themes/default/sirenodeck.json +170 -0
  431. package/src/themes/index.ts +14 -0
  432. package/src/themes/light/assets/IBMPlexSans-Italic-VariableFont_wdth,wght.ttf +0 -0
  433. package/src/themes/light/assets/IBMPlexSans-VariableFont_wdth,wght.ttf +0 -0
  434. package/src/themes/light/assets/IBM_Plex_Mono/IBMPlexMono-Bold.ttf +0 -0
  435. package/src/themes/light/assets/IBM_Plex_Mono/IBMPlexMono-Medium.ttf +0 -0
  436. package/src/themes/light/assets/IBM_Plex_Mono/IBMPlexMono-Regular.ttf +0 -0
  437. package/src/themes/light/assets/IBM_Plex_Mono/OFL.txt +93 -0
  438. package/src/themes/light/assets/OFL.txt +93 -0
  439. package/src/themes/light/assets/README.txt +106 -0
  440. package/src/themes/light/assets/static/IBMPlexSans-Light.ttf +0 -0
  441. package/src/themes/light/assets/static/IBMPlexSans-LightItalic.ttf +0 -0
  442. package/src/themes/light/assets/static/IBMPlexSans-Thin.ttf +0 -0
  443. package/src/themes/light/components.css +70 -0
  444. package/src/themes/light/sirenodeck.json +170 -0
  445. package/src/themes/loader.ts +343 -0
  446. package/src/themes/manifest.ts +164 -0
  447. package/src/themes/use-resolved-theme.tsx +32 -0
  448. package/src/ui/ButtonFrame.tsx +230 -0
  449. package/src/ui/contexts/AssetCacheContext.tsx +43 -0
  450. package/src/ui/index.ts +20 -0
  451. package/src/ui/primitives/Chip.tsx +53 -0
  452. package/src/ui/primitives/Icon.tsx +209 -0
  453. package/src/ui/primitives/Label.tsx +82 -0
  454. package/src/ui/primitives/ProgressBar.tsx +38 -0
  455. package/src/ui/primitives/TapIndicator.tsx +67 -0
  456. package/src/ui/primitives/Text.tsx +810 -0
  457. package/src/ui/primitives/index.ts +6 -0
  458. package/src/ui/surfaces/BarsSurface.tsx +211 -0
  459. package/src/ui/surfaces/IconLabelProgressSurface.tsx +133 -0
  460. package/src/ui/surfaces/IconLabelSurface.tsx +59 -0
  461. package/src/ui/surfaces/LabelValueListSurface.tsx +202 -0
  462. package/src/ui/surfaces/PaginatedSurface.tsx +164 -0
  463. package/src/ui/surfaces/SplitActionSurface.tsx +98 -0
  464. package/src/ui/surfaces/TemporaryErrorSurface.tsx +68 -0
  465. package/src/ui/surfaces/ValueChart.tsx +218 -0
  466. package/src/ui/surfaces/index.ts +32 -0
  467. package/src/ui/surfaces/paginated-schema.ts +22 -0
  468. package/src/ui/theme-presentation-builder.ts +184 -0
  469. package/src/ui/theme-presentation.tsx +146 -0
  470. package/src/ui/utils/cn.ts +12 -0
  471. package/src/util/cache-paths.ts +38 -0
  472. package/src/util/config-diff.ts +16 -0
  473. package/src/util/daemon-control.ts +85 -0
  474. package/src/util/daemon.ts +575 -0
  475. package/src/util/device-config.ts +56 -0
  476. package/src/util/errors.ts +13 -0
  477. package/src/util/log-reader.ts +114 -0
  478. package/src/util/log-tail.ts +103 -0
  479. package/src/util/logger.ts +417 -0
  480. package/src/util/process-title.ts +79 -0
  481. package/src/util/single-instance.ts +202 -0
  482. package/src/version.ts +10 -0
  483. package/src/vite/index.ts +6 -0
  484. package/src/vite/virtual-modules.ts +631 -0
  485. package/src/vite-env.d.ts +1 -0
@@ -0,0 +1,48 @@
1
+ export type PlayStatus = "play" | "pause" | "stop" | "unavailable"
2
+
3
+ export interface MediaTrack {
4
+ readonly name: string
5
+ readonly artist: string
6
+ readonly album?: string
7
+ }
8
+
9
+ export interface MediaStatus {
10
+ readonly track: MediaTrack | null
11
+ readonly totalTime: number
12
+ readonly currentTime: number
13
+ readonly playStatus: PlayStatus
14
+ readonly volume: number
15
+ readonly muted: boolean
16
+ }
17
+
18
+ export interface MediaStatusProvider {
19
+ getStatus(): Promise<MediaStatus>
20
+ play(): Promise<void>
21
+ pause(): Promise<void>
22
+ toggle(): Promise<void>
23
+ next(): Promise<void>
24
+ previous(): Promise<void>
25
+ setVolume(value: number): Promise<void>
26
+ volumeUp(step: number): Promise<void>
27
+ volumeDown(step: number): Promise<void>
28
+ toggleMute(): Promise<void>
29
+ }
30
+
31
+ export interface StatusProviderDeps {
32
+ readonly executor: ProviderExecutor
33
+ }
34
+
35
+ export interface ProviderExecutor {
36
+ run(
37
+ command: string,
38
+ args: ReadonlyArray<string>,
39
+ options?: { timeoutMs?: number },
40
+ ): Promise<{
41
+ exitCode: number
42
+ stdout: string
43
+ stderr: string
44
+ }>
45
+ }
46
+
47
+ export const DEFAULT_TIMEOUT_MS = 5_000
48
+ export const ONCHANGE_POLL_MS = 2_000
@@ -0,0 +1,121 @@
1
+ import type {
2
+ MediaStatus,
3
+ MediaStatusProvider,
4
+ ProviderExecutor,
5
+ } from "./types"
6
+
7
+ interface WindowsDeps {
8
+ readonly executor: ProviderExecutor
9
+ }
10
+
11
+ const runPowerShell = async (
12
+ deps: WindowsDeps,
13
+ script: string,
14
+ ): Promise<void> => {
15
+ const result = await deps.executor.run(
16
+ "powershell",
17
+ ["-NoProfile", "-Command", script],
18
+ {
19
+ timeoutMs: 5_000,
20
+ },
21
+ )
22
+ if (result.exitCode !== 0) {
23
+ throw new Error(
24
+ `powershell failed: ${result.stderr.trim() || "exit " + result.exitCode}`,
25
+ )
26
+ }
27
+ }
28
+
29
+ const PS_GET_STATE = `(Get-Process | Where-Object { $_.MainWindowTitle -ne '' } | Select-Object -First 1 -ExpandProperty ProcessName) 2>$null`
30
+ const PS_GET_TRACK = `try { $m = [Windows.Media.Control.GlobalSystemMediaTransportControlsSessionManager,Windows.Media.Content,Windows,ContentType=WindowsRuntime]::RequestAsync().GetAwaiter().GetResult().GetCurrentSession().GetMediaPropertiesAsync().GetAwaiter().GetResult(); "{0}|{1}|{2}" -f $m.Title, $m.Artist, $m.AlbumTitle } catch { "" }`
31
+ const PS_PLAY = `Add-Type -AssemblyName System.Runtime.WindowsRuntime; $null = [Windows.System.User, Windows.System, ContentType=WindowsRuntime]; $smtc = [Windows.Media.Control.GlobalSystemMediaTransportControlsSessionManager,Windows.Media.Content,Windows,ContentType=WindowsRuntime]::RequestAsync().GetAwaiter().GetResult(); $null = $smtc.GetCurrentSession().TryPlayAsync().GetAwaiter().GetResult()`
32
+ const PS_PAUSE = `$smtc = [Windows.Media.Control.GlobalSystemMediaTransportControlsSessionManager,Windows.Media.Content,Windows,ContentType=WindowsRuntime]::RequestAsync().GetAwaiter().GetResult(); $null = $smtc.GetCurrentSession().TryPauseAsync().GetAwaiter().GetResult()`
33
+ const PS_TOGGLE = `$smtc = [Windows.Media.Control.GlobalSystemMediaTransportControlsSessionManager,Windows.Media.Content,Windows,ContentType=WindowsRuntime]::RequestAsync().GetAwaiter().GetResult(); $null = $smtc.GetCurrentSession().TryTogglePlayPauseAsync().GetAwaiter().GetResult()`
34
+
35
+ const readStatus = async (deps: WindowsDeps): Promise<MediaStatus> => {
36
+ const [stateResult, trackResult] = await Promise.all([
37
+ deps.executor.run("powershell", ["-NoProfile", "-Command", PS_GET_STATE], {
38
+ timeoutMs: 2_000,
39
+ }),
40
+ deps.executor.run("powershell", ["-NoProfile", "-Command", PS_GET_TRACK], {
41
+ timeoutMs: 2_000,
42
+ }),
43
+ ])
44
+
45
+ // SMTC does not expose a distinct play/pause/stop status. We use the
46
+ // presence of a foreground media process as a proxy for "playing"; a real
47
+ // session manager would expose PlaybackStatus but the underlying Windows
48
+ // Media Control API does not surface it through PowerShell here.
49
+ const playStatus: MediaStatus["playStatus"] =
50
+ stateResult.exitCode === 0 && stateResult.stdout.trim().length > 0
51
+ ? "play"
52
+ : "stop"
53
+
54
+ const track =
55
+ trackResult.exitCode === 0 && trackResult.stdout.trim().length > 0
56
+ ? (() => {
57
+ const parts = trackResult.stdout.trim().split("|")
58
+ const name = (parts[0] ?? "").trim()
59
+ if (name.length === 0) return null
60
+ return {
61
+ name,
62
+ artist:
63
+ parts[1] !== undefined && parts[1].trim().length > 0
64
+ ? parts[1].trim()
65
+ : "",
66
+ album:
67
+ parts[2] !== undefined && parts[2].trim().length > 0
68
+ ? parts[2].trim()
69
+ : undefined,
70
+ }
71
+ })()
72
+ : null
73
+
74
+ return {
75
+ track,
76
+ totalTime: 0,
77
+ currentTime: 0,
78
+ playStatus,
79
+ volume: 1,
80
+ muted: false,
81
+ }
82
+ }
83
+
84
+ export const createWindowsProvider = (
85
+ deps: WindowsDeps,
86
+ ): MediaStatusProvider => {
87
+ return {
88
+ async getStatus() {
89
+ return readStatus(deps)
90
+ },
91
+
92
+ async play() {
93
+ await runPowerShell(deps, PS_PLAY)
94
+ },
95
+ async pause() {
96
+ await runPowerShell(deps, PS_PAUSE)
97
+ },
98
+ async toggle() {
99
+ await runPowerShell(deps, PS_TOGGLE)
100
+ },
101
+ async next() {
102
+ // SMTC doesn't expose next/previous directly.
103
+ },
104
+ async previous() {
105
+ // SMTC doesn't expose next/previous directly.
106
+ },
107
+
108
+ async setVolume(_value) {
109
+ // SMTC doesn't support volume control.
110
+ },
111
+ async volumeUp(_step) {
112
+ // SMTC doesn't support volume control.
113
+ },
114
+ async volumeDown(_step) {
115
+ // SMTC doesn't support volume control.
116
+ },
117
+ async toggleMute() {
118
+ // SMTC doesn't support mute.
119
+ },
120
+ }
121
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "kind": "addon",
3
+ "apiVersion": 1,
4
+ "name": "media",
5
+ "entry": "index.ts"
6
+ }
@@ -0,0 +1,19 @@
1
+ export type MediaButtonStatus =
2
+ | "play"
3
+ | "pause"
4
+ | "stop"
5
+ | "unsupported"
6
+ | "notAvailable"
7
+
8
+ export interface MediaPlayerState {
9
+ title: string | null
10
+ artist: string | null
11
+ source: string | null
12
+ status: MediaButtonStatus | null
13
+ isPlaying: boolean
14
+ progress: number
15
+ currentTime: number
16
+ totalTime: number
17
+ volume: number
18
+ muted: boolean
19
+ }
@@ -0,0 +1,65 @@
1
+ import type { AddonRegistry } from "@/addon/registry"
2
+
3
+ import { registerBuiltInThemes, registerSiblingThemes } from "@/themes/loader"
4
+
5
+ import { manifest as codingAgentsManifest } from "./coding-agents"
6
+ import { registerCodingAgentsAddon } from "./coding-agents"
7
+ import brightnessAddon from "./brightness/index"
8
+ import { coreAddon } from "./core/index"
9
+ import dateTimeAddon from "./date-time/index"
10
+ import emojiSelectorAddon from "./emoji-selector/index"
11
+ import { internalSettingsAddon } from "./internal-settings/index"
12
+ import mediaPlayerAddon from "./media/index"
13
+ import { sessionAddon } from "./session/index"
14
+ import { systemStatusAddon } from "./system-status/index"
15
+ import valueDisplayAddon from "./value-display/index"
16
+ import weatherAddon from "./weather/index"
17
+
18
+ export const registerBuiltins = (registry: AddonRegistry): void => {
19
+ registerBuiltInThemes(registry)
20
+ registerSiblingThemes(registry)
21
+ registry.load(coreAddon)
22
+ registry.load(internalSettingsAddon)
23
+ registry.load(sessionAddon)
24
+ registry.load(dateTimeAddon)
25
+ registry.load(emojiSelectorAddon)
26
+ registry.load(mediaPlayerAddon)
27
+ registry.load(systemStatusAddon)
28
+ registry.load(valueDisplayAddon)
29
+ registry.load(weatherAddon)
30
+ registry.load(brightnessAddon)
31
+ registerCodingAgentsAddon(registry)
32
+ }
33
+
34
+ /**
35
+ * The builtin manifests, by addon name, as objects rather than file paths.
36
+ *
37
+ * ponytail: the addon bridge used to reach a builtin's handlers by
38
+ * `await import(<path to its index.ts>)`. That works under tsx and fails under
39
+ * the published bundle, where plain node meets TypeScript source and a `@/`
40
+ * path alias and gives up — "Cannot find package '@/deck'". The buttons then
41
+ * rendered but never received data: system metrics sat at "—%", the weather
42
+ * read "---", and the media player showed an empty face, with the failure
43
+ * confined to one error line in the daemon log.
44
+ *
45
+ * These modules are statically imported above, so they are already inside the
46
+ * bundle and inside the dev process alike. Handing the bridge the object it
47
+ * would have imported removes the file-path round trip entirely, which is both
48
+ * faster and immune to how the process was started.
49
+ */
50
+ export const BUILTIN_MANIFESTS: ReadonlyMap<string, unknown> = new Map<
51
+ string,
52
+ unknown
53
+ >([
54
+ ["core", coreAddon],
55
+ ["internal-settings", internalSettingsAddon],
56
+ ["session", sessionAddon],
57
+ ["date-time", dateTimeAddon],
58
+ ["emoji-selector", emojiSelectorAddon],
59
+ ["media", mediaPlayerAddon],
60
+ ["system-status", systemStatusAddon],
61
+ ["value-display", valueDisplayAddon],
62
+ ["weather", weatherAddon],
63
+ ["brightness", brightnessAddon],
64
+ ["coding-agents", codingAgentsManifest],
65
+ ])
@@ -0,0 +1,14 @@
1
+ # session
2
+
3
+ **Internal-only addon.** Provides session-related info buttons. The locked deck itself is runtime-synthesized (see `packages/cli/src/deck/runtime.ts` → `buildDefaultLockDeck`); this addon does not register a deck factory.
4
+
5
+ ## Buttons
6
+
7
+ | Button id | Purpose |
8
+ | -------------- | ------------------------------------------------ |
9
+ | `session:info` | Shows current OS session state (locked/unlocked) |
10
+
11
+ ## See also
12
+
13
+ - [Internal settings](../internal-settings/README.md) — settings overlay
14
+ - `packages/cli/src/deck/runtime.ts` — runtime-synthesized lock deck
@@ -0,0 +1,8 @@
1
+ import type { AddonButtonTypeService } from "@/addon/api"
2
+
3
+ import { configSchema } from "./config"
4
+
5
+ export default {
6
+ configSchema,
7
+ onTap: async () => {},
8
+ } satisfies AddonButtonTypeService
@@ -0,0 +1,4 @@
1
+ import { z } from "zod"
2
+
3
+ export const configSchema = z.object({})
4
+ export type ConfigSchema = z.infer<typeof configSchema>
@@ -0,0 +1,2 @@
1
+ import { NullButton } from "@/api/react"
2
+ export default NullButton
@@ -0,0 +1,7 @@
1
+ import type { AddonButtonTypeService } from "@/addon/api"
2
+
3
+ import { configSchema } from "./config"
4
+
5
+ export default {
6
+ configSchema,
7
+ } satisfies AddonButtonTypeService
@@ -0,0 +1,6 @@
1
+ import { z } from "zod"
2
+
3
+ export const configSchema = z.object({
4
+ format: z.string().default("HH:mm"),
5
+ })
6
+ export type ConfigSchema = z.infer<typeof configSchema>
@@ -0,0 +1,2 @@
1
+ import { NullButton } from "@/api/react"
2
+ export default NullButton
@@ -0,0 +1,5 @@
1
+ import type { NewAddonManifest } from "@/addon/api"
2
+
3
+ declare const manifest: NewAddonManifest
4
+ export default manifest
5
+ export { manifest }
@@ -0,0 +1,18 @@
1
+ import type { AddonManifestV1 } from "@/addon/api"
2
+
3
+ import sessionInfoBackend from "./buttons/session-info/backend"
4
+ import sessionInfoFrontend from "./buttons/session-info/frontend"
5
+
6
+ export const manifest: AddonManifestV1 = {
7
+ apiVersion: 1,
8
+ name: "session",
9
+ buttonTypes: {
10
+ "session:info": {
11
+ frontend: sessionInfoFrontend,
12
+ service: { ...sessionInfoBackend, gestureHandlers: ["tap"] as const },
13
+ },
14
+ },
15
+ }
16
+
17
+ export const sessionAddon = manifest
18
+ export default manifest
@@ -0,0 +1,6 @@
1
+ {
2
+ "kind": "addon",
3
+ "apiVersion": 1,
4
+ "name": "session",
5
+ "entry": "index.ts"
6
+ }
@@ -0,0 +1,169 @@
1
+ # system-status
2
+
3
+ OS metrics as Stream Deck buttons. Three visual modes — horizontal bars, a
4
+ KPIs list, and a mini-chart — and 19 built-in metrics. Polls every second via
5
+ addon-global pollers per metric, publishes on `runtime:system-status:<id>`,
6
+ and chart history on `runtime:system-status:chart-history`.
7
+
8
+ ## Buttons
9
+
10
+ | Type | Description |
11
+ | ----------------------------- | ----------------------------------------------------- |
12
+ | `system-status:system-status` | 1–3 metrics rendered as horizontal bars + value chips |
13
+
14
+ > The `bars`, `kpis`, and `chart` layouts are pages within this single button
15
+ > type, not separate button types.
16
+
17
+ ## Config
18
+
19
+ ```yaml
20
+ - position: 5
21
+ type: "system-status:system-status"
22
+ config:
23
+ pages:
24
+ - type: bars
25
+ metrics:
26
+ - id: cpu
27
+ label: CPU
28
+ - id: ram
29
+ label: MEM
30
+ - swap
31
+ - type: kpis
32
+ metrics: [temperature, uptime]
33
+ ```
34
+
35
+ `metrics` accepts either a string id (`"cpu"`) or an object
36
+ (`{id: "cpu", label: "CPU"}`). At least one, at most three.
37
+
38
+ ### Page layouts
39
+
40
+ The single registered button type accepts up to five `pages`. Each page has one
41
+ of three layouts:
42
+
43
+ | Layout | Metric count | Notes |
44
+ | ------- | ------------ | ------------------------------------------ |
45
+ | `bars` | 1–3 | Horizontal bars + value chips |
46
+ | `kpis` | 1–3 | Label/value list |
47
+ | `chart` | 1–2 | Metrics plotted over a sliding time window |
48
+
49
+ ```yaml
50
+ - position: 6
51
+ type: "system-status:system-status"
52
+ config:
53
+ pages:
54
+ - type: kpis
55
+ metrics: [cpu, ram]
56
+ ```
57
+
58
+ `chart` supports an optional `windowSeconds` (default 60); the per-metric
59
+ history is published on a dedicated
60
+ `runtime:system-status:chart-history` channel, separate from the live
61
+ metric channels.
62
+
63
+ ## Metrics
64
+
65
+ | Id | Label (default) | Formatter | Unit | Views | Source |
66
+ | --------------- | --------------- | ------------- | ---- | ----------------- | --------------------------------------------------------------------------------- |
67
+ | `cpu` | CPU | percent | % | bars, chart, kpis | `/proc` jiffies delta over poll interval |
68
+ | `ram` | RAM | percent | % | bars, chart, kpis | `os.totalmem/freemem` |
69
+ | `swap` | Swap | percent | % | bars, chart, kpis | `/proc/meminfo` SwapTotal/SwapFree (Linux) |
70
+ | `disk` | Disk | percent | % | bars, chart, kpis | `statfs("/")` used/total |
71
+ | `disk-io` | Disk I/O | rate-bytes | B/s | kpis | `/proc/diskstats` sector delta × 512 (Linux) |
72
+ | `network` | Net | count | — | kpis | Interface count (placeholder — see `network-read` / `network-write`) |
73
+ | `network-read` | Net RX | rate-bytes | B/s | kpis | `/sys/class/net/*/statistics/rx_bytes` delta, non-loopback (Linux) |
74
+ | `network-write` | Net TX | rate-bytes | B/s | kpis | `/sys/class/net/*/statistics/tx_bytes` delta, non-loopback (Linux) |
75
+ | `battery` | Battery | percent | % | bars, chart, kpis | `/sys/class/power_supply/BAT0/capacity` (Linux) |
76
+ | `temperature` | Temp | count | °C | bars, chart, kpis | hwmon / `thermal_zone0` (Linux); `macmon` `temp.cpu_temp_avg` (macOS) |
77
+ | `gpu-temp` | GPU Temp | count | °C | bars, chart, kpis | amdgpu sysfs / `nvidia-smi` (Linux); `macmon` `temp.gpu_temp_avg` (macOS) |
78
+ | `gpu-usage` | GPU | percent | % | bars, chart, kpis | amdgpu `gpu_busy_percent`, fallback `nvidia-smi --query-gpu=utilization.gpu` |
79
+ | `uptime` | Uptime | uptime | — | kpis | `os.uptime()` |
80
+ | `frequency` | Freq | frequency-ghz | GHz | bars, chart, kpis | `os.cpus()[].speed`, fallback `/proc/cpuinfo` MHz |
81
+ | `load` | Load | count | — | bars, chart, kpis | `os.loadavg()[0]` |
82
+ | `processes` | Procs | count | — | kpis | `/proc` numeric-dir count (Linux) |
83
+ | `cpu-boost` | Boost | bool | — | kpis | `/sys/devices/system/cpu/cpufreq/boost`, fallback `intel_pstate/no_turbo` (Linux) |
84
+ | `cpu-voltages` | Vcore | count | V | kpis | hwmon `in0_input` on k10temp/zenpower/coretemp/acpitz (Linux) |
85
+ | `fan-rpm` | Fan | count | RPM | kpis | hwmon `fan*_input` first non-zero reading (Linux); `macmon` fastest fan (macOS) |
86
+
87
+ Metrics that aren't available on the current platform report
88
+ `available: false` and the button renders a `—` for that slot. No silent
89
+ zeros, no crashes.
90
+
91
+ #### Platform coverage
92
+
93
+ Most probes read Linux sysfs. macOS has no `/proc` or `/sys`, so the darwin
94
+ paths go through documented CLIs instead — `sysctl` for swap, `pmset` for
95
+ battery, `ps` for processes, `netstat` for network, and `ioreg` for GPU
96
+ utilisation and disk I/O.
97
+
98
+ Three metrics need a helper. CPU temperature, GPU temperature and fan RPM have
99
+ no unprivileged source on Apple Silicon from those tools: `powermetrics`
100
+ requires root, and the only `Temperature` key `ioreg` will hand a normal user
101
+ belongs to `AppleSmartBattery` — the battery's, not the SoC's, so reporting it
102
+ would be wrong rather than merely absent. [`macmon`](https://github.com/vladkens/macmon)
103
+ reads all three through IOReport without sudo:
104
+
105
+ ```sh
106
+ brew install macmon
107
+ ```
108
+
109
+ It is optional and follows the same pattern as the media addon preferring
110
+ `media-control` and brightness preferring `brightness`: present, the metrics
111
+ report live values; absent, they stay unavailable and `system-requirements`
112
+ names the install command.
113
+
114
+ `cpu-boost` and `cpu-voltages` stay unavailable on macOS whatever is
115
+ installed. Apple Silicon has no turbo toggle to report and no exposed voltage
116
+ rail, so there is nothing to read — this is not a gap waiting to be filled.
117
+
118
+ ### Formatters
119
+
120
+ | Formatter | Output |
121
+ | --------------- | ----------------------------------------- |
122
+ | `percent` | `5.4%` (<10) / `42%` (≥10) |
123
+ | `count` | `42` (≥100) / `5.4` (<100) |
124
+ | `bytes` | `5.2 MB` |
125
+ | `rate-bytes` | `5.2 MB/s` (uses KiB/MiB/GiB/TiB scaling) |
126
+ | `frequency-ghz` | `3.40` |
127
+ | `uptime` | `2h` |
128
+ | `bool` | `ON` (≥0.5) / `OFF` |
129
+
130
+ ## Example
131
+
132
+ ```yaml
133
+ decks:
134
+ sys:
135
+ name: Sys Stats
136
+ buttons:
137
+ - position: 0
138
+ type: "system-status:system-status"
139
+ config:
140
+ pages:
141
+ - type: bars
142
+ metrics:
143
+ - id: cpu
144
+ label: CPU
145
+ - id: ram
146
+ label: MEM
147
+ - swap
148
+ - position: 1
149
+ type: "system-status:system-status"
150
+ config:
151
+ pages:
152
+ - type: kpis
153
+ metrics: [disk-io, network-read, network-write]
154
+ - position: 2
155
+ type: "system-status:system-status"
156
+ config:
157
+ pages:
158
+ - type: kpis
159
+ metrics: [cpu-boost, cpu-voltages, fan-rpm]
160
+ ```
161
+
162
+ ## See also
163
+
164
+ - [media](../media/README.md) — same addon pattern (no config, polls OS)
165
+ - [brightness](../brightness/README.md) — same polling pattern; brightness is
166
+ just a one-button metric
167
+ - [value-display](../value-display/README.md) — same polling pattern, but
168
+ for built-in OS metrics via shell commands
169
+ - [date-time](../date-time/README.md) — sibling addon for time/date buttons
@@ -0,0 +1,131 @@
1
+ import { useAddonChannel } from "@/api/react"
2
+
3
+ import {
4
+ METRICS_CATALOG,
5
+ SYSTEM_METRIC_IDS,
6
+ type SystemMetricId,
7
+ type SystemMetricSnapshot,
8
+ } from "../shared/metrics-catalog"
9
+
10
+ export interface MetricPayload {
11
+ available: boolean
12
+ value?: number
13
+ percentage?: number
14
+ max?: number
15
+ unit?: string
16
+ }
17
+
18
+ export function readSnapshot(
19
+ payload: MetricPayload | undefined,
20
+ id: SystemMetricId,
21
+ ): SystemMetricSnapshot {
22
+ if (!payload)
23
+ return { available: false, id, label: METRICS_CATALOG[id].defaultLabel }
24
+ return {
25
+ available: payload.available,
26
+ id,
27
+ label: METRICS_CATALOG[id].defaultLabel,
28
+ ...(payload.max !== undefined ? { max: payload.max } : {}),
29
+ ...(payload.percentage !== undefined
30
+ ? { percentage: payload.percentage }
31
+ : {}),
32
+ ...(payload.unit !== undefined ? { unit: payload.unit } : {}),
33
+ ...(payload.value !== undefined ? { value: payload.value } : {}),
34
+ }
35
+ }
36
+
37
+ export function useAllMetricChannels(): Record<
38
+ SystemMetricId,
39
+ MetricPayload | undefined
40
+ > {
41
+ const cpu = useAddonChannel<MetricPayload>("runtime:system-status:cpu")
42
+ const ram = useAddonChannel<MetricPayload>("runtime:system-status:ram")
43
+ const swap = useAddonChannel<MetricPayload>("runtime:system-status:swap")
44
+ const disk = useAddonChannel<MetricPayload>("runtime:system-status:disk")
45
+ const network = useAddonChannel<MetricPayload>(
46
+ "runtime:system-status:network",
47
+ )
48
+ const battery = useAddonChannel<MetricPayload>(
49
+ "runtime:system-status:battery",
50
+ )
51
+ const temperature = useAddonChannel<MetricPayload>(
52
+ "runtime:system-status:temperature",
53
+ )
54
+ const uptime = useAddonChannel<MetricPayload>("runtime:system-status:uptime")
55
+ const frequency = useAddonChannel<MetricPayload>(
56
+ "runtime:system-status:frequency",
57
+ )
58
+ const load = useAddonChannel<MetricPayload>("runtime:system-status:load")
59
+ const processes = useAddonChannel<MetricPayload>(
60
+ "runtime:system-status:processes",
61
+ )
62
+ const cpuBoost = useAddonChannel<MetricPayload>(
63
+ "runtime:system-status:cpu-boost",
64
+ )
65
+ const cpuVoltages = useAddonChannel<MetricPayload>(
66
+ "runtime:system-status:cpu-voltages",
67
+ )
68
+ const diskIo = useAddonChannel<MetricPayload>("runtime:system-status:disk-io")
69
+ const fanRpm = useAddonChannel<MetricPayload>("runtime:system-status:fan-rpm")
70
+ const gpuTemp = useAddonChannel<MetricPayload>(
71
+ "runtime:system-status:gpu-temp",
72
+ )
73
+ const gpuUsage = useAddonChannel<MetricPayload>(
74
+ "runtime:system-status:gpu-usage",
75
+ )
76
+ const networkRead = useAddonChannel<MetricPayload>(
77
+ "runtime:system-status:network-read",
78
+ )
79
+ const networkWrite = useAddonChannel<MetricPayload>(
80
+ "runtime:system-status:network-write",
81
+ )
82
+ return {
83
+ cpu: cpu.data,
84
+ ram: ram.data,
85
+ swap: swap.data,
86
+ disk: disk.data,
87
+ network: network.data,
88
+ battery: battery.data,
89
+ temperature: temperature.data,
90
+ uptime: uptime.data,
91
+ frequency: frequency.data,
92
+ load: load.data,
93
+ processes: processes.data,
94
+ "cpu-boost": cpuBoost.data,
95
+ "cpu-voltages": cpuVoltages.data,
96
+ "disk-io": diskIo.data,
97
+ "fan-rpm": fanRpm.data,
98
+ "gpu-temp": gpuTemp.data,
99
+ "gpu-usage": gpuUsage.data,
100
+ "network-read": networkRead.data,
101
+ "network-write": networkWrite.data,
102
+ }
103
+ }
104
+
105
+ const isMetricId = (id: string): id is SystemMetricId =>
106
+ (SYSTEM_METRIC_IDS as readonly string[]).includes(id)
107
+
108
+ export function resolveMetricId(entry: unknown): SystemMetricId | null {
109
+ if (typeof entry === "string") return isMetricId(entry) ? entry : null
110
+ if (entry && typeof entry === "object" && "id" in entry) {
111
+ const id = (entry as { id: unknown }).id
112
+ if (typeof id === "string" && isMetricId(id)) return id
113
+ }
114
+ return null
115
+ }
116
+
117
+ export function pickLabel(entry: unknown, fallback: string): string {
118
+ if (entry && typeof entry === "object" && "label" in entry) {
119
+ const value = (entry as { label?: unknown }).label
120
+ if (typeof value === "string" && value.length > 0) return value
121
+ }
122
+ return fallback
123
+ }
124
+
125
+ export function pickShortLabel(entry: unknown, fallback: string): string {
126
+ if (entry && typeof entry === "object" && "shortLabel" in entry) {
127
+ const value = (entry as { shortLabel?: unknown }).shortLabel
128
+ if (typeof value === "string" && value.length > 0) return value
129
+ }
130
+ return fallback
131
+ }