@needle-tools/engine 4.15.0-next.f391a30 → 4.15.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 (150) hide show
  1. package/components.needle.json +1 -1
  2. package/dist/{gltf-progressive-CTlvpS3A.js → gltf-progressive-Bm_6aEi4.js} +1 -1
  3. package/dist/{gltf-progressive-CMwJPwEt.umd.cjs → gltf-progressive-BttGBXw6.umd.cjs} +1 -1
  4. package/dist/{gltf-progressive-DYL3SLVb.min.js → gltf-progressive-T5WKTux5.min.js} +1 -1
  5. package/dist/materialx-CJyQZtjt.min.js +90 -0
  6. package/dist/materialx-DMs1E08Z.js +4636 -0
  7. package/dist/materialx-DaKKOoVk.umd.cjs +90 -0
  8. package/dist/{needle-engine.bundle-DsTdfmeb.min.js → needle-engine.bundle-CBq_OMnI.min.js} +122 -124
  9. package/dist/{needle-engine.bundle-DB4kLWO_.js → needle-engine.bundle-DGyiwNWR.js} +3226 -3232
  10. package/dist/{needle-engine.bundle-C1BFRZDF.umd.cjs → needle-engine.bundle-JN3eiiYc.umd.cjs} +113 -115
  11. package/dist/needle-engine.d.ts +52 -33
  12. package/dist/needle-engine.js +288 -287
  13. package/dist/needle-engine.min.js +1 -1
  14. package/dist/needle-engine.umd.cjs +1 -1
  15. package/dist/{postprocessing-BN-f4viE.min.js → postprocessing-06AXuvdv.min.js} +1 -1
  16. package/dist/{postprocessing-De9ZpJrk.js → postprocessing-CI2x8Cln.js} +1 -1
  17. package/dist/{postprocessing-DYmYOVm4.umd.cjs → postprocessing-CPDcA21P.umd.cjs} +1 -1
  18. package/dist/{three-examples-BHqRVpO_.umd.cjs → three-examples-BMmNgNCN.umd.cjs} +12 -12
  19. package/dist/{three-examples-C0ZCCA_K.js → three-examples-CMYCd5nH.js} +192 -182
  20. package/dist/{three-examples-DmTY8tGr.min.js → three-examples-CQl1fFZp.min.js} +14 -14
  21. package/lib/engine/api.d.ts +2 -0
  22. package/lib/engine/api.js +2 -0
  23. package/lib/engine/api.js.map +1 -1
  24. package/lib/engine/debug/debug.js +1 -1
  25. package/lib/engine/debug/debug.js.map +1 -1
  26. package/lib/engine/debug/debug_spatial_console.js +1 -1
  27. package/lib/engine/debug/debug_spatial_console.js.map +1 -1
  28. package/lib/engine/engine_accessibility.d.ts +1 -1
  29. package/lib/engine/engine_accessibility.js +1 -1
  30. package/lib/engine/engine_accessibility.js.map +1 -1
  31. package/lib/engine/engine_context.d.ts +1 -1
  32. package/lib/engine/engine_context.js +2 -2
  33. package/lib/engine/engine_context.js.map +1 -1
  34. package/lib/engine/engine_create_objects.js +1 -1
  35. package/lib/engine/engine_create_objects.js.map +1 -1
  36. package/lib/engine/engine_gizmos.js +1 -1
  37. package/lib/engine/engine_gizmos.js.map +1 -1
  38. package/lib/engine/engine_license.js +2 -7
  39. package/lib/engine/engine_license.js.map +1 -1
  40. package/lib/engine/engine_test_utils.d.ts +39 -0
  41. package/lib/engine/engine_test_utils.js +84 -0
  42. package/lib/engine/engine_test_utils.js.map +1 -0
  43. package/lib/engine/engine_utils.js +2 -2
  44. package/lib/engine/engine_utils.js.map +1 -1
  45. package/lib/engine/export/gltf/index.js +1 -1
  46. package/lib/engine/export/gltf/index.js.map +1 -1
  47. package/lib/engine/webcomponents/logo-element.d.ts +3 -6
  48. package/lib/engine/webcomponents/logo-element.js +0 -18
  49. package/lib/engine/webcomponents/logo-element.js.map +1 -1
  50. package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js +2 -2
  51. package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js.map +1 -1
  52. package/lib/engine/webcomponents/needle menu/needle-menu.d.ts +7 -10
  53. package/lib/engine/webcomponents/needle menu/needle-menu.js +4 -14
  54. package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
  55. package/lib/engine/webcomponents/needle-engine.ar-overlay.js +1 -10
  56. package/lib/engine/webcomponents/needle-engine.ar-overlay.js.map +1 -1
  57. package/lib/engine/webcomponents/needle-engine.d.ts +0 -3
  58. package/lib/engine/webcomponents/needle-engine.js +0 -10
  59. package/lib/engine/webcomponents/needle-engine.js.map +1 -1
  60. package/lib/engine-components/Component.js +1 -0
  61. package/lib/engine-components/Component.js.map +1 -1
  62. package/lib/engine-components/ReflectionProbe.d.ts +2 -24
  63. package/lib/engine-components/ReflectionProbe.js +2 -28
  64. package/lib/engine-components/ReflectionProbe.js.map +1 -1
  65. package/lib/engine-components/Skybox.js +2 -4
  66. package/lib/engine-components/Skybox.js.map +1 -1
  67. package/lib/engine-components/export/gltf/GltfExport.js +1 -1
  68. package/lib/engine-components/export/gltf/GltfExport.js.map +1 -1
  69. package/lib/engine-components/export/usdz/ThreeUSDZExporter.js +2 -2
  70. package/lib/engine-components/export/usdz/USDZExporter.js +1 -1
  71. package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -1
  72. package/lib/engine-components/export/usdz/extensions/behavior/PhysicsExtension.js +2 -2
  73. package/lib/engine-components/export/usdz/extensions/behavior/PhysicsExtension.js.map +1 -1
  74. package/lib/engine-components/postprocessing/Effects/Tonemapping.utils.d.ts +1 -1
  75. package/lib/include/three/EXT_mesh_gpu_instancing_exporter.js.map +1 -0
  76. package/package.json +14 -18
  77. package/plugins/common/buildinfo.js +10 -46
  78. package/plugins/common/files.js +1 -2
  79. package/plugins/common/license.js +69 -144
  80. package/plugins/common/logger.js +11 -172
  81. package/plugins/common/worker.js +4 -5
  82. package/plugins/types/userconfig.d.ts +2 -40
  83. package/plugins/vite/alias.js +5 -6
  84. package/plugins/vite/asap.js +5 -6
  85. package/plugins/vite/build-pipeline.js +41 -224
  86. package/plugins/vite/buildinfo.js +6 -66
  87. package/plugins/vite/copyfiles.js +12 -41
  88. package/plugins/vite/custom-element-data.js +16 -26
  89. package/plugins/vite/defines.js +5 -8
  90. package/plugins/vite/dependencies.js +10 -16
  91. package/plugins/vite/dependency-watcher.js +7 -35
  92. package/plugins/vite/drop-client.js +5 -7
  93. package/plugins/vite/drop.js +14 -16
  94. package/plugins/vite/editor-connection.js +16 -18
  95. package/plugins/vite/imports-logger.js +2 -12
  96. package/plugins/vite/index.js +3 -8
  97. package/plugins/vite/local-files.js +441 -2
  98. package/plugins/vite/logger.client.js +35 -45
  99. package/plugins/vite/logger.js +3 -6
  100. package/plugins/vite/meta.js +4 -18
  101. package/plugins/vite/needle-app.js +3 -4
  102. package/plugins/vite/peer.js +1 -2
  103. package/plugins/vite/pwa.js +17 -33
  104. package/plugins/vite/reload.js +2 -24
  105. package/src/engine/api.ts +3 -0
  106. package/src/engine/debug/debug.ts +1 -1
  107. package/src/engine/debug/debug_spatial_console.ts +1 -5
  108. package/src/engine/engine_accessibility.ts +1 -2
  109. package/src/engine/engine_context.ts +2 -2
  110. package/src/engine/engine_create_objects.ts +1 -1
  111. package/src/engine/engine_gizmos.ts +5 -9
  112. package/src/engine/engine_license.ts +2 -7
  113. package/src/engine/engine_test_utils.ts +109 -0
  114. package/src/engine/engine_utils.ts +2 -2
  115. package/src/engine/export/gltf/index.ts +1 -1
  116. package/src/engine/webcomponents/logo-element.ts +3 -20
  117. package/src/engine/webcomponents/needle menu/needle-menu-spatial.ts +2 -6
  118. package/src/engine/webcomponents/needle menu/needle-menu.ts +11 -23
  119. package/src/engine/webcomponents/needle-engine.ar-overlay.ts +2 -13
  120. package/src/engine/webcomponents/needle-engine.ts +1 -13
  121. package/src/engine-components/Component.ts +2 -1
  122. package/src/engine-components/ReflectionProbe.ts +9 -33
  123. package/src/engine-components/Skybox.ts +2 -4
  124. package/src/engine-components/export/gltf/GltfExport.ts +1 -1
  125. package/src/engine-components/export/usdz/ThreeUSDZExporter.ts +2 -2
  126. package/src/engine-components/export/usdz/USDZExporter.ts +1 -1
  127. package/src/engine-components/export/usdz/extensions/behavior/PhysicsExtension.ts +2 -2
  128. package/src/include/draco/draco_decoder.js +34 -0
  129. package/src/include/draco/draco_decoder.wasm +0 -0
  130. package/src/include/draco/draco_wasm_wrapper.js +117 -0
  131. package/src/include/ktx2/basis_transcoder.js +19 -0
  132. package/src/include/ktx2/basis_transcoder.wasm +0 -0
  133. package/src/include/needle/arial-msdf.json +1472 -0
  134. package/src/include/needle/arial.png +0 -0
  135. package/src/include/needle/poweredbyneedle.webp +0 -0
  136. package/dist/materialx-4jJLLe9Q.js +0 -4174
  137. package/dist/materialx-Bt9FHwco.min.js +0 -158
  138. package/dist/materialx-NDD0y4JY.umd.cjs +0 -158
  139. package/lib/engine/export/gltf/EXT_mesh_gpu_instancing_exporter.js.map +0 -1
  140. package/plugins/common/needle-engine-skill.md +0 -175
  141. package/plugins/vite/ai.js +0 -71
  142. package/plugins/vite/local-files-analysis.js +0 -789
  143. package/plugins/vite/local-files-core.js +0 -992
  144. package/plugins/vite/local-files-internals.js +0 -28
  145. package/plugins/vite/local-files-types.d.ts +0 -111
  146. package/plugins/vite/local-files-utils.js +0 -359
  147. package/plugins/vite/logging.js +0 -129
  148. /package/lib/{engine/export/gltf → include/three}/EXT_mesh_gpu_instancing_exporter.d.ts +0 -0
  149. /package/lib/{engine/export/gltf → include/three}/EXT_mesh_gpu_instancing_exporter.js +0 -0
  150. /package/src/{engine/export/gltf → include/three}/EXT_mesh_gpu_instancing_exporter.js +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"file":"EXT_mesh_gpu_instancing_exporter.js","sourceRoot":"","sources":["../../../../src/engine/export/gltf/EXT_mesh_gpu_instancing_exporter.js"],"names":[],"mappings":"AAAA;;;;GAIG;AAEF,OAAO,EACP,eAAe,EACf,OAAO,EACP,OAAO,EACP,UAAU,GACV,MAAM,OAAO,CAAC;AAEf,MAAM,CAAC,OAAO,OAAO,8BAA8B;IAElD,YAAa,MAAM;QAElB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IAEvC,CAAC;IAED,SAAS,CAAE,IAAI,EAAE,OAAO;QAEvB,IAAG,IAAI,CAAC,WAAW,CAAC,IAAI,KAAK,eAAe;YAAE,OAAO;QAErD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,MAAM,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;QAC7C,MAAM,YAAY,GAAG,EAAE,CAAC;QAExB,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC;QAC9C,OAAO,CAAC,UAAU,CAAE,IAAI,CAAC,IAAI,CAAE,GAAG,YAAY,CAAC;QAE/C,IAAI,GAAG,GAAG,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;QAEzB,KAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,EAClC;YACC,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;YAEzB,IAAI,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC;YACtB,IAAI,CAAC,GAAG,IAAI,UAAU,EAAE,CAAC;YACzB,IAAI,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC;YAEtB,GAAG,CAAC,SAAS,CAAC,CAAC,EAAC,CAAC,EAAC,CAAC,CAAC,CAAC;YAErB,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAC,CAAC,CAAC,CAAC,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACvB,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAC,CAAC,CAAC,CAAC,EAAC,CAAC,CAAC,CAAC,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3B,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAC,CAAC,CAAC,CAAC,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SACvB;QAAA,CAAC;QAEF,MAAM,GAAG,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;QACnC,MAAM,GAAG,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;QACnC,MAAM,GAAG,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;QAEnC,YAAY,CAAC,UAAU,GAAG;YACzB,aAAa,EAAG,MAAM,CAAC,eAAe,CAAE,IAAI,eAAe,CAAE,GAAG,EAAE,CAAC,CAAE,CAAE;YACvE,UAAU,EAAG,MAAM,CAAC,eAAe,CAAE,IAAI,eAAe,CAAE,GAAG,EAAE,CAAC,CAAE,CAAE;YACpE,OAAO,EAAG,MAAM,CAAC,eAAe,CAAE,IAAI,eAAe,CAAE,GAAG,EAAE,CAAC,CAAE,CAAE;SACjE,CAAC;QAEF,cAAc,CAAE,IAAI,CAAC,IAAI,CAAE,GAAG,IAAI,CAAC;IAEpC,CAAC;CACD"}
@@ -1,175 +0,0 @@
1
- ---
2
- name: needle-engine
3
- description: Automatically provides Needle Engine context when working in a Needle Engine web project. Use this skill when editing TypeScript components, Vite config, GLB assets, or anything related to @needle-tools/engine.
4
- ---
5
-
6
- # Needle Engine
7
-
8
- You are an expert in Needle Engine — a web-first 3D engine built on Three.js with a Unity/Blender-based workflow.
9
-
10
- ## Key concepts
11
-
12
- **Needle Engine** ships 3D scenes from Unity (or Blender) as GLB files and renders them in the browser using Three.js. TypeScript components attached to GameObjects in Unity are serialized into the GLB and re-hydrated at runtime in the browser.
13
-
14
- ### Embedding in HTML
15
- ```html
16
- <!-- The <needle-engine> web component creates and manages a 3D context -->
17
- <needle-engine src="assets/scene.glb"></needle-engine>
18
- ```
19
- Access the context programmatically: `document.querySelector("needle-engine").context`
20
-
21
- ### Component lifecycle (mirrors Unity MonoBehaviour)
22
- ```ts
23
- import { Behaviour, serializable, registerType } from "@needle-tools/engine";
24
-
25
- @registerType
26
- export class MyComponent extends Behaviour {
27
- @serializable() myValue: number = 1;
28
-
29
- awake() {} // called once when instantiated
30
- start() {} // called once on first frame
31
- update() {} // called every frame
32
- onEnable() {}
33
- onDisable() {}
34
- onDestroy() {}
35
- onBeforeRender(_frame: XRFrame | null) {}
36
- }
37
- ```
38
-
39
- ### Serialization
40
- - `@registerType` — makes the class discoverable by the GLB deserializer
41
- - `@serializable()` — marks a field for GLB deserialization (primitives)
42
- - `@serializable(Object3D)` — for Three.js object references
43
- - `@serializable(Texture)` — for textures (import Texture from "three")
44
- - `@serializable(RGBAColor)` — for colors
45
-
46
- ### Accessing the scene
47
- ```ts
48
- this.context.scene // THREE.Scene
49
- this.context.mainCamera // active camera (THREE.Camera)
50
- this.context.renderer // THREE.WebGLRenderer
51
- this.context.time.frame // current frame number
52
- this.context.time.deltaTime // seconds since last frame
53
- this.gameObject // the THREE.Object3D this component is on
54
- ```
55
-
56
- ### Finding components
57
- ```ts
58
- this.gameObject.getComponent(MyComponent)
59
- this.gameObject.getComponentInChildren(MyComponent)
60
- this.context.scene.getComponentInChildren(MyComponent)
61
-
62
- // Global search (import as standalone functions from "@needle-tools/engine")
63
- import { findObjectOfType, findObjectsOfType } from "@needle-tools/engine";
64
- findObjectOfType(MyComponent, this.context)
65
- findObjectsOfType(MyComponent, this.context)
66
- ```
67
-
68
- ### Input handling
69
- ```ts
70
- // Polling
71
- if (this.context.input.getPointerDown(0)) { /* pointer pressed */ }
72
- if (this.context.input.getKeyDown("Space")) { /* space pressed */ }
73
-
74
- // Event-based (NEPointerEvent works across mouse, touch, and XR controllers)
75
- this.gameObject.addEventListener("pointerdown", (e: NEPointerEvent) => { });
76
- ```
77
-
78
- ### Physics & raycasting
79
- ```ts
80
- // Default raycasts hit visible geometry — no colliders needed
81
- // Uses mesh BVH (bounding volume hierarchy) for accelerated raycasting, BVH is generated on a worker
82
- const hits = this.context.physics.raycast();
83
-
84
- // Physics-based raycasts (require colliders, uses Rapier physics engine)
85
- const physicsHits = this.context.physics.raycastPhysics();
86
- ```
87
-
88
- ### Networking & multiplayer
89
- Needle Engine has built-in multiplayer. Add a `SyncedRoom` component to enable networking.
90
-
91
- - `@syncField()` — automatically syncs a field across all connected clients
92
- - Primitives (string, number, boolean) sync automatically on change
93
- - Complex types (arrays/objects) require reassignment to trigger sync: `this.myArray = this.myArray`
94
- - Key components: `SyncedRoom`, `SyncedTransform`, `PlayerSync`, `Voip`
95
- - Uses WebSockets + optional WebRTC peer-to-peer connections
96
-
97
- ### WebXR (VR & AR)
98
- Needle Engine has built-in WebXR support for VR and AR across Meta Quest, Apple Vision Pro, and mobile AR.
99
-
100
- - Add the `WebXR` component to enable VR/AR sessions
101
- - Use `XRRig` to define the user's starting position — the user is parented to the rig during XR sessions
102
- - Available components: `WebXRImageTracking`, `WebXRPlaneTracking`, `XRControllerModel`, `NeedleXRSession`
103
-
104
- ## Creating a new project
105
-
106
- Use `create-needle` to scaffold a new Needle Engine project:
107
- ```bash
108
- npm create needle my-app # default Vite template
109
- npm create needle my-app -t react # React template
110
- npm create needle my-app -t vue # Vue.js template
111
- ```
112
-
113
- Available templates: `vite` (default), `react`, `vue`, `sveltekit`, `svelte`, `nextjs`, `react-three-fiber`.
114
-
115
- Use `npm create needle --list` to see all available templates.
116
-
117
- ## Vite plugin system
118
-
119
- Needle Engine ships a set of Vite plugins via `needlePlugins(command, config, userSettings)`. Custom project plugins go in `vite.config.ts`.
120
-
121
- ```ts
122
- import { defineConfig } from "vite";
123
- import { needlePlugins } from "@needle-tools/engine/vite";
124
-
125
- export default defineConfig(async ({ command }) => ({
126
- plugins: [
127
- ...(await needlePlugins(command, {}, {})),
128
- ],
129
- }));
130
- ```
131
-
132
- ## Deployment
133
-
134
- Projects can be deployed to:
135
- - **Needle Cloud** — official hosting with automatic optimization (`npx needle-cloud deploy`)
136
- - **Vercel** / **Netlify** — standard web hosting
137
- - **itch.io** — for games and interactive experiences
138
- - **Any static host** — Needle Engine projects are standard Vite web apps
139
-
140
- From Unity, use built-in deployment components (e.g. `DeployToNeedleCloud`, `DeployToNetlify`).
141
-
142
- ## Progressive loading (`@needle-tools/gltf-progressive`)
143
-
144
- Needle Engine includes `@needle-tools/gltf-progressive` for progressive streaming of 3D models and textures. It creates a tiny initial file with embedded low-quality proxy geometry, then streams higher-quality LODs on demand. Results in ~90% smaller initial downloads with instant display.
145
-
146
- Works standalone with any three.js project:
147
- ```ts
148
- import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
149
- import { WebGLRenderer } from "three";
150
- import { useNeedleProgressive } from "@needle-tools/gltf-progressive";
151
-
152
- const gltfLoader = new GLTFLoader();
153
- const renderer = new WebGLRenderer();
154
-
155
- // Register once — progressive loading happens automatically for all subsequent loads
156
- useNeedleProgressive(gltfLoader, renderer);
157
-
158
- gltfLoader.load(url, (gltf) => scene.add(gltf.scene));
159
- ```
160
-
161
- In Needle Engine projects, progressive loading is built in and can be configured via the **Compression & LOD Settings** component in Unity.
162
-
163
- ## Important URLs
164
- - Docs: https://engine.needle.tools/docs/
165
- - Samples: https://engine.needle.tools/samples/
166
- - GitHub: https://github.com/needle-tools/needle-engine-support
167
- - npm: https://www.npmjs.com/package/@needle-tools/engine
168
-
169
- ## Searching the documentation
170
-
171
- Use the `needle_search` MCP tool to find relevant docs, forum posts, and community answers.
172
-
173
- ## Common gotchas
174
- - Components must use `@registerType` or they won't be instantiated from GLB (this is handled automatically when exporting from Unity or Blender, but must be added manually for hand-written components)
175
- - GLB assets are in `assets/`, static files in `include/` or `public/`
@@ -1,71 +0,0 @@
1
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
2
- import { dirname, join } from "path";
3
- import { fileURLToPath } from "url";
4
-
5
- const __filename = fileURLToPath(import.meta.url);
6
- const __dirname = dirname(__filename);
7
-
8
- const pluginName = "needle-ai";
9
-
10
- /**
11
- * Needle Engine Claude skill installer.
12
- *
13
- * Writes a Needle Engine skill to `.claude/skills/needle-engine/SKILL.md`.
14
- * Claude Code auto-loads skills based on their description frontmatter, so
15
- * Claude will automatically have Needle Engine context when working in the project.
16
- *
17
- * The skill is only written if `.claude/` already exists in the project root
18
- * (i.e. the developer is already using Claude Code). Old skill files are
19
- * always overwritten so the skill stays up to date with the engine version.
20
- *
21
- * @param {"build" | "serve"} command
22
- * @param {{} | undefined | null} config
23
- * @param {import('../types/index.js').userSettings} userSettings
24
- * @returns {import('vite').Plugin | null}
25
- */
26
- export const needleAI = (command, config, userSettings) => {
27
- return {
28
- name: pluginName,
29
- enforce: "pre",
30
- buildStart() {
31
- installClaudeSkill();
32
- },
33
- configureServer() {
34
- installClaudeSkill();
35
- },
36
- };
37
- };
38
-
39
- /** Read the engine version from our own package.json */
40
- function getEngineVersion() {
41
- try {
42
- const pkgPath = join(__dirname, "../../package.json");
43
- const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
44
- return pkg.version || "unknown";
45
- }
46
- catch {
47
- return "unknown";
48
- }
49
- }
50
-
51
- function writeSkill(claudeDir, version) {
52
- const skillDir = join(claudeDir, "skills", "needle-engine");
53
- if (!existsSync(skillDir)) {
54
- mkdirSync(skillDir, { recursive: true });
55
- }
56
- const skillPath = join(skillDir, "SKILL.md");
57
- const templatePath = join(__dirname, "../common/needle-engine-skill.md");
58
- const template = readFileSync(templatePath, "utf8");
59
- const content = template.replace("{{VERSION}}", version);
60
- writeFileSync(skillPath, content, "utf8");
61
- return skillPath;
62
- }
63
-
64
- function installClaudeSkill() {
65
- const claudeDir = join(process.cwd(), ".claude");
66
- if (!existsSync(claudeDir)) return; // only install if developer uses Claude Code
67
-
68
- const version = getEngineVersion();
69
- const path = writeSkill(claudeDir, version);
70
- console.log(`[${pluginName}] Installed Needle Engine Claude skill → ${path}`);
71
- }