@kaydash9999/banker-plugins 0.4.0 → 0.5.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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +20 -0
- package/README.md +20 -2
- package/codex/manifest.json +10 -0
- package/commands/setup.md +28 -16
- package/package.json +1 -1
- package/skills/harness-factory/SKILL.md +114 -0
- package/skills/setup-java/SKILL.md +113 -0
- package/skills/setup-lsp/SKILL.md +232 -0
- package/skills/setup-mcp/SKILL.md +156 -0
- package/skills/setup-node/SKILL.md +112 -0
- package/skills/setup-pwsh/SKILL.md +106 -0
- package/skills/setup-python/SKILL.md +121 -0
- package/skills/setup-sandbox/SKILL.md +202 -0
- package/skills/setup-tmux/SKILL.md +105 -0
|
@@ -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 보고)
|