rnxsim 0.1.313 → 0.1.314

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 (297) hide show
  1. package/LICENSE +11 -10
  2. package/README.md +5 -0
  3. package/cli/app-config.ts +65 -0
  4. package/cli/app-fonts.ts +408 -0
  5. package/cli/app-project.ts +231 -0
  6. package/cli/app-splash.ts +185 -0
  7. package/cli/app-state-reset.ts +24 -0
  8. package/cli/auth.ts +155 -0
  9. package/cli/bin.ts +594 -0
  10. package/cli/bridge-diagnostics.ts +226 -0
  11. package/cli/bridge-flow-runner.ts +2830 -0
  12. package/cli/browser-evals.ts +96 -0
  13. package/cli/commands/agent-wrapper.ts +986 -0
  14. package/cli/commands/agent.ts +423 -0
  15. package/cli/commands/app-fonts.ts +98 -0
  16. package/cli/commands/assert.ts +541 -0
  17. package/cli/commands/auth.ts +59 -0
  18. package/cli/commands/camera.ts +266 -0
  19. package/cli/commands/cleanup.ts +169 -0
  20. package/cli/commands/compat.ts +87 -0
  21. package/cli/commands/config.ts +32 -0
  22. package/cli/commands/control.ts +2142 -0
  23. package/cli/commands/cpu-profile.ts +269 -0
  24. package/cli/commands/daemon-mac-app.ts +169 -0
  25. package/cli/commands/daemon.ts +874 -0
  26. package/cli/commands/debug.ts +719 -0
  27. package/cli/commands/desktop.ts +39 -0
  28. package/cli/commands/detect.ts +197 -0
  29. package/cli/commands/detox.ts +385 -0
  30. package/cli/commands/device.ts +133 -0
  31. package/cli/commands/diagnose.ts +589 -0
  32. package/cli/commands/electron.ts +95 -0
  33. package/cli/commands/film.ts +379 -0
  34. package/cli/commands/flow.ts +1124 -0
  35. package/cli/commands/inspect/actions.ts +622 -0
  36. package/cli/commands/inspect/core.ts +2405 -0
  37. package/cli/commands/inspect/count.ts +17 -0
  38. package/cli/commands/inspect/describe.ts +192 -0
  39. package/cli/commands/inspect/env.ts +23 -0
  40. package/cli/commands/inspect/find.ts +171 -0
  41. package/cli/commands/inspect/get-layout.ts +39 -0
  42. package/cli/commands/inspect/keyboard.ts +52 -0
  43. package/cli/commands/inspect/list.ts +58 -0
  44. package/cli/commands/inspect/memory.ts +215 -0
  45. package/cli/commands/inspect/redaction.ts +39 -0
  46. package/cli/commands/inspect/resolve-target.ts +82 -0
  47. package/cli/commands/inspect/screens.ts +78 -0
  48. package/cli/commands/inspect/settle.ts +22 -0
  49. package/cli/commands/inspect/settling.ts +158 -0
  50. package/cli/commands/inspect/shared.ts +353 -0
  51. package/cli/commands/inspect/sleep.ts +14 -0
  52. package/cli/commands/inspect/tree.ts +32 -0
  53. package/cli/commands/inspect/url.ts +17 -0
  54. package/cli/commands/inspect/wait-event.ts +210 -0
  55. package/cli/commands/inspect/wait-idle.ts +24 -0
  56. package/cli/commands/inspect/wait-ready.ts +74 -0
  57. package/cli/commands/inspect/wait-selector.ts +54 -0
  58. package/cli/commands/inspect/wait.ts +31 -0
  59. package/cli/commands/inspect.ts +4519 -0
  60. package/cli/commands/install-desktop.ts +351 -0
  61. package/cli/commands/login.ts +331 -0
  62. package/cli/commands/logout.ts +31 -0
  63. package/cli/commands/maestro-generate.ts +361 -0
  64. package/cli/commands/maestro.ts +453 -0
  65. package/cli/commands/mode.ts +57 -0
  66. package/cli/commands/no-bridge-hint.ts +80 -0
  67. package/cli/commands/perf.ts +66 -0
  68. package/cli/commands/permissions.ts +203 -0
  69. package/cli/commands/profile.ts +108 -0
  70. package/cli/commands/react.ts +353 -0
  71. package/cli/commands/record.ts +1434 -0
  72. package/cli/commands/report-issue.ts +305 -0
  73. package/cli/commands/reset.ts +85 -0
  74. package/cli/commands/runtime.ts +351 -0
  75. package/cli/commands/screenshot-command.ts +106 -0
  76. package/cli/commands/screenshot-layers.ts +143 -0
  77. package/cli/commands/screenshot-mode.ts +37 -0
  78. package/cli/commands/screenshot.ts +488 -0
  79. package/cli/commands/screenshots-capture.ts +607 -0
  80. package/cli/commands/screenshots.ts +127 -0
  81. package/cli/commands/serve.ts +168 -0
  82. package/cli/commands/setup.ts +545 -0
  83. package/cli/commands/shell-boolean-mode.ts +81 -0
  84. package/cli/commands/skills.ts +467 -0
  85. package/cli/commands/slides.ts +361 -0
  86. package/cli/commands/state.ts +87 -0
  87. package/cli/commands/storage.ts +58 -0
  88. package/cli/commands/telemetry.ts +54 -0
  89. package/cli/commands/three-mode.ts +763 -0
  90. package/cli/commands/timeline.ts +122 -0
  91. package/cli/commands/upgrade.ts +208 -0
  92. package/cli/commands/upload.ts +1225 -0
  93. package/cli/commands/version.ts +54 -0
  94. package/cli/commands/what-happened.ts +327 -0
  95. package/cli/current-sim.ts +204 -0
  96. package/cli/desktop-companion.ts +300 -0
  97. package/cli/drivers/electron.ts +70 -0
  98. package/cli/drivers/index.ts +20 -0
  99. package/cli/drivers/playwright-provisioning.ts +180 -0
  100. package/cli/drivers/playwright.ts +698 -0
  101. package/cli/drivers/registry.ts +65 -0
  102. package/cli/drivers/types.ts +102 -0
  103. package/cli/flow-file.ts +142 -0
  104. package/cli/flow-live-status.ts +120 -0
  105. package/cli/flow-session.ts +187 -0
  106. package/cli/help.ts +80 -0
  107. package/cli/hidden-runtime-alias.ts +19 -0
  108. package/cli/hints.ts +216 -0
  109. package/cli/inspect-notice-state.ts +114 -0
  110. package/cli/maestro-js.ts +334 -0
  111. package/cli/open-url.ts +8 -0
  112. package/cli/parent-pid.ts +204 -0
  113. package/cli/parse-args.ts +211 -0
  114. package/cli/prompt.ts +51 -0
  115. package/cli/recording-access.ts +107 -0
  116. package/cli/registry.ts +1 -0
  117. package/cli/resolve-assets.ts +63 -0
  118. package/cli/run-registry.ts +226 -0
  119. package/cli/runtime-notes.ts +66 -0
  120. package/cli/runtime-summary.ts +25 -0
  121. package/cli/setup-repository.ts +187 -0
  122. package/cli/telemetry.ts +187 -0
  123. package/cli/ws-bridge.ts +798 -0
  124. package/dist-cli/bin.js +5 -5
  125. package/dist-cli/chunks/{agent-XZ2KTPCU.js → agent-7YBDCYMA.js} +2 -2
  126. package/dist-cli/chunks/{agent-wrapper-JJYYW2WH.js → agent-wrapper-2GHFBHCR.js} +2 -2
  127. package/dist-cli/chunks/{app-fonts-IXRNQG6B.js → app-fonts-RSNVPQSU.js} +2 -2
  128. package/dist-cli/chunks/{assert-54T5SK5F.js → assert-XCMX3XJX.js} +2 -2
  129. package/dist-cli/chunks/{auth-FI5UDI45.js → auth-B442HRAX.js} +2 -2
  130. package/dist-cli/chunks/{beta-JV6UKADW.js → beta-XJ55JK3M.js} +2 -2
  131. package/dist-cli/chunks/camera-UGYSSLIK.js +33 -0
  132. package/dist-cli/chunks/{chunk-3NV2NCNX.js → chunk-277AEQZX.js} +2 -2
  133. package/dist-cli/chunks/{chunk-2YR5BGA5.js → chunk-2JNSK774.js} +2 -2
  134. package/dist-cli/chunks/{chunk-RSZWCKNT.js → chunk-32WOTSTR.js} +3 -3
  135. package/dist-cli/chunks/{chunk-WEXDAC74.js → chunk-3S753SNQ.js} +2 -2
  136. package/dist-cli/chunks/{chunk-IJO63TDP.js → chunk-46ZOLOYA.js} +2 -2
  137. package/dist-cli/chunks/{chunk-WUSWBCWA.js → chunk-5L7ELDQL.js} +8 -9
  138. package/dist-cli/chunks/{chunk-WF3T4SVI.js → chunk-7OOPFSQS.js} +2 -2
  139. package/dist-cli/chunks/{chunk-TZFFR3SD.js → chunk-7SV3RPRW.js} +2 -2
  140. package/dist-cli/chunks/{chunk-WWZIXIRD.js → chunk-7ZC35MOU.js} +1 -1
  141. package/dist-cli/chunks/chunk-AMG5E6CC.js +9 -0
  142. package/dist-cli/chunks/{chunk-WINYQ44O.js → chunk-APWNH3A4.js} +1 -1
  143. package/dist-cli/chunks/chunk-B57XUKY3.js +4 -0
  144. package/dist-cli/chunks/{chunk-YDGQTMQL.js → chunk-C2NL26TD.js} +1 -1
  145. package/dist-cli/chunks/{chunk-NMF2ZMZQ.js → chunk-D2FNUWAB.js} +4 -4
  146. package/dist-cli/chunks/{chunk-YIFT42WN.js → chunk-E5T4XSJ3.js} +2 -2
  147. package/dist-cli/chunks/{chunk-46EUUFJ5.js → chunk-EAC34EQS.js} +1 -1
  148. package/dist-cli/chunks/{chunk-OVFJFXUD.js → chunk-EG32ML36.js} +2 -2
  149. package/dist-cli/chunks/{chunk-5YJCOWCH.js → chunk-FXUAC6D5.js} +1 -1
  150. package/dist-cli/chunks/chunk-GQSL4USA.js +6 -0
  151. package/dist-cli/chunks/{chunk-VFCMSYZK.js → chunk-HAXW27SS.js} +2 -2
  152. package/dist-cli/chunks/{chunk-2D2UPBBR.js → chunk-IZAHPAN6.js} +1 -1
  153. package/dist-cli/chunks/{chunk-7GN3LVWB.js → chunk-J62KM5TB.js} +2 -2
  154. package/dist-cli/chunks/{chunk-BTWORNNG.js → chunk-JEMCD5E4.js} +1 -1
  155. package/dist-cli/chunks/{chunk-DCEMHR2Y.js → chunk-JZS3Q37N.js} +2 -2
  156. package/dist-cli/chunks/{chunk-D4FFVGI5.js → chunk-KR4JON7D.js} +1 -1
  157. package/dist-cli/chunks/chunk-KWCYKQIQ.js +4 -0
  158. package/dist-cli/chunks/{chunk-VNQEB4L7.js → chunk-MCWPL644.js} +2 -2
  159. package/dist-cli/chunks/chunk-MJYK3N2I.js +4 -0
  160. package/dist-cli/chunks/{chunk-5TEF3ET3.js → chunk-O6TRIZNS.js} +2 -2
  161. package/dist-cli/chunks/{chunk-QKDWYITG.js → chunk-P7XL2E73.js} +3 -3
  162. package/dist-cli/chunks/{chunk-BBULZ7CG.js → chunk-PFQTUKQ4.js} +62 -87
  163. package/dist-cli/chunks/{chunk-GGRX24GF.js → chunk-PG5RZCTN.js} +2 -2
  164. package/dist-cli/chunks/{chunk-W6K4EFPH.js → chunk-QGRI2Z4M.js} +2 -2
  165. package/dist-cli/chunks/{chunk-ZMJD5GEC.js → chunk-QLXXE7GE.js} +1 -1
  166. package/dist-cli/chunks/{chunk-VZXWHRUZ.js → chunk-QOJJJWJE.js} +89 -133
  167. package/dist-cli/chunks/{chunk-OZSSI4WN.js → chunk-RWZY5427.js} +2 -2
  168. package/dist-cli/chunks/{chunk-UC6U3MML.js → chunk-RZKU2K3J.js} +2 -2
  169. package/dist-cli/chunks/{chunk-IJ5CAZZC.js → chunk-SBV4IK4H.js} +1 -1
  170. package/dist-cli/chunks/{chunk-DZS6WPUI.js → chunk-SGMVFFMK.js} +1 -1
  171. package/dist-cli/chunks/{chunk-OHAZNXLK.js → chunk-TAX4UT2N.js} +1 -1
  172. package/dist-cli/chunks/{chunk-5DHC6KHQ.js → chunk-TUOFAWXT.js} +1 -1
  173. package/dist-cli/chunks/{chunk-GASE6UBA.js → chunk-UHZLOHGP.js} +1 -1
  174. package/dist-cli/chunks/{chunk-F5ZRSS3C.js → chunk-VC7V76U3.js} +1 -1
  175. package/dist-cli/chunks/{chunk-RTN5C5RL.js → chunk-VQVMLW4U.js} +1 -1
  176. package/dist-cli/chunks/{chunk-WMIIKMGK.js → chunk-VUKKYPZN.js} +2 -2
  177. package/dist-cli/chunks/{chunk-5TPRP5QT.js → chunk-WGGRJDRE.js} +1 -1
  178. package/dist-cli/chunks/chunk-X6H76EKP.js +15 -0
  179. package/dist-cli/chunks/chunk-XLZ5FNRT.js +27 -0
  180. package/dist-cli/chunks/{chunk-HI5TFJWN.js → chunk-XULEACM4.js} +2 -2
  181. package/dist-cli/chunks/{chunk-MJRLLB4R.js → chunk-YFSDM7AX.js} +4 -4
  182. package/dist-cli/chunks/chunk-YWI3UEVX.js +5 -0
  183. package/dist-cli/chunks/{chunk-XEVZYVIW.js → chunk-ZBSJO4NB.js} +10 -9
  184. package/dist-cli/chunks/{cleanup-P27PA6JI.js → cleanup-EYLGCA6Z.js} +2 -2
  185. package/dist-cli/chunks/cli-version-LL2UGIHE.js +4 -0
  186. package/dist-cli/chunks/{compat-ZD65FED3.js → compat-TLJYHB4E.js} +2 -2
  187. package/dist-cli/chunks/{config-XMJRNM2A.js → config-4JWUOEXK.js} +2 -2
  188. package/dist-cli/chunks/{control-KMIQT3QP.js → control-HPAOYF4N.js} +2 -2
  189. package/dist-cli/chunks/daemon-OYLASXLE.js +4 -0
  190. package/dist-cli/chunks/{debug-PT4HOP7N.js → debug-4BKXF6KI.js} +5 -5
  191. package/dist-cli/chunks/{desktop-S3FG72AK.js → desktop-ZQ6ZD2S6.js} +3 -3
  192. package/dist-cli/chunks/{detox-B3D4IFCN.js → detox-WNPASSS3.js} +2 -2
  193. package/dist-cli/chunks/{device-XBNDSB2R.js → device-BXLXVG3V.js} +2 -2
  194. package/dist-cli/chunks/{diagnose-HMQXJE5N.js → diagnose-3QX7W5RW.js} +2 -2
  195. package/dist-cli/chunks/{disk-cleanup-BLCZ5BSZ.js → disk-cleanup-KSWKI7WB.js} +2 -2
  196. package/dist-cli/chunks/drivers-EPIEFF7P.js +4 -0
  197. package/dist-cli/chunks/{film-BJGTBYZB.js → film-GDMR33VO.js} +3 -3
  198. package/dist-cli/chunks/flow-NKMPBYCJ.js +4 -0
  199. package/dist-cli/chunks/help-OGCBHOKA.js +4 -0
  200. package/dist-cli/chunks/{hidden-runtime-alias-ANOYADHM.js → hidden-runtime-alias-S2GTDX3T.js} +2 -2
  201. package/dist-cli/chunks/home-paths-QRCDLTTV.js +4 -0
  202. package/dist-cli/chunks/inspect-FUYMOZPY.js +4 -0
  203. package/dist-cli/chunks/install-desktop-FR6YKW7Y.js +4 -0
  204. package/dist-cli/chunks/{login-FJ737MWG.js → login-IJAPUZHI.js} +4 -4
  205. package/dist-cli/chunks/{logout-ZCNMMHMY.js → logout-QMXDFU2X.js} +2 -2
  206. package/dist-cli/chunks/{maestro-SZTNKLDF.js → maestro-ZXU3YCVX.js} +3 -3
  207. package/dist-cli/chunks/{maestro-generate-DCFAIZ4H.js → maestro-generate-PYB5QY7K.js} +3 -3
  208. package/dist-cli/chunks/{mode-GRMQCRXR.js → mode-WGUCL5FZ.js} +2 -2
  209. package/dist-cli/chunks/{optional-demo-registry-W36EWFFB.js → optional-demo-registry-WH2O6H36.js} +2 -2
  210. package/dist-cli/chunks/{perf-QYBAAUZG.js → perf-TOD3UFAH.js} +2 -2
  211. package/dist-cli/chunks/{permissions-3QCQ6VF4.js → permissions-I5BRJGTB.js} +2 -2
  212. package/dist-cli/chunks/{record-QPPC2S4E.js → record-ZYL2FYSK.js} +3 -3
  213. package/dist-cli/chunks/{report-issue-7NMFP4HK.js → report-issue-TAI6DYZO.js} +2 -2
  214. package/dist-cli/chunks/reset-7YGYKQPQ.js +4 -0
  215. package/dist-cli/chunks/runtime-B4JO6QRI.js +4 -0
  216. package/dist-cli/chunks/{screenshot-command-67AECJFB.js → screenshot-command-7ANLODZY.js} +7 -7
  217. package/dist-cli/chunks/{screenshot-layers-ASWBYPJL.js → screenshot-layers-A7FYXSVU.js} +3 -3
  218. package/dist-cli/chunks/{screenshots-capture-PXA3HFQK.js → screenshots-capture-WT2ZY6CB.js} +2 -2
  219. package/dist-cli/chunks/serve-TG5WKA4V.js +44 -0
  220. package/dist-cli/chunks/{setup-7DWPMRSB.js → setup-PCWLD22V.js} +2 -2
  221. package/dist-cli/chunks/{skills-S3Y22TUA.js → skills-27ZHWCQS.js} +2 -2
  222. package/dist-cli/chunks/state-ZQVY46ZO.js +14 -0
  223. package/dist-cli/chunks/{storage-XUIMJWAJ.js → storage-OYC57C4X.js} +6 -6
  224. package/dist-cli/chunks/store-32HSPZHI.js +4 -0
  225. package/dist-cli/chunks/telemetry-PBJR7XHR.js +4 -0
  226. package/dist-cli/chunks/{timeline-TMPLQPSP.js → timeline-RAJJFQT6.js} +2 -2
  227. package/dist-cli/chunks/{upgrade-7HDSIM7K.js → upgrade-OEFNZRIP.js} +2 -2
  228. package/dist-cli/chunks/upload-LQJITLKK.js +4 -0
  229. package/dist-cli/chunks/version-NIXTY6PL.js +6 -0
  230. package/dist-cli/chunks/{web-DG3WBYD3.js → web-XBUTBVGR.js} +2 -2
  231. package/dist-cli/chunks/{what-happened-XFVUTZR7.js → what-happened-YNHRFUDX.js} +3 -3
  232. package/dist-lib/agent-daemon-client.cjs +1 -1
  233. package/dist-lib/agent-events.cjs +1 -1
  234. package/dist-lib/agent-identity.cjs +1 -1
  235. package/dist-lib/agent-sessions.cjs +1 -1
  236. package/dist-lib/attached-projects.cjs +1 -1
  237. package/dist-lib/auth/shared-session.cjs +1 -1
  238. package/dist-lib/backend-origin.cjs +1 -1
  239. package/dist-lib/beta.cjs +1 -1
  240. package/dist-lib/beta.mjs +1 -1
  241. package/dist-lib/bridge-constants.cjs +1 -1
  242. package/dist-lib/bridge-contract.cjs +20 -0
  243. package/dist-lib/cli-constants.cjs +1 -1
  244. package/dist-lib/config.cjs +1 -1
  245. package/dist-lib/detox/index.cjs +1 -1
  246. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  247. package/dist-lib/home-paths.cjs +67 -28
  248. package/dist-lib/host/bridge-host.cjs +140 -12
  249. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  250. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  251. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  252. package/dist-lib/host/websocket-proxy.cjs +1 -1
  253. package/dist-lib/index.cjs +2815 -40
  254. package/dist-lib/jump-to-source-babel.cjs +1 -1
  255. package/dist-lib/menu.cjs +1 -1
  256. package/dist-lib/menu.mjs +1 -1
  257. package/dist-lib/metro.cjs +1 -1
  258. package/dist-lib/profiles.cjs +1 -1
  259. package/dist-lib/public-brand.cjs +1 -1
  260. package/dist-lib/render-mode.cjs +1 -1
  261. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  262. package/dist-lib/sdk.cjs +2549 -2061
  263. package/dist-lib/sdk.mjs +2543 -2061
  264. package/dist-lib/skills.cjs +480 -280
  265. package/dist-lib/vite.cjs +1 -1
  266. package/package.json +8 -2
  267. package/src/bridge-constants.ts +3 -4
  268. package/src/bridge-contract.ts +251 -0
  269. package/src/connect.ts +83 -0
  270. package/src/disk-cleanup.ts +30 -0
  271. package/src/home-paths.ts +81 -38
  272. package/src/host/bridge-host.ts +134 -6
  273. package/src/index.ts +27 -1
  274. package/src/sdk.ts +8 -0
  275. package/src/sim-client.ts +660 -0
  276. package/dist-cli/chunks/camera-VL73YIKP.js +0 -22
  277. package/dist-cli/chunks/chunk-4NPPOV2N.js +0 -5
  278. package/dist-cli/chunks/chunk-FSUYIVJ6.js +0 -9
  279. package/dist-cli/chunks/chunk-G2WW6L2C.js +0 -23
  280. package/dist-cli/chunks/chunk-KTHV3RUS.js +0 -26
  281. package/dist-cli/chunks/chunk-LF2ZVT7O.js +0 -6
  282. package/dist-cli/chunks/chunk-NFK7T35W.js +0 -4
  283. package/dist-cli/chunks/chunk-TIVZIMMW.js +0 -4
  284. package/dist-cli/chunks/cli-version-WWLPBDQ7.js +0 -4
  285. package/dist-cli/chunks/daemon-G2ME7NLB.js +0 -4
  286. package/dist-cli/chunks/drivers-LDECZGP2.js +0 -4
  287. package/dist-cli/chunks/flow-UEQNVTU7.js +0 -4
  288. package/dist-cli/chunks/help-T5FYSVGB.js +0 -4
  289. package/dist-cli/chunks/home-paths-GT3LFNOR.js +0 -4
  290. package/dist-cli/chunks/inspect-ZA6XF5LD.js +0 -4
  291. package/dist-cli/chunks/install-desktop-TIMUDHPL.js +0 -4
  292. package/dist-cli/chunks/runtime-XOAXMSTU.js +0 -4
  293. package/dist-cli/chunks/serve-BI2NBAXG.js +0 -44
  294. package/dist-cli/chunks/store-JTHEJLAZ.js +0 -4
  295. package/dist-cli/chunks/telemetry-ZYJGD2DB.js +0 -4
  296. package/dist-cli/chunks/upload-GMSZPWM6.js +0 -4
  297. package/dist-cli/chunks/version-HOCHZ37L.js +0 -6
@@ -0,0 +1,467 @@
1
+ // sootsim skill - install and inspect agent skill files
2
+ //
3
+ // usage:
4
+ // sootsim skill install install all skills to supported agents
5
+ // sootsim skill install codex debug install specific skills to Codex only
6
+ // sootsim skill show [name] list skills or print one skill
7
+
8
+ import * as fs from 'fs'
9
+ import * as os from 'os'
10
+ import * as path from 'path'
11
+ import { fileURLToPath } from 'url'
12
+ import { rnxPublicBrand } from '../../src/public-brand'
13
+
14
+ function getSkillsDir(): string {
15
+ try {
16
+ const pkgPath = fileURLToPath(
17
+ import.meta.resolve(`${rnxPublicBrand.packageName}/package.json`),
18
+ )
19
+ return path.join(path.dirname(pkgPath), 'skills')
20
+ } catch {
21
+ const __dirname = path.dirname(fileURLToPath(import.meta.url))
22
+ return path.resolve(__dirname, '../../skills')
23
+ }
24
+ }
25
+
26
+ const SKILLS_DIR = getSkillsDir()
27
+ const AGENT_TARGET_IDS = new Set(['all', 'codex', 'claude'])
28
+
29
+ interface SkillInfo {
30
+ name: string
31
+ description: string
32
+ }
33
+
34
+ interface InstallTarget {
35
+ label: string
36
+ dir: string
37
+ }
38
+
39
+ function printSkillHelp() {
40
+ console.log(`rnxsim skill
41
+
42
+ install and inspect bundled rnx agent skills.
43
+
44
+ usage:
45
+ rnxsim skill install [all|codex|claude] [skill-name...]
46
+ rnxsim skill install --target <dir> [skill-name...]
47
+ rnxsim skill show [skill-name]
48
+
49
+ commands:
50
+ install install skills; no target means all supported local agents
51
+ show list bundled skills, or print one skill markdown
52
+
53
+ targets:
54
+ all Codex and Claude Code (default)
55
+ codex $CODEX_HOME/skills, or ~/.codex/skills
56
+ claude $CLAUDE_CONFIG_DIR/skills, or ~/.claude/skills
57
+ `)
58
+ }
59
+
60
+ function printInstallHelp() {
61
+ console.log(`rnxsim skill install
62
+
63
+ install bundled rnx skills in the agent skill layout: <skill>/SKILL.md.
64
+ each skill directory is symlinked back to its source, so edits stay live
65
+ without a re-install. an existing install from an older CLI is upgraded in
66
+ place; an unrelated skill directory is left alone unless --force is passed.
67
+
68
+ usage:
69
+ rnxsim skill install [all|codex|claude] [skill-name...]
70
+ rnxsim skill install --target <dir> [skill-name...]
71
+
72
+ options:
73
+ --force, -f replace a conflicting existing skill with the symlink
74
+
75
+ examples:
76
+ rnxsim skill install
77
+ rnxsim skill install codex
78
+ rnxsim skill install codex rnx-debug
79
+ rnxsim skill install --force rnx-debug
80
+ `)
81
+ }
82
+
83
+ function targetFromHome(envName: string, fallbackDir: string): string {
84
+ const home = process.env[envName] || path.join(os.homedir(), fallbackDir)
85
+ return path.join(home, 'skills')
86
+ }
87
+
88
+ function defaultAgentTargets(): InstallTarget[] {
89
+ return [
90
+ { label: 'codex', dir: targetFromHome('CODEX_HOME', '.codex') },
91
+ { label: 'claude', dir: targetFromHome('CLAUDE_CONFIG_DIR', '.claude') },
92
+ ]
93
+ }
94
+
95
+ function agentTarget(target: string): InstallTarget[] {
96
+ if (target === 'all') return defaultAgentTargets()
97
+ if (target === 'codex') {
98
+ return [{ label: 'codex', dir: targetFromHome('CODEX_HOME', '.codex') }]
99
+ }
100
+ if (target === 'claude') {
101
+ return [{ label: 'claude', dir: targetFromHome('CLAUDE_CONFIG_DIR', '.claude') }]
102
+ }
103
+ console.error(` unknown skill install target: ${target}`)
104
+ console.error(' expected all, codex, or claude')
105
+ process.exit(1)
106
+ }
107
+
108
+ function parseSkillFrontmatter(
109
+ content: string,
110
+ ): { name: string; description: string } | null {
111
+ const match = content.match(/^---\n([\s\S]*?)\n---/)
112
+ if (!match) return null
113
+ const frontmatter = match[1]
114
+ const name = readFrontmatterField(frontmatter, 'name')
115
+ if (!name) return null
116
+ return {
117
+ name,
118
+ description: readFrontmatterField(frontmatter, 'description') || '',
119
+ }
120
+ }
121
+
122
+ function readFrontmatterField(frontmatter: string, field: string): string | null {
123
+ const lines = frontmatter.split('\n')
124
+ const prefix = `${field}:`
125
+ for (let index = 0; index < lines.length; index++) {
126
+ const line = lines[index]
127
+ if (!line.startsWith(prefix)) continue
128
+
129
+ const rawValue = line.slice(prefix.length).trim()
130
+ if (rawValue === '>-' || rawValue === '>' || rawValue === '|-' || rawValue === '|') {
131
+ const blockLines: string[] = []
132
+ for (let blockIndex = index + 1; blockIndex < lines.length; blockIndex++) {
133
+ const blockLine = lines[blockIndex]
134
+ if (/^[A-Za-z0-9_-]+:\s*/.test(blockLine)) break
135
+ if (blockLine.trim() === '') {
136
+ blockLines.push('')
137
+ continue
138
+ }
139
+ if (!/^\s+/.test(blockLine)) break
140
+ blockLines.push(blockLine.trim())
141
+ }
142
+ return blockLines.join(rawValue.startsWith('|') ? '\n' : ' ').trim()
143
+ }
144
+
145
+ if (
146
+ (rawValue.startsWith('"') && rawValue.endsWith('"')) ||
147
+ (rawValue.startsWith("'") && rawValue.endsWith("'"))
148
+ ) {
149
+ return rawValue.slice(1, -1)
150
+ }
151
+ return rawValue
152
+ }
153
+ return null
154
+ }
155
+
156
+ // bundled skills live in the standard agent layout: skills/<name>/SKILL.md.
157
+ // the directory name is the skill name; frontmatter is the display metadata.
158
+ function listSkills(): SkillInfo[] {
159
+ if (!fs.existsSync(SKILLS_DIR)) return []
160
+ const skills: SkillInfo[] = []
161
+ for (const entry of fs.readdirSync(SKILLS_DIR)) {
162
+ const skillMd = path.join(SKILLS_DIR, entry, 'SKILL.md')
163
+ if (!fs.existsSync(skillMd)) continue
164
+ const meta = parseSkillFrontmatter(fs.readFileSync(skillMd, 'utf8'))
165
+ if (meta) {
166
+ skills.push({ name: entry, description: meta.description })
167
+ }
168
+ }
169
+ return skills.sort((a, b) => a.name.localeCompare(b.name))
170
+ }
171
+
172
+ function matchSkills(skills: SkillInfo[], filters: string[]): SkillInfo[] {
173
+ if (filters.length === 0) return skills
174
+ const matched = skills.filter((skill) =>
175
+ filters.some((filter) => {
176
+ const needle = filter.replace(/^sootsim-/, '').replace(/^rnx-/, '')
177
+ return (
178
+ skill.name.includes(filter) || skill.name.replace(/^rnx-/, '').includes(needle)
179
+ )
180
+ }),
181
+ )
182
+ if (matched.length === 0) {
183
+ console.error(` no skills matched: ${filters.join(', ')}`)
184
+ console.error(' available: ' + skills.map((skill) => skill.name).join(', '))
185
+ process.exit(1)
186
+ }
187
+ return matched
188
+ }
189
+
190
+ // install is a SYMLINK of the whole skill DIRECTORY from the agent store back
191
+ // to the source, not a copy, so editing the source skill is live everywhere
192
+ // without re-installing. the directory (not the SKILL.md file) is linked
193
+ // because Codex's skill discovery follows directory symlinks but silently
194
+ // skips a SKILL.md that is itself a file symlink. conflict-safe: skip if
195
+ // already linked to source, upgrade an install from an older CLI (or anything
196
+ // under --force), otherwise refuse so we never clobber a skill the user owns.
197
+ type LinkResult = 'up-to-date' | 'linked' | 'replaced' | 'conflict'
198
+
199
+ function lstatOrNull(p: string): fs.Stats | null {
200
+ try {
201
+ return fs.lstatSync(p)
202
+ } catch {
203
+ return null
204
+ }
205
+ }
206
+
207
+ function symlinkPointsTo(dest: string, src: string): boolean {
208
+ const stat = lstatOrNull(dest)
209
+ if (!stat || !stat.isSymbolicLink()) return false
210
+ try {
211
+ return fs.realpathSync(dest) === fs.realpathSync(src)
212
+ } catch {
213
+ return false
214
+ }
215
+ }
216
+
217
+ // a store entry left by an older CLI is safe to upgrade: either a real dir
218
+ // whose only content is a SKILL.md symlink into a sootsim skills source (the
219
+ // pre-dir-layout install — possibly broken after the source moved), or a dir
220
+ // holding a byte-identical copy of the skill. only our installer creates
221
+ // those shapes, so replacing them can't lose user work.
222
+ function isOwnLegacyInstall(stat: fs.Stats, dest: string, srcDir: string): boolean {
223
+ if (stat.isSymbolicLink() || !stat.isDirectory()) return false
224
+ let entries: string[]
225
+ try {
226
+ entries = fs.readdirSync(dest)
227
+ } catch {
228
+ return false
229
+ }
230
+ if (entries.length !== 1 || entries[0] !== 'SKILL.md') return false
231
+ const skillMd = path.join(dest, 'SKILL.md')
232
+ const mdStat = lstatOrNull(skillMd)
233
+ if (!mdStat) return false
234
+ if (mdStat.isSymbolicLink()) {
235
+ try {
236
+ return fs.readlinkSync(skillMd).includes(`${path.sep}skills${path.sep}`)
237
+ } catch {
238
+ return false
239
+ }
240
+ }
241
+ if (!mdStat.isFile()) return false
242
+ try {
243
+ return fs.readFileSync(skillMd).equals(fs.readFileSync(path.join(srcDir, 'SKILL.md')))
244
+ } catch {
245
+ return false
246
+ }
247
+ }
248
+
249
+ function linkSkill(skill: SkillInfo, targetDir: string, force: boolean): LinkResult {
250
+ const src = path.join(SKILLS_DIR, skill.name)
251
+ const dest = path.join(targetDir, skill.name)
252
+ fs.mkdirSync(targetDir, { recursive: true })
253
+
254
+ const existing = lstatOrNull(dest)
255
+ if (!existing) {
256
+ fs.symlinkSync(src, dest)
257
+ return 'linked'
258
+ }
259
+ if (symlinkPointsTo(dest, src)) {
260
+ return 'up-to-date'
261
+ }
262
+ if (force || isOwnLegacyInstall(existing, dest, src)) {
263
+ fs.rmSync(dest, { recursive: true, force: true })
264
+ fs.symlinkSync(src, dest)
265
+ return 'replaced'
266
+ }
267
+ return 'conflict'
268
+ }
269
+
270
+ // quiet, conflict-safe (re)install of all bundled skills into the agent stores
271
+ // that already exist on this machine. wired into the CLI build so building or
272
+ // updating the CLI re-establishes the symlinks idempotently — never forces, so
273
+ // it can't clobber a skill the user customized, and never creates a store for
274
+ // an agent that isn't set up here. silent on success.
275
+ export function refreshInstalledSkills() {
276
+ const skills = listSkills()
277
+ if (skills.length === 0) return
278
+ for (const target of defaultAgentTargets()) {
279
+ const skillsDir = path.resolve(target.dir)
280
+ // only touch agents already present (~/.claude, ~/.codex) — don't seed a
281
+ // store on a CI runner or a machine that doesn't use that agent.
282
+ if (!fs.existsSync(path.dirname(skillsDir))) continue
283
+ try {
284
+ fs.mkdirSync(skillsDir, { recursive: true })
285
+ } catch {
286
+ continue
287
+ }
288
+ try {
289
+ removeLegacyBundledSkills(skillsDir)
290
+ } catch {}
291
+ for (const skill of skills) {
292
+ try {
293
+ linkSkill(skill, skillsDir, false)
294
+ } catch {
295
+ // best-effort: a single bad store must not fail the build
296
+ }
297
+ }
298
+ }
299
+ }
300
+
301
+ const LEGACY_BUNDLED_SKILL_DIRS = [
302
+ 'sootsim-setup',
303
+ 'sootsim-debug',
304
+ 'sootsim-perf',
305
+ 'sootsim-test',
306
+ 'sootsim-visual',
307
+ ]
308
+
309
+ function removeLegacyBundledSkills(targetDir: string) {
310
+ for (const name of LEGACY_BUNDLED_SKILL_DIRS) {
311
+ const dest = path.join(targetDir, name)
312
+ const stat = lstatOrNull(dest)
313
+ if (!stat) continue
314
+ if (
315
+ stat.isSymbolicLink() ||
316
+ isOwnLegacyInstall(stat, dest, path.join(SKILLS_DIR, name))
317
+ ) {
318
+ fs.rmSync(dest, { recursive: true, force: true })
319
+ }
320
+ }
321
+ }
322
+
323
+ function printSkillList(skills: SkillInfo[]) {
324
+ if (skills.length === 0) {
325
+ console.log(' no skills found')
326
+ return
327
+ }
328
+ console.log('\n available skills:\n')
329
+ for (const skill of skills) {
330
+ console.log(` ${skill.name}`)
331
+ console.log(` ${skill.description}\n`)
332
+ }
333
+ console.log(' usage: rnxsim skill install [all|codex|claude] [skill-name...]')
334
+ console.log(' usage: rnxsim skill show [skill-name]\n')
335
+ }
336
+
337
+ function parseInstallArgs(args: string[]): {
338
+ targets: InstallTarget[]
339
+ filters: string[]
340
+ force: boolean
341
+ } {
342
+ let targets: InstallTarget[] | null = null
343
+ let force = false
344
+ const filters: string[] = []
345
+
346
+ for (let index = 0; index < args.length; index++) {
347
+ const arg = args[index]
348
+ if (arg === '--help' || arg === '-h') {
349
+ printInstallHelp()
350
+ process.exit(0)
351
+ }
352
+ if (arg === '--force' || arg === '-f') {
353
+ force = true
354
+ continue
355
+ }
356
+ if (arg === '--target') {
357
+ const dir = args[index + 1]
358
+ if (!dir || dir.startsWith('-')) {
359
+ console.error(' --target requires a directory')
360
+ process.exit(1)
361
+ }
362
+ if (targets) {
363
+ console.error(' pass only one install target')
364
+ process.exit(1)
365
+ }
366
+ targets = [{ label: 'target', dir }]
367
+ index++
368
+ continue
369
+ }
370
+ if (arg.startsWith('-')) {
371
+ console.error(` unknown option: ${arg}`)
372
+ printInstallHelp()
373
+ process.exit(1)
374
+ }
375
+ if (!targets && AGENT_TARGET_IDS.has(arg)) {
376
+ targets = agentTarget(arg)
377
+ continue
378
+ }
379
+ filters.push(arg)
380
+ }
381
+
382
+ return { targets: targets ?? defaultAgentTargets(), filters, force }
383
+ }
384
+
385
+ async function runInstall(args: string[]) {
386
+ const skills = listSkills()
387
+ if (skills.length === 0) {
388
+ console.error(' no skills found in rnxsim package')
389
+ process.exit(1)
390
+ }
391
+
392
+ const parsed = parseInstallArgs(args)
393
+ const toInstall = matchSkills(skills, parsed.filters)
394
+ const resolvedTargets = parsed.targets.map((target) => ({
395
+ ...target,
396
+ dir: path.resolve(target.dir),
397
+ }))
398
+ for (const target of resolvedTargets) {
399
+ fs.mkdirSync(target.dir, { recursive: true })
400
+ if (!fs.statSync(target.dir).isDirectory()) {
401
+ console.error(` target is not a directory: ${target.dir}`)
402
+ process.exit(1)
403
+ }
404
+ removeLegacyBundledSkills(target.dir)
405
+ }
406
+
407
+ console.log(
408
+ `\n installing ${toInstall.length} skill(s) to ${resolvedTargets.length} target(s)\n`,
409
+ )
410
+ let conflicts = 0
411
+ for (const target of resolvedTargets) {
412
+ console.log(` target ${target.label}: ${target.dir}`)
413
+ for (const skill of toInstall) {
414
+ const dest = path.join(target.dir, skill.name)
415
+ const result = linkSkill(skill, target.dir, parsed.force)
416
+ if (result === 'linked') console.log(` linked ${skill.name} -> ${dest}`)
417
+ else if (result === 'replaced') console.log(` relinked ${skill.name} -> ${dest}`)
418
+ else if (result === 'up-to-date') console.log(` up to date ${skill.name}`)
419
+ else {
420
+ conflicts++
421
+ console.log(
422
+ ` conflict ${skill.name}: ${dest} exists and is not this skill — pass --force to replace`,
423
+ )
424
+ }
425
+ }
426
+ console.log('')
427
+ }
428
+ if (conflicts > 0) {
429
+ console.error(
430
+ ` ${conflicts} conflict(s); rerun with --force only if replacing them is intended.\n`,
431
+ )
432
+ process.exit(1)
433
+ }
434
+ console.log(' done. restart the agent session to load newly installed skills.\n')
435
+ }
436
+
437
+ function runShow(args: string[]) {
438
+ const skills = listSkills()
439
+ const name = args.find((arg) => !arg.startsWith('-'))
440
+ if (!name) {
441
+ printSkillList(skills)
442
+ return
443
+ }
444
+ const [skill] = matchSkills(skills, [name])
445
+ const content = fs.readFileSync(path.join(SKILLS_DIR, skill.name, 'SKILL.md'), 'utf8')
446
+ console.log(content)
447
+ }
448
+
449
+ export async function runSkill(args: string[]) {
450
+ const [command, ...rest] = args
451
+ if (!command || command === '--help' || command === '-h') {
452
+ printSkillHelp()
453
+ return
454
+ }
455
+ if (command === 'install') {
456
+ await runInstall(rest)
457
+ return
458
+ }
459
+ if (command === 'show' || command === 'list') {
460
+ runShow(rest)
461
+ return
462
+ }
463
+
464
+ console.error(` unknown skill command: ${command}`)
465
+ printSkillHelp()
466
+ process.exit(1)
467
+ }