@open-press/cli 0.8.0 → 1.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 (250) hide show
  1. package/README.md +33 -23
  2. package/dist/cli.js +320 -252
  3. package/package.json +9 -8
  4. package/template/core/AGENTS.md +0 -126
  5. package/template/core/CHANGELOG.md +0 -215
  6. package/template/core/README.md +0 -40
  7. package/template/core/engine/cli.mjs +0 -96
  8. package/template/core/engine/commands/_shared.mjs +0 -177
  9. package/template/core/engine/commands/deploy.mjs +0 -31
  10. package/template/core/engine/commands/dev.mjs +0 -49
  11. package/template/core/engine/commands/doctor.mjs +0 -229
  12. package/template/core/engine/commands/export.mjs +0 -8
  13. package/template/core/engine/commands/init.mjs +0 -24
  14. package/template/core/engine/commands/inspect.mjs +0 -35
  15. package/template/core/engine/commands/pdf.mjs +0 -26
  16. package/template/core/engine/commands/preview.mjs +0 -26
  17. package/template/core/engine/commands/render.mjs +0 -17
  18. package/template/core/engine/commands/replace.mjs +0 -41
  19. package/template/core/engine/commands/search.mjs +0 -33
  20. package/template/core/engine/commands/typecheck.mjs +0 -5
  21. package/template/core/engine/commands/upgrade.mjs +0 -159
  22. package/template/core/engine/commands/validate.mjs +0 -17
  23. package/template/core/engine/document-export.mjs +0 -15
  24. package/template/core/engine/init.mjs +0 -90
  25. package/template/core/engine/output/chrome-pdf.d.mts +0 -34
  26. package/template/core/engine/output/chrome-pdf.mjs +0 -358
  27. package/template/core/engine/output/deploy-sync.mjs +0 -15
  28. package/template/core/engine/output/fonts.mjs +0 -62
  29. package/template/core/engine/output/katex-assets.mjs +0 -45
  30. package/template/core/engine/output/page-block.mjs +0 -30
  31. package/template/core/engine/output/pdf-media.mjs +0 -45
  32. package/template/core/engine/output/public-assets.mjs +0 -19
  33. package/template/core/engine/output/static-server.mjs +0 -532
  34. package/template/core/engine/react/caption-numbering.mjs +0 -73
  35. package/template/core/engine/react/comment-endpoint.d.mts +0 -11
  36. package/template/core/engine/react/comment-endpoint.mjs +0 -102
  37. package/template/core/engine/react/comment-marker.mjs +0 -374
  38. package/template/core/engine/react/document-entry.mjs +0 -324
  39. package/template/core/engine/react/document-export.mjs +0 -373
  40. package/template/core/engine/react/http-json.mjs +0 -24
  41. package/template/core/engine/react/mdx-compile.mjs +0 -599
  42. package/template/core/engine/react/measurement-css.mjs +0 -136
  43. package/template/core/engine/react/object-entities.mjs +0 -119
  44. package/template/core/engine/react/pagination/allocator.mjs +0 -122
  45. package/template/core/engine/react/pagination/regions.mjs +0 -81
  46. package/template/core/engine/react/pagination-constants.mjs +0 -3
  47. package/template/core/engine/react/pagination.mjs +0 -9
  48. package/template/core/engine/react/pipeline/allocate.mjs +0 -251
  49. package/template/core/engine/react/pipeline/final-render.mjs +0 -94
  50. package/template/core/engine/react/pipeline/frame-measurement.mjs +0 -302
  51. package/template/core/engine/react/pipeline/press-tree.mjs +0 -135
  52. package/template/core/engine/react/project-asset-endpoint.d.mts +0 -10
  53. package/template/core/engine/react/project-asset-endpoint.mjs +0 -361
  54. package/template/core/engine/react/section-css.mjs +0 -56
  55. package/template/core/engine/react/source-edit-endpoint.d.mts +0 -10
  56. package/template/core/engine/react/source-edit-endpoint.mjs +0 -75
  57. package/template/core/engine/react/sources/heading-numbering.mjs +0 -132
  58. package/template/core/engine/react/sources/mdx-resolver.mjs +0 -439
  59. package/template/core/engine/react/style-discovery.mjs +0 -142
  60. package/template/core/engine/runtime/config.d.mts +0 -40
  61. package/template/core/engine/runtime/config.mjs +0 -175
  62. package/template/core/engine/runtime/file-utils.mjs +0 -106
  63. package/template/core/engine/runtime/file-walk.mjs +0 -22
  64. package/template/core/engine/runtime/inspection.mjs +0 -328
  65. package/template/core/engine/runtime/issue-report.mjs +0 -44
  66. package/template/core/engine/runtime/path-utils.mjs +0 -20
  67. package/template/core/engine/runtime/source-text-tools.d.mts +0 -102
  68. package/template/core/engine/runtime/source-text-tools.mjs +0 -832
  69. package/template/core/engine/runtime/source-workspace.mjs +0 -159
  70. package/template/core/engine/runtime/validation.mjs +0 -174
  71. package/template/core/index.html +0 -13
  72. package/template/core/openpress.config.mjs +0 -12
  73. package/template/core/package.json +0 -91
  74. package/template/core/src/main.tsx +0 -16
  75. package/template/core/src/openpress/app/OpenPressApp.tsx +0 -140
  76. package/template/core/src/openpress/app/OpenPressRuntime.tsx +0 -94
  77. package/template/core/src/openpress/app/index.ts +0 -2
  78. package/template/core/src/openpress/core/Frame.tsx +0 -78
  79. package/template/core/src/openpress/core/FrameContext.tsx +0 -24
  80. package/template/core/src/openpress/core/MdxArea.tsx +0 -34
  81. package/template/core/src/openpress/core/Press.tsx +0 -34
  82. package/template/core/src/openpress/core/cn.ts +0 -4
  83. package/template/core/src/openpress/core/index.tsx +0 -40
  84. package/template/core/src/openpress/core/primitives.tsx +0 -44
  85. package/template/core/src/openpress/core/types.ts +0 -191
  86. package/template/core/src/openpress/core/useSource.ts +0 -28
  87. package/template/core/src/openpress/document-model/anchorMapModel.ts +0 -27
  88. package/template/core/src/openpress/document-model/documentIndexes.ts +0 -329
  89. package/template/core/src/openpress/document-model/documentTypes.ts +0 -138
  90. package/template/core/src/openpress/document-model/index.ts +0 -6
  91. package/template/core/src/openpress/document-model/objectEntityModel.ts +0 -51
  92. package/template/core/src/openpress/document-model/projectIdentityModel.ts +0 -15
  93. package/template/core/src/openpress/document-model/reactDocumentMetadataModel.ts +0 -27
  94. package/template/core/src/openpress/manuscript/index.tsx +0 -238
  95. package/template/core/src/openpress/mdx/index.ts +0 -88
  96. package/template/core/src/openpress/numbering/index.ts +0 -294
  97. package/template/core/src/openpress/reader/PublicReaderPage.tsx +0 -267
  98. package/template/core/src/openpress/reader/ReaderNavigationPanel.tsx +0 -123
  99. package/template/core/src/openpress/reader/index.ts +0 -10
  100. package/template/core/src/openpress/reader/pageViewportScaleModel.ts +0 -73
  101. package/template/core/src/openpress/reader/readerPageRegistry.ts +0 -41
  102. package/template/core/src/openpress/reader/readerPageRoute.ts +0 -21
  103. package/template/core/src/openpress/reader/readerScroll.ts +0 -92
  104. package/template/core/src/openpress/reader/readerStateModel.ts +0 -15
  105. package/template/core/src/openpress/reader/readerTypes.ts +0 -4
  106. package/template/core/src/openpress/reader/usePageViewportScale.ts +0 -119
  107. package/template/core/src/openpress/reader/usePanelState.ts +0 -56
  108. package/template/core/src/openpress/reader/useReaderHashSync.ts +0 -61
  109. package/template/core/src/openpress/reader/useReaderKeyboardNav.ts +0 -48
  110. package/template/core/src/openpress/reader/useReaderRuntime.ts +0 -146
  111. package/template/core/src/openpress/reader/useReaderScrollAnchor.ts +0 -64
  112. package/template/core/src/openpress/shared/Panel.tsx +0 -77
  113. package/template/core/src/openpress/shared/frameScheduler.ts +0 -32
  114. package/template/core/src/openpress/shared/index.ts +0 -4
  115. package/template/core/src/openpress/shared/numberUtils.ts +0 -3
  116. package/template/core/src/openpress/shared/runtimeMode.ts +0 -11
  117. package/template/core/src/openpress/workbench/Workbench.tsx +0 -407
  118. package/template/core/src/openpress/workbench/actions/DeploymentControl.tsx +0 -157
  119. package/template/core/src/openpress/workbench/actions/PageZoomControl.tsx +0 -182
  120. package/template/core/src/openpress/workbench/actions/SearchControl.tsx +0 -345
  121. package/template/core/src/openpress/workbench/actions/deploymentStatusModel.ts +0 -112
  122. package/template/core/src/openpress/workbench/actions/index.ts +0 -5
  123. package/template/core/src/openpress/workbench/actions/useDeploymentWorkbench.ts +0 -136
  124. package/template/core/src/openpress/workbench/dialog/WorkbenchDialog.tsx +0 -72
  125. package/template/core/src/openpress/workbench/dialog/index.ts +0 -1
  126. package/template/core/src/openpress/workbench/document/components/DocumentPanel.tsx +0 -127
  127. package/template/core/src/openpress/workbench/document/components/InlineSourceEditorLayer.tsx +0 -207
  128. package/template/core/src/openpress/workbench/document/components/ReaderStage.tsx +0 -9
  129. package/template/core/src/openpress/workbench/document/hooks/useDocumentWorkbenchModel.ts +0 -34
  130. package/template/core/src/openpress/workbench/document/hooks/useInlineDocumentEditor.ts +0 -525
  131. package/template/core/src/openpress/workbench/document/index.ts +0 -10
  132. package/template/core/src/openpress/workbench/index.ts +0 -2
  133. package/template/core/src/openpress/workbench/inspector/InlineInspectorLayer.tsx +0 -459
  134. package/template/core/src/openpress/workbench/inspector/index.ts +0 -5
  135. package/template/core/src/openpress/workbench/inspector/inlineCommentModel.ts +0 -125
  136. package/template/core/src/openpress/workbench/inspector/inspectorGeometryModel.ts +0 -160
  137. package/template/core/src/openpress/workbench/inspector/inspectorModel.ts +0 -408
  138. package/template/core/src/openpress/workbench/inspector/useInspectorComments.ts +0 -248
  139. package/template/core/src/openpress/workbench/mentions/MentionSuggestionList.tsx +0 -41
  140. package/template/core/src/openpress/workbench/mentions/index.ts +0 -2
  141. package/template/core/src/openpress/workbench/mentions/useComposerMentions.ts +0 -185
  142. package/template/core/src/openpress/workbench/panels/Panel.tsx +0 -1
  143. package/template/core/src/openpress/workbench/panels/PendingCommentsPanel.tsx +0 -76
  144. package/template/core/src/openpress/workbench/panels/WorkbenchControlPanel.tsx +0 -29
  145. package/template/core/src/openpress/workbench/panels/index.ts +0 -3
  146. package/template/core/src/openpress/workbench/project/ProjectEntryPanel.tsx +0 -523
  147. package/template/core/src/openpress/workbench/project/ProjectPreviewDialog.tsx +0 -35
  148. package/template/core/src/openpress/workbench/project/index.ts +0 -2
  149. package/template/core/src/openpress/workbench/project/projectPreviewTypes.ts +0 -11
  150. package/template/core/src/openpress/workbench/project/projectSourceModel.ts +0 -24
  151. package/template/core/src/openpress/workbench/shell/WorkbenchShell.tsx +0 -167
  152. package/template/core/src/openpress/workbench/shell/index.ts +0 -1
  153. package/template/core/src/openpress/workbench/workbenchFormatters.ts +0 -120
  154. package/template/core/src/openpress/workbench/workbenchTypes.ts +0 -35
  155. package/template/core/src/styles/openpress/app-shell.css +0 -251
  156. package/template/core/src/styles/openpress/media-workspace.css +0 -230
  157. package/template/core/src/styles/openpress/print-route.css +0 -184
  158. package/template/core/src/styles/openpress/project-preview-panel.css +0 -924
  159. package/template/core/src/styles/openpress/public-viewer.css +0 -688
  160. package/template/core/src/styles/openpress/reader-runtime.css +0 -980
  161. package/template/core/src/styles/openpress/responsive.css +0 -245
  162. package/template/core/src/styles/openpress/workbench-panels.css +0 -594
  163. package/template/core/src/styles/openpress/workbench.css +0 -1255
  164. package/template/core/src/styles/openpress.css +0 -14
  165. package/template/core/src/vite-env.d.ts +0 -9
  166. package/template/core/tsconfig.json +0 -40
  167. package/template/core/vite.config.ts +0 -584
  168. package/template/packs/academic-paper/document/chapters/01-introduction/content/01-introduction.mdx +0 -35
  169. package/template/packs/academic-paper/document/chapters/02-methods/content/01-methods.mdx +0 -50
  170. package/template/packs/academic-paper/document/chapters/03-results-and-discussion/content/01-results.mdx +0 -47
  171. package/template/packs/academic-paper/document/chapters/04-acknowledgment/content/01-acknowledgment.mdx +0 -26
  172. package/template/packs/academic-paper/document/chapters/05-references/content/01-references.mdx +0 -32
  173. package/template/packs/academic-paper/document/components/ChapterOpenerVisual/index.tsx +0 -76
  174. package/template/packs/academic-paper/document/components/Page.tsx +0 -60
  175. package/template/packs/academic-paper/document/components/TokenSwatchGrid/index.tsx +0 -46
  176. package/template/packs/academic-paper/document/components/TokenSwatchGrid/style.css +0 -63
  177. package/template/packs/academic-paper/document/components/TypeSpecimen/index.tsx +0 -38
  178. package/template/packs/academic-paper/document/components/TypeSpecimen/style.css +0 -111
  179. package/template/packs/academic-paper/document/design.md +0 -279
  180. package/template/packs/academic-paper/document/index.tsx +0 -123
  181. package/template/packs/academic-paper/document/media/README.md +0 -13
  182. package/template/packs/academic-paper/document/media/figure-placeholder.svg +0 -9
  183. package/template/packs/academic-paper/document/openpress.config.mjs +0 -26
  184. package/template/packs/academic-paper/document/theme/README.md +0 -11
  185. package/template/packs/academic-paper/document/theme/base/page-contract.css +0 -522
  186. package/template/packs/academic-paper/document/theme/base/print.css +0 -93
  187. package/template/packs/academic-paper/document/theme/base/typography.css +0 -333
  188. package/template/packs/academic-paper/document/theme/fonts.css +0 -3
  189. package/template/packs/academic-paper/document/theme/page-surfaces/back-cover.css +0 -43
  190. package/template/packs/academic-paper/document/theme/page-surfaces/chapter-opener.css +0 -205
  191. package/template/packs/academic-paper/document/theme/page-surfaces/cover.css +0 -294
  192. package/template/packs/academic-paper/document/theme/page-surfaces/toc.css +0 -149
  193. package/template/packs/academic-paper/document/theme/patterns/_chart-frame.css +0 -49
  194. package/template/packs/academic-paper/document/theme/patterns/figure-grid.css +0 -68
  195. package/template/packs/academic-paper/document/theme/patterns/table-utilities.css +0 -66
  196. package/template/packs/academic-paper/document/theme/shell/reader-controls.css +0 -761
  197. package/template/packs/academic-paper/document/theme/tokens.css +0 -80
  198. package/template/packs/academic-paper/openpress.config.mjs +0 -5
  199. package/template/packs/claude-document/document/chapters/01-document-shape/content/01-document-shape.mdx +0 -51
  200. package/template/packs/claude-document/document/chapters/02-review-loop/content/01-review-loop.mdx +0 -31
  201. package/template/packs/claude-document/document/components/ChapterOpenerVisual.tsx +0 -96
  202. package/template/packs/claude-document/document/components/Page.tsx +0 -37
  203. package/template/packs/claude-document/document/design.md +0 -142
  204. package/template/packs/claude-document/document/index.tsx +0 -94
  205. package/template/packs/claude-document/document/media/README.md +0 -13
  206. package/template/packs/claude-document/document/openpress.config.mjs +0 -26
  207. package/template/packs/claude-document/document/theme/README.md +0 -15
  208. package/template/packs/claude-document/document/theme/base/page-contract.css +0 -525
  209. package/template/packs/claude-document/document/theme/base/print.css +0 -93
  210. package/template/packs/claude-document/document/theme/base/typography.css +0 -612
  211. package/template/packs/claude-document/document/theme/fonts.css +0 -4
  212. package/template/packs/claude-document/document/theme/page-surfaces/back-cover.css +0 -72
  213. package/template/packs/claude-document/document/theme/page-surfaces/chapter-opener.css +0 -236
  214. package/template/packs/claude-document/document/theme/page-surfaces/cover.css +0 -309
  215. package/template/packs/claude-document/document/theme/page-surfaces/toc.css +0 -225
  216. package/template/packs/claude-document/document/theme/patterns/_chart-frame.css +0 -53
  217. package/template/packs/claude-document/document/theme/patterns/figure-grid.css +0 -68
  218. package/template/packs/claude-document/document/theme/patterns/table-utilities.css +0 -66
  219. package/template/packs/claude-document/document/theme/shell/reader-controls.css +0 -789
  220. package/template/packs/claude-document/document/theme/tokens.css +0 -89
  221. package/template/packs/claude-document/openpress.config.mjs +0 -5
  222. package/template/packs/editorial-monograph/document/chapters/01-product-and-use-cases/content/01-product-and-use-cases.mdx +0 -31
  223. package/template/packs/editorial-monograph/document/chapters/02-workflow/content/01-workflow.mdx +0 -89
  224. package/template/packs/editorial-monograph/document/chapters/03-agent-skills-contributors/content/01-agent-skills-contributors.mdx +0 -51
  225. package/template/packs/editorial-monograph/document/chapters/04-validation-deploy/content/01-validation-deploy.mdx +0 -39
  226. package/template/packs/editorial-monograph/document/components/ChapterOpenerVisual/index.tsx +0 -76
  227. package/template/packs/editorial-monograph/document/components/Page.tsx +0 -37
  228. package/template/packs/editorial-monograph/document/components/TokenSwatchGrid/index.tsx +0 -46
  229. package/template/packs/editorial-monograph/document/components/TokenSwatchGrid/style.css +0 -63
  230. package/template/packs/editorial-monograph/document/components/TypeSpecimen/index.tsx +0 -38
  231. package/template/packs/editorial-monograph/document/components/TypeSpecimen/style.css +0 -111
  232. package/template/packs/editorial-monograph/document/design.md +0 -279
  233. package/template/packs/editorial-monograph/document/index.tsx +0 -97
  234. package/template/packs/editorial-monograph/document/media/README.md +0 -13
  235. package/template/packs/editorial-monograph/document/openpress.config.mjs +0 -26
  236. package/template/packs/editorial-monograph/document/theme/README.md +0 -11
  237. package/template/packs/editorial-monograph/document/theme/base/page-contract.css +0 -505
  238. package/template/packs/editorial-monograph/document/theme/base/print.css +0 -93
  239. package/template/packs/editorial-monograph/document/theme/base/typography.css +0 -336
  240. package/template/packs/editorial-monograph/document/theme/fonts.css +0 -3
  241. package/template/packs/editorial-monograph/document/theme/page-surfaces/back-cover.css +0 -43
  242. package/template/packs/editorial-monograph/document/theme/page-surfaces/chapter-opener.css +0 -205
  243. package/template/packs/editorial-monograph/document/theme/page-surfaces/cover.css +0 -147
  244. package/template/packs/editorial-monograph/document/theme/page-surfaces/toc.css +0 -149
  245. package/template/packs/editorial-monograph/document/theme/patterns/_chart-frame.css +0 -49
  246. package/template/packs/editorial-monograph/document/theme/patterns/figure-grid.css +0 -68
  247. package/template/packs/editorial-monograph/document/theme/patterns/table-utilities.css +0 -66
  248. package/template/packs/editorial-monograph/document/theme/shell/reader-controls.css +0 -761
  249. package/template/packs/editorial-monograph/document/theme/tokens.css +0 -80
  250. package/template/packs/editorial-monograph/openpress.config.mjs +0 -5
package/dist/cli.js CHANGED
@@ -1,66 +1,29 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli.ts
4
+ import { spawn as spawn2 } from "child_process";
5
+ import { createRequire } from "module";
6
+ import path2 from "path";
4
7
  import process2 from "process";
5
8
 
6
9
  // src/init.ts
7
10
  import { spawn } from "child_process";
8
11
  import { existsSync } from "fs";
9
- import { cp, mkdir as mkdir2, rm as rm2 } from "fs/promises";
10
- import path2 from "path";
12
+ import { mkdir, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
13
+ import path from "path";
11
14
  import process from "process";
12
15
  import { fileURLToPath } from "url";
13
16
 
14
- // src/degit.ts
15
- import { createWriteStream } from "fs";
16
- import { mkdir, rm, stat } from "fs/promises";
17
- import { tmpdir } from "os";
18
- import path from "path";
19
- import { Readable } from "stream";
20
- import { pipeline } from "stream/promises";
21
- import { x as extract } from "tar";
22
- async function degit({ owner, repo, ref = "main", dest, subdir }) {
23
- const url = `https://codeload.github.com/${owner}/${repo}/tar.gz/refs/heads/${ref}`;
24
- const tmpDir = await mkdir(path.join(tmpdir(), `open-press-degit-${Date.now()}`), { recursive: true });
25
- const tarballPath = path.join(tmpDir, "repo.tar.gz");
26
- try {
27
- await fetchTo(url, tarballPath);
28
- await mkdir(dest, { recursive: true });
29
- const subdirSegments = subdir ? subdir.split("/").filter(Boolean).length : 0;
30
- const totalStrip = 1 + subdirSegments;
31
- const filterPrefix = subdir ? subdir.replace(/\/$/, "") + "/" : null;
32
- await extract({
33
- file: tarballPath,
34
- cwd: dest,
35
- strip: totalStrip,
36
- filter: (filePath) => {
37
- const segments = filePath.split("/");
38
- const inside = segments.slice(1).join("/");
39
- if (filterPrefix) {
40
- return inside.startsWith(filterPrefix);
41
- }
42
- return true;
43
- }
44
- });
45
- } finally {
46
- await rm(tmpDir, { recursive: true, force: true }).catch(() => {
47
- });
48
- }
49
- }
50
- async function fetchTo(url, destFile) {
51
- const res = await fetch(url, { redirect: "follow" });
52
- if (!res.ok || !res.body) {
53
- throw new Error(`Failed to fetch ${url}: ${res.status} ${res.statusText}`);
54
- }
55
- await pipeline(Readable.fromWeb(res.body), createWriteStream(destFile));
56
- }
57
- async function pathIsEmpty(target) {
17
+ // src/path-is-empty.ts
18
+ import { readdir, stat } from "fs/promises";
19
+ var HARMLESS_TARGET_ENTRIES = /* @__PURE__ */ new Set([".git", ".gitignore", ".gitkeep", ".DS_Store"]);
20
+ async function pathIsEmpty(target, options = {}) {
58
21
  try {
59
22
  const s = await stat(target);
60
23
  if (!s.isDirectory()) return false;
61
- const { readdir } = await import("fs/promises");
62
24
  const entries = await readdir(target);
63
- return entries.length === 0;
25
+ if (!options.ignoreHarmless) return entries.length === 0;
26
+ return entries.every((entry) => HARMLESS_TARGET_ENTRIES.has(entry));
64
27
  } catch {
65
28
  return true;
66
29
  }
@@ -68,133 +31,51 @@ async function pathIsEmpty(target) {
68
31
 
69
32
  // src/metadata.ts
70
33
  import { readFile, writeFile } from "fs/promises";
71
- async function patchOpenpressConfig(configPath, patch) {
72
- let source = await readFile(configPath, "utf8");
73
- for (const [key, value] of Object.entries(patch)) {
74
- if (value === void 0 || value === null || value === "") continue;
75
- const escaped = escapeStringForJs(value);
76
- const re = new RegExp(`(${key}\\s*:\\s*)("[^"]*"|'[^']*'|\`[^\`]*\`)`, "m");
77
- if (re.test(source)) {
78
- source = source.replace(re, `$1"${escaped}"`);
79
- } else {
80
- source = source.replace(/(export\s+default\s*\{)/, `$1
81
- ${key}: "${escaped}",`);
82
- }
34
+ async function patchPressTitle(entryPath, title) {
35
+ const source = await readFile(entryPath, "utf8");
36
+ const escaped = escapeStringForJs(title);
37
+ const existing = /(<Press\b[^>]*\btitle\s*=\s*)("[^"]*"|'[^']*'|\{`[^`]*`\})/;
38
+ let next;
39
+ if (existing.test(source)) {
40
+ next = source.replace(existing, `$1"${escaped}"`);
41
+ } else {
42
+ next = source.replace(/<Press\b/, `<Press title="${escaped}"`);
83
43
  }
84
- await writeFile(configPath, source);
44
+ await writeFile(entryPath, next);
85
45
  }
86
46
  function escapeStringForJs(value) {
87
47
  return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
88
48
  }
89
- async function patchPackageJsonName(packagePath, newName) {
90
- const text = await readFile(packagePath, "utf8");
91
- const pkg = JSON.parse(text);
92
- const prevName = typeof pkg.name === "string" ? pkg.name : "";
93
- pkg.name = newName;
94
- pkg.version = "0.0.0";
95
- pkg.private = true;
96
- pkg.description = `open-press workspace: ${newName}`;
97
- for (const field of [
98
- "publishConfig",
99
- "files",
100
- "bin",
101
- "main",
102
- "types",
103
- "exports",
104
- "homepage",
105
- "repository",
106
- "bugs",
107
- "keywords",
108
- "license",
109
- "author"
110
- ]) {
111
- delete pkg[field];
112
- }
113
- await writeFile(packagePath, JSON.stringify(pkg, null, 2) + "\n");
114
- return prevName;
115
- }
116
49
 
117
50
  // src/init.ts
118
- var BUNDLED_PACKS = ["editorial-monograph", "claude-document", "academic-paper"];
119
51
  var FRAMEWORK_SKILLS_SOURCE = "quan0715/open-press";
120
- var __dirname = path2.dirname(fileURLToPath(import.meta.url));
121
- var TEMPLATE_ROOT = path2.resolve(__dirname, "..", "template");
122
- var TEMPLATE_CORE = path2.join(TEMPLATE_ROOT, "core");
123
- var TEMPLATE_PACKS = path2.join(TEMPLATE_ROOT, "packs");
52
+ var __dirname = path.dirname(fileURLToPath(import.meta.url));
53
+ var CLI_PACKAGE_JSON = path.resolve(__dirname, "..", "package.json");
124
54
  async function init(options) {
125
- const packSpec = options.pack ? parsePackSpec(options.pack) : null;
126
- ensureTemplateBundled();
127
- const target = path2.resolve(process.cwd(), options.target);
128
- await ensureTarget(target, options.force);
55
+ const target = path.resolve(process.cwd(), options.target);
56
+ await ensureTarget(target);
57
+ const workspaceName = path.basename(target);
58
+ const title = options.title ?? "OpenPress Document";
59
+ const version = await readCliVersion();
129
60
  log(`Creating open-press workspace at ${target}`);
130
- log("Copying framework (engine + runtime + config)\u2026");
131
- await cp(TEMPLATE_CORE, target, { recursive: true });
132
- const docDest = path2.join(target, "document");
133
- await rm2(docDest, { recursive: true, force: true });
134
- await mkdir2(docDest, { recursive: true });
135
- if (packSpec?.kind === "bundled") {
136
- log(`Applying bundled style pack: ${packSpec.name}`);
137
- const packStarter = path2.join(TEMPLATE_PACKS, packSpec.name, "document");
138
- if (!existsSync(packStarter)) {
139
- throw new Error(`Bundled style pack starter not found: ${packStarter}`);
140
- }
141
- await cp(packStarter, docDest, { recursive: true });
142
- } else if (packSpec?.kind === "github") {
143
- log(`Fetching style pack from github:${packSpec.owner}/${packSpec.repo}${packSpec.ref ? `#${packSpec.ref}` : ""}\u2026`);
144
- try {
145
- await degit({
146
- owner: packSpec.owner,
147
- repo: packSpec.repo,
148
- ref: packSpec.ref,
149
- dest: docDest,
150
- subdir: "starter/document"
151
- });
152
- } catch (err) {
153
- throw new Error(
154
- `Failed to fetch pack from github:${packSpec.owner}/${packSpec.repo}: ${err instanceof Error ? err.message : String(err)}`
155
- );
156
- }
157
- if (await pathIsEmpty(docDest)) {
158
- throw new Error(
159
- `github:${packSpec.owner}/${packSpec.repo} doesn't contain starter/document/ at the repo root.
160
- Third-party pack repos should follow this layout:
161
- <repo>/
162
- \u251C\u2500\u2500 starter/
163
- \u2502 \u2514\u2500\u2500 document/ \u2190 cli copies this into your workspace's document/
164
- \u2514\u2500\u2500 skills/<pack>/SKILL.md \u2190 npx skills add picks this up`
165
- );
166
- }
61
+ await writeWorkspacePackageJson(target, workspaceName, version);
62
+ await writeWorkspaceGitignore(target);
63
+ await writeStarterPress(target, title);
64
+ if (options.title) {
65
+ const pressEntry = path.join(target, "press", "index.tsx");
66
+ log("Writing title into <Press> in press/index.tsx");
67
+ await patchPressTitle(pressEntry, options.title);
167
68
  }
168
- const pkgPath = path2.join(target, "package.json");
169
- if (existsSync(pkgPath)) {
170
- await patchPackageJsonName(pkgPath, path2.basename(target));
171
- }
172
- const configPath = path2.join(target, "openpress.config.mjs");
173
- if (existsSync(configPath) && hasMetadata(options)) {
174
- log("Writing metadata into openpress.config.mjs");
175
- await patchOpenpressConfig(configPath, {
176
- title: options.title,
177
- subtitle: options.subtitle,
178
- organization: options.organization,
179
- author: options.author
180
- });
181
- }
182
- log(`Installing framework skills via \`npx skills add ${FRAMEWORK_SKILLS_SOURCE}\`\u2026`);
183
- try {
184
- await runInTarget(target, "npx", ["-y", "skills@latest", "add", FRAMEWORK_SKILLS_SOURCE]);
185
- } catch (err) {
186
- log(`(framework skills install failed; retry: npx skills add ${FRAMEWORK_SKILLS_SOURCE})`);
187
- log(` reason: ${err instanceof Error ? err.message : String(err)}`);
188
- }
189
- if (packSpec?.kind === "github") {
190
- const packSource = `${packSpec.owner}/${packSpec.repo}`;
191
- log(`Installing pack skills via \`npx skills add ${packSource}\`\u2026`);
69
+ if (options.skills) {
70
+ log(`Installing framework skills via \`open-press skills add\`\u2026`);
192
71
  try {
193
- await runInTarget(target, "npx", ["-y", "skills@latest", "add", packSource]);
72
+ await runInTarget(target, "npx", ["-y", "skills@latest", "add", FRAMEWORK_SKILLS_SOURCE]);
194
73
  } catch (err) {
195
- log(`(pack skills install failed; retry: npx skills add ${packSource})`);
74
+ log(`(framework skills install failed; retry later: open-press skills add)`);
196
75
  log(` reason: ${err instanceof Error ? err.message : String(err)}`);
197
76
  }
77
+ } else {
78
+ log("Skipping agent skills (--no-skills)");
198
79
  }
199
80
  if (options.install) {
200
81
  log("Installing dependencies (npm install)\u2026");
@@ -216,46 +97,200 @@ Third-party pack repos should follow this layout:
216
97
  }
217
98
  printNextSteps(target, options);
218
99
  }
219
- function parsePackSpec(spec) {
220
- if (spec.startsWith("github:")) {
221
- const rest = spec.slice("github:".length);
222
- const [pathPart, ref] = rest.split("#");
223
- const segments = pathPart.split("/").filter(Boolean);
224
- if (segments.length !== 2) {
100
+ async function ensureTarget(target) {
101
+ if (existsSync(target)) {
102
+ const empty = await pathIsEmpty(target, { ignoreHarmless: true });
103
+ if (!empty) {
225
104
  throw new Error(
226
- `Invalid --pack spec: "${spec}". Use github:owner/repo or github:owner/repo#ref.`
105
+ `Target ${target} is not empty. Remove existing files first, or scaffold into a different directory.`
227
106
  );
228
107
  }
229
- const [owner, repo] = segments;
230
- return { kind: "github", owner, repo, ref: ref?.trim() || void 0 };
231
- }
232
- if (!BUNDLED_PACKS.includes(spec)) {
233
- throw new Error(
234
- `Unknown style pack: "${spec}". Bundled packs: ${BUNDLED_PACKS.join(", ")}. For third-party packs use github:owner/repo (e.g. github:quan0715/openpress-pack-nycu-thesis).`
235
- );
108
+ return;
236
109
  }
237
- return { kind: "bundled", name: spec };
110
+ await mkdir(target, { recursive: true });
238
111
  }
239
- function ensureTemplateBundled() {
240
- if (!existsSync(TEMPLATE_CORE) || !existsSync(TEMPLATE_PACKS)) {
241
- throw new Error(
242
- `Template not bundled at ${TEMPLATE_ROOT}. If running from source, run \`pnpm sync:template\` in packages/cli first.`
243
- );
244
- }
112
+ async function readCliVersion() {
113
+ const pkg = JSON.parse(await readFile2(CLI_PACKAGE_JSON, "utf8"));
114
+ return typeof pkg.version === "string" && pkg.version ? pkg.version : "latest";
245
115
  }
246
- async function ensureTarget(target, force) {
247
- if (existsSync(target)) {
248
- if (force) return;
249
- const empty = await pathIsEmpty(target);
250
- if (!empty) {
251
- throw new Error(`Target ${target} is not empty. Pass --force to scaffold into it anyway.`);
116
+ async function writeWorkspacePackageJson(target, workspaceName, version) {
117
+ const pkg = {
118
+ name: workspaceName,
119
+ version: "0.0.0",
120
+ private: true,
121
+ type: "module",
122
+ description: `open-press workspace: ${workspaceName}`,
123
+ scripts: {
124
+ dev: "open-press dev . --renderer react",
125
+ build: "open-press render . --renderer react",
126
+ preview: "open-press preview . --renderer react",
127
+ typecheck: "open-press typecheck .",
128
+ "openpress:image": "open-press image .",
129
+ "openpress:pdf": "open-press pdf .",
130
+ "openpress:deploy": "open-press deploy .",
131
+ "openpress:deploy:dry-run": "open-press deploy . --confirm --dry-run",
132
+ "openpress:skills": "open-press skills update"
133
+ },
134
+ dependencies: {
135
+ "@open-press/core": version
136
+ },
137
+ devDependencies: {
138
+ "@open-press/cli": version,
139
+ "@types/node": "^25.8.0",
140
+ "@types/react": "^19.2.14",
141
+ "@types/react-dom": "^19.2.3",
142
+ typescript: "^6.0.3"
143
+ },
144
+ openpress: {
145
+ pdf: {
146
+ filename: "document.pdf"
147
+ },
148
+ deploy: {
149
+ adapter: "cloudflare-pages",
150
+ source: ".deploy/openpress",
151
+ projectName: null,
152
+ commitDirty: false,
153
+ requiresConfirmation: true
154
+ }
252
155
  }
253
- return;
156
+ };
157
+ await writeFile2(path.join(target, "package.json"), `${JSON.stringify(pkg, null, 2)}
158
+ `, "utf8");
159
+ }
160
+ async function writeWorkspaceGitignore(target) {
161
+ const content = [
162
+ "node_modules/",
163
+ ".DS_Store",
164
+ "*.log",
165
+ "",
166
+ "# OpenPress generated artifacts",
167
+ ".openpress/",
168
+ ".deploy/",
169
+ ".turbo/",
170
+ "dist/",
171
+ "dist-react/",
172
+ "public/openpress/",
173
+ "output/",
174
+ ""
175
+ ].join("\n");
176
+ await writeFile2(path.join(target, ".gitignore"), content, "utf8");
177
+ }
178
+ async function writeStarterPress(target, title) {
179
+ const pressRoot = path.join(target, "press");
180
+ await mkdir(path.join(pressRoot, "components"), { recursive: true });
181
+ await mkdir(path.join(pressRoot, "media"), { recursive: true });
182
+ await mkdir(path.join(pressRoot, "theme", "base"), { recursive: true });
183
+ await mkdir(path.join(pressRoot, "theme", "page-surfaces"), { recursive: true });
184
+ await mkdir(path.join(pressRoot, "theme", "shell"), { recursive: true });
185
+ await writeFile2(path.join(pressRoot, "design.md"), `# ${title}
186
+
187
+ Starter OpenPress workspace.
188
+ `, "utf8");
189
+ await writeFile2(path.join(pressRoot, "media", "README.md"), "# Media\n\nPlace project media here.\n", "utf8");
190
+ await writeFile2(
191
+ path.join(pressRoot, "theme", "base", "page-contract.css"),
192
+ `* {
193
+ box-sizing: border-box;
194
+ }
195
+
196
+ html,
197
+ body {
198
+ margin: 0;
199
+ background: #181818;
200
+ }
201
+
202
+ body {
203
+ color: #171717;
204
+ font-family: var(--openpress-font-body, system-ui, sans-serif);
205
+ -webkit-print-color-adjust: exact;
206
+ print-color-adjust: exact;
207
+ }
208
+
209
+ .reader-page {
210
+ background: #ffffff;
211
+ }
212
+ `,
213
+ "utf8"
214
+ );
215
+ await writeFile2(
216
+ path.join(pressRoot, "theme", "base", "typography.css"),
217
+ `h1,
218
+ h2,
219
+ h3,
220
+ p {
221
+ margin: 0;
222
+ }
223
+
224
+ h1 {
225
+ font-family: var(--openpress-font-serif, Georgia, serif);
226
+ font-size: clamp(42px, 8cqw, 72px);
227
+ line-height: 1;
228
+ font-weight: 500;
229
+ }
230
+
231
+ p {
232
+ font-size: clamp(16px, 2cqw, 22px);
233
+ line-height: 1.5;
234
+ }
235
+
236
+ code {
237
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
238
+ }
239
+ `,
240
+ "utf8"
241
+ );
242
+ await writeFile2(
243
+ path.join(pressRoot, "theme", "base", "print.css"),
244
+ `@media print {
245
+ html,
246
+ body {
247
+ background: #ffffff;
254
248
  }
255
- await mkdir2(target, { recursive: true });
256
249
  }
257
- function hasMetadata(options) {
258
- return Boolean(options.title || options.subtitle || options.organization || options.author);
250
+ `,
251
+ "utf8"
252
+ );
253
+ await writeFile2(path.join(pressRoot, "theme", "page-surfaces", "cover.css"), "/* Starter cover surface. */\n", "utf8");
254
+ await writeFile2(path.join(pressRoot, "theme", "page-surfaces", "back-cover.css"), "/* Starter back-cover surface. */\n", "utf8");
255
+ await writeFile2(path.join(pressRoot, "theme", "page-surfaces", "toc.css"), "/* Starter TOC surface. */\n", "utf8");
256
+ await writeFile2(path.join(pressRoot, "theme", "shell", "reader-controls.css"), "/* Starter reader controls surface. */\n", "utf8");
257
+ await writeFile2(
258
+ path.join(pressRoot, "theme", "tokens.css"),
259
+ `:root {
260
+ --openpress-font-body: system-ui, sans-serif;
261
+ --openpress-font-serif: Georgia, serif;
262
+ }
263
+ `,
264
+ "utf8"
265
+ );
266
+ await writeFile2(
267
+ path.join(pressRoot, "index.tsx"),
268
+ `import { Frame, Press, Workspace } from "@open-press/core";
269
+
270
+ export default function OpenPressDocument() {
271
+ return (
272
+ <Workspace name="${escapeJsxAttribute(title)}">
273
+ <Press title="${escapeJsxAttribute(title)}">
274
+ <Frame frameKey="cover" role="manuscript.cover">
275
+ <main style={{ padding: "72px", fontFamily: "var(--openpress-font-serif, Georgia, serif)" }}>
276
+ <p style={{ letterSpacing: "0.12em", textTransform: "uppercase" }}>OpenPress</p>
277
+ <h1>${escapeText(title)}</h1>
278
+ <p>Edit <code>press/index.tsx</code>, then run <code>npm run dev</code>.</p>
279
+ </main>
280
+ </Frame>
281
+ </Press>
282
+ </Workspace>
283
+ );
284
+ }
285
+ `,
286
+ "utf8"
287
+ );
288
+ }
289
+ function escapeJsxAttribute(value) {
290
+ return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;");
291
+ }
292
+ function escapeText(value) {
293
+ return value.replace(/{/g, "&#123;").replace(/}/g, "&#125;").replace(/</g, "&lt;");
259
294
  }
260
295
  async function runInTarget(cwd, command, args, opts = {}) {
261
296
  return new Promise((resolve, reject) => {
@@ -276,7 +311,7 @@ function log(message) {
276
311
  `);
277
312
  }
278
313
  function printNextSteps(target, options) {
279
- const rel = path2.relative(process.cwd(), target) || ".";
314
+ const rel = path.relative(process.cwd(), target) || ".";
280
315
  const lines = [
281
316
  "",
282
317
  "\u2713 Done. Your open-press workspace is ready.",
@@ -287,6 +322,9 @@ function printNextSteps(target, options) {
287
322
  if (!options.install) {
288
323
  lines.push(" npm install");
289
324
  }
325
+ if (!options.skills) {
326
+ lines.push(" npm run openpress:skills");
327
+ }
290
328
  lines.push(
291
329
  "",
292
330
  " # start the workbench:",
@@ -294,44 +332,49 @@ function printNextSteps(target, options) {
294
332
  "",
295
333
  "Then open the local URL printed by Vite (typically http://127.0.0.1:5173/?dev=1).",
296
334
  "",
297
- "Agent skills installed under .agents/skills/ (universal \u2014 read by Claude Code,",
298
- `Cursor, Codex, Gemini CLI, etc.). Update later with: npx skills upgrade`,
299
- "",
300
- "Edit content under document/chapters/, or ask your AI agent to help.",
335
+ "Use an OpenPress-ready skill to add or adapt the press source tree.",
301
336
  ""
302
337
  );
303
338
  process.stdout.write(lines.join("\n"));
304
339
  }
305
340
 
306
341
  // src/cli.ts
342
+ var require2 = createRequire(import.meta.url);
307
343
  var HELP = `open-press \u2014 AI-first fixed-layout document workspaces.
308
344
 
309
345
  Usage:
310
- npx @open-press/cli init <target> [flags]
346
+ open-press init <target> [flags]
347
+ open-press <command> [path] [options]
348
+ open-press skills <add|update> [--source <owner/repo>]
311
349
 
312
- Flags:
313
- --pack <spec> Style pack source. Either:
314
- \u2022 a bundled name \u2014 editorial-monograph | claude-document | academic-paper
315
- \u2022 github:owner/repo (third-party pack)
316
- \u2022 github:owner/repo#branch-or-tag
317
- --title <s> Document title (written to openpress.config.mjs)
318
- --subtitle <s> Document subtitle
319
- --organization <s> Organization name
320
- --author <s> Author name
350
+ Init flags:
351
+ --title <s> Document title (written into <Press title="..."> in press/index.tsx)
321
352
  --no-git Skip git init
322
353
  --no-install Skip npm install
323
- --force Allow non-empty target
354
+ --skills Install OpenPress agent skills after scaffolding
355
+ --no-skills Skip agent skill installation
324
356
  --help Show this help
325
357
 
326
- Examples:
327
- # Bundled
328
- npx @open-press/cli init my-doc --pack editorial-monograph
329
- npx @open-press/cli init my-brief --pack claude-document --title "Q2 Brief" --author Quan
330
- npx @open-press/cli init my-paper --pack academic-paper --title "Paper Title" --author "First Author"
358
+ Runtime commands:
359
+ dev Start the local OpenPress workbench
360
+ render Build the static reader
361
+ preview Preview the static reader
362
+ image Export pages to PNG
363
+ pdf Export pages to PDF
364
+ validate Validate source structure
365
+ inspect Inspect rendered output
366
+ search Search workspace source
367
+ replace Replace workspace source text
368
+ doctor Check package and skill freshness
369
+ upgrade Update workspace dependencies and skills
370
+ migrate Alias for upgrade
371
+ skills Install or update OpenPress agent skills
331
372
 
332
- # Third-party (any GitHub repo with starter/document/ at the root)
333
- npx @open-press/cli init my-thesis --pack github:quan0715/openpress-pack-nycu-thesis
334
- npx @open-press/cli init my-paper --pack github:foo/their-pack#v1.2
373
+ Examples:
374
+ npx @open-press/cli init my-doc
375
+ npx @open-press/cli init my-brief --title "Q2 Brief"
376
+ npx open-press dev .
377
+ npx open-press image .
335
378
  `;
336
379
  async function main(argv) {
337
380
  if (argv.length === 0 || argv.includes("--help") || argv.includes("-h")) {
@@ -339,27 +382,26 @@ async function main(argv) {
339
382
  return 0;
340
383
  }
341
384
  const [subcommand, ...rest] = argv;
342
- if (subcommand !== "init") {
343
- process2.stderr.write(`Unknown command: ${subcommand}
344
-
385
+ if (subcommand === "init") {
386
+ const options = parseInitArgs(rest);
387
+ if (!options) {
388
+ process2.stderr.write(HELP);
389
+ return 1;
390
+ }
391
+ try {
392
+ await init(options);
393
+ return 0;
394
+ } catch (err) {
395
+ const msg = err instanceof Error ? err.message : String(err);
396
+ process2.stderr.write(`open-press init failed: ${msg}
345
397
  `);
346
- process2.stderr.write(HELP);
347
- return 1;
348
- }
349
- const options = parseInitArgs(rest);
350
- if (!options) {
351
- process2.stderr.write(HELP);
352
- return 1;
398
+ return 1;
399
+ }
353
400
  }
354
- try {
355
- await init(options);
356
- return 0;
357
- } catch (err) {
358
- const msg = err instanceof Error ? err.message : String(err);
359
- process2.stderr.write(`open-press init failed: ${msg}
360
- `);
361
- return 1;
401
+ if (subcommand === "skills") {
402
+ return delegateToCore(normalizeSkillsArgs(rest));
362
403
  }
404
+ return delegateToCore([subcommand, ...rest]);
363
405
  }
364
406
  function parseInitArgs(args) {
365
407
  if (args.length === 0) {
@@ -368,47 +410,34 @@ function parseInitArgs(args) {
368
410
  }
369
411
  const options = {
370
412
  target: "",
371
- pack: void 0,
372
413
  title: void 0,
373
- subtitle: void 0,
374
- organization: void 0,
375
- author: void 0,
376
414
  git: true,
377
415
  install: true,
378
- force: false
416
+ skills: false
379
417
  };
380
418
  for (let i = 0; i < args.length; i++) {
381
419
  const arg = args[i];
382
420
  switch (arg) {
383
- case "--pack":
384
- options.pack = args[++i];
385
- break;
386
421
  case "--title":
387
422
  options.title = args[++i];
388
423
  break;
389
- case "--subtitle":
390
- options.subtitle = args[++i];
391
- break;
392
- case "--organization":
393
- options.organization = args[++i];
394
- break;
395
- case "--author":
396
- options.author = args[++i];
397
- break;
398
424
  case "--no-git":
399
425
  options.git = false;
400
426
  break;
401
427
  case "--no-install":
402
428
  options.install = false;
403
429
  break;
430
+ case "--no-skills":
431
+ options.skills = false;
432
+ break;
404
433
  case "--git":
405
434
  options.git = true;
406
435
  break;
407
436
  case "--install":
408
437
  options.install = true;
409
438
  break;
410
- case "--force":
411
- options.force = true;
439
+ case "--skills":
440
+ options.skills = true;
412
441
  break;
413
442
  default:
414
443
  if (arg.startsWith("--")) {
@@ -432,6 +461,45 @@ function parseInitArgs(args) {
432
461
  }
433
462
  return options;
434
463
  }
464
+ function normalizeSkillsArgs(args) {
465
+ const [subcommand, ...rest] = args;
466
+ if (!subcommand || subcommand === "add" || subcommand === "update") {
467
+ return ["skills:sync", ...rest];
468
+ }
469
+ return ["skills:sync", subcommand, ...rest];
470
+ }
471
+ async function delegateToCore(args) {
472
+ const coreCli = resolveCoreCli();
473
+ return new Promise((resolve, reject) => {
474
+ const child = spawn2(process2.execPath, [coreCli, ...args], {
475
+ cwd: process2.cwd(),
476
+ stdio: "inherit"
477
+ });
478
+ child.once("error", reject);
479
+ child.once("close", (code) => resolve(code ?? 1));
480
+ });
481
+ }
482
+ function resolveCoreCli() {
483
+ const coreEntry = require2.resolve("@open-press/core");
484
+ const coreRoot = findPackageRoot(coreEntry, "@open-press/core");
485
+ return path2.join(coreRoot, "engine", "cli.mjs");
486
+ }
487
+ function findPackageRoot(startPath, packageName) {
488
+ let dir = path2.dirname(startPath);
489
+ while (true) {
490
+ const pkgPath = path2.join(dir, "package.json");
491
+ try {
492
+ const pkg = require2(pkgPath);
493
+ if (pkg.name === packageName) return dir;
494
+ } catch {
495
+ }
496
+ const parent = path2.dirname(dir);
497
+ if (parent === dir) {
498
+ throw new Error(`Could not find ${packageName} package root from ${startPath}`);
499
+ }
500
+ dir = parent;
501
+ }
502
+ }
435
503
  main(process2.argv.slice(2)).then((code) => process2.exit(code)).catch((err) => {
436
504
  process2.stderr.write(`${err instanceof Error ? err.stack ?? err.message : String(err)}
437
505
  `);