@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.
- package/CHANGELOG.md +12 -1
- package/README.md +59 -10
- package/VERSION.md +3 -3
- package/bin/lib/client-config.mjs +293 -0
- package/bin/lib/menu-core.mjs +509 -131
- package/bin/lib/skill-installation.mjs +215 -0
- package/bin/skill-master-bootstrap-global.mjs +2 -1
- package/bin/skill-master-doctor.mjs +92 -32
- package/bin/skill-master-install-global-skills.mjs +4 -42
- package/bin/skill-master-install-project-skills.mjs +97 -0
- package/bin/skill-master-menu.mjs +91 -6
- package/bin/skill-master-register-clients.mjs +91 -115
- package/docs/operations/GUIA_MULTI_COMPUTADOR.md +262 -0
- package/docs/operations/GUIA_NPM_PUBLICO.md +147 -0
- package/docs/operations/MENU_VISUAL_EVIDENCE_2026-06-28.md +66 -0
- package/docs/operations/assets/menu-frame-compact.html +76 -0
- package/docs/operations/assets/menu-frame-compact.png +0 -0
- package/docs/operations/assets/menu-frame-large.html +84 -0
- package/docs/operations/assets/menu-frame-large.png +0 -0
- package/docs/operations/assets/menu-frame-running.html +80 -0
- package/docs/operations/assets/menu-frame-running.png +0 -0
- package/docs/operations/cross-platform-auth-transfer/ANALISE_COMPATIBILIDADE_MCP_2026-06-28.md +140 -0
- package/docs/operations/cross-platform-auth-transfer/README_TRANSFERENCIA.md +85 -0
- package/docs/operations/reborn-menu-cyberpunk-transfer/ANALISE_MENU_REBORN_CYBERPUNK_2026-06-28.md +174 -0
- package/docs/operations/reborn-menu-cyberpunk-transfer/HANDOFF_IMPLEMENTACAO_REBORN_CYBERPUNK_2026-06-28.md +119 -0
- package/docs/operations/reborn-menu-cyberpunk-transfer/ORDEM_DE_EXECUCAO_MENU_REBORN_CYBERPUNK.md +134 -0
- package/docs/operations/reborn-menu-cyberpunk-transfer/README_TRANSFERENCIA.md +84 -0
- package/docs/operations/reborn-menu-cyberpunk-transfer/README_TRANSFERENCIA_REBORN_PACKAGE.md +56 -0
- package/docs/operations/reborn-menu-cyberpunk-transfer/references/cyan-hud-frame-sheet.jpg +0 -0
- package/docs/operations/reborn-menu-cyberpunk-transfer/references/cyberpunk-pattern-sheet.jpg +0 -0
- package/docs/operations/reborn-menu-cyberpunk-transfer/references/fluid-workflow-windows.gif +0 -0
- package/docs/prompt-tasks/PROMPT_TASK_001_BOOTSTRAP_SKILL_MASTER_MCP.md +6 -0
- package/docs/prompt-tasks/PROMPT_TASK_002_AUTO_UPDATE_LAUNCHER.md +6 -0
- package/docs/prompt-tasks/PROMPT_TASK_003_REMOTE_MANIFEST_AND_RELEASES.md +6 -0
- package/docs/prompt-tasks/PROMPT_TASK_004_MULTI_USER_DISTRIBUTION.md +6 -0
- package/docs/prompt-tasks/PROMPT_TASK_005_SECURITY_AND_QUALITY_GATE.md +6 -0
- package/docs/prompt-tasks/PROMPT_TASK_006_MASTER_ACIONAMENTO_APRENDIZADO.md +83 -0
- package/docs/prompt-tasks/PROMPT_TASK_007_PERSONA_ORQUESTRADORA.md +88 -0
- package/docs/prompt-tasks/PROMPT_TASK_008_PROMPT_ROUTER_MODOS_ATIVACAO.md +156 -0
- package/docs/prompt-tasks/PROMPT_TASK_009_PIPELINE_APRENDIZADO_SUCESSO.md +105 -0
- package/docs/prompt-tasks/PROMPT_TASK_010_EVALS_GOVERNANCA_ATIVACAO.md +119 -0
- package/docs/prompt-tasks/PROMPT_TASK_011_MENU_NOTIFICACOES_NOTION.md +120 -0
- package/docs/prompt-tasks/PROMPT_TASK_012_MENU_CYBERPUNK_PIXEL_FRAME.md +123 -0
- package/docs/prompt-tasks/PROMPT_TASK_013_MENU_FLUID_DNA_ANIMATION.md +114 -0
- package/docs/prompt-tasks/PROMPT_TASK_014_MENU_FUNCTIONAL_PARITY_QA.md +157 -0
- package/docs/prompt-tasks/PROMPT_TASK_015_TRANSFER_RELEASE_HANDOFF.md +127 -0
- package/docs/prompt-tasks/PROMPT_TASK_016_CROSS_PLATFORM_MCP_AUTH_REGISTRATION.md +107 -0
- package/docs/prompt-tasks/PROMPT_TASK_018_NPM_PUBLISH_2FA_SETUP.md +80 -0
- package/docs/prompt-tasks/PROMPT_TASK_MASTER_EXECUTOR.md +6 -0
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/SKILL.md +399 -0
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/common-patterns.md +331 -0
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/complete-examples.md +872 -0
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/component-patterns.md +502 -0
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/data-fetching.md +767 -0
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/file-organization.md +502 -0
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/loading-and-error-states.md +501 -0
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/performance.md +406 -0
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/routing-guide.md +364 -0
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/styling-guide.md +428 -0
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/typescript-standards.md +418 -0
- package/docs/skill-candidates/v0.0.11/git-version-control-ops/SKILL.md +34 -0
- package/docs/skill-candidates/v0.0.11/go-engineering/SKILL.md +34 -0
- package/docs/skill-candidates/v0.0.11/java-engineering/SKILL.md +34 -0
- package/docs/skill-candidates/v0.0.11/javascript-engineering/SKILL.md +34 -0
- package/docs/skill-candidates/v0.0.11/json-contract-design/SKILL.md +34 -0
- package/docs/skill-candidates/v0.0.11/multi-client-mcp-ops/SKILL.md +36 -0
- package/docs/skill-candidates/v0.0.11/nextjs/SKILL.md +745 -0
- package/docs/skill-candidates/v0.0.11/nextjs/agents/openai.yaml +3 -0
- package/docs/skill-candidates/v0.0.11/nextjs/references/app-router-files.md +94 -0
- package/docs/skill-candidates/v0.0.11/python-engineering/SKILL.md +34 -0
- package/docs/skill-candidates/v0.0.11/ruby-engineering/SKILL.md +34 -0
- package/docs/skill-candidates/v0.0.11/senior-fullstack/SKILL.md +209 -0
- package/docs/skill-candidates/v0.0.11/senior-fullstack/references/architecture_patterns.md +103 -0
- package/docs/skill-candidates/v0.0.11/senior-fullstack/references/development_workflows.md +103 -0
- package/docs/skill-candidates/v0.0.11/senior-fullstack/references/tech_stack_guide.md +103 -0
- package/docs/skill-candidates/v0.0.11/senior-fullstack/scripts/code_quality_analyzer.py +114 -0
- package/docs/skill-candidates/v0.0.11/senior-fullstack/scripts/fullstack_scaffolder.py +114 -0
- package/docs/skill-candidates/v0.0.11/senior-fullstack/scripts/project_scaffolder.py +114 -0
- package/docs/skill-candidates/v0.0.11/shadcn/SKILL.md +573 -0
- package/docs/skill-candidates/v0.0.11/shadcn/agents/openai.yaml +3 -0
- package/docs/skill-candidates/v0.0.11/sql-postgresql-engineering/SKILL.md +34 -0
- package/docs/skill-candidates/v0.0.11/terminal-shell-ops/SKILL.md +34 -0
- package/docs/skill-candidates/v0.0.11/typescript-expert/SKILL.md +429 -0
- package/docs/skill-candidates/v0.0.11/typescript-expert/references/tsconfig-strict.json +92 -0
- package/docs/skill-candidates/v0.0.11/typescript-expert/references/typescript-cheatsheet.md +383 -0
- package/docs/skill-candidates/v0.0.11/typescript-expert/references/utility-types.ts +335 -0
- package/docs/skill-candidates/v0.0.11/typescript-expert/scripts/ts_diagnostic.py +203 -0
- package/docs/skill-candidates/v0.0.11/ui-component-primitives/SKILL.md +34 -0
- package/docs/skill-candidates/v0.0.11/web-mobile-design-systems/SKILL.md +34 -0
- package/docs/skill-candidates/v0.0.11/windows-linux-platform-ops/SKILL.md +34 -0
- package/docs/skill-candidates/v0.0.12/csharp-senior-master-engineering/SKILL.md +32 -0
- package/docs/skill-candidates/v0.0.12/css-senior-master-engineering/SKILL.md +32 -0
- package/docs/skill-candidates/v0.0.12/go-senior-master-engineering/SKILL.md +32 -0
- package/docs/skill-candidates/v0.0.12/html-senior-master-engineering/SKILL.md +32 -0
- package/docs/skill-candidates/v0.0.12/javascript-senior-master-engineering/SKILL.md +32 -0
- package/docs/skill-candidates/v0.0.12/json-senior-master-engineering/SKILL.md +32 -0
- package/docs/skill-candidates/v0.0.12/python-senior-master-engineering/SKILL.md +32 -0
- package/docs/skill-candidates/v0.0.12/react-senior-master-engineering/SKILL.md +32 -0
- package/docs/skill-candidates/v0.0.12/ruby-senior-master-engineering/SKILL.md +32 -0
- package/docs/skill-candidates/v0.0.12/senior-master-code-optimizer/SKILL.md +48 -0
- package/docs/skill-candidates/v0.0.12/sql-senior-master-engineering/SKILL.md +31 -0
- package/docs/skill-candidates/v0.0.12/typescript-senior-master-engineering/SKILL.md +35 -0
- package/examples/client-configs/claude-code.commands.md +11 -7
- package/manifests/channels/beta.json +7 -7
- package/manifests/channels/stable.json +8 -8
- package/package.json +14 -2
- package/scripts/render-menu-evidence.mjs +130 -0
- 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
|
-
|
|
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
|
-
|
|
111
|
+
Fluxo atual:
|
|
112
112
|
|
|
113
|
-
-
|
|
114
|
-
-
|
|
115
|
-
- validacao
|
|
116
|
-
-
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
3
|
+
Versão funcional planejada: `00.06`
|
|
4
4
|
|
|
5
|
-
Versão técnica para empacotamento semântico: `0.0.
|
|
5
|
+
Versão técnica para empacotamento semântico: `0.0.12`
|
|
6
6
|
|
|
7
7
|
## Observação
|
|
8
8
|
|
|
9
|
-
O nome `00.
|
|
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
|
+
}
|