@fprad0/skill-master-mcp 0.0.12 → 1.0.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 (331) hide show
  1. package/CHANGELOG.md +96 -90
  2. package/README.md +472 -472
  3. package/VERSION.md +9 -9
  4. package/bin/lib/bootstrap-global-core.mjs +34 -0
  5. package/bin/lib/client-config.mjs +293 -293
  6. package/bin/lib/doctor-core.mjs +202 -0
  7. package/bin/lib/menu-core.mjs +1629 -1522
  8. package/bin/lib/operation-result.mjs +59 -0
  9. package/bin/lib/register-clients-core.mjs +247 -0
  10. package/bin/lib/skill-installation.mjs +215 -215
  11. package/bin/lib/update-cli-core.mjs +117 -0
  12. package/bin/skill-master-activation.mjs +163 -163
  13. package/bin/skill-master-bootstrap-global.mjs +61 -49
  14. package/bin/skill-master-configure-private-registry.mjs +3 -3
  15. package/bin/skill-master-doctor.mjs +239 -228
  16. package/bin/skill-master-eval-activation.mjs +32 -32
  17. package/bin/skill-master-install-global-skills.mjs +59 -59
  18. package/bin/skill-master-install-project-skills.mjs +97 -97
  19. package/bin/skill-master-menu.mjs +406 -405
  20. package/bin/skill-master-register-clients.mjs +232 -153
  21. package/bin/skill-master-success-skills.mjs +307 -307
  22. package/bin/skill-master-update.mjs +121 -72
  23. package/bin/skill-master.mjs +3 -3
  24. package/dist/activation.d.ts.map +1 -1
  25. package/dist/activation.js +12 -0
  26. package/dist/activation.js.map +1 -1
  27. package/dist/prompt-router.d.ts.map +1 -1
  28. package/dist/prompt-router.js +19 -0
  29. package/dist/prompt-router.js.map +1 -1
  30. package/dist/recommender.d.ts.map +1 -1
  31. package/dist/recommender.js +4 -1
  32. package/dist/recommender.js.map +1 -1
  33. package/docs/architecture/APRENDIZADO_DE_IMPLEMENTACOES_BEM_SUCEDIDAS.md +125 -125
  34. package/docs/architecture/ARQUITETURA_AUTO_UPDATE.md +9 -9
  35. package/docs/architecture/PLANO_MASTER_ACIONAMENTO_AUTOMATICO_E_APRENDIZADO.md +341 -341
  36. package/docs/architecture/REDE_SEGURA_DE_SKILLS.md +148 -148
  37. package/docs/operations/GUIA_MULTI_COMPUTADOR.md +262 -262
  38. package/docs/operations/GUIA_NPM_PRIVADO.md +294 -294
  39. package/docs/operations/GUIA_NPM_PUBLICO.md +147 -147
  40. package/docs/operations/MENU_VISUAL_EVIDENCE_2026-06-28.md +66 -66
  41. package/docs/operations/assets/menu-frame-compact.html +75 -75
  42. package/docs/operations/assets/menu-frame-large.html +83 -83
  43. package/docs/operations/assets/menu-frame-running.html +79 -79
  44. package/docs/operations/cross-platform-auth-transfer/ANALISE_COMPATIBILIDADE_MCP_2026-06-28.md +140 -140
  45. package/docs/operations/cross-platform-auth-transfer/README_TRANSFERENCIA.md +85 -85
  46. package/docs/operations/reborn-menu-cyberpunk-transfer/ANALISE_MENU_REBORN_CYBERPUNK_2026-06-28.md +174 -174
  47. package/docs/operations/reborn-menu-cyberpunk-transfer/HANDOFF_IMPLEMENTACAO_REBORN_CYBERPUNK_2026-06-28.md +119 -119
  48. package/docs/operations/reborn-menu-cyberpunk-transfer/ORDEM_DE_EXECUCAO_MENU_REBORN_CYBERPUNK.md +134 -134
  49. package/docs/operations/reborn-menu-cyberpunk-transfer/README_TRANSFERENCIA.md +84 -84
  50. package/docs/operations/reborn-menu-cyberpunk-transfer/README_TRANSFERENCIA_REBORN_PACKAGE.md +56 -56
  51. package/docs/operations/token-economy-transfer/ANALISE_AVANCADA_ECONOMIA_TOKENS_2026-06-30.md +141 -0
  52. package/docs/operations/token-economy-transfer/PLANO_DEV_SENIOR_MASTER_TOKEN_ECONOMY_2026-06-30.md +171 -0
  53. package/docs/operations/token-economy-transfer/README_TRANSFERENCIA_TOKEN_ECONOMY.md +31 -0
  54. package/docs/planning/MENU_RUNTIME_CORRECTION_PLAN_2026-06-30.md +551 -0
  55. package/docs/planning/V0_0_9_APROVACAO_CRITICA_MENSAGENS_DE_VENDA.md +85 -85
  56. package/docs/planning/V0_0_9_FONTES_E_CRITERIOS_DE_AUTORIDADE.md +139 -139
  57. package/docs/planning/V0_0_9_MATRIZ_SKILLS_MULTIDISCIPLINARES.md +105 -105
  58. package/docs/planning/V0_0_9_POLITICA_MORAL_CATOLICA_PARA_IA.md +181 -181
  59. package/docs/planning/V0_0_9_PROMPTS_EXECUCAO.md +59 -59
  60. package/docs/planning/V0_0_9_ROADMAP_DISCERNIMENTO_E_CONHECIMENTO_AMPLO.md +181 -181
  61. package/docs/prompt-tasks/PROMPT_TASK_001_BOOTSTRAP_SKILL_MASTER_MCP.md +6 -6
  62. package/docs/prompt-tasks/PROMPT_TASK_002_AUTO_UPDATE_LAUNCHER.md +6 -6
  63. package/docs/prompt-tasks/PROMPT_TASK_003_REMOTE_MANIFEST_AND_RELEASES.md +6 -6
  64. package/docs/prompt-tasks/PROMPT_TASK_004_MULTI_USER_DISTRIBUTION.md +6 -6
  65. package/docs/prompt-tasks/PROMPT_TASK_005_SECURITY_AND_QUALITY_GATE.md +6 -6
  66. package/docs/prompt-tasks/PROMPT_TASK_006_MASTER_ACIONAMENTO_APRENDIZADO.md +83 -83
  67. package/docs/prompt-tasks/PROMPT_TASK_007_PERSONA_ORQUESTRADORA.md +88 -88
  68. package/docs/prompt-tasks/PROMPT_TASK_008_PROMPT_ROUTER_MODOS_ATIVACAO.md +156 -156
  69. package/docs/prompt-tasks/PROMPT_TASK_009_PIPELINE_APRENDIZADO_SUCESSO.md +105 -105
  70. package/docs/prompt-tasks/PROMPT_TASK_010_EVALS_GOVERNANCA_ATIVACAO.md +119 -119
  71. package/docs/prompt-tasks/PROMPT_TASK_011_MENU_NOTIFICACOES_NOTION.md +120 -120
  72. package/docs/prompt-tasks/PROMPT_TASK_012_MENU_CYBERPUNK_PIXEL_FRAME.md +123 -123
  73. package/docs/prompt-tasks/PROMPT_TASK_013_MENU_FLUID_DNA_ANIMATION.md +114 -114
  74. package/docs/prompt-tasks/PROMPT_TASK_014_MENU_FUNCTIONAL_PARITY_QA.md +157 -157
  75. package/docs/prompt-tasks/PROMPT_TASK_015_TRANSFER_RELEASE_HANDOFF.md +127 -127
  76. package/docs/prompt-tasks/PROMPT_TASK_016_CROSS_PLATFORM_MCP_AUTH_REGISTRATION.md +107 -107
  77. package/docs/prompt-tasks/PROMPT_TASK_018_NPM_PUBLISH_2FA_SETUP.md +80 -80
  78. package/docs/prompt-tasks/PROMPT_TASK_019_TOKEN_ECONOMY_GLOBAL_SKILLS.md +56 -0
  79. package/docs/prompt-tasks/PROMPT_TASK_MASTER_EXECUTOR.md +6 -6
  80. package/docs/skill-candidates/v0.0.10/cli-creator/LICENSE.txt +201 -201
  81. package/docs/skill-candidates/v0.0.10/cli-creator/SKILL.md +160 -160
  82. package/docs/skill-candidates/v0.0.10/cli-creator/agents/openai.yaml +4 -4
  83. package/docs/skill-candidates/v0.0.10/cli-creator/references/agent-cli-patterns.md +154 -154
  84. package/docs/skill-candidates/v0.0.10/developer-workstation-ops/SKILL.md +32 -32
  85. package/docs/skill-candidates/v0.0.10/figma/LICENSE.txt +1 -1
  86. package/docs/skill-candidates/v0.0.10/figma/SKILL.md +42 -42
  87. package/docs/skill-candidates/v0.0.10/figma/agents/openai.yaml +14 -14
  88. package/docs/skill-candidates/v0.0.10/figma/assets/figma-small.svg +3 -3
  89. package/docs/skill-candidates/v0.0.10/figma/assets/icon.svg +28 -28
  90. package/docs/skill-candidates/v0.0.10/figma/references/figma-mcp-config.md +35 -35
  91. package/docs/skill-candidates/v0.0.10/figma/references/figma-tools-and-prompts.md +34 -34
  92. package/docs/skill-candidates/v0.0.10/figma-code-connect-components/LICENSE.TXT +1 -1
  93. package/docs/skill-candidates/v0.0.10/figma-code-connect-components/SKILL.md +349 -349
  94. package/docs/skill-candidates/v0.0.10/figma-code-connect-components/agents/openai.yaml +14 -14
  95. package/docs/skill-candidates/v0.0.10/figma-code-connect-components/assets/figma-small.svg +3 -3
  96. package/docs/skill-candidates/v0.0.10/figma-code-connect-components/assets/icon.svg +28 -28
  97. package/docs/skill-candidates/v0.0.10/figma-code-connect-components/references/mapping-checklist.md +7 -7
  98. package/docs/skill-candidates/v0.0.10/figma-code-connect-components/scripts/normalize_node_id.py +25 -25
  99. package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/LICENSE.TXT +1 -1
  100. package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/SKILL.md +537 -537
  101. package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/agents/openai.yaml +14 -14
  102. package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/assets/figma-small.svg +3 -3
  103. package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/assets/icon.svg +28 -28
  104. package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/references/rule-template.md +15 -15
  105. package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/scripts/check_agents_md.sh +9 -9
  106. package/docs/skill-candidates/v0.0.10/figma-generate-design/LICENSE.TXT +1 -1
  107. package/docs/skill-candidates/v0.0.10/figma-generate-design/SKILL.md +341 -341
  108. package/docs/skill-candidates/v0.0.10/figma-generate-design/agents/openai.yaml +14 -14
  109. package/docs/skill-candidates/v0.0.10/figma-generate-design/assets/figma-small.svg +3 -3
  110. package/docs/skill-candidates/v0.0.10/figma-generate-design/assets/icon.svg +28 -28
  111. package/docs/skill-candidates/v0.0.10/figma-generate-design/maintainers.yml +1 -1
  112. package/docs/skill-candidates/v0.0.10/figma-generate-library/LICENSE.TXT +1 -1
  113. package/docs/skill-candidates/v0.0.10/figma-generate-library/SKILL.md +314 -314
  114. package/docs/skill-candidates/v0.0.10/figma-generate-library/agents/openai.yaml +14 -14
  115. package/docs/skill-candidates/v0.0.10/figma-generate-library/assets/figma-small.svg +3 -3
  116. package/docs/skill-candidates/v0.0.10/figma-generate-library/assets/icon.svg +28 -28
  117. package/docs/skill-candidates/v0.0.10/figma-generate-library/maintainers.yml +3 -3
  118. package/docs/skill-candidates/v0.0.10/figma-generate-library/references/code-connect-setup.md +260 -260
  119. package/docs/skill-candidates/v0.0.10/figma-generate-library/references/component-creation.md +1014 -1014
  120. package/docs/skill-candidates/v0.0.10/figma-generate-library/references/discovery-phase.md +518 -518
  121. package/docs/skill-candidates/v0.0.10/figma-generate-library/references/documentation-creation.md +834 -834
  122. package/docs/skill-candidates/v0.0.10/figma-generate-library/references/error-recovery.md +540 -540
  123. package/docs/skill-candidates/v0.0.10/figma-generate-library/references/naming-conventions.md +527 -527
  124. package/docs/skill-candidates/v0.0.10/figma-generate-library/references/token-creation.md +962 -962
  125. package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/bindVariablesToComponent.js +110 -110
  126. package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/cleanupOrphans.js +127 -127
  127. package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/createComponentWithVariants.js +148 -148
  128. package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/createDocumentationPage.js +139 -139
  129. package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/createSemanticTokens.js +108 -108
  130. package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/createVariableCollection.js +49 -49
  131. package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/inspectFileStructure.js +121 -121
  132. package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/rehydrateState.js +92 -92
  133. package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/validateCreation.js +83 -83
  134. package/docs/skill-candidates/v0.0.10/figma-implement-design/LICENSE.txt +1 -1
  135. package/docs/skill-candidates/v0.0.10/figma-implement-design/SKILL.md +258 -258
  136. package/docs/skill-candidates/v0.0.10/figma-implement-design/agents/openai.yaml +14 -14
  137. package/docs/skill-candidates/v0.0.10/figma-implement-design/assets/figma-small.svg +3 -3
  138. package/docs/skill-candidates/v0.0.10/figma-implement-design/assets/icon.svg +28 -28
  139. package/docs/skill-candidates/v0.0.10/figma-use/LICENSE.TXT +1 -1
  140. package/docs/skill-candidates/v0.0.10/figma-use/SKILL.md +233 -233
  141. package/docs/skill-candidates/v0.0.10/figma-use/agents/openai.yaml +14 -14
  142. package/docs/skill-candidates/v0.0.10/figma-use/assets/figma-small.svg +3 -3
  143. package/docs/skill-candidates/v0.0.10/figma-use/assets/icon.svg +28 -28
  144. package/docs/skill-candidates/v0.0.10/figma-use/maintainers.yml +1 -1
  145. package/docs/skill-candidates/v0.0.10/figma-use/references/api-reference.md +301 -301
  146. package/docs/skill-candidates/v0.0.10/figma-use/references/common-patterns.md +512 -512
  147. package/docs/skill-candidates/v0.0.10/figma-use/references/component-patterns.md +488 -488
  148. package/docs/skill-candidates/v0.0.10/figma-use/references/effect-style-patterns.md +123 -123
  149. package/docs/skill-candidates/v0.0.10/figma-use/references/gotchas.md +599 -599
  150. package/docs/skill-candidates/v0.0.10/figma-use/references/maintainers.yml +12 -12
  151. package/docs/skill-candidates/v0.0.10/figma-use/references/plugin-api-patterns.md +513 -513
  152. package/docs/skill-candidates/v0.0.10/figma-use/references/plugin-api-standalone.d.ts +11293 -11293
  153. package/docs/skill-candidates/v0.0.10/figma-use/references/plugin-api-standalone.index.md +441 -441
  154. package/docs/skill-candidates/v0.0.10/figma-use/references/text-style-patterns.md +203 -203
  155. package/docs/skill-candidates/v0.0.10/figma-use/references/validation-and-recovery.md +109 -109
  156. package/docs/skill-candidates/v0.0.10/figma-use/references/variable-patterns.md +354 -354
  157. package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/maintainers.yml +9 -9
  158. package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-components--creating.md +17 -17
  159. package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-components--using.md +17 -17
  160. package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-components.md +50 -50
  161. package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-effect-styles.md +52 -52
  162. package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-text-styles.md +90 -90
  163. package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-variables--creating.md +13 -13
  164. package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-variables--using.md +13 -13
  165. package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-variables.md +64 -64
  166. package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds.md +41 -41
  167. package/docs/skill-candidates/v0.0.10/frontend-design/LICENSE.txt +177 -177
  168. package/docs/skill-candidates/v0.0.10/frontend-design/SKILL.md +55 -55
  169. package/docs/skill-candidates/v0.0.10/frontend-ui-ux-systems/SKILL.md +32 -32
  170. package/docs/skill-candidates/v0.0.10/github/SKILL.md +74 -74
  171. package/docs/skill-candidates/v0.0.10/github/agents/openai.yaml +6 -6
  172. package/docs/skill-candidates/v0.0.10/github/assets/github-small.svg +3 -3
  173. package/docs/skill-candidates/v0.0.10/image-graphic-design-rendering/SKILL.md +28 -28
  174. package/docs/skill-candidates/v0.0.10/language-quality-pt-en-fr-it-ru/SKILL.md +28 -28
  175. package/docs/skill-candidates/v0.0.10/math-physics-reasoning/SKILL.md +28 -28
  176. package/docs/skill-candidates/v0.0.10/mcp-builder/LICENSE.txt +201 -201
  177. package/docs/skill-candidates/v0.0.10/mcp-builder/SKILL.md +236 -236
  178. package/docs/skill-candidates/v0.0.10/mcp-builder/reference/evaluation.md +601 -601
  179. package/docs/skill-candidates/v0.0.10/mcp-builder/reference/mcp_best_practices.md +249 -249
  180. package/docs/skill-candidates/v0.0.10/mcp-builder/reference/node_mcp_server.md +969 -969
  181. package/docs/skill-candidates/v0.0.10/mcp-builder/reference/python_mcp_server.md +718 -718
  182. package/docs/skill-candidates/v0.0.10/mcp-builder/scripts/connections.py +151 -151
  183. package/docs/skill-candidates/v0.0.10/mcp-builder/scripts/evaluation.py +373 -373
  184. package/docs/skill-candidates/v0.0.10/mcp-builder/scripts/example_evaluation.xml +22 -22
  185. package/docs/skill-candidates/v0.0.10/mcp-builder/scripts/requirements.txt +2 -2
  186. package/docs/skill-candidates/v0.0.10/mcp-client-readiness/SKILL.md +31 -31
  187. package/docs/skill-candidates/v0.0.10/openai-docs/LICENSE.txt +201 -201
  188. package/docs/skill-candidates/v0.0.10/openai-docs/SKILL.md +161 -161
  189. package/docs/skill-candidates/v0.0.10/openai-docs/agents/openai.yaml +14 -14
  190. package/docs/skill-candidates/v0.0.10/openai-docs/assets/openai-small.svg +3 -3
  191. package/docs/skill-candidates/v0.0.10/openai-docs/references/latest-model.md +37 -37
  192. package/docs/skill-candidates/v0.0.10/openai-docs/references/prompting-guide.md +244 -244
  193. package/docs/skill-candidates/v0.0.10/openai-docs/references/upgrade-guide.md +181 -181
  194. package/docs/skill-candidates/v0.0.10/openai-docs/scripts/fetch-codex-manual.mjs +598 -598
  195. package/docs/skill-candidates/v0.0.10/openai-docs/scripts/resolve-latest-model-info.js +147 -147
  196. package/docs/skill-candidates/v0.0.10/playwright/NOTICE.txt +14 -14
  197. package/docs/skill-candidates/v0.0.10/playwright/SKILL.md +147 -147
  198. package/docs/skill-candidates/v0.0.10/playwright/agents/openai.yaml +6 -6
  199. package/docs/skill-candidates/v0.0.10/playwright/assets/playwright-small.svg +3 -3
  200. package/docs/skill-candidates/v0.0.10/playwright/references/cli.md +116 -116
  201. package/docs/skill-candidates/v0.0.10/playwright/references/workflows.md +95 -95
  202. package/docs/skill-candidates/v0.0.10/playwright/scripts/playwright_cli.sh +25 -25
  203. package/docs/skill-candidates/v0.0.10/polyglot-backend-engineering/SKILL.md +32 -32
  204. package/docs/skill-candidates/v0.0.10/screenshot/LICENSE.txt +201 -201
  205. package/docs/skill-candidates/v0.0.10/screenshot/SKILL.md +267 -267
  206. package/docs/skill-candidates/v0.0.10/screenshot/agents/openai.yaml +6 -6
  207. package/docs/skill-candidates/v0.0.10/screenshot/assets/screenshot-small.svg +5 -5
  208. package/docs/skill-candidates/v0.0.10/screenshot/scripts/ensure_macos_permissions.sh +54 -54
  209. package/docs/skill-candidates/v0.0.10/screenshot/scripts/macos_display_info.swift +22 -22
  210. package/docs/skill-candidates/v0.0.10/screenshot/scripts/macos_permissions.swift +40 -40
  211. package/docs/skill-candidates/v0.0.10/screenshot/scripts/macos_window_info.swift +126 -126
  212. package/docs/skill-candidates/v0.0.10/screenshot/scripts/take_screenshot.ps1 +163 -163
  213. package/docs/skill-candidates/v0.0.10/screenshot/scripts/take_screenshot.py +585 -585
  214. package/docs/skill-candidates/v0.0.10/skill-master-orchestrator/SKILL.md +62 -62
  215. package/docs/skill-candidates/v0.0.10/skill-master-orchestrator/agents/openai.yaml +4 -4
  216. package/docs/skill-candidates/v0.0.10/skill-master-orchestrator/references/activation-policy.md +77 -77
  217. package/docs/skill-candidates/v0.0.10/skill-master-orchestrator/references/human-approval-policy.md +83 -83
  218. package/docs/skill-candidates/v0.0.10/skill-master-orchestrator/references/persona-dev-senior-master.md +46 -46
  219. package/docs/skill-candidates/v0.0.10/terminal-menu-operations/SKILL.md +30 -30
  220. package/docs/skill-candidates/v0.0.10/terminal-pixel-art-tui/SKILL.md +43 -43
  221. package/docs/skill-candidates/v0.0.10/webapp-testing/LICENSE.txt +201 -201
  222. package/docs/skill-candidates/v0.0.10/webapp-testing/SKILL.md +95 -95
  223. package/docs/skill-candidates/v0.0.10/webapp-testing/examples/console_logging.py +34 -34
  224. package/docs/skill-candidates/v0.0.10/webapp-testing/examples/element_discovery.py +39 -39
  225. package/docs/skill-candidates/v0.0.10/webapp-testing/examples/static_html_automation.py +32 -32
  226. package/docs/skill-candidates/v0.0.10/webapp-testing/scripts/with_server.py +105 -105
  227. package/docs/skill-candidates/v0.0.10/winui-app/LICENSE.txt +201 -201
  228. package/docs/skill-candidates/v0.0.10/winui-app/SKILL.md +94 -94
  229. package/docs/skill-candidates/v0.0.10/winui-app/agents/openai.yaml +5 -5
  230. package/docs/skill-candidates/v0.0.10/winui-app/config.yaml +50 -50
  231. package/docs/skill-candidates/v0.0.10/winui-app/references/_sections.md +96 -96
  232. package/docs/skill-candidates/v0.0.10/winui-app/references/accessibility-input-and-localization.md +51 -51
  233. package/docs/skill-candidates/v0.0.10/winui-app/references/build-run-and-launch-verification.md +72 -72
  234. package/docs/skill-candidates/v0.0.10/winui-app/references/community-toolkit-controls-and-helpers.md +57 -57
  235. package/docs/skill-candidates/v0.0.10/winui-app/references/controls-layout-and-adaptive-ui.md +84 -84
  236. package/docs/skill-candidates/v0.0.10/winui-app/references/foundation-environment-audit-and-remediation.md +82 -82
  237. package/docs/skill-candidates/v0.0.10/winui-app/references/foundation-setup-and-project-selection.md +67 -67
  238. package/docs/skill-candidates/v0.0.10/winui-app/references/foundation-template-first-recovery.md +62 -62
  239. package/docs/skill-candidates/v0.0.10/winui-app/references/foundation-winui-app-structure.md +62 -62
  240. package/docs/skill-candidates/v0.0.10/winui-app/references/motion-animations-and-polish.md +45 -45
  241. package/docs/skill-candidates/v0.0.10/winui-app/references/performance-diagnostics-and-responsiveness.md +46 -46
  242. package/docs/skill-candidates/v0.0.10/winui-app/references/sample-source-map.md +37 -37
  243. package/docs/skill-candidates/v0.0.10/winui-app/references/shell-navigation-and-windowing.md +67 -67
  244. package/docs/skill-candidates/v0.0.10/winui-app/references/styling-theming-materials-and-icons.md +71 -71
  245. package/docs/skill-candidates/v0.0.10/winui-app/references/testing-debugging-and-review-checklists.md +77 -77
  246. package/docs/skill-candidates/v0.0.10/winui-app/references/windows-app-sdk-lifecycle-notifications-and-deployment.md +52 -52
  247. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/SKILL.md +398 -398
  248. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/common-patterns.md +330 -330
  249. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/complete-examples.md +871 -871
  250. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/component-patterns.md +501 -501
  251. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/data-fetching.md +766 -766
  252. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/file-organization.md +501 -501
  253. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/loading-and-error-states.md +500 -500
  254. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/performance.md +405 -405
  255. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/routing-guide.md +363 -363
  256. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/styling-guide.md +427 -427
  257. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/typescript-standards.md +417 -417
  258. package/docs/skill-candidates/v0.0.11/git-version-control-ops/SKILL.md +34 -34
  259. package/docs/skill-candidates/v0.0.11/go-engineering/SKILL.md +34 -34
  260. package/docs/skill-candidates/v0.0.11/java-engineering/SKILL.md +34 -34
  261. package/docs/skill-candidates/v0.0.11/javascript-engineering/SKILL.md +34 -34
  262. package/docs/skill-candidates/v0.0.11/json-contract-design/SKILL.md +34 -34
  263. package/docs/skill-candidates/v0.0.11/multi-client-mcp-ops/SKILL.md +36 -36
  264. package/docs/skill-candidates/v0.0.11/nextjs/SKILL.md +745 -745
  265. package/docs/skill-candidates/v0.0.11/nextjs/agents/openai.yaml +3 -3
  266. package/docs/skill-candidates/v0.0.11/nextjs/references/app-router-files.md +94 -94
  267. package/docs/skill-candidates/v0.0.11/python-engineering/SKILL.md +34 -34
  268. package/docs/skill-candidates/v0.0.11/ruby-engineering/SKILL.md +34 -34
  269. package/docs/skill-candidates/v0.0.11/senior-fullstack/SKILL.md +209 -209
  270. package/docs/skill-candidates/v0.0.11/senior-fullstack/references/architecture_patterns.md +103 -103
  271. package/docs/skill-candidates/v0.0.11/senior-fullstack/references/development_workflows.md +103 -103
  272. package/docs/skill-candidates/v0.0.11/senior-fullstack/references/tech_stack_guide.md +103 -103
  273. package/docs/skill-candidates/v0.0.11/senior-fullstack/scripts/code_quality_analyzer.py +114 -114
  274. package/docs/skill-candidates/v0.0.11/senior-fullstack/scripts/fullstack_scaffolder.py +114 -114
  275. package/docs/skill-candidates/v0.0.11/senior-fullstack/scripts/project_scaffolder.py +114 -114
  276. package/docs/skill-candidates/v0.0.11/shadcn/SKILL.md +573 -573
  277. package/docs/skill-candidates/v0.0.11/shadcn/agents/openai.yaml +3 -3
  278. package/docs/skill-candidates/v0.0.11/sql-postgresql-engineering/SKILL.md +34 -34
  279. package/docs/skill-candidates/v0.0.11/terminal-shell-ops/SKILL.md +34 -34
  280. package/docs/skill-candidates/v0.0.11/typescript-expert/SKILL.md +429 -429
  281. package/docs/skill-candidates/v0.0.11/typescript-expert/references/tsconfig-strict.json +91 -91
  282. package/docs/skill-candidates/v0.0.11/typescript-expert/references/typescript-cheatsheet.md +383 -383
  283. package/docs/skill-candidates/v0.0.11/typescript-expert/references/utility-types.ts +335 -335
  284. package/docs/skill-candidates/v0.0.11/typescript-expert/scripts/ts_diagnostic.py +203 -203
  285. package/docs/skill-candidates/v0.0.11/ui-component-primitives/SKILL.md +34 -34
  286. package/docs/skill-candidates/v0.0.11/web-mobile-design-systems/SKILL.md +34 -34
  287. package/docs/skill-candidates/v0.0.11/windows-linux-platform-ops/SKILL.md +34 -34
  288. package/docs/skill-candidates/v0.0.12/context-compression-handoff/SKILL.md +47 -0
  289. package/docs/skill-candidates/v0.0.12/csharp-senior-master-engineering/SKILL.md +32 -32
  290. package/docs/skill-candidates/v0.0.12/css-senior-master-engineering/SKILL.md +32 -32
  291. package/docs/skill-candidates/v0.0.12/go-senior-master-engineering/SKILL.md +32 -32
  292. package/docs/skill-candidates/v0.0.12/html-senior-master-engineering/SKILL.md +32 -32
  293. package/docs/skill-candidates/v0.0.12/javascript-senior-master-engineering/SKILL.md +32 -32
  294. package/docs/skill-candidates/v0.0.12/json-senior-master-engineering/SKILL.md +32 -32
  295. package/docs/skill-candidates/v0.0.12/prompt-budget-gate/SKILL.md +46 -0
  296. package/docs/skill-candidates/v0.0.12/python-senior-master-engineering/SKILL.md +32 -32
  297. package/docs/skill-candidates/v0.0.12/react-senior-master-engineering/SKILL.md +32 -32
  298. package/docs/skill-candidates/v0.0.12/ruby-senior-master-engineering/SKILL.md +32 -32
  299. package/docs/skill-candidates/v0.0.12/senior-master-code-optimizer/SKILL.md +48 -48
  300. package/docs/skill-candidates/v0.0.12/sql-senior-master-engineering/SKILL.md +31 -31
  301. package/docs/skill-candidates/v0.0.12/token-economy-orchestrator/SKILL.md +38 -0
  302. package/docs/skill-candidates/v0.0.12/typescript-senior-master-engineering/SKILL.md +35 -35
  303. package/docs/skill-candidates/v0.0.9/ai-ethics-human-dignity/SKILL.md +32 -32
  304. package/docs/skill-candidates/v0.0.9/broad-domain-router/SKILL.md +41 -41
  305. package/docs/skill-candidates/v0.0.9/catholic-moral-discernment/SKILL.md +31 -31
  306. package/docs/skill-candidates/v0.0.9/engineering-systems-master/SKILL.md +31 -31
  307. package/docs/skill-candidates/v0.0.9/language-quality-pt-en-fr/SKILL.md +28 -28
  308. package/docs/skill-candidates/v0.0.9/math-science-reasoning/SKILL.md +29 -29
  309. package/docs/skill-candidates/v0.0.9/philosophy-sociology-discernment/SKILL.md +28 -28
  310. package/docs/skill-candidates/v0.0.9/professional-boundary-triage/SKILL.md +40 -40
  311. package/docs/skill-candidates/v0.0.9/release-ethics-gate/SKILL.md +32 -32
  312. package/docs/skill-candidates/v0.0.9/source-authority-reviewer/SKILL.md +31 -31
  313. package/examples/client-configs/claude-code.commands.md +21 -21
  314. package/examples/client-configs/claude-code.project.mcp.json +18 -18
  315. package/examples/client-configs/claude-desktop.macos.json +18 -18
  316. package/examples/client-configs/claude-desktop.windows.json +20 -20
  317. package/examples/client-configs/codex.windows.toml +11 -11
  318. package/examples/client-configs/gemini-code-assist.intellij.mcp.json +18 -18
  319. package/examples/client-configs/gemini.linux.settings.json +21 -21
  320. package/examples/client-configs/gemini.windows.settings.json +23 -23
  321. package/examples/client-configs/generic-stdio.json +16 -16
  322. package/manifests/channels/beta.json +26 -26
  323. package/manifests/channels/stable.json +27 -27
  324. package/network/approved-skills.json +54 -54
  325. package/network/unapproved-skill-candidates.json +110 -110
  326. package/package.json +87 -86
  327. package/scripts/configure-private-registry.mjs +208 -208
  328. package/scripts/lib/private-registry.mjs +97 -97
  329. package/scripts/render-menu-evidence.mjs +130 -130
  330. package/scripts/verify-menu-actions.mjs +117 -117
  331. package/sources.json +11 -11
@@ -1,598 +1,598 @@
1
- #!/usr/bin/env node
2
- import {
3
- access,
4
- mkdir,
5
- readFile,
6
- rename,
7
- rm,
8
- stat,
9
- writeFile,
10
- } from "node:fs/promises";
11
- import { constants as fsConstants } from "node:fs";
12
- import { execFile } from "node:child_process";
13
- import { createHash } from "node:crypto";
14
- import path from "node:path";
15
- import process from "node:process";
16
- import { pathToFileURL } from "node:url";
17
- import { inspect, promisify } from "node:util";
18
-
19
- const DEFAULT_MANUAL_URL = "https://developers.openai.com/codex/codex-manual.md";
20
- const DEFAULT_CACHE_DIR_NAME = "openai-docs-cache";
21
- const CACHE_FILE_NAME = "codex-manual.md";
22
- const OUTLINE_FILE_NAME = "codex-manual.outline.md";
23
- const HASH_HEADER = "x-content-sha256";
24
- const USER_AGENT = "codex-openai-docs";
25
- const execFileAsync = promisify(execFile);
26
-
27
- class ManualFetchError extends Error {
28
- constructor(message, options) {
29
- super(message, options);
30
- this.name = "ManualFetchError";
31
- }
32
- }
33
-
34
- const sha256 = (value) => createHash("sha256").update(value).digest("hex");
35
-
36
- const withTimeout = async (promiseFactory, timeoutMs) => {
37
- const controller = new AbortController();
38
- const timeout = setTimeout(() => controller.abort(), timeoutMs);
39
- try {
40
- return await promiseFactory(controller.signal);
41
- } finally {
42
- clearTimeout(timeout);
43
- }
44
- };
45
-
46
- const proxyConfigured = () =>
47
- process.env.HTTP_PROXY ||
48
- process.env.HTTPS_PROXY ||
49
- process.env.http_proxy ||
50
- process.env.https_proxy;
51
-
52
- const responseHeaders = (headers) => ({
53
- get(name) {
54
- return headers.get(name.toLowerCase()) ?? null;
55
- },
56
- });
57
-
58
- const makeResponse = ({ body, headers, status }) => ({
59
- headers: responseHeaders(headers),
60
- ok: status >= 200 && status < 300,
61
- status,
62
- async text() {
63
- return body;
64
- },
65
- });
66
-
67
- const parseCurlHeaders = (rawHeaders) => {
68
- const normalized = rawHeaders.replace(/\r\n/g, "\n").trim();
69
- const blocks = normalized.split(/\n\n+/).filter(Boolean);
70
- const headerBlock = [...blocks]
71
- .reverse()
72
- .find((block) => block.startsWith("HTTP/"));
73
-
74
- if (!headerBlock) {
75
- throw new ManualFetchError("curl did not return HTTP response headers.");
76
- }
77
-
78
- const [statusLine, ...lines] = headerBlock.split("\n");
79
- const statusMatch = /^HTTP\/\S+\s+(\d{3})/.exec(statusLine);
80
- if (!statusMatch) {
81
- throw new ManualFetchError(
82
- `Could not parse HTTP status from curl response: ${statusLine}`
83
- );
84
- }
85
-
86
- const headers = new Map();
87
- lines.forEach((line) => {
88
- const separator = line.indexOf(":");
89
- if (separator === -1) return;
90
- const name = line.slice(0, separator).trim().toLowerCase();
91
- const value = line.slice(separator + 1).trim();
92
- headers.set(name, value);
93
- });
94
-
95
- return {
96
- headers,
97
- status: Number(statusMatch[1]),
98
- };
99
- };
100
-
101
- const tempFilePath = (cacheDir, suffix) =>
102
- path.join(
103
- cacheDir,
104
- `.fetch-codex-manual-${process.pid}-${Date.now()}-${Math.random()
105
- .toString(16)
106
- .slice(2)}${suffix}`
107
- );
108
-
109
- const requestManualWithCurl = async (url, { cacheDir, method, timeoutMs }) => {
110
- const headerPath = tempFilePath(cacheDir, ".headers");
111
- const bodyPath = tempFilePath(cacheDir, ".body");
112
- const curlNames =
113
- process.platform === "win32" ? ["curl.exe", "curl"] : ["curl"];
114
- const args = [
115
- "--silent",
116
- "--show-error",
117
- "--location",
118
- "--dump-header",
119
- headerPath,
120
- "--output",
121
- bodyPath,
122
- "--user-agent",
123
- USER_AGENT,
124
- "--max-time",
125
- String(Math.max(1, Math.ceil(timeoutMs / 1000))),
126
- ];
127
-
128
- if (method === "HEAD") {
129
- args.push("--head");
130
- } else {
131
- args.push("--request", method);
132
- }
133
- args.push(url);
134
-
135
- let lastError;
136
- for (const curlName of curlNames) {
137
- try {
138
- await execFileAsync(curlName, args, { windowsHide: true });
139
- const [rawHeaders, body] = await Promise.all([
140
- readFile(headerPath, "utf8"),
141
- readFile(bodyPath, "utf8"),
142
- ]);
143
- const { headers, status } = parseCurlHeaders(rawHeaders);
144
- return makeResponse({ body, headers, status });
145
- } catch (error) {
146
- lastError = error;
147
- if (error?.code !== "ENOENT") break;
148
- } finally {
149
- await Promise.all([
150
- rm(headerPath, { force: true }),
151
- rm(bodyPath, { force: true }),
152
- ]);
153
- }
154
- }
155
-
156
- if (lastError?.code === "ENOENT") {
157
- throw new ManualFetchError("curl is unavailable in this environment.", {
158
- cause: lastError,
159
- });
160
- }
161
- throw new ManualFetchError(`${method} ${url} could not be fetched.`, {
162
- cause: lastError,
163
- });
164
- };
165
-
166
- const requestManualWithFetch = async (url, { method, timeoutMs }) => {
167
- if (typeof fetch !== "function") {
168
- throw new ManualFetchError(
169
- "Native fetch is unavailable in this Node runtime."
170
- );
171
- }
172
-
173
- return withTimeout(
174
- (signal) =>
175
- fetch(url, {
176
- method,
177
- headers: { "User-Agent": USER_AGENT },
178
- signal,
179
- }),
180
- timeoutMs
181
- );
182
- };
183
-
184
- const requestManual = async (url, { cacheDir, method, timeoutMs }) => {
185
- const preferCurl = Boolean(proxyConfigured()) || typeof fetch !== "function";
186
- const transports = preferCurl
187
- ? [
188
- () => requestManualWithCurl(url, { cacheDir, method, timeoutMs }),
189
- () => requestManualWithFetch(url, { method, timeoutMs }),
190
- ]
191
- : [
192
- () => requestManualWithFetch(url, { method, timeoutMs }),
193
- () => requestManualWithCurl(url, { cacheDir, method, timeoutMs }),
194
- ];
195
-
196
- let lastError;
197
- for (const transport of transports) {
198
- try {
199
- const response = await transport();
200
- if (!response.ok) {
201
- throw new ManualFetchError(
202
- `${method} ${url} failed with HTTP ${response.status}.`
203
- );
204
- }
205
- return response;
206
- } catch (error) {
207
- lastError = error;
208
- }
209
- }
210
-
211
- throw new ManualFetchError(`${method} ${url} could not be fetched.`, {
212
- cause: lastError,
213
- });
214
- };
215
-
216
- const readHeaderSha = (response) => {
217
- const value = response.headers.get(HASH_HEADER);
218
- if (!value || !/^[a-f0-9]{64}$/i.test(value)) {
219
- throw new ManualFetchError(`Manual response is missing ${HASH_HEADER}.`);
220
- }
221
- return value.toLowerCase();
222
- };
223
-
224
- const nearestExistingParent = async (target) => {
225
- let current = target;
226
- while (true) {
227
- try {
228
- const info = await stat(current);
229
- return info.isDirectory() ? current : null;
230
- } catch (error) {
231
- if (error?.code !== "ENOENT") return null;
232
- }
233
-
234
- const parent = path.dirname(current);
235
- if (parent === current) return null;
236
- current = parent;
237
- }
238
- };
239
-
240
- const usableCacheDir = async (cacheDir) => {
241
- if (!cacheDir) return null;
242
- const resolved = path.resolve(cacheDir);
243
-
244
- try {
245
- const info = await stat(resolved);
246
- if (!info.isDirectory()) return null;
247
- } catch (error) {
248
- if (error?.code !== "ENOENT") return null;
249
- }
250
-
251
- const parent = await nearestExistingParent(resolved);
252
- if (!parent) return null;
253
-
254
- try {
255
- await access(parent, fsConstants.W_OK | fsConstants.X_OK);
256
- } catch {
257
- return null;
258
- }
259
-
260
- return resolved;
261
- };
262
-
263
- const defaultCacheDirCandidates = () => {
264
- const candidates = [];
265
- const seen = new Set();
266
- const pushCandidate = (candidate) => {
267
- if (!candidate || seen.has(candidate)) return;
268
- seen.add(candidate);
269
- candidates.push(candidate);
270
- };
271
-
272
- [process.env.TMPDIR, process.env.TEMP, process.env.TMP].forEach((baseDir) => {
273
- if (baseDir) {
274
- pushCandidate(path.join(baseDir, DEFAULT_CACHE_DIR_NAME));
275
- }
276
- });
277
-
278
- if (process.platform !== "win32") {
279
- pushCandidate(`/private/tmp/${DEFAULT_CACHE_DIR_NAME}`);
280
- pushCandidate(`/tmp/${DEFAULT_CACHE_DIR_NAME}`);
281
- }
282
-
283
- return candidates;
284
- };
285
-
286
- const resolveCacheDir = async (cacheDir) => {
287
- if (cacheDir) {
288
- return usableCacheDir(cacheDir);
289
- }
290
-
291
- for (const candidate of defaultCacheDirCandidates()) {
292
- const usable = await usableCacheDir(candidate);
293
- if (usable) return usable;
294
- }
295
-
296
- return null;
297
- };
298
-
299
- const cacheFilePath = (cacheDir) => path.join(cacheDir, CACHE_FILE_NAME);
300
-
301
- const outlineFilePath = (cacheDir) => path.join(cacheDir, OUTLINE_FILE_NAME);
302
-
303
- const manualLines = (manual) => {
304
- const lines = manual.replace(/\r\n/g, "\n").split("\n");
305
- if (lines[lines.length - 1] === "") lines.pop();
306
- return lines;
307
- };
308
-
309
- const sectionTitle = (rawTitle) =>
310
- rawTitle.replace(/\s+#+\s*$/, "").replace(/\s+/g, " ").trim();
311
-
312
- const buildOutline = (manual) => {
313
- const lines = manualLines(manual);
314
- const headings = [];
315
- let inFence = false;
316
-
317
- lines.forEach((line, index) => {
318
- if (/^\s*(```|~~~)/.test(line)) {
319
- inFence = !inFence;
320
- return;
321
- }
322
- if (inFence) return;
323
-
324
- const match = /^(#{1,6})\s+(.+?)\s*$/.exec(line);
325
- if (!match) return;
326
-
327
- const level = match[1].length;
328
- if (level < 2 || level > 3) return;
329
-
330
- headings.push({
331
- level,
332
- title: sectionTitle(match[2]),
333
- startLine: index + 1,
334
- endLine: lines.length,
335
- });
336
- });
337
-
338
- for (let index = 0; index < headings.length; index += 1) {
339
- const heading = headings[index];
340
- const nextPeer = headings
341
- .slice(index + 1)
342
- .find((candidate) => candidate.level <= heading.level);
343
- if (nextPeer) {
344
- heading.endLine = nextPeer.startLine - 1;
345
- }
346
- }
347
-
348
- if (headings.length === 0) {
349
- return {
350
- headingCount: 0,
351
- lineCount: lines.length,
352
- text: "No markdown headings found.",
353
- };
354
- }
355
-
356
- const minLevel = Math.min(...headings.map((heading) => heading.level));
357
- return {
358
- headingCount: headings.length,
359
- lineCount: lines.length,
360
- text: headings
361
- .map((heading) => {
362
- const indent = " ".repeat(heading.level - minLevel);
363
- return `${indent}- ${heading.title} (lines ${heading.startLine}-${heading.endLine})`;
364
- })
365
- .join("\n"),
366
- };
367
- };
368
-
369
- const outlineMarkdown = (outline) => `# Codex Manual Outline\n\n${outline.text}\n`;
370
-
371
- const manualStatusLine = (status) =>
372
- status.cacheStatus === "hit"
373
- ? "Manual status: local manual was already current."
374
- : "Manual status: local manual was updated.";
375
-
376
- const formatResult = ({ status, outlineText }) =>
377
- [
378
- `Manual path: ${status.manualPath}`,
379
- `Outline path: ${status.outlinePath}`,
380
- manualStatusLine(status),
381
- "",
382
- outlineText,
383
- ].join("\n");
384
-
385
- const readCachedManual = async (cacheDir, expectedSha256) => {
386
- try {
387
- const manual = await readFile(cacheFilePath(cacheDir), "utf8");
388
- return sha256(manual) === expectedSha256 ? manual : null;
389
- } catch {
390
- return null;
391
- }
392
- };
393
-
394
- const writeCachedManual = async (cacheDir, manual) => {
395
- await mkdir(cacheDir, { recursive: true });
396
- const tmpPath = tempFilePath(cacheDir, `.${CACHE_FILE_NAME}.tmp`);
397
- await writeFile(tmpPath, manual, "utf8");
398
- await rename(tmpPath, cacheFilePath(cacheDir));
399
- };
400
-
401
- const writeOutline = async (cacheDir, outlineText) => {
402
- await mkdir(cacheDir, { recursive: true });
403
- const tmpPath = tempFilePath(cacheDir, `.${OUTLINE_FILE_NAME}.tmp`);
404
- await writeFile(tmpPath, outlineText, "utf8");
405
- await rename(tmpPath, outlineFilePath(cacheDir));
406
- };
407
-
408
- const fetchCodexManual = async ({
409
- manualUrl = DEFAULT_MANUAL_URL,
410
- cacheDir,
411
- timeoutMs = 30000,
412
- } = {}) => {
413
- const resolvedCacheDir = await resolveCacheDir(cacheDir);
414
- if (!resolvedCacheDir) {
415
- throw new ManualFetchError(
416
- "Manual cache directory is unavailable; pass --cache-dir to override or use OpenAI Docs MCP fallback."
417
- );
418
- }
419
- await mkdir(resolvedCacheDir, { recursive: true });
420
-
421
- const headResponse = await requestManual(manualUrl, {
422
- cacheDir: resolvedCacheDir,
423
- method: "HEAD",
424
- timeoutMs,
425
- });
426
- const expectedSha256 = readHeaderSha(headResponse);
427
- const manualPath = cacheFilePath(resolvedCacheDir);
428
- const outlinePath = outlineFilePath(resolvedCacheDir);
429
- const checkedAt = new Date().toISOString();
430
-
431
- const cachedManual = await readCachedManual(resolvedCacheDir, expectedSha256);
432
- if (cachedManual !== null) {
433
- const outline = buildOutline(cachedManual);
434
- const outlineText = outlineMarkdown(outline);
435
- await writeOutline(resolvedCacheDir, outlineText);
436
-
437
- return {
438
- outlineText,
439
- status: {
440
- manualUrl,
441
- headerSha256: expectedSha256,
442
- fetchedManualSha256: expectedSha256,
443
- manualHashMatches: true,
444
- cacheStatus: "hit",
445
- cacheDir: resolvedCacheDir,
446
- manualPath,
447
- outlinePath,
448
- checkedAt,
449
- lineCount: outline.lineCount,
450
- headingCount: outline.headingCount,
451
- },
452
- };
453
- }
454
-
455
- const getResponse = await requestManual(manualUrl, {
456
- cacheDir: resolvedCacheDir,
457
- method: "GET",
458
- timeoutMs,
459
- });
460
- const getHeaderSha256 = readHeaderSha(getResponse);
461
- if (getHeaderSha256 !== expectedSha256) {
462
- throw new ManualFetchError(
463
- `${HASH_HEADER} changed between HEAD and GET for ${manualUrl}.`
464
- );
465
- }
466
-
467
- const manualText = await getResponse.text();
468
- const actualSha256 = sha256(manualText);
469
- const manualHashMatches = actualSha256 === expectedSha256;
470
- if (!manualHashMatches) {
471
- throw new ManualFetchError(
472
- `${HASH_HEADER} did not match the fetched manual body for ${manualUrl}.`
473
- );
474
- }
475
-
476
- await writeCachedManual(resolvedCacheDir, manualText);
477
- const outline = buildOutline(manualText);
478
- const outlineText = outlineMarkdown(outline);
479
- await writeOutline(resolvedCacheDir, outlineText);
480
-
481
- return {
482
- outlineText,
483
- status: {
484
- manualUrl,
485
- headerSha256: expectedSha256,
486
- fetchedManualSha256: actualSha256,
487
- manualHashMatches,
488
- cacheStatus: "updated",
489
- cacheDir: resolvedCacheDir,
490
- manualPath,
491
- outlinePath,
492
- checkedAt,
493
- lineCount: outline.lineCount,
494
- headingCount: outline.headingCount,
495
- },
496
- };
497
- };
498
-
499
- const parseArgs = (argv) => {
500
- const args = {
501
- manualUrl: DEFAULT_MANUAL_URL,
502
- cacheDir: undefined,
503
- timeoutMs: 30000,
504
- statusJson: false,
505
- };
506
-
507
- for (let index = 0; index < argv.length; index += 1) {
508
- const arg = argv[index];
509
- if (arg === "--manual-url") {
510
- args.manualUrl = argv[++index];
511
- } else if (arg === "--cache-dir") {
512
- args.cacheDir = argv[++index];
513
- } else if (arg === "--timeout-ms") {
514
- args.timeoutMs = Number(argv[++index]);
515
- } else if (arg === "--status-json") {
516
- args.statusJson = true;
517
- } else {
518
- throw new ManualFetchError(`Unknown argument: ${arg}`);
519
- }
520
- }
521
-
522
- if (!args.manualUrl) {
523
- throw new ManualFetchError("--manual-url cannot be empty.");
524
- }
525
- if (!Number.isFinite(args.timeoutMs) || args.timeoutMs <= 0) {
526
- throw new ManualFetchError("--timeout-ms must be a positive number.");
527
- }
528
-
529
- return args;
530
- };
531
-
532
- const main = async () => {
533
- const args = parseArgs(process.argv.slice(2));
534
- const { outlineText, status } = await fetchCodexManual(args);
535
-
536
- process.stdout.write(formatResult({ status, outlineText }));
537
-
538
- if (args.statusJson) {
539
- console.error(JSON.stringify(status));
540
- }
541
- };
542
-
543
- const envProxyHint = () => {
544
- if (proxyConfigured()) {
545
- return "Hint: proxy env vars are present. This helper prefers `curl` in proxied sessions; if requests still fail, verify `curl` is installed and the proxy configuration is valid.";
546
- }
547
- if (typeof fetch !== "function") {
548
- return "Hint: native fetch is unavailable in this Node runtime. Install `curl` or use a newer Node version to fetch the manual.";
549
- }
550
- if (process.platform === "win32") {
551
- return "Hint: on Windows, pass a cache dir under `%TEMP%` or `%TMP%`.";
552
- }
553
- return null;
554
- };
555
-
556
- const formatErrorDetails = (error) => {
557
- const details = inspect(error, {
558
- breakLength: 120,
559
- colors: false,
560
- compact: false,
561
- depth: 8,
562
- });
563
- if (!error?.cause) {
564
- return details;
565
- }
566
-
567
- return `${details}\n\nCause:\n${inspect(error.cause, {
568
- breakLength: 120,
569
- colors: false,
570
- compact: false,
571
- depth: 8,
572
- })}`;
573
- };
574
-
575
- const isCliEntrypoint = () => {
576
- const entrypoint = process.argv[1];
577
- if (!entrypoint) {
578
- return false;
579
- }
580
-
581
- return pathToFileURL(entrypoint).href === import.meta.url;
582
- };
583
-
584
- if (isCliEntrypoint()) {
585
- main().catch((error) => {
586
- console.error(`Error: ${error.message}`);
587
- const hint = envProxyHint();
588
- if (hint) {
589
- console.error(hint);
590
- }
591
- console.error("");
592
- console.error("Details:");
593
- console.error(formatErrorDetails(error));
594
- process.exitCode = 1;
595
- });
596
- }
597
-
598
- export { DEFAULT_MANUAL_URL, fetchCodexManual };
1
+ #!/usr/bin/env node
2
+ import {
3
+ access,
4
+ mkdir,
5
+ readFile,
6
+ rename,
7
+ rm,
8
+ stat,
9
+ writeFile,
10
+ } from "node:fs/promises";
11
+ import { constants as fsConstants } from "node:fs";
12
+ import { execFile } from "node:child_process";
13
+ import { createHash } from "node:crypto";
14
+ import path from "node:path";
15
+ import process from "node:process";
16
+ import { pathToFileURL } from "node:url";
17
+ import { inspect, promisify } from "node:util";
18
+
19
+ const DEFAULT_MANUAL_URL = "https://developers.openai.com/codex/codex-manual.md";
20
+ const DEFAULT_CACHE_DIR_NAME = "openai-docs-cache";
21
+ const CACHE_FILE_NAME = "codex-manual.md";
22
+ const OUTLINE_FILE_NAME = "codex-manual.outline.md";
23
+ const HASH_HEADER = "x-content-sha256";
24
+ const USER_AGENT = "codex-openai-docs";
25
+ const execFileAsync = promisify(execFile);
26
+
27
+ class ManualFetchError extends Error {
28
+ constructor(message, options) {
29
+ super(message, options);
30
+ this.name = "ManualFetchError";
31
+ }
32
+ }
33
+
34
+ const sha256 = (value) => createHash("sha256").update(value).digest("hex");
35
+
36
+ const withTimeout = async (promiseFactory, timeoutMs) => {
37
+ const controller = new AbortController();
38
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
39
+ try {
40
+ return await promiseFactory(controller.signal);
41
+ } finally {
42
+ clearTimeout(timeout);
43
+ }
44
+ };
45
+
46
+ const proxyConfigured = () =>
47
+ process.env.HTTP_PROXY ||
48
+ process.env.HTTPS_PROXY ||
49
+ process.env.http_proxy ||
50
+ process.env.https_proxy;
51
+
52
+ const responseHeaders = (headers) => ({
53
+ get(name) {
54
+ return headers.get(name.toLowerCase()) ?? null;
55
+ },
56
+ });
57
+
58
+ const makeResponse = ({ body, headers, status }) => ({
59
+ headers: responseHeaders(headers),
60
+ ok: status >= 200 && status < 300,
61
+ status,
62
+ async text() {
63
+ return body;
64
+ },
65
+ });
66
+
67
+ const parseCurlHeaders = (rawHeaders) => {
68
+ const normalized = rawHeaders.replace(/\r\n/g, "\n").trim();
69
+ const blocks = normalized.split(/\n\n+/).filter(Boolean);
70
+ const headerBlock = [...blocks]
71
+ .reverse()
72
+ .find((block) => block.startsWith("HTTP/"));
73
+
74
+ if (!headerBlock) {
75
+ throw new ManualFetchError("curl did not return HTTP response headers.");
76
+ }
77
+
78
+ const [statusLine, ...lines] = headerBlock.split("\n");
79
+ const statusMatch = /^HTTP\/\S+\s+(\d{3})/.exec(statusLine);
80
+ if (!statusMatch) {
81
+ throw new ManualFetchError(
82
+ `Could not parse HTTP status from curl response: ${statusLine}`
83
+ );
84
+ }
85
+
86
+ const headers = new Map();
87
+ lines.forEach((line) => {
88
+ const separator = line.indexOf(":");
89
+ if (separator === -1) return;
90
+ const name = line.slice(0, separator).trim().toLowerCase();
91
+ const value = line.slice(separator + 1).trim();
92
+ headers.set(name, value);
93
+ });
94
+
95
+ return {
96
+ headers,
97
+ status: Number(statusMatch[1]),
98
+ };
99
+ };
100
+
101
+ const tempFilePath = (cacheDir, suffix) =>
102
+ path.join(
103
+ cacheDir,
104
+ `.fetch-codex-manual-${process.pid}-${Date.now()}-${Math.random()
105
+ .toString(16)
106
+ .slice(2)}${suffix}`
107
+ );
108
+
109
+ const requestManualWithCurl = async (url, { cacheDir, method, timeoutMs }) => {
110
+ const headerPath = tempFilePath(cacheDir, ".headers");
111
+ const bodyPath = tempFilePath(cacheDir, ".body");
112
+ const curlNames =
113
+ process.platform === "win32" ? ["curl.exe", "curl"] : ["curl"];
114
+ const args = [
115
+ "--silent",
116
+ "--show-error",
117
+ "--location",
118
+ "--dump-header",
119
+ headerPath,
120
+ "--output",
121
+ bodyPath,
122
+ "--user-agent",
123
+ USER_AGENT,
124
+ "--max-time",
125
+ String(Math.max(1, Math.ceil(timeoutMs / 1000))),
126
+ ];
127
+
128
+ if (method === "HEAD") {
129
+ args.push("--head");
130
+ } else {
131
+ args.push("--request", method);
132
+ }
133
+ args.push(url);
134
+
135
+ let lastError;
136
+ for (const curlName of curlNames) {
137
+ try {
138
+ await execFileAsync(curlName, args, { windowsHide: true });
139
+ const [rawHeaders, body] = await Promise.all([
140
+ readFile(headerPath, "utf8"),
141
+ readFile(bodyPath, "utf8"),
142
+ ]);
143
+ const { headers, status } = parseCurlHeaders(rawHeaders);
144
+ return makeResponse({ body, headers, status });
145
+ } catch (error) {
146
+ lastError = error;
147
+ if (error?.code !== "ENOENT") break;
148
+ } finally {
149
+ await Promise.all([
150
+ rm(headerPath, { force: true }),
151
+ rm(bodyPath, { force: true }),
152
+ ]);
153
+ }
154
+ }
155
+
156
+ if (lastError?.code === "ENOENT") {
157
+ throw new ManualFetchError("curl is unavailable in this environment.", {
158
+ cause: lastError,
159
+ });
160
+ }
161
+ throw new ManualFetchError(`${method} ${url} could not be fetched.`, {
162
+ cause: lastError,
163
+ });
164
+ };
165
+
166
+ const requestManualWithFetch = async (url, { method, timeoutMs }) => {
167
+ if (typeof fetch !== "function") {
168
+ throw new ManualFetchError(
169
+ "Native fetch is unavailable in this Node runtime."
170
+ );
171
+ }
172
+
173
+ return withTimeout(
174
+ (signal) =>
175
+ fetch(url, {
176
+ method,
177
+ headers: { "User-Agent": USER_AGENT },
178
+ signal,
179
+ }),
180
+ timeoutMs
181
+ );
182
+ };
183
+
184
+ const requestManual = async (url, { cacheDir, method, timeoutMs }) => {
185
+ const preferCurl = Boolean(proxyConfigured()) || typeof fetch !== "function";
186
+ const transports = preferCurl
187
+ ? [
188
+ () => requestManualWithCurl(url, { cacheDir, method, timeoutMs }),
189
+ () => requestManualWithFetch(url, { method, timeoutMs }),
190
+ ]
191
+ : [
192
+ () => requestManualWithFetch(url, { method, timeoutMs }),
193
+ () => requestManualWithCurl(url, { cacheDir, method, timeoutMs }),
194
+ ];
195
+
196
+ let lastError;
197
+ for (const transport of transports) {
198
+ try {
199
+ const response = await transport();
200
+ if (!response.ok) {
201
+ throw new ManualFetchError(
202
+ `${method} ${url} failed with HTTP ${response.status}.`
203
+ );
204
+ }
205
+ return response;
206
+ } catch (error) {
207
+ lastError = error;
208
+ }
209
+ }
210
+
211
+ throw new ManualFetchError(`${method} ${url} could not be fetched.`, {
212
+ cause: lastError,
213
+ });
214
+ };
215
+
216
+ const readHeaderSha = (response) => {
217
+ const value = response.headers.get(HASH_HEADER);
218
+ if (!value || !/^[a-f0-9]{64}$/i.test(value)) {
219
+ throw new ManualFetchError(`Manual response is missing ${HASH_HEADER}.`);
220
+ }
221
+ return value.toLowerCase();
222
+ };
223
+
224
+ const nearestExistingParent = async (target) => {
225
+ let current = target;
226
+ while (true) {
227
+ try {
228
+ const info = await stat(current);
229
+ return info.isDirectory() ? current : null;
230
+ } catch (error) {
231
+ if (error?.code !== "ENOENT") return null;
232
+ }
233
+
234
+ const parent = path.dirname(current);
235
+ if (parent === current) return null;
236
+ current = parent;
237
+ }
238
+ };
239
+
240
+ const usableCacheDir = async (cacheDir) => {
241
+ if (!cacheDir) return null;
242
+ const resolved = path.resolve(cacheDir);
243
+
244
+ try {
245
+ const info = await stat(resolved);
246
+ if (!info.isDirectory()) return null;
247
+ } catch (error) {
248
+ if (error?.code !== "ENOENT") return null;
249
+ }
250
+
251
+ const parent = await nearestExistingParent(resolved);
252
+ if (!parent) return null;
253
+
254
+ try {
255
+ await access(parent, fsConstants.W_OK | fsConstants.X_OK);
256
+ } catch {
257
+ return null;
258
+ }
259
+
260
+ return resolved;
261
+ };
262
+
263
+ const defaultCacheDirCandidates = () => {
264
+ const candidates = [];
265
+ const seen = new Set();
266
+ const pushCandidate = (candidate) => {
267
+ if (!candidate || seen.has(candidate)) return;
268
+ seen.add(candidate);
269
+ candidates.push(candidate);
270
+ };
271
+
272
+ [process.env.TMPDIR, process.env.TEMP, process.env.TMP].forEach((baseDir) => {
273
+ if (baseDir) {
274
+ pushCandidate(path.join(baseDir, DEFAULT_CACHE_DIR_NAME));
275
+ }
276
+ });
277
+
278
+ if (process.platform !== "win32") {
279
+ pushCandidate(`/private/tmp/${DEFAULT_CACHE_DIR_NAME}`);
280
+ pushCandidate(`/tmp/${DEFAULT_CACHE_DIR_NAME}`);
281
+ }
282
+
283
+ return candidates;
284
+ };
285
+
286
+ const resolveCacheDir = async (cacheDir) => {
287
+ if (cacheDir) {
288
+ return usableCacheDir(cacheDir);
289
+ }
290
+
291
+ for (const candidate of defaultCacheDirCandidates()) {
292
+ const usable = await usableCacheDir(candidate);
293
+ if (usable) return usable;
294
+ }
295
+
296
+ return null;
297
+ };
298
+
299
+ const cacheFilePath = (cacheDir) => path.join(cacheDir, CACHE_FILE_NAME);
300
+
301
+ const outlineFilePath = (cacheDir) => path.join(cacheDir, OUTLINE_FILE_NAME);
302
+
303
+ const manualLines = (manual) => {
304
+ const lines = manual.replace(/\r\n/g, "\n").split("\n");
305
+ if (lines[lines.length - 1] === "") lines.pop();
306
+ return lines;
307
+ };
308
+
309
+ const sectionTitle = (rawTitle) =>
310
+ rawTitle.replace(/\s+#+\s*$/, "").replace(/\s+/g, " ").trim();
311
+
312
+ const buildOutline = (manual) => {
313
+ const lines = manualLines(manual);
314
+ const headings = [];
315
+ let inFence = false;
316
+
317
+ lines.forEach((line, index) => {
318
+ if (/^\s*(```|~~~)/.test(line)) {
319
+ inFence = !inFence;
320
+ return;
321
+ }
322
+ if (inFence) return;
323
+
324
+ const match = /^(#{1,6})\s+(.+?)\s*$/.exec(line);
325
+ if (!match) return;
326
+
327
+ const level = match[1].length;
328
+ if (level < 2 || level > 3) return;
329
+
330
+ headings.push({
331
+ level,
332
+ title: sectionTitle(match[2]),
333
+ startLine: index + 1,
334
+ endLine: lines.length,
335
+ });
336
+ });
337
+
338
+ for (let index = 0; index < headings.length; index += 1) {
339
+ const heading = headings[index];
340
+ const nextPeer = headings
341
+ .slice(index + 1)
342
+ .find((candidate) => candidate.level <= heading.level);
343
+ if (nextPeer) {
344
+ heading.endLine = nextPeer.startLine - 1;
345
+ }
346
+ }
347
+
348
+ if (headings.length === 0) {
349
+ return {
350
+ headingCount: 0,
351
+ lineCount: lines.length,
352
+ text: "No markdown headings found.",
353
+ };
354
+ }
355
+
356
+ const minLevel = Math.min(...headings.map((heading) => heading.level));
357
+ return {
358
+ headingCount: headings.length,
359
+ lineCount: lines.length,
360
+ text: headings
361
+ .map((heading) => {
362
+ const indent = " ".repeat(heading.level - minLevel);
363
+ return `${indent}- ${heading.title} (lines ${heading.startLine}-${heading.endLine})`;
364
+ })
365
+ .join("\n"),
366
+ };
367
+ };
368
+
369
+ const outlineMarkdown = (outline) => `# Codex Manual Outline\n\n${outline.text}\n`;
370
+
371
+ const manualStatusLine = (status) =>
372
+ status.cacheStatus === "hit"
373
+ ? "Manual status: local manual was already current."
374
+ : "Manual status: local manual was updated.";
375
+
376
+ const formatResult = ({ status, outlineText }) =>
377
+ [
378
+ `Manual path: ${status.manualPath}`,
379
+ `Outline path: ${status.outlinePath}`,
380
+ manualStatusLine(status),
381
+ "",
382
+ outlineText,
383
+ ].join("\n");
384
+
385
+ const readCachedManual = async (cacheDir, expectedSha256) => {
386
+ try {
387
+ const manual = await readFile(cacheFilePath(cacheDir), "utf8");
388
+ return sha256(manual) === expectedSha256 ? manual : null;
389
+ } catch {
390
+ return null;
391
+ }
392
+ };
393
+
394
+ const writeCachedManual = async (cacheDir, manual) => {
395
+ await mkdir(cacheDir, { recursive: true });
396
+ const tmpPath = tempFilePath(cacheDir, `.${CACHE_FILE_NAME}.tmp`);
397
+ await writeFile(tmpPath, manual, "utf8");
398
+ await rename(tmpPath, cacheFilePath(cacheDir));
399
+ };
400
+
401
+ const writeOutline = async (cacheDir, outlineText) => {
402
+ await mkdir(cacheDir, { recursive: true });
403
+ const tmpPath = tempFilePath(cacheDir, `.${OUTLINE_FILE_NAME}.tmp`);
404
+ await writeFile(tmpPath, outlineText, "utf8");
405
+ await rename(tmpPath, outlineFilePath(cacheDir));
406
+ };
407
+
408
+ const fetchCodexManual = async ({
409
+ manualUrl = DEFAULT_MANUAL_URL,
410
+ cacheDir,
411
+ timeoutMs = 30000,
412
+ } = {}) => {
413
+ const resolvedCacheDir = await resolveCacheDir(cacheDir);
414
+ if (!resolvedCacheDir) {
415
+ throw new ManualFetchError(
416
+ "Manual cache directory is unavailable; pass --cache-dir to override or use OpenAI Docs MCP fallback."
417
+ );
418
+ }
419
+ await mkdir(resolvedCacheDir, { recursive: true });
420
+
421
+ const headResponse = await requestManual(manualUrl, {
422
+ cacheDir: resolvedCacheDir,
423
+ method: "HEAD",
424
+ timeoutMs,
425
+ });
426
+ const expectedSha256 = readHeaderSha(headResponse);
427
+ const manualPath = cacheFilePath(resolvedCacheDir);
428
+ const outlinePath = outlineFilePath(resolvedCacheDir);
429
+ const checkedAt = new Date().toISOString();
430
+
431
+ const cachedManual = await readCachedManual(resolvedCacheDir, expectedSha256);
432
+ if (cachedManual !== null) {
433
+ const outline = buildOutline(cachedManual);
434
+ const outlineText = outlineMarkdown(outline);
435
+ await writeOutline(resolvedCacheDir, outlineText);
436
+
437
+ return {
438
+ outlineText,
439
+ status: {
440
+ manualUrl,
441
+ headerSha256: expectedSha256,
442
+ fetchedManualSha256: expectedSha256,
443
+ manualHashMatches: true,
444
+ cacheStatus: "hit",
445
+ cacheDir: resolvedCacheDir,
446
+ manualPath,
447
+ outlinePath,
448
+ checkedAt,
449
+ lineCount: outline.lineCount,
450
+ headingCount: outline.headingCount,
451
+ },
452
+ };
453
+ }
454
+
455
+ const getResponse = await requestManual(manualUrl, {
456
+ cacheDir: resolvedCacheDir,
457
+ method: "GET",
458
+ timeoutMs,
459
+ });
460
+ const getHeaderSha256 = readHeaderSha(getResponse);
461
+ if (getHeaderSha256 !== expectedSha256) {
462
+ throw new ManualFetchError(
463
+ `${HASH_HEADER} changed between HEAD and GET for ${manualUrl}.`
464
+ );
465
+ }
466
+
467
+ const manualText = await getResponse.text();
468
+ const actualSha256 = sha256(manualText);
469
+ const manualHashMatches = actualSha256 === expectedSha256;
470
+ if (!manualHashMatches) {
471
+ throw new ManualFetchError(
472
+ `${HASH_HEADER} did not match the fetched manual body for ${manualUrl}.`
473
+ );
474
+ }
475
+
476
+ await writeCachedManual(resolvedCacheDir, manualText);
477
+ const outline = buildOutline(manualText);
478
+ const outlineText = outlineMarkdown(outline);
479
+ await writeOutline(resolvedCacheDir, outlineText);
480
+
481
+ return {
482
+ outlineText,
483
+ status: {
484
+ manualUrl,
485
+ headerSha256: expectedSha256,
486
+ fetchedManualSha256: actualSha256,
487
+ manualHashMatches,
488
+ cacheStatus: "updated",
489
+ cacheDir: resolvedCacheDir,
490
+ manualPath,
491
+ outlinePath,
492
+ checkedAt,
493
+ lineCount: outline.lineCount,
494
+ headingCount: outline.headingCount,
495
+ },
496
+ };
497
+ };
498
+
499
+ const parseArgs = (argv) => {
500
+ const args = {
501
+ manualUrl: DEFAULT_MANUAL_URL,
502
+ cacheDir: undefined,
503
+ timeoutMs: 30000,
504
+ statusJson: false,
505
+ };
506
+
507
+ for (let index = 0; index < argv.length; index += 1) {
508
+ const arg = argv[index];
509
+ if (arg === "--manual-url") {
510
+ args.manualUrl = argv[++index];
511
+ } else if (arg === "--cache-dir") {
512
+ args.cacheDir = argv[++index];
513
+ } else if (arg === "--timeout-ms") {
514
+ args.timeoutMs = Number(argv[++index]);
515
+ } else if (arg === "--status-json") {
516
+ args.statusJson = true;
517
+ } else {
518
+ throw new ManualFetchError(`Unknown argument: ${arg}`);
519
+ }
520
+ }
521
+
522
+ if (!args.manualUrl) {
523
+ throw new ManualFetchError("--manual-url cannot be empty.");
524
+ }
525
+ if (!Number.isFinite(args.timeoutMs) || args.timeoutMs <= 0) {
526
+ throw new ManualFetchError("--timeout-ms must be a positive number.");
527
+ }
528
+
529
+ return args;
530
+ };
531
+
532
+ const main = async () => {
533
+ const args = parseArgs(process.argv.slice(2));
534
+ const { outlineText, status } = await fetchCodexManual(args);
535
+
536
+ process.stdout.write(formatResult({ status, outlineText }));
537
+
538
+ if (args.statusJson) {
539
+ console.error(JSON.stringify(status));
540
+ }
541
+ };
542
+
543
+ const envProxyHint = () => {
544
+ if (proxyConfigured()) {
545
+ return "Hint: proxy env vars are present. This helper prefers `curl` in proxied sessions; if requests still fail, verify `curl` is installed and the proxy configuration is valid.";
546
+ }
547
+ if (typeof fetch !== "function") {
548
+ return "Hint: native fetch is unavailable in this Node runtime. Install `curl` or use a newer Node version to fetch the manual.";
549
+ }
550
+ if (process.platform === "win32") {
551
+ return "Hint: on Windows, pass a cache dir under `%TEMP%` or `%TMP%`.";
552
+ }
553
+ return null;
554
+ };
555
+
556
+ const formatErrorDetails = (error) => {
557
+ const details = inspect(error, {
558
+ breakLength: 120,
559
+ colors: false,
560
+ compact: false,
561
+ depth: 8,
562
+ });
563
+ if (!error?.cause) {
564
+ return details;
565
+ }
566
+
567
+ return `${details}\n\nCause:\n${inspect(error.cause, {
568
+ breakLength: 120,
569
+ colors: false,
570
+ compact: false,
571
+ depth: 8,
572
+ })}`;
573
+ };
574
+
575
+ const isCliEntrypoint = () => {
576
+ const entrypoint = process.argv[1];
577
+ if (!entrypoint) {
578
+ return false;
579
+ }
580
+
581
+ return pathToFileURL(entrypoint).href === import.meta.url;
582
+ };
583
+
584
+ if (isCliEntrypoint()) {
585
+ main().catch((error) => {
586
+ console.error(`Error: ${error.message}`);
587
+ const hint = envProxyHint();
588
+ if (hint) {
589
+ console.error(hint);
590
+ }
591
+ console.error("");
592
+ console.error("Details:");
593
+ console.error(formatErrorDetails(error));
594
+ process.exitCode = 1;
595
+ });
596
+ }
597
+
598
+ export { DEFAULT_MANUAL_URL, fetchCodexManual };