@fprad0/skill-master-mcp 0.0.10 → 0.0.12

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 (108) hide show
  1. package/CHANGELOG.md +12 -1
  2. package/README.md +59 -10
  3. package/VERSION.md +3 -3
  4. package/bin/lib/client-config.mjs +293 -0
  5. package/bin/lib/menu-core.mjs +509 -131
  6. package/bin/lib/skill-installation.mjs +215 -0
  7. package/bin/skill-master-bootstrap-global.mjs +2 -1
  8. package/bin/skill-master-doctor.mjs +92 -32
  9. package/bin/skill-master-install-global-skills.mjs +4 -42
  10. package/bin/skill-master-install-project-skills.mjs +97 -0
  11. package/bin/skill-master-menu.mjs +91 -6
  12. package/bin/skill-master-register-clients.mjs +91 -115
  13. package/docs/operations/GUIA_MULTI_COMPUTADOR.md +262 -0
  14. package/docs/operations/GUIA_NPM_PUBLICO.md +147 -0
  15. package/docs/operations/MENU_VISUAL_EVIDENCE_2026-06-28.md +66 -0
  16. package/docs/operations/assets/menu-frame-compact.html +76 -0
  17. package/docs/operations/assets/menu-frame-compact.png +0 -0
  18. package/docs/operations/assets/menu-frame-large.html +84 -0
  19. package/docs/operations/assets/menu-frame-large.png +0 -0
  20. package/docs/operations/assets/menu-frame-running.html +80 -0
  21. package/docs/operations/assets/menu-frame-running.png +0 -0
  22. package/docs/operations/cross-platform-auth-transfer/ANALISE_COMPATIBILIDADE_MCP_2026-06-28.md +140 -0
  23. package/docs/operations/cross-platform-auth-transfer/README_TRANSFERENCIA.md +85 -0
  24. package/docs/operations/reborn-menu-cyberpunk-transfer/ANALISE_MENU_REBORN_CYBERPUNK_2026-06-28.md +174 -0
  25. package/docs/operations/reborn-menu-cyberpunk-transfer/HANDOFF_IMPLEMENTACAO_REBORN_CYBERPUNK_2026-06-28.md +119 -0
  26. package/docs/operations/reborn-menu-cyberpunk-transfer/ORDEM_DE_EXECUCAO_MENU_REBORN_CYBERPUNK.md +134 -0
  27. package/docs/operations/reborn-menu-cyberpunk-transfer/README_TRANSFERENCIA.md +84 -0
  28. package/docs/operations/reborn-menu-cyberpunk-transfer/README_TRANSFERENCIA_REBORN_PACKAGE.md +56 -0
  29. package/docs/operations/reborn-menu-cyberpunk-transfer/references/cyan-hud-frame-sheet.jpg +0 -0
  30. package/docs/operations/reborn-menu-cyberpunk-transfer/references/cyberpunk-pattern-sheet.jpg +0 -0
  31. package/docs/operations/reborn-menu-cyberpunk-transfer/references/fluid-workflow-windows.gif +0 -0
  32. package/docs/prompt-tasks/PROMPT_TASK_001_BOOTSTRAP_SKILL_MASTER_MCP.md +6 -0
  33. package/docs/prompt-tasks/PROMPT_TASK_002_AUTO_UPDATE_LAUNCHER.md +6 -0
  34. package/docs/prompt-tasks/PROMPT_TASK_003_REMOTE_MANIFEST_AND_RELEASES.md +6 -0
  35. package/docs/prompt-tasks/PROMPT_TASK_004_MULTI_USER_DISTRIBUTION.md +6 -0
  36. package/docs/prompt-tasks/PROMPT_TASK_005_SECURITY_AND_QUALITY_GATE.md +6 -0
  37. package/docs/prompt-tasks/PROMPT_TASK_006_MASTER_ACIONAMENTO_APRENDIZADO.md +83 -0
  38. package/docs/prompt-tasks/PROMPT_TASK_007_PERSONA_ORQUESTRADORA.md +88 -0
  39. package/docs/prompt-tasks/PROMPT_TASK_008_PROMPT_ROUTER_MODOS_ATIVACAO.md +156 -0
  40. package/docs/prompt-tasks/PROMPT_TASK_009_PIPELINE_APRENDIZADO_SUCESSO.md +105 -0
  41. package/docs/prompt-tasks/PROMPT_TASK_010_EVALS_GOVERNANCA_ATIVACAO.md +119 -0
  42. package/docs/prompt-tasks/PROMPT_TASK_011_MENU_NOTIFICACOES_NOTION.md +120 -0
  43. package/docs/prompt-tasks/PROMPT_TASK_012_MENU_CYBERPUNK_PIXEL_FRAME.md +123 -0
  44. package/docs/prompt-tasks/PROMPT_TASK_013_MENU_FLUID_DNA_ANIMATION.md +114 -0
  45. package/docs/prompt-tasks/PROMPT_TASK_014_MENU_FUNCTIONAL_PARITY_QA.md +157 -0
  46. package/docs/prompt-tasks/PROMPT_TASK_015_TRANSFER_RELEASE_HANDOFF.md +127 -0
  47. package/docs/prompt-tasks/PROMPT_TASK_016_CROSS_PLATFORM_MCP_AUTH_REGISTRATION.md +107 -0
  48. package/docs/prompt-tasks/PROMPT_TASK_018_NPM_PUBLISH_2FA_SETUP.md +80 -0
  49. package/docs/prompt-tasks/PROMPT_TASK_MASTER_EXECUTOR.md +6 -0
  50. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/SKILL.md +399 -0
  51. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/common-patterns.md +331 -0
  52. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/complete-examples.md +872 -0
  53. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/component-patterns.md +502 -0
  54. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/data-fetching.md +767 -0
  55. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/file-organization.md +502 -0
  56. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/loading-and-error-states.md +501 -0
  57. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/performance.md +406 -0
  58. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/routing-guide.md +364 -0
  59. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/styling-guide.md +428 -0
  60. package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/typescript-standards.md +418 -0
  61. package/docs/skill-candidates/v0.0.11/git-version-control-ops/SKILL.md +34 -0
  62. package/docs/skill-candidates/v0.0.11/go-engineering/SKILL.md +34 -0
  63. package/docs/skill-candidates/v0.0.11/java-engineering/SKILL.md +34 -0
  64. package/docs/skill-candidates/v0.0.11/javascript-engineering/SKILL.md +34 -0
  65. package/docs/skill-candidates/v0.0.11/json-contract-design/SKILL.md +34 -0
  66. package/docs/skill-candidates/v0.0.11/multi-client-mcp-ops/SKILL.md +36 -0
  67. package/docs/skill-candidates/v0.0.11/nextjs/SKILL.md +745 -0
  68. package/docs/skill-candidates/v0.0.11/nextjs/agents/openai.yaml +3 -0
  69. package/docs/skill-candidates/v0.0.11/nextjs/references/app-router-files.md +94 -0
  70. package/docs/skill-candidates/v0.0.11/python-engineering/SKILL.md +34 -0
  71. package/docs/skill-candidates/v0.0.11/ruby-engineering/SKILL.md +34 -0
  72. package/docs/skill-candidates/v0.0.11/senior-fullstack/SKILL.md +209 -0
  73. package/docs/skill-candidates/v0.0.11/senior-fullstack/references/architecture_patterns.md +103 -0
  74. package/docs/skill-candidates/v0.0.11/senior-fullstack/references/development_workflows.md +103 -0
  75. package/docs/skill-candidates/v0.0.11/senior-fullstack/references/tech_stack_guide.md +103 -0
  76. package/docs/skill-candidates/v0.0.11/senior-fullstack/scripts/code_quality_analyzer.py +114 -0
  77. package/docs/skill-candidates/v0.0.11/senior-fullstack/scripts/fullstack_scaffolder.py +114 -0
  78. package/docs/skill-candidates/v0.0.11/senior-fullstack/scripts/project_scaffolder.py +114 -0
  79. package/docs/skill-candidates/v0.0.11/shadcn/SKILL.md +573 -0
  80. package/docs/skill-candidates/v0.0.11/shadcn/agents/openai.yaml +3 -0
  81. package/docs/skill-candidates/v0.0.11/sql-postgresql-engineering/SKILL.md +34 -0
  82. package/docs/skill-candidates/v0.0.11/terminal-shell-ops/SKILL.md +34 -0
  83. package/docs/skill-candidates/v0.0.11/typescript-expert/SKILL.md +429 -0
  84. package/docs/skill-candidates/v0.0.11/typescript-expert/references/tsconfig-strict.json +92 -0
  85. package/docs/skill-candidates/v0.0.11/typescript-expert/references/typescript-cheatsheet.md +383 -0
  86. package/docs/skill-candidates/v0.0.11/typescript-expert/references/utility-types.ts +335 -0
  87. package/docs/skill-candidates/v0.0.11/typescript-expert/scripts/ts_diagnostic.py +203 -0
  88. package/docs/skill-candidates/v0.0.11/ui-component-primitives/SKILL.md +34 -0
  89. package/docs/skill-candidates/v0.0.11/web-mobile-design-systems/SKILL.md +34 -0
  90. package/docs/skill-candidates/v0.0.11/windows-linux-platform-ops/SKILL.md +34 -0
  91. package/docs/skill-candidates/v0.0.12/csharp-senior-master-engineering/SKILL.md +32 -0
  92. package/docs/skill-candidates/v0.0.12/css-senior-master-engineering/SKILL.md +32 -0
  93. package/docs/skill-candidates/v0.0.12/go-senior-master-engineering/SKILL.md +32 -0
  94. package/docs/skill-candidates/v0.0.12/html-senior-master-engineering/SKILL.md +32 -0
  95. package/docs/skill-candidates/v0.0.12/javascript-senior-master-engineering/SKILL.md +32 -0
  96. package/docs/skill-candidates/v0.0.12/json-senior-master-engineering/SKILL.md +32 -0
  97. package/docs/skill-candidates/v0.0.12/python-senior-master-engineering/SKILL.md +32 -0
  98. package/docs/skill-candidates/v0.0.12/react-senior-master-engineering/SKILL.md +32 -0
  99. package/docs/skill-candidates/v0.0.12/ruby-senior-master-engineering/SKILL.md +32 -0
  100. package/docs/skill-candidates/v0.0.12/senior-master-code-optimizer/SKILL.md +48 -0
  101. package/docs/skill-candidates/v0.0.12/sql-senior-master-engineering/SKILL.md +31 -0
  102. package/docs/skill-candidates/v0.0.12/typescript-senior-master-engineering/SKILL.md +35 -0
  103. package/examples/client-configs/claude-code.commands.md +11 -7
  104. package/manifests/channels/beta.json +7 -7
  105. package/manifests/channels/stable.json +8 -8
  106. package/package.json +14 -2
  107. package/scripts/render-menu-evidence.mjs +130 -0
  108. package/scripts/verify-menu-actions.mjs +117 -0
package/CHANGELOG.md CHANGED
@@ -4,7 +4,18 @@ All notable changes to `skill_master` will be tracked here.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
- - Await explicit authorization before the next npm publication.
7
+ ## [0.0.12] - 2026-06-29
8
+
9
+ - Publish the Reborn cyberpunk HUD layer with intro, visual confirmation, running workflow frame, and low-flicker interactive menu flow.
10
+ - Redesign `DNA-CORE` into `DNA CYBER HELIX` with fuller braille pixel art, cyan/amber palette layering, halo fill, and a smoothed 36-frame animation cycle.
11
+ - Add explicit Claude Code registration through `skill-master-register-clients --apply-claude-code`, using `claude mcp add` with absolute Node and package entrypoint.
12
+ - Keep menu actions and MCP client registration robust across Codex, Claude, Gemini, and Antigravity while packaging updated visual evidence and handoff docs.
13
+
14
+ ## [0.0.11] - 2026-06-28
15
+
16
+ - Register MCP clients with an absolute Node.js executable plus the absolute `bin/skill-master.mjs` entrypoint, avoiding PATH-dependent startup failures in Windows, Linux, macOS, and desktop MCP clients.
17
+ - Add shared client-config helpers, Codex/JSON config assessment, doctor reporting for robust vs legacy registration modes, and a menu action matrix verifier.
18
+ - Add a second bundled global skill pack `v0.0.11` with more granular language, data, terminal, Git, OS, MCP client and UI/design skills for global installation.
8
19
 
9
20
  ## [0.0.10] - 2026-06-28
10
21
 
package/README.md CHANGED
@@ -108,13 +108,12 @@ npm install -g @fprad0/skill-master-mcp
108
108
  npx -y @fprad0/skill-master-mcp@latest
109
109
  ```
110
110
 
111
- Estado atual preparado em `2026-06-28`:
111
+ Fluxo atual:
112
112
 
113
- - release publica: `@fprad0/skill-master-mcp@0.0.9`
114
- - `latest` no npmjs aponta para `0.0.9`
115
- - validacao de pacote por tarball local confirmada
116
- - validacao de instalacao publica via `npm install @fprad0/skill-master-mcp@0.0.9` confirmada
117
- - preparacao local seguinte: `0.0.10`, focada em confiabilidade do menu, doctor, Antigravity e separacao entre acoes globais e acoes de desenvolvimento
113
+ - instalacao publica simples por `npm install -g @fprad0/skill-master-mcp`
114
+ - execucao sem install global por `npx -y @fprad0/skill-master-mcp@latest`
115
+ - validacao rapida da versao publicada por `npm view @fprad0/skill-master-mcp version --registry=https://registry.npmjs.org`
116
+ - esta linha de release publica o HUD Reborn `v0.0.12`, com DNA cyberpunk pixel art mais artistico e registro MCP multi-cliente com Node absoluto
118
117
 
119
118
  Comandos globais principais:
120
119
 
@@ -145,6 +144,7 @@ skill-master-menu --run doctor
145
144
  skill-master-menu --run check
146
145
  skill-master-menu --run update --yes
147
146
  skill-master-menu --run install-global-skills
147
+ skill-master-menu --run install-project-skills
148
148
  skill-master-menu --run bootstrap-global
149
149
  skill-master-menu --run register-clients
150
150
  skill-master-menu --run notifications
@@ -157,7 +157,7 @@ skill-master-menu --run notion-summary
157
157
 
158
158
  O menu visual usa `prompts` para ficar mais legivel no terminal e manter compatibilidade com `Node 18+`.
159
159
 
160
- Quando o menu detectar que o MCP ainda nao esta globalmente pronto neste computador, ele mostra um alerta forte e um aviso sutil explicando que a instalacao global e o registro dos clientes sao necessarios para o `skill_master` parecer parte do sistema em Codex, Claude e Gemini.
160
+ Quando o menu detectar que o MCP ainda nao esta globalmente pronto neste computador, ele mostra um alerta forte e um aviso sutil explicando que a instalacao global e o registro dos clientes sao necessarios para o `skill_master` parecer parte do sistema em Codex, Claude, Gemini e Antigravity.
161
161
 
162
162
  Em instalacoes globais via npm, o menu tambem separa acoes operacionais de acoes de desenvolvimento. Acoes como `check` e `build` dependem do clone completo do repositorio; quando o pacote estiver instalado globalmente, use:
163
163
 
@@ -173,7 +173,36 @@ Para instalar as skills globais embutidas de discernimento, conhecimento amplo,
173
173
  skill-master-install-global-skills
174
174
  ```
175
175
 
176
- No estado atual do pacote, esse bundle global tambem inclui cobertura para frontend, backend, CLI, terminal, GitHub, Windows/Linux, clientes MCP, design, Figma, Playwright, idiomas e raciocinio tecnico, usando uma combinacao de skills locais aprovadas e skills oficiais empacotadas em `docs/skill-candidates/v0.0.10`.
176
+ No estado atual do pacote, esse bundle global tambem inclui cobertura para frontend, backend, CLI, terminal, GitHub, Windows/Linux, clientes MCP, design, Figma, Playwright, idiomas e raciocinio tecnico, usando uma combinacao de skills locais aprovadas e skills oficiais empacotadas em `docs/skill-candidates/v0.0.10` e `docs/skill-candidates/v0.0.11`.
177
+
178
+ O bundle tambem inclui uma camada `senior master` de otimizacao e hardening por linguagem em `docs/skill-candidates/v0.0.12`, cobrindo TypeScript, Python, JavaScript, Go, SQL, JSON, Ruby, React, HTML, CSS e C#. Essas skills orientam escrita, organizacao, reducao de complexidade, performance, seguranca, testes e validacao real antes de declarar uma mudanca pronta.
179
+
180
+ O pacote `v0.0.12` preserva esse bundle granular e adiciona a passada visual Reborn do menu, com HUD operacional mais estavel, estados de execucao mais claros e um `DNA-CORE` mais artistico em cyberpunk pixel art.
181
+
182
+ Para instalar o mesmo bundle como skills locais de um projeto, rode o comando dentro da pasta do projeto:
183
+
184
+ ```bash
185
+ skill-master-install-project-skills --sync-package-json
186
+ ```
187
+
188
+ Por padrao ele copia as skills para:
189
+
190
+ - `.agents/skills`
191
+ - `.codex/skills`
192
+ - `.claude/skills`
193
+ - `.gemini/skills`
194
+
195
+ O comando tambem grava `.skill-master/catalog.json` e, quando existe `package.json`, adiciona metadados em `skillMaster` e o script `skill-master:install-project-skills`. Isso permite que o projeto fique catalogado e que outro notebook reinstale as skills locais com:
196
+
197
+ ```bash
198
+ npm run skill-master:install-project-skills
199
+ ```
200
+
201
+ Para projetos npm que precisam materializar o lock depois de alterar dependencias ou scripts, rode:
202
+
203
+ ```bash
204
+ npm install --package-lock-only
205
+ ```
177
206
 
178
207
  Para fazer o bootstrap global completo em um passo:
179
208
 
@@ -181,11 +210,12 @@ Para fazer o bootstrap global completo em um passo:
181
210
  skill-master-bootstrap-global
182
211
  ```
183
212
 
184
- Para registrar o MCP nos clientes principais usando o binario global `skill-master-mcp`:
213
+ Para registrar o MCP nos clientes principais, use o registrador. Ele grava `command` com o Node.js absoluto e `args` com o caminho absoluto de `bin/skill-master.mjs`, evitando falhas de `PATH` em Windows, Linux, macOS e apps desktop que nao herdam o terminal:
185
214
 
186
215
  ```bash
187
216
  skill-master-register-clients --apply-codex
188
217
  skill-master-register-clients --apply-claude
218
+ skill-master-register-clients --apply-claude-code --claude-code-scope user
189
219
  skill-master-register-clients --apply-gemini
190
220
  skill-master-register-clients --apply-antigravity
191
221
  ```
@@ -196,7 +226,26 @@ Atalho para gerar snippets e aplicar nos clientes principais:
196
226
  skill-master-register-clients --apply-all
197
227
  ```
198
228
 
199
- Isso configura o servidor MCP `skill_master` em Codex, Claude Desktop, Gemini e Antigravity quando os arquivos de configuracao locais estiverem disponiveis. Reinicie o cliente depois do registro.
229
+ Isso configura o servidor MCP `skill_master` em Codex, Claude Desktop, Claude Code, Gemini e Antigravity quando os clientes locais estiverem disponiveis. Claude Code e registrado via `claude mcp add`; reinicie o cliente depois do registro.
230
+
231
+ Se um cliente ja tiver uma configuracao antiga por `skill-master-mcp`, `npx` ou launcher local e nao estiver iniciando, force a migracao para o modo robusto:
232
+
233
+ ```bash
234
+ skill-master-register-clients --apply-all --force
235
+ skill-master-menu --run doctor
236
+ ```
237
+
238
+ No Codex, o bloco recomendado fica no formato:
239
+
240
+ ```toml
241
+ [mcp_servers.skill_master]
242
+ command = "/caminho/absoluto/para/node"
243
+ args = ["/caminho/absoluto/para/bin/skill-master.mjs"]
244
+ startup_timeout_sec = 120
245
+
246
+ [mcp_servers.skill_master.env]
247
+ SKILL_MASTER_UPDATE_CHANNEL = "stable"
248
+ ```
200
249
 
201
250
  O menu tambem mostra notificacoes de skills aprendidas pendentes e links externos para estudo. As acoes de ativacao sao:
202
251
 
package/VERSION.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # Versão
2
2
 
3
- Versão funcional planejada: `00.04`
3
+ Versão funcional planejada: `00.06`
4
4
 
5
- Versão técnica para empacotamento semântico: `0.0.10`
5
+ Versão técnica para empacotamento semântico: `0.0.12`
6
6
 
7
7
  ## Observação
8
8
 
9
- O nome `00.04` será usado na comunicação e nos documentos. Para ferramentas que exigem SemVer, como npm e alguns fluxos de release, usar `0.0.10`.
9
+ O nome `00.06` será usado na comunicação e nos documentos. Para ferramentas que exigem SemVer, como npm e alguns fluxos de release, usar `0.0.12`.
@@ -0,0 +1,293 @@
1
+ import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import process from 'node:process';
5
+ import { fileURLToPath } from 'node:url';
6
+
7
+ export const DEFAULT_SERVER_ENV = {
8
+ SKILL_MASTER_UPDATE_CHANNEL: 'stable',
9
+ };
10
+
11
+ export function defaultClaudeConfigPath(home = os.homedir(), platform = process.platform) {
12
+ if (platform === 'win32') {
13
+ return path.join(process.env.APPDATA ?? path.join(home, 'AppData', 'Roaming'), 'Claude', 'claude_desktop_config.json');
14
+ }
15
+
16
+ if (platform === 'darwin') {
17
+ return path.join(home, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');
18
+ }
19
+
20
+ return path.join(home, '.config', 'Claude', 'claude_desktop_config.json');
21
+ }
22
+
23
+ export function defaultClientConfigPaths({
24
+ home = os.homedir(),
25
+ env = process.env,
26
+ platform = process.platform,
27
+ } = {}) {
28
+ return {
29
+ codex: path.join(env.CODEX_HOME ?? path.join(home, '.codex'), 'config.toml'),
30
+ claude: defaultClaudeConfigPath(home, platform),
31
+ gemini: path.join(home, '.gemini', 'settings.json'),
32
+ antigravity: path.join(home, '.gemini', 'config', 'mcp_config.json'),
33
+ };
34
+ }
35
+
36
+ export function buildSkillMasterServerConfig({
37
+ rootDir,
38
+ nodeExecPath = process.execPath,
39
+ env = DEFAULT_SERVER_ENV,
40
+ } = {}) {
41
+ const packageRoot = rootDir ?? path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
42
+ const serverEntry = path.join(packageRoot, 'bin', 'skill-master.mjs');
43
+
44
+ return {
45
+ command: nodeExecPath,
46
+ args: [serverEntry],
47
+ env: { ...env },
48
+ metadata: {
49
+ mode: 'absolute-node',
50
+ packageRoot,
51
+ serverEntry,
52
+ },
53
+ };
54
+ }
55
+
56
+ function tomlString(value) {
57
+ return JSON.stringify(String(value));
58
+ }
59
+
60
+ function tomlStringArray(values) {
61
+ return `[${values.map((value) => tomlString(value)).join(', ')}]`;
62
+ }
63
+
64
+ export function buildCodexBlock(serverConfig) {
65
+ const envEntries = Object.entries(serverConfig.env ?? {});
66
+ const envBlock = envEntries.length
67
+ ? `\n[mcp_servers.skill_master.env]\n${envEntries.map(([key, value]) => `${key} = ${tomlString(value)}`).join('\n')}\n`
68
+ : '';
69
+
70
+ return `
71
+ [mcp_servers.skill_master]
72
+ command = ${tomlString(serverConfig.command)}
73
+ args = ${tomlStringArray(serverConfig.args ?? [])}
74
+ startup_timeout_sec = 120
75
+ ${envBlock}`;
76
+ }
77
+
78
+ export function buildJsonMcpSnippet(serverConfig) {
79
+ return {
80
+ mcpServers: {
81
+ skill_master: {
82
+ command: serverConfig.command,
83
+ args: serverConfig.args ?? [],
84
+ env: serverConfig.env ?? {},
85
+ },
86
+ },
87
+ };
88
+ }
89
+
90
+ export function buildClaudeCodeAddArgs(serverConfig, {
91
+ scope = 'user',
92
+ serverName = 'skill_master',
93
+ } = {}) {
94
+ return [
95
+ 'mcp',
96
+ 'add',
97
+ serverName,
98
+ '--scope',
99
+ scope,
100
+ '--',
101
+ serverConfig.command,
102
+ ...(serverConfig.args ?? []),
103
+ ];
104
+ }
105
+
106
+ export function formatShellCommand(command, args = []) {
107
+ const quote = (value) => {
108
+ const text = String(value ?? '');
109
+ if (/^[A-Za-z0-9_./:@%+=,-]+$/.test(text)) return text;
110
+ return `"${text.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
111
+ };
112
+ return [command, ...args].map(quote).join(' ');
113
+ }
114
+
115
+ export function ensureParent(filePath) {
116
+ mkdirSync(path.dirname(filePath), { recursive: true });
117
+ }
118
+
119
+ function backupPath(filePath) {
120
+ const stamp = new Date().toISOString().replace(/[:.]/g, '-');
121
+ return `${filePath}.invalid-${stamp}.bak`;
122
+ }
123
+
124
+ export function readJsonOrEmpty(filePath, { recoverInvalidJson = false } = {}) {
125
+ if (!existsSync(filePath)) return {};
126
+ const raw = readFileSync(filePath, 'utf8').trim();
127
+ if (!raw) return {};
128
+ try {
129
+ return JSON.parse(raw);
130
+ } catch (error) {
131
+ if (recoverInvalidJson) {
132
+ copyFileSync(filePath, backupPath(filePath));
133
+ return {};
134
+ }
135
+ const message = error instanceof Error ? error.message : String(error);
136
+ throw new Error(`Invalid JSON at ${filePath}: ${message}`);
137
+ }
138
+ }
139
+
140
+ export function writeJson(filePath, value) {
141
+ ensureParent(filePath);
142
+ writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, 'utf8');
143
+ }
144
+
145
+ export function mergeMcpServer(filePath, serverConfig, options = {}) {
146
+ const current = readJsonOrEmpty(filePath, options);
147
+ const next = {
148
+ ...current,
149
+ mcpServers: {
150
+ ...(current.mcpServers ?? {}),
151
+ skill_master: buildJsonMcpSnippet(serverConfig).mcpServers.skill_master,
152
+ },
153
+ };
154
+ writeJson(filePath, next);
155
+ }
156
+
157
+ export function removeCodexSkillMasterBlock(content) {
158
+ const lines = String(content ?? '').split('\n');
159
+ const kept = [];
160
+ let skipping = false;
161
+ for (const line of lines) {
162
+ const trimmed = line.trim();
163
+ if (trimmed === '[mcp_servers.skill_master]') {
164
+ skipping = true;
165
+ continue;
166
+ }
167
+ if (skipping && trimmed.startsWith('[') && !trimmed.startsWith('[mcp_servers.skill_master')) {
168
+ skipping = false;
169
+ }
170
+ if (!skipping) kept.push(line);
171
+ }
172
+ return kept.join('\n').trimEnd();
173
+ }
174
+
175
+ export function appendCodexServer(filePath, serverConfig, { force = false } = {}) {
176
+ ensureParent(filePath);
177
+ const current = existsSync(filePath) ? readFileSync(filePath, 'utf8') : '';
178
+ if (current.includes('[mcp_servers.skill_master]') && !force) {
179
+ return false;
180
+ }
181
+ const base = force ? removeCodexSkillMasterBlock(current) : current.trimEnd();
182
+ writeFileSync(filePath, `${base}\n${buildCodexBlock(serverConfig)}`, 'utf8');
183
+ return true;
184
+ }
185
+
186
+ function normalizeSlashes(value) {
187
+ return String(value ?? '').replace(/\\/g, '/').toLowerCase();
188
+ }
189
+
190
+ function basename(value) {
191
+ const normalized = normalizeSlashes(value);
192
+ return normalized.split('/').pop() ?? '';
193
+ }
194
+
195
+ function isNodeCommand(command) {
196
+ const name = basename(command);
197
+ return name === 'node' || name === 'node.exe';
198
+ }
199
+
200
+ function hasSkillMasterEntryArg(args = []) {
201
+ return args.some((arg) => normalizeSlashes(arg).endsWith('/bin/skill-master.mjs'));
202
+ }
203
+
204
+ function hasLauncherArg(args = []) {
205
+ return args.some((arg) => {
206
+ const normalized = normalizeSlashes(arg);
207
+ return normalized.endsWith('/scripts/skill-master-launcher.ps1')
208
+ || normalized.endsWith('/scripts/skill-master-launcher.sh');
209
+ });
210
+ }
211
+
212
+ export function assessMcpServerConfig(server) {
213
+ if (!server?.command) {
214
+ return {
215
+ present: Boolean(server),
216
+ robust: false,
217
+ mode: server ? 'missing-command' : 'missing',
218
+ command: server?.command ?? null,
219
+ };
220
+ }
221
+
222
+ const command = String(server.command);
223
+ const args = Array.isArray(server.args) ? server.args : [];
224
+ const commandName = basename(command);
225
+ const normalizedCommand = normalizeSlashes(command);
226
+
227
+ if (isNodeCommand(command) && hasSkillMasterEntryArg(args)) {
228
+ return { present: true, robust: true, mode: 'absolute-node', command };
229
+ }
230
+
231
+ if (commandName === 'skill-master-mcp' || commandName === 'skill-master-mcp.cmd') {
232
+ return { present: true, robust: false, mode: 'path-bin', command };
233
+ }
234
+
235
+ if ((normalizedCommand.includes('powershell') || commandName === 'bash' || commandName === 'env') && hasLauncherArg(args)) {
236
+ return { present: true, robust: false, mode: 'launcher', command };
237
+ }
238
+
239
+ return { present: true, robust: false, mode: 'custom', command };
240
+ }
241
+
242
+ function parseTomlStringToken(token) {
243
+ const value = String(token ?? '').trim();
244
+ if (!value) return '';
245
+ if (value.startsWith('"')) {
246
+ try {
247
+ return JSON.parse(value);
248
+ } catch {
249
+ return value.slice(1, -1);
250
+ }
251
+ }
252
+ if (value.startsWith("'")) {
253
+ return value.slice(1, -1);
254
+ }
255
+ return value;
256
+ }
257
+
258
+ function parseTomlStringArray(value) {
259
+ const matches = [...String(value ?? '').matchAll(/"(?:\\.|[^"])*"|'[^']*'/g)];
260
+ return matches.map((match) => parseTomlStringToken(match[0]));
261
+ }
262
+
263
+ export function extractCodexSkillMasterServer(content) {
264
+ const lines = String(content ?? '').split('\n');
265
+ const block = [];
266
+ let collecting = false;
267
+
268
+ for (const line of lines) {
269
+ const trimmed = line.trim();
270
+ if (trimmed === '[mcp_servers.skill_master]') {
271
+ collecting = true;
272
+ continue;
273
+ }
274
+ if (collecting && trimmed.startsWith('[')) {
275
+ break;
276
+ }
277
+ if (collecting) block.push(line);
278
+ }
279
+
280
+ if (!block.length) return null;
281
+
282
+ const commandLine = block.find((line) => line.trim().startsWith('command'));
283
+ const argsLine = block.find((line) => line.trim().startsWith('args'));
284
+ const commandToken = commandLine?.match(/=\s*("(?:\\.|[^"])*"|'[^']*')/)?.[1] ?? null;
285
+ const command = commandToken ? parseTomlStringToken(commandToken) : null;
286
+ const args = argsLine ? parseTomlStringArray(argsLine.split('=').slice(1).join('=')) : [];
287
+
288
+ return command ? { command, args } : null;
289
+ }
290
+
291
+ export function assessCodexConfigContent(content) {
292
+ return assessMcpServerConfig(extractCodexSkillMasterServer(content));
293
+ }