videowright 0.1.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 (306) hide show
  1. package/README.md +91 -0
  2. package/dist/cli/argv.d.ts +28 -0
  3. package/dist/cli/argv.d.ts.map +1 -0
  4. package/dist/cli/argv.js +115 -0
  5. package/dist/cli/argv.js.map +1 -0
  6. package/dist/cli/bin.d.ts +7 -0
  7. package/dist/cli/bin.d.ts.map +1 -0
  8. package/dist/cli/bin.js +10 -0
  9. package/dist/cli/bin.js.map +1 -0
  10. package/dist/cli/dev.d.ts +19 -0
  11. package/dist/cli/dev.d.ts.map +1 -0
  12. package/dist/cli/dev.js +104 -0
  13. package/dist/cli/dev.js.map +1 -0
  14. package/dist/cli/discover.d.ts +29 -0
  15. package/dist/cli/discover.d.ts.map +1 -0
  16. package/dist/cli/discover.js +104 -0
  17. package/dist/cli/discover.js.map +1 -0
  18. package/dist/cli/discover_project.d.ts +29 -0
  19. package/dist/cli/discover_project.d.ts.map +1 -0
  20. package/dist/cli/discover_project.js +108 -0
  21. package/dist/cli/discover_project.js.map +1 -0
  22. package/dist/cli/errors.d.ts +10 -0
  23. package/dist/cli/errors.d.ts.map +1 -0
  24. package/dist/cli/errors.js +13 -0
  25. package/dist/cli/errors.js.map +1 -0
  26. package/dist/cli/ffmpeg.d.ts +57 -0
  27. package/dist/cli/ffmpeg.d.ts.map +1 -0
  28. package/dist/cli/ffmpeg.js +122 -0
  29. package/dist/cli/ffmpeg.js.map +1 -0
  30. package/dist/cli/index.d.ts +7 -0
  31. package/dist/cli/index.d.ts.map +1 -0
  32. package/dist/cli/index.js +152 -0
  33. package/dist/cli/index.js.map +1 -0
  34. package/dist/cli/playwright_check.d.ts +44 -0
  35. package/dist/cli/playwright_check.d.ts.map +1 -0
  36. package/dist/cli/playwright_check.js +20 -0
  37. package/dist/cli/playwright_check.js.map +1 -0
  38. package/dist/cli/prompt.d.ts +13 -0
  39. package/dist/cli/prompt.d.ts.map +1 -0
  40. package/dist/cli/prompt.js +47 -0
  41. package/dist/cli/prompt.js.map +1 -0
  42. package/dist/cli/render.d.ts +60 -0
  43. package/dist/cli/render.d.ts.map +1 -0
  44. package/dist/cli/render.js +471 -0
  45. package/dist/cli/render.js.map +1 -0
  46. package/dist/cli/script_cmd.d.ts +26 -0
  47. package/dist/cli/script_cmd.d.ts.map +1 -0
  48. package/dist/cli/script_cmd.js +88 -0
  49. package/dist/cli/script_cmd.js.map +1 -0
  50. package/dist/cli/time_shim.d.ts +44 -0
  51. package/dist/cli/time_shim.d.ts.map +1 -0
  52. package/dist/cli/time_shim.js +390 -0
  53. package/dist/cli/time_shim.js.map +1 -0
  54. package/dist/cli/ts_loader.d.ts +28 -0
  55. package/dist/cli/ts_loader.d.ts.map +1 -0
  56. package/dist/cli/ts_loader.js +95 -0
  57. package/dist/cli/ts_loader.js.map +1 -0
  58. package/dist/cli/vite_helpers.d.ts +62 -0
  59. package/dist/cli/vite_helpers.d.ts.map +1 -0
  60. package/dist/cli/vite_helpers.js +273 -0
  61. package/dist/cli/vite_helpers.js.map +1 -0
  62. package/dist/index.d.ts +11 -0
  63. package/dist/index.d.ts.map +1 -0
  64. package/dist/index.js +14 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/player/hash_router.d.ts +23 -0
  67. package/dist/player/hash_router.d.ts.map +1 -0
  68. package/dist/player/hash_router.js +49 -0
  69. package/dist/player/hash_router.js.map +1 -0
  70. package/dist/player/hud.d.ts +33 -0
  71. package/dist/player/hud.d.ts.map +1 -0
  72. package/dist/player/hud.js +357 -0
  73. package/dist/player/hud.js.map +1 -0
  74. package/dist/player/index.d.ts +123 -0
  75. package/dist/player/index.d.ts.map +1 -0
  76. package/dist/player/index.js +848 -0
  77. package/dist/player/index.js.map +1 -0
  78. package/dist/player/input.d.ts +14 -0
  79. package/dist/player/input.d.ts.map +1 -0
  80. package/dist/player/input.js +90 -0
  81. package/dist/player/input.js.map +1 -0
  82. package/dist/player/slot.d.ts +22 -0
  83. package/dist/player/slot.d.ts.map +1 -0
  84. package/dist/player/slot.js +43 -0
  85. package/dist/player/slot.js.map +1 -0
  86. package/dist/player/transitions/cut.d.ts +7 -0
  87. package/dist/player/transitions/cut.d.ts.map +1 -0
  88. package/dist/player/transitions/cut.js +9 -0
  89. package/dist/player/transitions/cut.js.map +1 -0
  90. package/dist/player/transitions/fade.d.ts +7 -0
  91. package/dist/player/transitions/fade.d.ts.map +1 -0
  92. package/dist/player/transitions/fade.js +18 -0
  93. package/dist/player/transitions/fade.js.map +1 -0
  94. package/dist/player/transitions/index.d.ts +4 -0
  95. package/dist/player/transitions/index.d.ts.map +1 -0
  96. package/dist/player/transitions/index.js +4 -0
  97. package/dist/player/transitions/index.js.map +1 -0
  98. package/dist/player/transitions/slide.d.ts +6 -0
  99. package/dist/player/transitions/slide.d.ts.map +1 -0
  100. package/dist/player/transitions/slide.js +35 -0
  101. package/dist/player/transitions/slide.js.map +1 -0
  102. package/dist/script/index.d.ts +2 -0
  103. package/dist/script/index.d.ts.map +1 -0
  104. package/dist/script/index.js +2 -0
  105. package/dist/script/index.js.map +1 -0
  106. package/dist/script/script.d.ts +10 -0
  107. package/dist/script/script.d.ts.map +1 -0
  108. package/dist/script/script.js +41 -0
  109. package/dist/script/script.js.map +1 -0
  110. package/dist/segment/SegmentRunner.d.ts +52 -0
  111. package/dist/segment/SegmentRunner.d.ts.map +1 -0
  112. package/dist/segment/SegmentRunner.js +187 -0
  113. package/dist/segment/SegmentRunner.js.map +1 -0
  114. package/dist/segment/defineConfig.d.ts +6 -0
  115. package/dist/segment/defineConfig.d.ts.map +1 -0
  116. package/dist/segment/defineConfig.js +7 -0
  117. package/dist/segment/defineConfig.js.map +1 -0
  118. package/dist/segment/defineSegment.d.ts +7 -0
  119. package/dist/segment/defineSegment.d.ts.map +1 -0
  120. package/dist/segment/defineSegment.js +25 -0
  121. package/dist/segment/defineSegment.js.map +1 -0
  122. package/dist/segment/index.d.ts +5 -0
  123. package/dist/segment/index.d.ts.map +1 -0
  124. package/dist/segment/index.js +4 -0
  125. package/dist/segment/index.js.map +1 -0
  126. package/dist/timeline/index.d.ts +73 -0
  127. package/dist/timeline/index.d.ts.map +1 -0
  128. package/dist/timeline/index.js +142 -0
  129. package/dist/timeline/index.js.map +1 -0
  130. package/dist/timeline/loadAudioTrack.d.ts +18 -0
  131. package/dist/timeline/loadAudioTrack.d.ts.map +1 -0
  132. package/dist/timeline/loadAudioTrack.js +44 -0
  133. package/dist/timeline/loadAudioTrack.js.map +1 -0
  134. package/dist/timeline/loadVoiceover.d.ts +18 -0
  135. package/dist/timeline/loadVoiceover.d.ts.map +1 -0
  136. package/dist/timeline/loadVoiceover.js +38 -0
  137. package/dist/timeline/loadVoiceover.js.map +1 -0
  138. package/dist/timeline/resolveTiming.d.ts +28 -0
  139. package/dist/timeline/resolveTiming.d.ts.map +1 -0
  140. package/dist/timeline/resolveTiming.js +63 -0
  141. package/dist/timeline/resolveTiming.js.map +1 -0
  142. package/dist/timeline/validateTiming.d.ts +29 -0
  143. package/dist/timeline/validateTiming.d.ts.map +1 -0
  144. package/dist/timeline/validateTiming.js +62 -0
  145. package/dist/timeline/validateTiming.js.map +1 -0
  146. package/dist/types.d.ts +216 -0
  147. package/dist/types.d.ts.map +1 -0
  148. package/dist/types.js +6 -0
  149. package/dist/types.js.map +1 -0
  150. package/package.json +47 -0
  151. package/skill/SKILL.md +64 -0
  152. package/skill/assets/hello_world/PLAN.md +31 -0
  153. package/skill/assets/hello_world/README.md +27 -0
  154. package/skill/assets/hello_world/audio/audio_plan.md +14 -0
  155. package/skill/assets/hello_world/segments/hello_intro.ts +69 -0
  156. package/skill/assets/hello_world/segments/hello_outro.ts +71 -0
  157. package/skill/assets/hello_world/timeline.ts +15 -0
  158. package/skill/assets/hello_world/voiceover_script/script.md +10 -0
  159. package/skill/assets/install/package.json +10 -0
  160. package/skill/assets/install/tsconfig.json +23 -0
  161. package/skill/assets/styles/editorial-mono/STYLE.md +124 -0
  162. package/skill/assets/styles/editorial-mono/brand.md +85 -0
  163. package/skill/assets/styles/editorial-mono/reference/animations.jsx +752 -0
  164. package/skill/assets/styles/editorial-mono/reference/scenes.html +563 -0
  165. package/skill/assets/styles/editorial-mono/sample/bullet.ts +101 -0
  166. package/skill/assets/styles/editorial-mono/sample/content.ts +104 -0
  167. package/skill/assets/styles/editorial-mono/sample/cta.ts +113 -0
  168. package/skill/assets/styles/editorial-mono/sample/feature.ts +111 -0
  169. package/skill/assets/styles/editorial-mono/sample/grid.ts +97 -0
  170. package/skill/assets/styles/editorial-mono/sample/kinetic.ts +96 -0
  171. package/skill/assets/styles/editorial-mono/sample/section.ts +101 -0
  172. package/skill/assets/styles/editorial-mono/sample/stat.ts +128 -0
  173. package/skill/assets/styles/editorial-mono/sample/title.ts +97 -0
  174. package/skill/assets/styles/editorial-mono/sample/ui-showcase.ts +159 -0
  175. package/skill/assets/styles/editorial-mono/tokens.css +44 -0
  176. package/skill/assets/styles/iso-diagram/STYLE.md +109 -0
  177. package/skill/assets/styles/iso-diagram/brand.md +32 -0
  178. package/skill/assets/styles/iso-diagram/reference/animations.jsx +673 -0
  179. package/skill/assets/styles/iso-diagram/reference/scenes.html +427 -0
  180. package/skill/assets/styles/iso-diagram/sample/bullet.ts +144 -0
  181. package/skill/assets/styles/iso-diagram/sample/content.ts +192 -0
  182. package/skill/assets/styles/iso-diagram/sample/cta.ts +162 -0
  183. package/skill/assets/styles/iso-diagram/sample/feature.ts +205 -0
  184. package/skill/assets/styles/iso-diagram/sample/grid.ts +181 -0
  185. package/skill/assets/styles/iso-diagram/sample/kinetic.ts +102 -0
  186. package/skill/assets/styles/iso-diagram/sample/section.ts +149 -0
  187. package/skill/assets/styles/iso-diagram/sample/stat.ts +164 -0
  188. package/skill/assets/styles/iso-diagram/sample/title.ts +173 -0
  189. package/skill/assets/styles/iso-diagram/sample/ui-showcase.ts +162 -0
  190. package/skill/assets/styles/iso-diagram/tokens.css +40 -0
  191. package/skill/assets/styles/motion-engineering/STYLE.md +106 -0
  192. package/skill/assets/styles/motion-engineering/brand.md +29 -0
  193. package/skill/assets/styles/motion-engineering/reference/animations.jsx +673 -0
  194. package/skill/assets/styles/motion-engineering/reference/scenes.html +513 -0
  195. package/skill/assets/styles/motion-engineering/sample/bullet.ts +176 -0
  196. package/skill/assets/styles/motion-engineering/sample/content.ts +228 -0
  197. package/skill/assets/styles/motion-engineering/sample/cta.ts +209 -0
  198. package/skill/assets/styles/motion-engineering/sample/feature.ts +299 -0
  199. package/skill/assets/styles/motion-engineering/sample/grid.ts +190 -0
  200. package/skill/assets/styles/motion-engineering/sample/kinetic.ts +159 -0
  201. package/skill/assets/styles/motion-engineering/sample/section.ts +196 -0
  202. package/skill/assets/styles/motion-engineering/sample/stat.ts +230 -0
  203. package/skill/assets/styles/motion-engineering/sample/title.ts +219 -0
  204. package/skill/assets/styles/motion-engineering/sample/ui-showcase.ts +267 -0
  205. package/skill/assets/styles/motion-engineering/tokens.css +40 -0
  206. package/skill/assets/styles/neon-terminal/STYLE.md +105 -0
  207. package/skill/assets/styles/neon-terminal/brand.md +27 -0
  208. package/skill/assets/styles/neon-terminal/reference/animations.jsx +673 -0
  209. package/skill/assets/styles/neon-terminal/reference/scenes.html +387 -0
  210. package/skill/assets/styles/neon-terminal/sample/bullet.ts +113 -0
  211. package/skill/assets/styles/neon-terminal/sample/content.ts +117 -0
  212. package/skill/assets/styles/neon-terminal/sample/cta.ts +131 -0
  213. package/skill/assets/styles/neon-terminal/sample/feature.ts +112 -0
  214. package/skill/assets/styles/neon-terminal/sample/grid.ts +128 -0
  215. package/skill/assets/styles/neon-terminal/sample/kinetic.ts +105 -0
  216. package/skill/assets/styles/neon-terminal/sample/section.ts +96 -0
  217. package/skill/assets/styles/neon-terminal/sample/stat.ts +123 -0
  218. package/skill/assets/styles/neon-terminal/sample/title.ts +122 -0
  219. package/skill/assets/styles/neon-terminal/sample/ui-showcase.ts +127 -0
  220. package/skill/assets/styles/neon-terminal/tokens.css +39 -0
  221. package/skill/assets/styles/risograph/STYLE.md +110 -0
  222. package/skill/assets/styles/risograph/brand.md +26 -0
  223. package/skill/assets/styles/risograph/reference/animations.jsx +673 -0
  224. package/skill/assets/styles/risograph/reference/scenes.html +403 -0
  225. package/skill/assets/styles/risograph/sample/bullet.ts +124 -0
  226. package/skill/assets/styles/risograph/sample/content.ts +135 -0
  227. package/skill/assets/styles/risograph/sample/cta.ts +149 -0
  228. package/skill/assets/styles/risograph/sample/feature.ts +152 -0
  229. package/skill/assets/styles/risograph/sample/grid.ts +123 -0
  230. package/skill/assets/styles/risograph/sample/kinetic.ts +125 -0
  231. package/skill/assets/styles/risograph/sample/section.ts +130 -0
  232. package/skill/assets/styles/risograph/sample/stat.ts +145 -0
  233. package/skill/assets/styles/risograph/sample/title.ts +132 -0
  234. package/skill/assets/styles/risograph/sample/ui-showcase.ts +147 -0
  235. package/skill/assets/styles/risograph/tokens.css +39 -0
  236. package/skill/assets/styles/swiss-console/STYLE.md +107 -0
  237. package/skill/assets/styles/swiss-console/brand.md +37 -0
  238. package/skill/assets/styles/swiss-console/reference/animations.jsx +673 -0
  239. package/skill/assets/styles/swiss-console/reference/scenes.html +420 -0
  240. package/skill/assets/styles/swiss-console/sample/bullet.ts +122 -0
  241. package/skill/assets/styles/swiss-console/sample/content.ts +137 -0
  242. package/skill/assets/styles/swiss-console/sample/cta.ts +109 -0
  243. package/skill/assets/styles/swiss-console/sample/feature.ts +163 -0
  244. package/skill/assets/styles/swiss-console/sample/grid.ts +145 -0
  245. package/skill/assets/styles/swiss-console/sample/kinetic.ts +117 -0
  246. package/skill/assets/styles/swiss-console/sample/section.ts +127 -0
  247. package/skill/assets/styles/swiss-console/sample/stat.ts +148 -0
  248. package/skill/assets/styles/swiss-console/sample/title.ts +148 -0
  249. package/skill/assets/styles/swiss-console/sample/ui-showcase.ts +198 -0
  250. package/skill/assets/styles/swiss-console/tokens.css +39 -0
  251. package/skill/install/INSTALL.md +400 -0
  252. package/skill/references/audio/audio_plan.md +199 -0
  253. package/skill/references/audio/build.md +208 -0
  254. package/skill/references/audio/cue_template.md +219 -0
  255. package/skill/references/audio/ffmpeg_cookbook.md +267 -0
  256. package/skill/references/audio/music/music.md +171 -0
  257. package/skill/references/audio/music/providers/elevenlabs.md +170 -0
  258. package/skill/references/audio/music/providers/manual.md +140 -0
  259. package/skill/references/audio/music/providers/openverse.md +265 -0
  260. package/skill/references/audio/sfx/providers/elevenlabs.md +152 -0
  261. package/skill/references/audio/sfx/providers/manual.md +117 -0
  262. package/skill/references/audio/sfx/providers/openverse.md +243 -0
  263. package/skill/references/audio/sfx/sfx.md +149 -0
  264. package/skill/references/audio/styles.md +102 -0
  265. package/skill/references/audio/sync.md +237 -0
  266. package/skill/references/audio/voiceover/animation_sync.md +142 -0
  267. package/skill/references/audio/voiceover/provider_script.md +153 -0
  268. package/skill/references/audio/voiceover/providers/elevenlabs.md +288 -0
  269. package/skill/references/audio/voiceover/providers/manual.md +100 -0
  270. package/skill/references/audio/voiceover/script_writing.md +100 -0
  271. package/skill/references/audio/voiceover/style_intake.md +56 -0
  272. package/skill/references/audio/voiceover/sync_algorithm.md +167 -0
  273. package/skill/references/audio/voiceover.md +296 -0
  274. package/skill/references/audio.md +135 -0
  275. package/skill/references/authoring_segment.md +446 -0
  276. package/skill/references/create_or_edit_video.md +232 -0
  277. package/skill/references/dev_server.md +157 -0
  278. package/skill/references/export.md +145 -0
  279. package/skill/references/new_video.md +117 -0
  280. package/skill/references/project_structure.md +144 -0
  281. package/skill/references/setup.md +109 -0
  282. package/skill/references/setup_new_style.md +158 -0
  283. package/skill/references/styles.md +154 -0
  284. package/skill/references/testing.md +115 -0
  285. package/skill/references/types.md +240 -0
  286. package/src/cli/entry/components/copy_button.ts +42 -0
  287. package/src/cli/entry/components/download_modal.ts +204 -0
  288. package/src/cli/entry/components/empty_state.ts +55 -0
  289. package/src/cli/entry/components/hide_hud_tab.ts +37 -0
  290. package/src/cli/entry/components/icons.ts +31 -0
  291. package/src/cli/entry/components/top_bar.ts +69 -0
  292. package/src/cli/entry/components/video_card.ts +57 -0
  293. package/src/cli/entry/dev_frame.ts +189 -0
  294. package/src/cli/entry/entry_index.ts +16 -0
  295. package/src/cli/entry/entry_video.ts +24 -0
  296. package/src/cli/entry/index.html +12 -0
  297. package/src/cli/entry/parse_slug.ts +14 -0
  298. package/src/cli/entry/render.html +17 -0
  299. package/src/cli/entry/render_entry.ts +121 -0
  300. package/src/cli/entry/styles/base.css +45 -0
  301. package/src/cli/entry/styles/components.css +605 -0
  302. package/src/cli/entry/styles/tokens.css +44 -0
  303. package/src/cli/entry/video.html +22 -0
  304. package/src/cli/entry/views/homepage.ts +66 -0
  305. package/src/cli/entry/views/video_view.ts +286 -0
  306. package/src/cli/entry/virtual.d.ts +8 -0
@@ -0,0 +1,400 @@
1
+ # Install Videowright
2
+
3
+ *This file is an install script for coding agents (Claude Code, Codex, opencode). Read it top-to-bottom and execute each step.*
4
+
5
+ You are installing Videowright -- a library for composing animated explainer videos in HTML/CSS/JS. Follow these steps in order. Do not skip steps. Do not reorder.
6
+
7
+ Each step includes exact prompts to show the user. Use them verbatim -- do not rephrase.
8
+
9
+ ---
10
+
11
+ ## Step 1: Folder check
12
+
13
+ Videowright expects to own its folder. It can live in a sub-folder of a larger repo, but it should not share a folder with another project.
14
+
15
+ Inspect the current working directory. Apply these rules in order:
16
+
17
+ 1. **Empty folder, or only innocent files** (`README.md`, `LICENSE`, `.gitignore`, `.git/`, an empty or near-empty `package.json` with no meaningful dependencies): proceed without asking. This is the happy path.
18
+
19
+ 2. **Already a Videowright project** (`videowright.config.ts` exists, or `package.json` has `videowright` in `dependencies` or `devDependencies`): proceed without asking. This is a re-install or repair.
20
+
21
+ 3. **Has other project content** (source code, populated `package.json` with unrelated dependencies, framework config files, etc.): stop and ask the user exactly:
22
+
23
+ > This folder already contains another project. Videowright should own its own folder. Options:
24
+ > 1. Cancel and `cd` into a clean folder.
25
+ > 2. Install into a sub-folder of this project (recommended sub-folder name: `videos/`).
26
+ >
27
+ > Which would you like?
28
+
29
+ - If they pick **1**: stop the install. Tell the user to `cd` into a clean folder and re-run.
30
+ - If they pick **2**: confirm or adjust the sub-folder name (default `videos/`). Create the directory if it does not exist. `cd` into it for the remainder of the install. Remember: the instruction file (Step 6) is written to the **root** of the larger project, not the sub-folder.
31
+
32
+ ---
33
+
34
+ ## Step 2: Agent detection
35
+
36
+ Detect which supported coding agents are installed. Run these commands separately (since `&&` short-circuits on failure). On macOS/Linux use `which`; on Windows use `where`:
37
+
38
+ ```bash
39
+ # macOS / Linux
40
+ which claude
41
+ which codex
42
+ which opencode
43
+
44
+ # Windows (if not using WSL)
45
+ where claude
46
+ where codex
47
+ where opencode
48
+ ```
49
+
50
+ The agent you are running in is implicitly installed -- include it in the detected set even if `which` fails (e.g., it may not be on `PATH` inside the sandbox).
51
+
52
+ **Decision:**
53
+
54
+ - **Only one supported agent installed** (the current one): proceed without asking. You will install the skill and instruction file for this agent only.
55
+
56
+ - **Multiple supported agents installed**: ask the user exactly:
57
+
58
+ > I see you have [list of detected agents] installed. Should I set up Videowright for all of them, or just [current agent]?
59
+ > 1. Just [current agent].
60
+ > 2. All installed agents.
61
+ >
62
+ > Which?
63
+
64
+ Default suggestion is **1** (just the current agent). The user can re-run install in another agent later.
65
+
66
+ Record the chosen set of agents for Step 6.
67
+
68
+ ---
69
+
70
+ ## Step 3: Package manager detection
71
+
72
+ Detect the package manager. Apply these rules in order:
73
+
74
+ 1. **Lockfile exists**: `package-lock.json` -> use `npm`. `pnpm-lock.yaml` -> use `pnpm`. If `yarn.lock` or `bun.lockb` exists (but no npm/pnpm lockfile), warn the user:
75
+ > This project uses yarn/bun, which Videowright does not support. Would you like to proceed with npm or pnpm instead?
76
+ If they agree, continue to step 2 to pick npm or pnpm. If not, stop.
77
+
78
+ 2. **No lockfile -- check availability** (use `which` on macOS/Linux, `where` on Windows):
79
+ ```bash
80
+ # macOS / Linux
81
+ which npm
82
+ which pnpm
83
+
84
+ # Windows (if not using WSL)
85
+ where npm
86
+ where pnpm
87
+ ```
88
+ - Only one installed: use it without asking.
89
+ - Both installed: ask the user exactly:
90
+ > Which package manager do you want to use? [npm] or [pnpm]?
91
+ >
92
+ > Default: npm.
93
+ - Neither installed: stop with this exact message:
94
+ > Videowright requires npm or pnpm. Install one and try again.
95
+
96
+ Record the chosen package manager as `<pm>` for the remaining steps.
97
+
98
+ ---
99
+
100
+ ## Step 4: Package install
101
+
102
+ ### 4a: Ensure package.json exists
103
+
104
+ If `package.json` does **not** exist in the current directory, write one with these fields:
105
+
106
+ ```json
107
+ {
108
+ "name": "my-videowright-project",
109
+ "version": "0.1.0",
110
+ "private": true,
111
+ "type": "module",
112
+ "scripts": {
113
+ "dev": "npx videowright dev",
114
+ "render": "npx videowright render"
115
+ }
116
+ }
117
+ ```
118
+
119
+ Optionally rename the `"name"` field to match the current directory name (kebab-case).
120
+
121
+ The canonical source for this shape is `node_modules/videowright/skill/assets/install/package.json` (available after step 4b).
122
+
123
+ If `package.json` **does** exist:
124
+
125
+ 1. Read the file and check for the `"type"` field.
126
+ 2. If `"type"` is missing: add `"type": "module"` to the existing package.json. Do not overwrite other fields.
127
+ 3. If `"type"` exists and equals `"module"`: no action needed.
128
+ 4. If `"type"` exists with a value other than `"module"`: stop and tell the user exactly:
129
+ > Your package.json has `"type": "<current-value>"`. Videowright requires `"type": "module"` for ESM imports. Should I change it?
130
+ If the user agrees, update the field. If not, stop the install -- Videowright will not work without ESM.
131
+ 5. Check for `"scripts"` and add `"dev"` and `"render"` entries if they do not already exist. Do not overwrite existing script entries.
132
+
133
+ ### 4b: Install Videowright
134
+
135
+ ```bash
136
+ <pm> install videowright
137
+ ```
138
+
139
+ ### 4c: Install dev toolchain
140
+
141
+ Install the dev tools that Videowright projects use. These mirror the core Videowright repo's own toolchain.
142
+
143
+ **Pin versions from the core package:** after step 4b, read `node_modules/videowright/package.json` and note the version ranges in its `devDependencies` for `vitest` and `@playwright/test`. Use those same version ranges when installing:
144
+
145
+ ```bash
146
+ <pm> install --save-dev vitest@<version-from-core> @playwright/test@<version-from-core>
147
+ ```
148
+
149
+ **Install latest for tools not in core:** `typescript` and `@biomejs/biome` are not listed in the core `videowright` package's `package.json`. Install the latest version of each:
150
+
151
+ ```bash
152
+ <pm> install --save-dev typescript @biomejs/biome
153
+ ```
154
+
155
+ | Tool | Version source | Purpose |
156
+ |---|---|---|
157
+ | `vitest` | Pin from core package.json | Unit tests for segment helpers |
158
+ | `@playwright/test` | Pin from core package.json | E2e/browser tests for video output |
159
+ | `typescript` | Latest | Type-checking for segments and config |
160
+ | `@biomejs/biome` | Latest | Lint + format (single tool) |
161
+
162
+ If a dev dependency is already present at a compatible version, skip it. If present at an incompatible version, warn the user and let them decide whether to upgrade.
163
+
164
+ ### 4d: Ensure tsconfig.json exists
165
+
166
+ If `tsconfig.json` does **not** exist in the current directory, copy the template:
167
+
168
+ ```bash
169
+ cp node_modules/videowright/skill/assets/install/tsconfig.json tsconfig.json
170
+ ```
171
+
172
+ If `tsconfig.json` **does** exist, leave it alone. Do not attempt to merge tsconfig files — the user's existing configuration takes precedence.
173
+
174
+ ### 4e: Install Playwright browsers
175
+
176
+ ```bash
177
+ npx playwright install
178
+ ```
179
+
180
+ This downloads the browser binaries Playwright needs for e2e testing and video export.
181
+
182
+ ### 4f: Check and install ffmpeg
183
+
184
+ ffmpeg is required for video rendering (combining frames into the final video file). Check whether it is available on PATH:
185
+
186
+ ```bash
187
+ # macOS / Linux
188
+ which ffmpeg
189
+
190
+ # Windows (if not using WSL)
191
+ where ffmpeg
192
+ ```
193
+
194
+ **If ffmpeg is found:** proceed to the next step without prompting.
195
+
196
+ **If ffmpeg is not found:** detect the platform, then check for a supported package manager to attempt auto-install.
197
+
198
+ **Platform detection:** on macOS/Linux, run `uname -s` — a result of `Darwin` means macOS, `Linux` means Linux. On Windows, skip this step (you already know). Then check for a package manager from the matching platform row(s) in the table below (first match wins):
199
+
200
+ | Platform | Package manager detection | Install command |
201
+ |---|---|---|
202
+ | macOS | `which brew` | `brew install ffmpeg` |
203
+ | Linux (Debian/Ubuntu) | `which apt` | `sudo apt update && sudo apt install -y ffmpeg` |
204
+ | Linux (Fedora/RHEL) | `which dnf` | `sudo dnf install -y ffmpeg-free` |
205
+ | Linux (Arch) | `which pacman` | `sudo pacman -S --noconfirm ffmpeg` |
206
+ | Windows | `where choco` | `choco install ffmpeg -y` |
207
+ | Windows | `where scoop` | `scoop install ffmpeg` |
208
+ | Windows | `where winget` | `winget install --id Gyan.FFmpeg -e --accept-source-agreements` |
209
+
210
+ Apply these rules in order:
211
+
212
+ 1. **Recognized package manager found:** ask the user exactly:
213
+
214
+ > ffmpeg is required for video rendering but was not found on your PATH. I can install it for you using `<install-command>`. Proceed?
215
+ > 1. Yes, install ffmpeg.
216
+ > 2. No, I'll install it manually.
217
+
218
+ - If **yes**: run the install command. Then re-verify that `ffmpeg` is on PATH (re-run `which`/`where`). If it still cannot be found, tell the user the install may have failed and show the same manual install message as the "no" case below.
219
+ - If **no**: tell the user exactly:
220
+
221
+ > OK — please install ffmpeg manually and make sure it is on your PATH, then say "done" to continue.
222
+ >
223
+ > - macOS: `brew install ffmpeg` (install Homebrew from https://brew.sh if needed)
224
+ > - Linux: use your distribution's package manager (e.g., `sudo apt install ffmpeg`)
225
+ > - Windows: download from https://ffmpeg.org/download.html, or use `choco install ffmpeg` / `winget install ffmpeg`
226
+
227
+ Wait for the user to confirm, then re-verify that `ffmpeg` is on PATH. If still not found, repeat the message. Do not proceed until ffmpeg is confirmed available.
228
+
229
+ 2. **No recognized package manager found:** tell the user exactly:
230
+
231
+ > ffmpeg is required for video rendering but was not found on your PATH, and I could not detect a supported package manager to install it automatically.
232
+ >
233
+ > Please install ffmpeg manually:
234
+ > - macOS: `brew install ffmpeg` (install Homebrew from https://brew.sh if needed)
235
+ > - Linux: use your distribution's package manager (e.g., `sudo apt install ffmpeg`)
236
+ > - Windows: download from https://ffmpeg.org/download.html, or use `choco install ffmpeg` / `winget install ffmpeg`
237
+ >
238
+ > After installing, make sure `ffmpeg` is on your PATH, then say "done" to continue.
239
+
240
+ Wait for the user to confirm, then re-verify that `ffmpeg` is on PATH. If still not found, repeat the message. Do not proceed until ffmpeg is confirmed available.
241
+
242
+ ### 4g: Verify install
243
+
244
+ 1. Confirm that `node_modules/videowright/` exists after installation. If it does not, surface the error to the user and stop.
245
+ 2. Read `package.json` and verify that `"type"` is set to `"module"`. If it is not, the dev server will fail with `Cannot use import statement outside a module`. Fix it before proceeding.
246
+ 3. Confirm that `tsconfig.json` exists.
247
+
248
+ ---
249
+
250
+ ## Step 5: Skill installation (symlinks)
251
+
252
+ Create **both** of these symlinks at the install root (the Videowright project folder), regardless of which agent(s) the user chose in Step 2. This keeps the install idempotent and future-proof.
253
+
254
+ **Symlinks to create:**
255
+
256
+ | Symlink path | Target |
257
+ |---|---|
258
+ | `.claude/skills/videowright` | `node_modules/videowright/skill/` |
259
+ | `.agents/skills/videowright` | `node_modules/videowright/skill/` |
260
+
261
+ **Coverage:**
262
+
263
+ | Agent | Reads from |
264
+ |---|---|
265
+ | Claude Code | `.claude/skills/` |
266
+ | Codex | `.agents/skills/` |
267
+ | opencode | both `.claude/skills/` and `.agents/skills/` |
268
+
269
+ **How to create each symlink:**
270
+
271
+ Follow the symlink creation algorithm in Appendix B. In summary:
272
+
273
+ 1. Create intermediate directories if they do not exist (e.g., `.claude/skills/`).
274
+ 2. Compute the target as a **relative path** from the symlink's parent directory to `node_modules/videowright/skill/`. See Appendix B for examples.
275
+ 3. If the symlink already exists and points to the correct target: leave it alone.
276
+ 4. If the symlink exists but points elsewhere: ask the user before replacing.
277
+ 5. If a real file or directory exists at the symlink path: ask the user before replacing.
278
+ 6. Create the symlink:
279
+ - macOS/Linux: `ln -s <relative-target> <symlink-path>`
280
+ - Windows: `mklink /D <symlink-path> <relative-target>`
281
+
282
+ **Windows note:** If symlink creation fails on Windows, tell the user exactly:
283
+
284
+ > Symlink creation failed. On Windows, this usually means Developer Mode is off. Either enable Developer Mode (Settings > Privacy & security > For developers > Developer Mode) and re-run, or create the link manually with `mklink /D .claude\skills\videowright node_modules\videowright\skill` (run from an admin terminal). Then verify by running setup again.
285
+
286
+ ---
287
+
288
+ ## Step 6: Instruction file
289
+
290
+ Write or update the instruction file for each agent the user opted to install for in Step 2.
291
+
292
+ **File mapping:**
293
+
294
+ | Agent | Instruction file |
295
+ |---|---|
296
+ | Claude Code | `CLAUDE.md` |
297
+ | Codex | `AGENTS.md` |
298
+ | opencode | `AGENTS.md` |
299
+
300
+ If installing for multiple agents that need different files (e.g., Claude Code + Codex), write the **same content** into each file. Do not symlink between them.
301
+
302
+ **File location:** the instruction file is written at the **root** of the project. If Step 1 chose sub-folder mode, the instruction file goes in the parent (the larger repo's root), not in the sub-folder.
303
+
304
+ **Content:** use a marked region so re-installs are idempotent. Follow the marked-region writer algorithm in Appendix A.
305
+
306
+ The content to place inside the marked region depends on whether this is a root install or sub-folder install:
307
+
308
+ ### Root install content:
309
+
310
+ ```
311
+ <!-- videowright:start -->
312
+ *Auto-managed by Videowright installer. Edits inside this block will be overwritten on re-install. Add your own context outside the markers.*
313
+
314
+ This project is a [Videowright](https://github.com/scosman/videowright) project -- a library for composing animated explainer videos in HTML/CSS/JS.
315
+
316
+ For any video-related work, use the `videowright` skill (loaded automatically from `.claude/skills/videowright` or `.agents/skills/videowright`). It has full guidance on segments, voiceovers, styles, and the dev server.
317
+
318
+ Key paths:
319
+ - `videowright.config.ts` -- project config and default style.
320
+ - `videos/` -- one folder per video.
321
+ - `styles/` -- design tokens and shared styling.
322
+ - `segments/`, `components/`, `transitions/` -- shared building blocks.
323
+ <!-- videowright:end -->
324
+ ```
325
+
326
+ ### Sub-folder install content:
327
+
328
+ When Step 1 chose sub-folder mode (e.g., sub-folder `videos/`), use this complete block instead:
329
+
330
+ ```
331
+ <!-- videowright:start -->
332
+ *Auto-managed by Videowright installer. Edits inside this block will be overwritten on re-install. Add your own context outside the markers.*
333
+
334
+ The folder `<subfolder>/` in this project is a [Videowright](https://github.com/scosman/videowright) project -- a library for composing animated explainer videos in HTML/CSS/JS.
335
+
336
+ For any video-related work, use the `videowright` skill (loaded automatically from `.claude/skills/videowright` or `.agents/skills/videowright`). It has full guidance on segments, voiceovers, styles, and the dev server.
337
+
338
+ Key paths:
339
+ - `<subfolder>/videowright.config.ts` -- project config and default style.
340
+ - `<subfolder>/videos/` -- one folder per video.
341
+ - `<subfolder>/styles/` -- design tokens and shared styling.
342
+ - `<subfolder>/segments/`, `<subfolder>/components/`, `<subfolder>/transitions/` -- shared building blocks.
343
+ <!-- videowright:end -->
344
+ ```
345
+
346
+ Replace `<subfolder>` with the actual sub-folder name chosen in Step 1.
347
+
348
+ ---
349
+
350
+ ## Step 7: Continue to setup
351
+
352
+ Tell the user exactly:
353
+
354
+ > Videowright installed. Now configuring the project.
355
+
356
+ Then immediately load [references/setup.md](../references/setup.md) and follow it. Do **not** wait for user input between install and setup — proceed directly.
357
+
358
+ ---
359
+
360
+ ## Appendix A: Marked-region writer algorithm
361
+
362
+ Given a target file path and the content string to place inside the markers:
363
+
364
+ 1. **File does not exist**: create a new file containing exactly the full marked region as shown in Step 6 (including the start/end markers, the auto-managed note, and the content). For example:
365
+ ```
366
+ <!-- videowright:start -->
367
+ *Auto-managed by Videowright installer. Edits inside this block will be overwritten on re-install. Add your own context outside the markers.*
368
+
369
+ ... rest of content ...
370
+ <!-- videowright:end -->
371
+ ```
372
+
373
+ 2. **File exists**: read its contents and search for the pattern `<!-- videowright:start -->` ... `<!-- videowright:end -->`:
374
+ - **Match found**: replace everything from `<!-- videowright:start -->` through `<!-- videowright:end -->` (inclusive) with the new marked region. This is an idempotent re-install.
375
+ - **No match**: append the full marked region (start marker, auto-managed note, content, end marker -- exactly as shown in point 1) at the end of the file. If the file does not end with a newline, add two blank lines before the region; otherwise add one blank line.
376
+
377
+ 3. **Never modify content outside the markers.**
378
+
379
+ ## Appendix B: Symlink creation algorithm
380
+
381
+ Given a symlink path (e.g., `.claude/skills/videowright`) and a target directory (`node_modules/videowright/skill/`):
382
+
383
+ 1. **Create intermediate directories**: ensure the parent directory of the symlink exists (e.g., `.claude/skills/`). Create with `mkdir -p` if needed.
384
+
385
+ 2. **Compute relative target**: the symlink target must be a relative path from the symlink's parent directory to the target. Compute this dynamically based on the actual directory depth. Examples:
386
+ - **Root install**: symlink at `.claude/skills/videowright`, target at `node_modules/videowright/skill/` -- relative target is `../../node_modules/videowright/skill/`
387
+ - **Sub-folder install** (e.g., project in `videos/`): symlink at `videos/.claude/skills/videowright`, target at `videos/node_modules/videowright/skill/` -- relative target is `../../node_modules/videowright/skill/` (same, because both are relative to the sub-folder root)
388
+
389
+ 3. **Check existing state**:
390
+ - If the path is a symlink pointing to the correct relative target: do nothing (idempotent).
391
+ - If the path is a symlink pointing to a different target: ask the user before replacing:
392
+ > `.claude/skills/videowright` currently points to `<old-target>`. Replace it with a link to `node_modules/videowright/skill/`?
393
+ - If the path is a real file or directory (not a symlink): ask the user before replacing.
394
+ - If the path does not exist: proceed to create.
395
+
396
+ 4. **Create the symlink**:
397
+ - macOS/Linux: `ln -s <relative-target> <symlink-path>`
398
+ - Windows: `mklink /D <symlink-path> <relative-target>`
399
+
400
+ Apply this algorithm identically for both `.claude/skills/videowright` and `.agents/skills/videowright`.
@@ -0,0 +1,199 @@
1
+ # Audio Plan Format
2
+
3
+ ## When this is loaded
4
+
5
+ You are authoring or editing an `audio_plan.md` file for a video. This reference specifies the format, the two-section structure, and the conventions the build and sync stages depend on.
6
+
7
+ ## Overview
8
+
9
+ Every video with audio gets one `audio_plan.md` at `videos/<video-slug>/audio/audio_plan.md`. It describes the complete audio composition: which source assets are used, how they are sliced and placed in time, their volume curves and fades, and the ffmpeg command that renders the final mix.
10
+
11
+ The file has two sections:
12
+
13
+ 1. **Plan** (top) -- the current intended audio composition. Overwritten as the mix evolves.
14
+ 2. **Log** (bottom) -- append-only history of edits and renders. Never delete entries.
15
+
16
+ The build stage reads the Plan section to produce a rendered track. The sync stage reads the rendered track's snapshot to compute per-segment timing. The Log section is for human and agent reference only.
17
+
18
+ ## Plan section
19
+
20
+ ### Structure
21
+
22
+ ```markdown
23
+ # Audio Plan
24
+
25
+ ## Plan
26
+
27
+ <prose summary>
28
+
29
+ ### Cue 1 -- <short name>
30
+ <labeled fields + ffmpeg snippet>
31
+
32
+ ### Cue 2 -- <short name>
33
+ <labeled fields + ffmpeg snippet>
34
+
35
+ ...
36
+
37
+ ### Final mix command
38
+
39
+ <single ffmpeg invocation>
40
+
41
+ ## Log
42
+
43
+ <append-only entries>
44
+ ```
45
+
46
+ ### Prose summary
47
+
48
+ A 1-3 sentence description of the audio composition. It anchors what the mix is trying to achieve and helps when reviewing cue-level detail.
49
+
50
+ Examples:
51
+
52
+ > Music bed throughout. VO carries the demo (4.5-22s). Keyboard SFX over the terminal segment, brief whoosh on transitions.
53
+
54
+ > VO-only track. Single full-file voiceover placed at 0s.
55
+
56
+ ### Cues
57
+
58
+ Cues are listed in playback order. Each cue uses the labeled-field template defined in [cue_template.md](cue_template.md). Every cue ends with an ffmpeg snippet that produces a labeled audio stream.
59
+
60
+ Number cues sequentially starting at 1. When cues are added or removed, renumber.
61
+
62
+ ### Final mix command
63
+
64
+ After all cues, the plan includes a single complete ffmpeg invocation that:
65
+
66
+ 1. Takes every input file referenced by the cues
67
+ 2. Applies the per-cue filter fragments
68
+ 3. Mixes them with `amix` (or equivalent)
69
+ 4. Writes output to `{TRACK_OUT}`
70
+
71
+ The `{TRACK_OUT}` placeholder is replaced at build time with the actual output path (e.g., `audio/tracks/v3/track.mp3`).
72
+
73
+ The final mix command must be a **self-contained, runnable ffmpeg command** -- not a fragment. It should include all inputs, the complete filter graph, and the output path placeholder.
74
+
75
+ Example (VO-only, simplest case):
76
+
77
+ ```bash
78
+ ffmpeg -y \
79
+ -i audio/originals/voiceovers/v1/audio.mp3 \
80
+ -c:a libmp3lame -q:a 2 \
81
+ {TRACK_OUT}
82
+ ```
83
+
84
+ Example (VO + music with ducking):
85
+
86
+ ```bash
87
+ ffmpeg -y \
88
+ -i audio/originals/voiceovers/v1/audio.mp3 \
89
+ -i audio/originals/music/uplift_piano/audio.mp3 \
90
+ -filter_complex "
91
+ [0:a] atrim=0:22.5, asetpts=PTS-STARTPTS [vo];
92
+ [1:a] atrim=0:30, asetpts=PTS-STARTPTS,
93
+ volume='if(between(t,4.5,22),0.15,1)':eval=frame,
94
+ afade=t=in:st=0:d=0.5, afade=t=out:st=28:d=2 [music];
95
+ [vo][music] amix=inputs=2:duration=longest:normalize=0 [mix];
96
+ [mix] loudnorm=I=-14:TP=-1:LRA=11 [out]
97
+ " -map "[out]" -c:a libmp3lame -q:a 2 {TRACK_OUT}
98
+ ```
99
+
100
+ ### Paths in the plan
101
+
102
+ All paths in the plan are **relative to the video folder** (the parent of `audio/`). This matches the working directory when the agent runs ffmpeg from the video folder.
103
+
104
+ Example: `audio/originals/voiceovers/v1/audio.mp3`, not an absolute path.
105
+
106
+ ## Log section
107
+
108
+ The Log section is below the Plan section, separated by `## Log`. Entries are newest-first (most recent at the top, matching PLAN.md convention). Each entry records one discrete event.
109
+
110
+ ### Render entry
111
+
112
+ ```markdown
113
+ ## YYYY-MM-DD HH:MM -- <summary of what changed>
114
+ **Change:** <what was modified in the plan>
115
+ **Why:** <user feedback or reason>
116
+ **Render:** ffmpeg ... -> audio/tracks/vN/track.mp3
117
+ ```
118
+
119
+ ### Activation entry
120
+
121
+ Written when the user approves a track and it becomes the default:
122
+
123
+ ```markdown
124
+ ## YYYY-MM-DD HH:MM -- Adopted vN as active track
125
+ ```
126
+
127
+ ### Discard entry
128
+
129
+ Written when the user discards a rendered track:
130
+
131
+ ```markdown
132
+ ## YYYY-MM-DD HH:MM -- Discarded vN
133
+ **Why:** <user feedback>
134
+ ```
135
+
136
+ ### Edit entry
137
+
138
+ For plan-only changes (no render):
139
+
140
+ ```markdown
141
+ ## YYYY-MM-DD HH:MM -- <what changed>
142
+ **Change:** <description>
143
+ **Why:** <reason>
144
+ ```
145
+
146
+ Free-text body below the structured fields is welcome for longer notes.
147
+
148
+ ## VO-only shortcut
149
+
150
+ For videos with only a voiceover and no SFX or music, the audio plan is minimal:
151
+
152
+ ```markdown
153
+ # Audio Plan
154
+
155
+ ## Plan
156
+
157
+ VO-only track. Single full-file voiceover placed at 0s.
158
+
159
+ ### Cue 1 -- VO (full file)
160
+ Source: audio/originals/voiceovers/v1/
161
+ Slice: full file
162
+ Place at: 0s
163
+ Volume: 100%
164
+ Fades: none
165
+ Notes: Full voiceover, see timing.json for word timings.
166
+
167
+ ffmpeg snippet:
168
+ [0:a] acopy [vo1]
169
+
170
+ ### Final mix command
171
+
172
+ ffmpeg -y \
173
+ -i audio/originals/voiceovers/v1/audio.mp3 \
174
+ -c:a libmp3lame -q:a 2 \
175
+ {TRACK_OUT}
176
+
177
+ ## Log
178
+
179
+ (No entries yet.)
180
+ ```
181
+
182
+ For VO-only videos, the plan is auto-emitted by the skill. The user does not need to understand the plan format -- it is created as part of the voiceover flow and consumed transparently by build and sync.
183
+
184
+ ## Editing the plan
185
+
186
+ When the user requests changes to the audio mix:
187
+
188
+ 1. Update the relevant cues in the Plan section (add, remove, or modify cues).
189
+ 2. Update the final mix command to match the new cue set.
190
+ 3. Renumber cues if needed.
191
+ 4. Do **not** modify the Log section when editing the plan. Log entries are appended only at build time or when significant plan changes are recorded.
192
+
193
+ ## Relationship to other files
194
+
195
+ - **`cue_template.md`** -- defines the per-cue field format
196
+ - **`build.md`** -- reads the plan to produce a rendered track
197
+ - **`sync.md`** -- reads the track's plan snapshot to compute timing
198
+ - **`ffmpeg_cookbook.md`** -- recipes for common ffmpeg operations used in cue snippets
199
+ - **`styles.md`** -- guidance on volume levels, ducking, and mix aesthetics