@kaydash9999/banker-plugins 0.4.0 → 0.6.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.
@@ -0,0 +1,232 @@
1
+ ---
2
+ name: setup-lsp
3
+ description: "(banker) 언어별 LSP 서버(vtsls·basedpyright·bash·jdtls·spring)와 lsp-mcp 브리지 설치·연동. 'setup-lsp'/'LSP 설치'/'언어 서버' 또는 /banker:setup 시 사용."
4
+ ---
5
+
6
+ # setup-lsp: 언어별 LSP 서버 + lsp-mcp 브리지
7
+
8
+ symbol/type/reference 기반 코드 탐색(grep 대체)을 위해 언어별 language server(TypeScript·Python·Bash·Java·Spring)와
9
+ 이를 MCP 로 노출하는 `lsp-mcp` 브리지를 설치·연동한다. 설치는 **멱등**(이미 있으면 skip·검증만). 답변은 한글(기술 토큰·경로·명령은 영문).
10
+
11
+ ## 런타임 배선
12
+
13
+ 이 스킬은 두 가지를 설치한다 - (A) 표준 language server 바이너리, (B) `codex-lsp-bridge`(lsp-mcp). **소비 방식이 런타임마다 다르다**:
14
+
15
+ - **Claude Code (OMC)** - 네이티브 `lsp_*` MCP 도구(`lsp_servers`·`lsp_goto_definition`·`lsp_find_references`·`lsp_hover`·`lsp_document_symbols` 등) 또는 `typescript-lsp@claude-plugins-official` 플러그인이 **PATH 의 서버 바이너리를 직접 구동**한다. **브리지 불필요** → §6·§7-Codex 는 건너뛰고 §2~§5 설치 후 §7-Claude 만 수행.
16
+ - **Codex (OMX)** - `codex-lsp-bridge` 를 `~/.codex/config.toml` 의 `[mcp_servers.lsp_bridge]` 에 등록해 `lsp_bridge` tool 로 노출. §2~§7 전부 수행.
17
+
18
+ 먼저 §0 에서 **어느 런타임인지 감지**하고 해당 경로만 실행한다(둘 다 있으면 둘 다).
19
+
20
+ ## 0. 감지 (먼저, 추정 금지)
21
+ ```bash
22
+ [ -f /etc/os-release ] && . /etc/os-release && echo "distro=$ID ${VERSION_ID}"; uname -m
23
+ # 런타임
24
+ command -v claude >/dev/null && echo "runtime: claude(OMC)" || echo "claude 없음"
25
+ command -v codex >/dev/null && echo "runtime: codex(OMX)" || echo "codex 없음"
26
+ # 선행 런타임 (§1 preflight 대상)
27
+ command -v npm >/dev/null && echo "npm=$(npm -v)" || echo "npm 없음 → setup-node"
28
+ command -v pipx >/dev/null && echo "pipx=$(pipx --version)" || echo "pipx 없음 → setup-python"
29
+ command -v java >/dev/null && java -version 2>&1 | head -1 || echo "java 없음 → setup-java"
30
+ # 이미 설치된 서버
31
+ for c in vtsls basedpyright-langserver ruff bash-language-server jdtls codex-lsp-bridge; do
32
+ command -v $c >/dev/null && echo "✓ $c" || echo "✗ $c"
33
+ done
34
+ # 프로젝트 언어 (--lang 미지정 시 이 결과로 선택)
35
+ ls tsconfig.json package.json >/dev/null 2>&1 && echo "lang: ts"
36
+ { ls pyproject.toml setup.py >/dev/null 2>&1 || ls ./*.py >/dev/null 2>&1; } && echo "lang: py"
37
+ ls ./*.sh >/dev/null 2>&1 && echo "lang: bash"
38
+ ls pom.xml build.gradle build.gradle.kts >/dev/null 2>&1 && echo "lang: java"
39
+ ls src/main/resources/application.* >/dev/null 2>&1 && echo "lang: spring"
40
+ ```
41
+ > Windows(PowerShell): `Get-Command claude,codex,npm,pipx,java`, `Test-Path tsconfig.json,pom.xml` 등으로 동일 감지. jdtls 는 `jdtls.bat`.
42
+
43
+ ## 1. 사전요구(preflight)
44
+
45
+ 각 서버는 선행 런타임이 필요하다 - **없으면 먼저 해당 setup 스킬을 실행**(추정·강행 금지):
46
+
47
+ | 대상 | 필요 런타임 | 없을 때 |
48
+ |---|---|---|
49
+ | vtsls·vscode-langservers-extracted·bash-language-server | **Node/npm** | `setup-node` 먼저 |
50
+ | basedpyright·ruff (+ lsp-mcp 브리지도 pipx) | **Python/pipx** (3.8+) | `setup-python` 먼저 |
51
+ | jdtls·Spring Boot LS | **JDK 21** (jdtls 는 21 필수) | `setup-java` 먼저 |
52
+
53
+ ```bash
54
+ command -v npm >/dev/null || echo "npm 필요 → setup-node 실행 후 재시도"
55
+ command -v pipx >/dev/null || echo "pipx 필요 → setup-python 실행 후 재시도"
56
+ # jdtls 는 Java 21+ 필수 - 미만이면 조용히 실패
57
+ java -version 2>&1 | grep -qE '"(2[1-9]|[3-9][0-9])' || echo "Java 21+ 아님 → setup-java 먼저(java/spring 스킵 가능)"
58
+ ```
59
+
60
+ ## 2. 언어 선택
61
+
62
+ `--lang ts,py,bash,java,spring` 로 명시. 없으면 §0 감지(프로젝트 언어), 그것도 없으면 **전체**.
63
+ 매핑: `ts`→§3(npm), `bash`→§3(npm), `py`→§4(pipx), `java`→§5(jdtls), `spring`→§5(jdtls+Spring LS).
64
+
65
+ ## 3. npm 서버 (ts·bash - Node 필요)
66
+ ```bash
67
+ npm install -g \
68
+ @vtsls/language-server \
69
+ vscode-langservers-extracted \
70
+ bash-language-server
71
+ for c in vtsls bash-language-server; do command -v $c >/dev/null && echo "✓ $c" || echo "✗ $c"; done
72
+ ```
73
+ - `@vtsls/language-server`→`vtsls`(TS/JS), `vscode-langservers-extracted`→JSON/CSS/HTML/ESLint 서버, `bash-language-server`→shell.
74
+ - 전역 설치 권한 필요 - **`sudo npm -g` 금지**(nvm/prefix 는 `setup-node` 참조).
75
+
76
+ ## 4. pipx 서버 (py - Python 필요)
77
+ ```bash
78
+ pipx install basedpyright # → basedpyright-langserver (타입체커 LSP)
79
+ pipx install ruff # → ruff (formatter/linter + `ruff server` LSP)
80
+ for c in basedpyright-langserver ruff; do command -v $c >/dev/null && echo "✓ $c" || echo "✗ $c"; done
81
+ ```
82
+ - pipx 격리 설치 → shebang 고정이라 시스템 Python 변경에 영향 없음.
83
+
84
+ ## 5. jdtls + Spring Boot LS (java·spring - JDK 21 필요)
85
+
86
+ **jdtls (Java LSP)** - Eclipse 최신 스냅샷:
87
+ ```bash
88
+ mkdir -p ~/.local/jdtls
89
+ curl -fLo /tmp/jdtls.tar.gz \
90
+ "https://download.eclipse.org/jdtls/snapshots/jdt-language-server-latest.tar.gz"
91
+ tar -xzf /tmp/jdtls.tar.gz -C ~/.local/jdtls
92
+ rm /tmp/jdtls.tar.gz
93
+ chmod +x ~/.local/jdtls/bin/jdtls
94
+ which jdtls # PATH 에 ~/.local/jdtls/bin 필요
95
+ ```
96
+ > jdtls 는 **Java 21 미만이면 무증상으로 죽는다** → §1 preflight 필수. Windows 는 `~/.local/jdtls\bin` 을 PATH 에 넣고 `jdtls.bat` 로 호출.
97
+
98
+ **Spring Boot Language Server** - VSIX(=ZIP) 다운로드. vsassets.io/marketplace 가 **HTML 에러페이지**를 반환할 수 있어 **ZIP 매직바이트(`504b0304`) 검증** 후 `find` 로 `*-exec.jar` 탐색 + 심볼릭 링크:
99
+ ```bash
100
+ set -euo pipefail
101
+ TARGET="$HOME/.local/spring-boot-ls"; VSIX=/tmp/sbls.vsix; LINK=spring-boot-language-server.jar
102
+ mkdir -p "$TARGET"
103
+ VSIX_URL="https://vmware.gallery.vsassets.io/_apis/public/gallery/publisher/vmware/extension/vscode-spring-boot/latest/assetbyname/Microsoft.VisualStudio.Services.VSIXPackage"
104
+ FALLBACK="https://marketplace.visualstudio.com/_apis/public/gallery/publishers/vmware/vsextensions/vscode-spring-boot/latest/vspackage"
105
+ curl -fL --connect-timeout 30 --retry 2 -H "User-Agent: Mozilla/5.0" -o "$VSIX" "$VSIX_URL" 2>/dev/null \
106
+ || curl -fL --connect-timeout 30 --retry 2 -H "User-Agent: Mozilla/5.0" -o "$VSIX" "$FALLBACK"
107
+ # ZIP 매직 검증 (HTML 에러페이지면 즉시 중단)
108
+ [ "$(xxd -l 4 "$VSIX" | awk 'NR==1{print $2$3}')" = "504b0304" ] \
109
+ || { echo "✗ ZIP 아님(HTML 에러페이지?)"; rm -f "$VSIX"; exit 1; }
110
+ rm -rf "${TARGET:?}"/*; unzip -o -q "$VSIX" -d "$TARGET"
111
+ JAR=$(find "$TARGET" -name "spring-boot-language-server-*-exec.jar" | sort -V | tail -1)
112
+ [ -n "$JAR" ] || { echo "✗ exec.jar 미발견"; rm -f "$VSIX"; exit 1; }
113
+ ln -sf "$(basename "$JAR")" "$(dirname "$JAR")/$LINK" # 디렉토리 이동에도 유효한 상대 링크
114
+ rm -f "$VSIX"; find ~/.local/spring-boot-ls -name "$LINK" -ls
115
+ ```
116
+ > Windows: 심볼릭 링크는 **개발자 모드/관리자 권한** 필요 → 없으면 `Copy-Item` 복사 fallback(둘 다 동작). 매직검증·find 는 PowerShell 로 동일 수행, JAR 경로는 `.Replace('\','/')`. RHEL8 에 `xxd` 없으면 `dnf install -y vim-common` 또는 `od -An -tx1 -N4`.
117
+
118
+ ## 6. lsp-mcp 브리지 설치 (Codex 경로 - Claude Code 는 건너뜀)
119
+ ```bash
120
+ mkdir -p ~/.local/src
121
+ git clone https://github.com/CesarPetrescu/lsp-mcp.git ~/.local/src/lsp-mcp
122
+ pipx install --editable ~/.local/src/lsp-mcp # → ~/.local/bin/codex-lsp-bridge (Windows: .exe)
123
+ which codex-lsp-bridge && codex-lsp-bridge --help | head -5
124
+ ```
125
+
126
+ **브리지에 Java/Spring 서버 등록** - `config/default.toml` 에 `[servers.java]`/`[servers.spring-boot-properties]` append. **idempotent guard 필수**: 두 번 실행하면 중복 선언 → TOML 파싱 실패 → `codex-lsp-bridge` 즉사 → `MCP client for 'lsp_bridge' failed to start`. 기본 default.toml 에 이미 있는 서버(ts/py/bash 등)는 그대로 두고 java/spring 만 추가:
127
+ ```bash
128
+ cd ~/.local/src/lsp-mcp
129
+ cp -n config/default.toml config/default.toml.bak # 최초 1회만 백업
130
+ # guard: 이미 있으면 skip. unquoted heredoc - $HOME 를 셸이 절대경로로 확장
131
+ grep -q '\[servers.java\]' config/default.toml || cat >> config/default.toml << EOF
132
+
133
+ [servers.java]
134
+ command = "jdtls"
135
+ args = []
136
+ file_extensions = ["java"]
137
+ language_id = "java"
138
+
139
+ [servers.spring-boot-properties]
140
+ command = "java"
141
+ args = ["-jar", "$HOME/.local/spring-boot-ls/extension/jars/spring-boot-language-server.jar"]
142
+ file_extensions = ["properties", "yml", "yaml"]
143
+ language_id = "spring-boot-properties"
144
+ EOF
145
+ # TOML 유효성 (중복/문법오류 즉시 감지). tomllib 는 Python 3.11+ - RHEL8/Rocky8 기본 python3(3.6)면 setup-python 의 3.11 을 쓴다:
146
+ PY="$(command -v python3.12 || command -v python3.11 || command -v python3)"
147
+ "$PY" -c "import tomllib; tomllib.loads(open('config/default.toml',encoding='utf-8').read()); print('OK lsp-mcp TOML')" 2>/dev/null \
148
+ || echo "⚠ tomllib(3.11+) 미가용 - append 는 위 grep guard 로 이미 적용됨, setup-python 설치 후 재검증"
149
+ cd - >/dev/null
150
+ ```
151
+ > Spring JAR 경로는 §5 `find` 실제 결과와 일치해야 함(환경마다 디렉토리 상이). 깨졌으면 `cp config/default.toml.bak config/default.toml` 복구.
152
+ > Windows: `Get-Content -Raw` 로 읽어 `-match '\[servers\.java\]'` guard 후 `[System.IO.File]::WriteAllText(path, text, [System.Text.UTF8Encoding]::new($false))` 로만 append(CP949/BOM 회피).
153
+
154
+ ## 7. 배선 (Codex config.toml · Claude 네이티브)
155
+
156
+ ### 7-Codex - `[mcp_servers.lsp_bridge]` 등록
157
+ OMX 가 배포한 기존 엔트리를 보존하려 **Python replace-or-append** 로 patch(전체 덮어쓰기 금지):
158
+ ```bash
159
+ python3 - << 'PY'
160
+ import re
161
+ from pathlib import Path
162
+ home = str(Path.home()) # Windows: str(Path.home()).replace("\\","/")
163
+ p = Path.home() / ".codex" / "config.toml"
164
+ txt = p.read_text(encoding="utf-8") if p.exists() else ""
165
+ def rep(body, header, block):
166
+ pat = rf'\[{re.escape(header)}\].*?(?=\n\[|\Z)'
167
+ if re.search(pat, body, flags=re.DOTALL):
168
+ return re.sub(pat, block.strip() + '\n', body, flags=re.DOTALL, count=1)
169
+ return body.rstrip() + '\n\n' + block.strip() + '\n'
170
+ binname = "codex-lsp-bridge" # Windows: codex-lsp-bridge.exe
171
+ block = "\n".join([
172
+ "[mcp_servers.lsp_bridge]",
173
+ f'command = "{home}/.local/bin/{binname}"',
174
+ f'args = ["serve", "--transport", "stdio", "--config", "{home}/.local/src/lsp-mcp/config/default.toml"]',
175
+ "startup_timeout_sec = 300", # 첫 기동/다운로드 대비
176
+ ])
177
+ txt = rep(txt, "mcp_servers.lsp_bridge", block + "\n")
178
+ p.write_text(txt, encoding="utf-8") # Windows: encoding 필수(CP949 회피)
179
+ print("patched")
180
+ PY
181
+ PY="$(command -v python3.12 || command -v python3.11 || command -v python3)" # tomllib=3.11+
182
+ "$PY" -c "import tomllib; tomllib.loads(open('$HOME/.codex/config.toml',encoding='utf-8').read()); print('OK config.toml valid')" 2>/dev/null \
183
+ || echo "⚠ tomllib(3.11+) 미가용 - patch 는 적용됨, setup-python 후 재검증"
184
+ ```
185
+
186
+ ### 7-Claude - 네이티브 lsp_* / 플러그인
187
+ 브리지·config.toml patch **불필요**. PATH 의 서버 바이너리가 OMC `lsp_*` 도구를 뒷받침한다:
188
+ - 설치 후 `/reload-plugins`(또는 Claude 재시작) → `lsp_servers` 로 인식된 서버 확인.
189
+ - TypeScript 전용은 `typescript-lsp@claude-plugins-official` 플러그인도 가능(`/plugin install typescript-lsp@claude-plugins-official`).
190
+ - 서버가 `lsp_servers` 에 안 뜨면 PATH(§0)·재시작 확인.
191
+
192
+ **OS 경로 차이 (요약)**
193
+
194
+ | 요소 | Linux(rocky/rhel/ubuntu/debian) | Windows | macOS |
195
+ |---|---|---|---|
196
+ | bridge 바이너리 | `$HOME/.local/bin/codex-lsp-bridge` | `...\codex-lsp-bridge.exe` | Linux 동일 |
197
+ | jdtls 실행 | `jdtls` | `jdtls.bat` | `jdtls` |
198
+ | config patch home | `str(Path.home())` | `.replace("\\","/")` | `str(Path.home())` |
199
+ | TOML read/write | 기본 | `encoding='utf-8'` 필수(CP949) | 기본 |
200
+ | Spring JAR 링크 | `ln -sf` | SymbolicLink→권한없으면 `Copy-Item` | `ln -sf` |
201
+
202
+ ## 검증 (보고 의무)
203
+
204
+ **존재 ≠ 동작** - 각 서버가 실제 응답하는지까지 확인:
205
+ ```bash
206
+ basedpyright --version # CLI 로 버전 확인(langserver 는 stdio 서버라 --version 없음)
207
+ command -v basedpyright-langserver >/dev/null && echo "✓ basedpyright-langserver"
208
+ vtsls --version
209
+ bash-language-server --version
210
+ ruff --version
211
+ jdtls --version 2>/dev/null || which jdtls # Windows: jdtls.bat
212
+ # Codex 만:
213
+ codex-lsp-bridge --help | head -3
214
+ grep -q 'lsp_bridge' ~/.codex/config.toml && echo "✓ config.toml lsp_bridge" || echo "✗ 미등록"
215
+ PY="$(command -v python3.12 || command -v python3.11 || command -v python3)" # tomllib=3.11+
216
+ "$PY" -c "import tomllib; tomllib.loads(open('$HOME/.codex/config.toml',encoding='utf-8').read()); print('✓ config.toml valid')" 2>/dev/null || echo "⚠ tomllib(3.11+) 미가용 - setup-python 후 재검증"
217
+ # Claude 만: lsp_servers 도구로 인식 서버 나열
218
+ ```
219
+ 4-field 보고: **변경**(설치 서버·브리지·config 배선) / **Evidence**(위 --version·valid 출력) / **검증**(각 서버 응답 + 브리지·config TOML valid + 런타임 인식) / **Unknown**(네트워크 차단으로 미설치·JDK 21 부재로 java/spring 스킵 등).
220
+
221
+ ## 함정
222
+
223
+ - **Spring VSIX = HTML 에러페이지** - vsassets.io/marketplace 가 ZIP 대신 에러페이지를 반환 → **매직바이트 `504b0304` 검증 필수**(안 하면 깨진 JAR 로 진행). fallback URL 자동 전환.
224
+ - **`[servers.java]` 중복 → 브리지 즉사** - §6 append 를 guard 없이 두 번 → TOML 파싱 실패 → `MCP client for 'lsp_bridge' failed to start`. **grep/`-match` guard 필수**, 깨졌으면 `.bak` 복구.
225
+ - **jdtls Java 21 미만 → 무증상 실패** - preflight(§1)로 `java -version` 21+ 확인. 아니면 `setup-java` 먼저.
226
+ - **Windows CP949/BOM** - 모든 Python `open(...,encoding='utf-8')`, PowerShell append 는 `WriteAllText`+`UTF8Encoding($false)` 만(`Add-Content`/`Out-File -Encoding UTF8` 금지). config patch home 은 forward-slash(`.replace("\\","/")`).
227
+ - **Windows 심볼릭 링크 권한** - 개발자 모드/관리자 아니면 `Copy-Item` 복사 fallback. `.exe`(bridge)·`.bat`(jdtls) 확장자 주의.
228
+ - **첫 실행 timeout** - 브리지/npx 최초 기동은 느림 → `startup_timeout_sec = 300`. 첫 회만 느리면 정상(캐싱 후 빠름).
229
+ - **PATH 미반영** - `~/.local/bin`·`~/.local/jdtls/bin` 이 PATH 에 없으면 서버 미인식 → 새 셸/`source ~/.bashrc` 또는 절대경로(Claude 는 `lsp_servers` 로 재확인).
230
+ - **config 전체 덮어쓰기 금지** - Codex `config.toml` 은 반드시 replace-or-append(§7-Codex)로 patch - OMX 가 배포한 다른 MCP/agents 엔트리를 보존.
231
+
232
+ ARGUMENTS: [--lang ts,py,bash,java,spring] (없으면 프로젝트 언어 감지 또는 전체)
@@ -0,0 +1,156 @@
1
+ ---
2
+ name: setup-mcp
3
+ description: "(banker) context7·sequential-thinking·filesystem·git·fetch(+선택 tavily) 범용 MCP 서버를 Claude Code(claude mcp add)·Codex(codex mcp add+config.toml)에 배선(serena·lsp_bridge 제외). 'setup-mcp'/'MCP 서버 설치'/'context7·sequential-thinking 설치' 또는 /banker:setup 시 사용."
4
+ ---
5
+
6
+ # setup-mcp: 범용 MCP 서버 설치
7
+
8
+ context7·sequential-thinking·filesystem·git·fetch - 특정 도구에 종속되지 않는 5종 표준 MCP 서버를
9
+ Claude Code·Codex 양쪽에 배선한다. **`setup-omc`(OMC/OMX 프레임워크 자체 설치, 자기 도구를 따로 들고 옴)와도,
10
+ `setup-lsp`(`lsp_bridge` 전용)와도 다르다** - 이 스킬은 그 외 범용 standalone 서버만 다룬다. Serena 는
11
+ 프로젝트 스코프(`--project` 가 홈 디렉터리면 인덱싱 과부하)라 여기서 제외한다. 설치는 **멱등**(있으면
12
+ remove 후 재-add). 답변은 한글(기술 토큰 영문).
13
+
14
+ ## 런타임 배선
15
+ - **Claude Code**: `claude mcp add <name> -s user -- <command> ...` - CLI 가 설정을 직접 관리.
16
+ - **Codex**: 현재 공식 CLI `codex mcp add <name> -- <command> ...` 로 등록(내부적으로 `~/.codex/config.toml`
17
+ `[mcp_servers.<name>]` 에 기록) - 단 `startup_timeout_sec`(기본 10초, 첫 npx/uvx 다운로드 대비 300초로
18
+ 올려야 함)은 CLI 플래그로 노출되지 않는다 → **Python replace-or-append** 로 그 필드만 추가 패치한다.
19
+
20
+ ## 0. 감지 (먼저, 추정 금지)
21
+ ```bash
22
+ command -v npx >/dev/null && echo "npx=yes" || echo "npx=no (setup-node 먼저)"
23
+ command -v uvx >/dev/null && echo "uvx=yes" || echo "uvx=no (setup-python 먼저)"
24
+ command -v claude >/dev/null && claude mcp list 2>/dev/null
25
+ command -v codex >/dev/null && codex mcp list 2>/dev/null
26
+ [ -f ~/.codex/config.toml ] && grep -c 'startup_timeout_sec = 300' ~/.codex/config.toml
27
+ ```
28
+
29
+ ## 1. Preflight
30
+ - **npx 없음** → Node 미설치 → `setup-node` 스킬로 먼저 설치.
31
+ - **uvx 없음** → uv 미설치 → `setup-python` 스킬로 먼저 설치(uv 설치는 그 스킬 소관).
32
+ - 둘 다 있으면 2로 진행.
33
+
34
+ ## 2. 서버 목록
35
+ | name | command | args |
36
+ |---|---|---|
37
+ | context7 | npx | `-y @upstash/context7-mcp` |
38
+ | sequential-thinking | npx | `-y @modelcontextprotocol/server-sequential-thinking` |
39
+ | filesystem | npx | `-y @modelcontextprotocol/server-filesystem <dir>` |
40
+ | git | uvx | `mcp-server-git` |
41
+ | fetch | uvx | `mcp-server-fetch` |
42
+ | tavily(선택) | npx | `-y tavily-mcp` (env `TAVILY_API_KEY`) |
43
+
44
+ `<dir>` = `--fs-dir` 인자 또는 기본 `$HOME/projects`. **홈 디렉터리 전체를 넘기지 않는다** - Serena
45
+ `--project` 경고와 같은 이유(파일 노출 범위 과다)로, 실제 프로젝트 경로만 지정한다.
46
+
47
+ ## 3. Claude Code 배선
48
+ ```bash
49
+ FS_DIR="${FS_DIR:-$HOME/projects}"
50
+
51
+ claude mcp remove context7 -s user 2>/dev/null
52
+ claude mcp add context7 -s user -- npx -y @upstash/context7-mcp
53
+
54
+ claude mcp remove sequential-thinking -s user 2>/dev/null
55
+ claude mcp add sequential-thinking -s user -- npx -y @modelcontextprotocol/server-sequential-thinking
56
+
57
+ claude mcp remove filesystem -s user 2>/dev/null
58
+ claude mcp add filesystem -s user -- npx -y @modelcontextprotocol/server-filesystem "$FS_DIR"
59
+
60
+ claude mcp remove git -s user 2>/dev/null
61
+ claude mcp add git -s user -- uvx mcp-server-git
62
+
63
+ claude mcp remove fetch -s user 2>/dev/null
64
+ claude mcp add fetch -s user -- uvx mcp-server-fetch
65
+
66
+ claude mcp list
67
+ ```
68
+ 선택(Tavily) - **실제 키를 채팅·로그에 남기지 말 것**, 사용자가 자기 터미널에서 직접 교체:
69
+ ```bash
70
+ claude mcp remove tavily -s user 2>/dev/null
71
+ claude mcp add tavily -s user -e TAVILY_API_KEY=YOUR_TAVILY_API_KEY -- npx -y tavily-mcp
72
+ ```
73
+
74
+ ## 4. Codex 배선
75
+ ```bash
76
+ codex mcp remove context7 2>/dev/null
77
+ codex mcp add context7 -- npx -y @upstash/context7-mcp
78
+
79
+ codex mcp remove sequential-thinking 2>/dev/null
80
+ codex mcp add sequential-thinking -- npx -y @modelcontextprotocol/server-sequential-thinking
81
+
82
+ codex mcp remove filesystem 2>/dev/null
83
+ codex mcp add filesystem -- npx -y @modelcontextprotocol/server-filesystem "${FS_DIR:-$HOME/projects}"
84
+
85
+ codex mcp remove git 2>/dev/null
86
+ codex mcp add git -- uvx mcp-server-git
87
+
88
+ codex mcp remove fetch 2>/dev/null
89
+ codex mcp add fetch -- uvx mcp-server-fetch
90
+
91
+ codex mcp list
92
+ ```
93
+ 선택(Tavily, 실제 키 미노출):
94
+ ```bash
95
+ codex mcp remove tavily 2>/dev/null
96
+ codex mcp add tavily --env TAVILY_API_KEY=YOUR_TAVILY_API_KEY -- npx -y tavily-mcp
97
+ ```
98
+
99
+ `startup_timeout_sec` 패치(기본 10초는 첫 npx/uvx 다운로드엔 부족) - **Python replace-or-append** 로 방금
100
+ 등록한 테이블에만 삽입하고 그 외(OMX 가 배포한 엔트리 등)는 건드리지 않는다(멱등: 이미 있으면 스킵).
101
+ `tomllib` 는 Python **3.11+** 전용이라(RHEL8/Rocky8 기본 `python3` 는 3.6 인 경우가 흔함) 먼저 인터프리터를
102
+ 고른다:
103
+ ```bash
104
+ PY="$(command -v python3.12 || command -v python3.11 || command -v python3)"
105
+ "$PY" -c "import tomllib" 2>/dev/null || echo "⚠ tomllib 없음 - Python 3.11+ 설치 후 재시도(setup-python 참고)"
106
+ ```
107
+ ```bash
108
+ "$PY" <<'EOF'
109
+ import re
110
+ from pathlib import Path
111
+ import tomllib
112
+
113
+ CFG = Path.home() / ".codex" / "config.toml"
114
+ NAMES = ["context7", "sequential-thinking", "filesystem", "git", "fetch"] # tavily 추가했으면 여기도 추가
115
+
116
+ text = CFG.read_text(encoding="utf-8")
117
+ tomllib.loads(text) # 사전 검증 - 깨진 TOML이면 여기서 예외
118
+
119
+ parts = re.split(r"(?=^\[)", text, flags=re.MULTILINE)
120
+ out = []
121
+ for part in parts:
122
+ m = re.match(r"\[mcp_servers\.([^\]]+)\]", part)
123
+ if m and m.group(1) in NAMES and "startup_timeout_sec" not in part:
124
+ head, _, rest = part.partition("\n")
125
+ part = f"{head}\nstartup_timeout_sec = 300\n{rest}"
126
+ out.append(part)
127
+
128
+ new_text = "".join(out)
129
+ tomllib.loads(new_text) # 패치 후 재검증
130
+ CFG.write_text(new_text, encoding="utf-8")
131
+ print("patched:", [n for n in NAMES if f"[mcp_servers.{n}]" in new_text])
132
+ EOF
133
+ ```
134
+
135
+ ## 검증 (보고 의무)
136
+ ```bash
137
+ claude mcp list # 각 서버가 ✔ Connected 인지 확인
138
+ codex mcp list --json | python3 -m json.tool # 각 서버 등록 확인(json.tool 은 아무 python3 로 충분)
139
+ PY="$(command -v python3.12 || command -v python3.11 || command -v python3)" # tomllib=3.11+
140
+ "$PY" -c "import tomllib; tomllib.loads(open('$HOME/.codex/config.toml', encoding='utf-8').read()); print('✓ TOML 유효')"
141
+ grep -c 'startup_timeout_sec = 300' ~/.codex/config.toml # 5(+tavily)건 이상 기대
142
+ ```
143
+ 4-field 보고: 변경(등록한 서버 목록·config.toml 패치분) / Evidence(위 출력) / 검증(Connected·TOML 유효) /
144
+ Unknown(네트워크 차단으로 첫 다운로드 실패 등).
145
+
146
+ ## 함정
147
+ - **첫 실행 지연**: npx/uvx 첫 다운로드는 수십 초 걸릴 수 있다 - Codex 는 `startup_timeout_sec=300` 로
148
+ 여유를 두지만, Claude Code 쪽은 최초 1회 재시도가 필요할 수 있다(정직 안내).
149
+ - **Tavily 키**: 플레이스홀더 `YOUR_TAVILY_API_KEY` 를 실제 키로 교체하기 전엔 연결 실패 - 채팅·로그·커밋에
150
+ 실키를 노출하지 않는다.
151
+ - **uvx 전제**: uv 미설치 시 git·fetch 서버가 실패 → `setup-python` 선행.
152
+ - **filesystem 디렉터리 범위**: 홈 전체를 넘기면 과다 노출 - 프로젝트 디렉터리로 한정한다.
153
+ - **`codex mcp add` 는 timeout 플래그가 없다**: 위 Python 패치를 별도로 수행해야 300초가 실제로 반영된다.
154
+ - **Windows 인코딩**: config.toml 을 다루는 Python 은 `encoding='utf-8'` 명시(CP949 회피).
155
+
156
+ ARGUMENTS: [--fs-dir <path>] [--tavily] [--server <name>,...] (없으면 context7·sequential-thinking·filesystem·git·fetch 5종 전부, tavily 는 --tavily 명시 시에만)
@@ -0,0 +1,112 @@
1
+ ---
2
+ name: setup-node
3
+ description: "(banker) nvm + Node 22(LTS) 런타임 설치(Windows는 winget 또는 nvm-windows). Claude Code npm 설치·Codex/OMX·npx 기반 MCP 서버 전제. 'setup-node'/'Node 설치'/'nvm 설치' 또는 /banker:setup 시 사용."
4
+ ---
5
+
6
+ # setup-node: nvm + Node 22(LTS) 런타임 설치
7
+
8
+ Claude Code·Codex/OMX 및 다수 npx 기반 MCP 서버가 딛고 서는 Node.js 런타임을 설치한다.
9
+ 버전 고정 대신 **현재 LTS**를 설치하는 것이 원칙(2026-07 기준 최소 22 이상). 멱등(이미 있으면 확인만). 답변은 한글.
10
+
11
+ ## 런타임 배선
12
+ - **Claude Code**: 네이티브 인스톨러 자체는 Node가 불필요하지만, npm 설치 경로(v2.1.198+)는 Node 22+를 요구한다. `context7`·`sequential-thinking`·`playwright` 등 다수 MCP 서버가 `npx -y ...`로 구동되어 Node에 의존한다.
13
+ - **Codex/OMX**: `npm install -g @openai/codex oh-my-codex` 자체가 npm(Node)을 전제. LSP 스택(`@vtsls/language-server`·`vscode-langservers-extracted`·`bash-language-server`)도 npm 전역 설치로 배포된다.
14
+ - 즉 이 스킬은 두 런타임 공통 하위 의존성이며, 다른 setup-* 스킬보다 먼저 실행되는 편이 안전하다.
15
+
16
+ ## 0. 감지 (먼저, 추정 금지)
17
+ ```bash
18
+ [ -f /etc/os-release ] && . /etc/os-release && echo "distro=$ID ${VERSION_ID}"
19
+ uname -s # Linux / Darwin
20
+ [ -s "$HOME/.nvm/nvm.sh" ] && echo "nvm=설치됨" || echo "nvm=미설치"
21
+ command -v node >/dev/null && echo "node=$(node -v)" || echo "node=미설치"
22
+ command -v npm >/dev/null && echo "npm=$(npm -v)"
23
+ ```
24
+ ```powershell
25
+ $PSVersionTable.PSVersion
26
+ winget --version
27
+ if (Get-Command node -ErrorAction SilentlyContinue) { node -v } else { "node: 미설치" }
28
+ if (Get-Command nvm -ErrorAction SilentlyContinue) { nvm version } else { "nvm-windows: 미설치" }
29
+ ```
30
+
31
+ ## 1. Rocky Linux 8
32
+ ```bash
33
+ command -v curl >/dev/null && command -v git >/dev/null || sudo dnf install -y curl git
34
+ ```
35
+ 이후 아래 "nvm 공통 설치"를 그대로 실행.
36
+ > ⚠️ Rocky8/RHEL8 glibc는 정확히 2.28. Node 최신 메이저의 prebuilt 바이너리 glibc 최저요구치가 이보다 올라가면(예: 2.31+) 설치 실패 가능 → `ldd --version`으로 사전 확인, 실패 시 nvm이 소스빌드로 폴백하거나 에러를 낸다(정직 보고).
37
+
38
+ ## 2. Ubuntu 20.04~24.04
39
+ ```bash
40
+ command -v curl >/dev/null && command -v git >/dev/null || sudo apt install -y curl git
41
+ ```
42
+ 이후 "nvm 공통 설치" 그대로. 최소 서버 이미지가 아니면 대개 이미 충족.
43
+
44
+ ## 3. Debian 12
45
+ ```bash
46
+ command -v curl >/dev/null && command -v git >/dev/null || sudo apt install -y curl git
47
+ ```
48
+ 이후 "nvm 공통 설치" 그대로.
49
+
50
+ ## nvm 공통 설치 (Rocky8·Ubuntu·Debian·macOS)
51
+ ```bash
52
+ # 최신 nvm 릴리스 태그 자동확인(하드코딩 회피). 실패 시 수동 확인 안내
53
+ NVM_LATEST=$(curl -fsSL https://api.github.com/repos/nvm-sh/nvm/releases/latest \
54
+ | grep -m1 '"tag_name":' | sed -E 's/.*"tag_name": *"([^"]+)".*/\1/')
55
+ if [ -z "$NVM_LATEST" ]; then
56
+ echo "⚠️ 최신 태그 자동확인 실패. https://github.com/nvm-sh/nvm/releases 에서 수동 확인 후 <TAG> 치환"
57
+ NVM_LATEST="<TAG>"
58
+ fi
59
+ curl -o- "https://raw.githubusercontent.com/nvm-sh/nvm/${NVM_LATEST}/install.sh" | bash
60
+
61
+ # 설치 스크립트가 rc 파일을 자동 갱신하나, 컨테이너 등 미반영 환경 대비 idempotent 마커도 병행
62
+ RC_FILE="$HOME/.bashrc" # macOS는 $HOME/.zshrc
63
+ grep -q '### BANKER_NODE_BEGIN ###' "$RC_FILE" || cat >> "$RC_FILE" <<'EOF'
64
+
65
+ ### BANKER_NODE_BEGIN ###
66
+ export NVM_DIR="$HOME/.nvm"
67
+ [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
68
+ [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
69
+ ### BANKER_NODE_END ###
70
+ EOF
71
+ source "$RC_FILE"
72
+
73
+ nvm install --lts # 2026-07 기준 22 이상의 현재 LTS 자동 설치
74
+ nvm alias default 'lts/*'
75
+ node -v && npm -v
76
+ ```
77
+
78
+ ## 4. macOS (Apple Silicon / Intel)
79
+ curl은 기본 내장. Apple Silicon/Intel 차이는 Homebrew prefix 정도로 nvm 자체엔 영향 없음. 위 "nvm 공통 설치"를 zsh(`~/.zshrc`)에 그대로 적용.
80
+ - Homebrew의 `nvm` formula도 존재하나 `NVM_DIR` 캐비어트가 있어 **공식 curl 스크립트를 우선** 권장(공식 문서 기준).
81
+
82
+ ## 5. Windows 10/11
83
+ 멀티버전 전환이 불필요하면 winget 단일 설치가 가장 단순:
84
+ ```powershell
85
+ winget install --id OpenJS.NodeJS.LTS -e
86
+ node -v; npm -v
87
+ ```
88
+ 여러 Node 버전을 넘나들어야 하면 nvm-windows(별개 프로젝트, POSIX nvm과 무관):
89
+ ```powershell
90
+ winget install --id CoreyButler.NVMforWindows -e
91
+ # 새 터미널에서
92
+ nvm install lts
93
+ nvm use <설치된 버전>
94
+ ```
95
+ > ⚠️ **winget Node와 nvm-windows를 동시에 설치하지 않는다.** 두 경로가 PATH에 동시 등록되면 `node.exe`가 어느 쪽을 가리키는지 꼬인다. 하나만 선택.
96
+
97
+ ## 검증 (보고 의무)
98
+ ```bash
99
+ node -v # v22.x.x 이상 기대(현재 LTS)
100
+ npm -v
101
+ corepack enable 2>/dev/null && corepack --version # pnpm/yarn 필요 시만(선택, Node 버전에 따라 기본 포함 여부 상이)
102
+ ```
103
+ 4-field 보고: 변경(nvm 설치 경로·rc 마커·설치된 Node 버전) / Evidence(위 출력) / 검증(`node -v` ≥22 확인) / Unknown(관리자 권한 부재로 시스템 전역 설치 불가 등).
104
+
105
+ ## 함정
106
+ - **새 셸에만 반영**: nvm은 현재 셸에 `source ~/.bashrc`(또는 `~/.zshrc`) 하지 않으면 안 보임.
107
+ - **Windows PATH 충돌**: winget Node와 nvm-windows 동시 설치 금지(위 참조).
108
+ - **corepack**: pnpm/yarn 격리 관리용. Node 메이저에 따라 기본 포함 여부가 바뀔 수 있어 `corepack --version` 미동작 시 `npm install -g corepack`.
109
+ - **EL8 glibc 2.28**: 향후 Node 메이저가 최저 glibc 요구치를 올리면 prebuilt 설치 실패 가능(사전 `ldd --version` 확인).
110
+ - **버전 기준 재확인**: "22 이상"은 2026-07 시점 기준선. `nvm install --lts`는 항상 그 시점 현재 LTS를 설치하므로 자연히 충족되지만, 특정 메이저 고정이 필요하면 `--version` 인자 사용.
111
+
112
+ ARGUMENTS: [--version <major>] (없으면 `nvm install --lts`로 현재 LTS 자동 설치)
@@ -0,0 +1,106 @@
1
+ ---
2
+ name: setup-pwsh
3
+ description: "(banker) Windows PowerShell 7 + Git + $PROFILE(UTF-8 무BOM) 환경을 winget 으로 설치·검증(비-Windows 는 감지 후 no-op). 'setup-pwsh'/'PowerShell 설치'/'pwsh 환경 설정' 또는 /banker:setup 시 사용."
4
+ ---
5
+
6
+ # setup-pwsh: Windows PowerShell 7 환경 설치
7
+
8
+ banker 의 Windows 워크플로 - Claude Code 의 Git Bash 배선, Codex/OMX 의 네이티브 셸 실행 - 이
9
+ 전제하는 PowerShell 7 + Git + `$PROFILE` 환경을 구성한다. **Windows 전용 스킬**이다 - 다른 OS 에서는
10
+ 먼저 감지해 "Windows 전용 - 해당 없음"으로 정직하게 no-op 보고한다(이것도 유효한 결과). 설치는
11
+ **멱등**. 답변은 한글(기술 토큰 영문).
12
+
13
+ ## 런타임 배선
14
+ - **Claude Code**: Bash 도구가 Git Bash 를 쓰도록 `settings.json` 의 `env.CLAUDE_CODE_GIT_BASH_PATH`
15
+ 를 설정한다(예: `C:\Program Files\Git\bin\bash.exe`). 네이티브 Windows 는 1급 지원이며 **WSL 은
16
+ 필요 없다**(현재 공식 문서 기준 - WSL 은 샌드박싱·Linux 툴체인이 필요할 때만 선택 사항).
17
+ - **Codex**: 네이티브 PowerShell 셸에서 그대로 동작한다(별도 배선 불필요). AOAI 키 등 환경변수는
18
+ **User-scope** 로 저장하고, Process/User/Machine **3-scope 동기화**에 유의한다 - 저장 직후 현재
19
+ 프로세스에는 반영되지 않을 수 있다.
20
+
21
+ ## 0. 감지 (먼저 - 추정 금지)
22
+ ```powershell
23
+ $PSVersionTable.PSVersion
24
+ $env:OS # Windows = 'Windows_NT' (PS 5.1·7 공통), 비-Windows 는 미설정
25
+ Get-Command git, pwsh -ErrorAction SilentlyContinue
26
+ ```
27
+ - **Windows 판정 = `$env:OS -eq 'Windows_NT'`** (또는 `[System.Environment]::OSVersion.Platform -eq 'Win32NT'`).
28
+ ⚠️ `$IsWindows` 자동 변수는 **PowerShell 7+ 에만** 있어, 이 스킬이 업그레이드하려는 **Windows PowerShell 5.1
29
+ 에서는 `$null`(미정의)** 이다 - `$IsWindows` 로만 판정하면 진짜 Windows 를 비-Windows 로 오판해 no-op 한다. 보조 신호로만 쓴다.
30
+ - 비-Windows(PowerShell 없이 `uname` 만)면 **"Windows 전용 - 해당 없음"** 을 보고하고 멈춘다(no-op 도 유효한 결과).
31
+
32
+ ## 1. winget 설치
33
+ ```powershell
34
+ winget install --id Microsoft.PowerShell -e
35
+ winget install --id Microsoft.WindowsTerminal -e
36
+ winget install --id Git.Git -e
37
+ git config --global core.autocrlf input
38
+ ```
39
+ winget 은 이미 설치된 패키지를 스스로 skip 한다(멱등) - 강제 재설치 불필요.
40
+
41
+ ## 2. `$PROFILE` 작성 - UTF-8 무BOM 전용 경로
42
+ **`Add-Content`/`Out-File -Encoding UTF8` 금지** - 둘 다 CP949 재인코딩 또는 UTF-8 BOM 혼입으로
43
+ 이후 한글 주석·파싱을 깨뜨린다. 반드시 아래 방식만 쓴다:
44
+ ```powershell
45
+ $marker = "# BANKER_PWSH_BEGIN"
46
+ $existing = if (Test-Path $PROFILE) { [System.IO.File]::ReadAllText($PROFILE) } else { "" }
47
+ if ($existing -notmatch [regex]::Escape($marker)) {
48
+ # <java21-bin>/<python-dir> 은 실제 설치 경로로 교체 - 추정 금지, §0/설치 로그에서 확인 후 채운다
49
+ # (winget install Microsoft.OpenJDK.21 후 `Get-ChildItem "$env:ProgramFiles" -Filter "*jdk-21*"` 등으로 확인)
50
+ $block = @"
51
+ $marker
52
+ # PATH 순서: Java21 우선(잔존 구버전 Java 덮기) -> python -> ~/.local/bin -> jdtls
53
+ `$env:PATH = "<java21-bin>;`$env:PATH"
54
+ `$env:PATH = "`$env:PATH;<python-dir>"
55
+ `$env:PATH = "`$env:PATH;`$HOME\.local\bin"
56
+ `$env:PATH = "`$env:PATH;`$HOME\.local\jdtls\bin"
57
+ # BANKER_PWSH_END
58
+ "@
59
+ $content = $existing + "`n" + $block
60
+ [System.IO.File]::WriteAllText($PROFILE, $content, (New-Object System.Text.UTF8Encoding($false)))
61
+ }
62
+ ```
63
+ - PATH 순서 원칙: **Java21 을 맨 앞**에 둬 PATH 상에 남아있을 수 있는 구버전 Java 를 덮고, 그다음
64
+ python, `~/.local/bin`, jdtls 순으로 이어붙인다.
65
+ - 마커 블록(`# BANKER_PWSH_BEGIN`/`END`)으로 재실행해도 중복 append 되지 않는다(사용자 기존 내용은
66
+ 보존).
67
+
68
+ ## 3. 런타임 배선 적용
69
+ **Claude Code** - `settings.json` 에 기존 키를 보존하며 병합:
70
+ ```json
71
+ { "env": { "CLAUDE_CODE_GIT_BASH_PATH": "C:\\Program Files\\Git\\bin\\bash.exe" } }
72
+ ```
73
+ **Codex/OMX 환경변수** - User-scope 로 저장(예: AOAI 키):
74
+ ```powershell
75
+ [Environment]::SetEnvironmentVariable('AZURE_OPENAI_API_KEY', $env:AZURE_OPENAI_API_KEY, 'User')
76
+ ```
77
+
78
+ ## 검증 (보고 의무)
79
+ ```powershell
80
+ pwsh -v
81
+ $PSVersionTable.PSVersion
82
+ git config --get core.autocrlf # input 기대
83
+
84
+ $b = [System.IO.File]::ReadAllBytes($PROFILE)[0..2]
85
+ if (("{0:X2}{1:X2}{2:X2}" -f $b[0],$b[1],$b[2]) -eq "EFBBBF") { "BOM 있음 -- 재작성 필요" } else { "무BOM 확인" }
86
+
87
+ pwsh -Command "Write-Output 'profile-load-ok'" # $PROFILE 이 에러 없이 실제 로드되는지
88
+ ```
89
+ 4-field 보고: 변경(설치 패키지·`$PROFILE` 마커블록·settings.json 병합 여부) / Evidence(위 출력) /
90
+ 검증(무BOM·`profile-load-ok`·autocrlf=input) / Unknown(관리자 권한이 필요한 항목 등).
91
+
92
+ ## 함정
93
+ - **CP949/BOM 오염**: `$PROFILE` 은 오직 `[System.IO.File]::WriteAllText(..., UTF8Encoding($false))`
94
+ 로만 쓴다 - `Add-Content`/`Out-File -Encoding UTF8` 은 절대 쓰지 않는다.
95
+ - **MS Store Python stub**: `python`/`python3` 를 MS Store 앱 실행 별칭(App execution aliases)이
96
+ 가로채 스토어를 여는 경우가 있다 → 설정 → 앱 → 고급 앱 설정 → 앱 실행 별칭에서 꺼야 실제 설치된
97
+ Python 이 잡힌다.
98
+ - **심볼릭 링크 권한**: 심볼릭 링크 생성은 개발자 모드 또는 관리자 권한이 필요하다 - 둘 다 없으면
99
+ 조용히 실패하므로 **복사로 대체**하고 정직히 보고한다.
100
+ - **Process/User/Machine 3-scope 동기화**: `SetEnvironmentVariable(..., 'User')` 직후 현재
101
+ 프로세스(`Process` scope)에는 반영되지 않을 수 있다 - 새 pwsh 세션에서 재확인.
102
+ - **이미지 붙여넣기**: 터미널에 이미지 붙여넣기는 `Ctrl+V` 가 아니라 **`Alt+V`**.
103
+ - **비-Windows 오인 실행**: 이 스킬은 Windows 전용이다 - `$IsWindows` 감지 없이 무작정 진행하지
104
+ 않는다.
105
+
106
+ ARGUMENTS: 없음 (비-Windows 는 자동 감지 후 "Windows 전용 - 해당 없음" no-op 보고)