큐레이터 단비가 Windows PowerShell에서 OpenCode CLI를 새로 설치하고 KIE의 Claude 호환 API에 연결하는 과정을 처음부터 끝까지 정리했다. Node.js 확인부터 OpenCode 1.18.25 설치, API 키 숨김 입력, 모델 목록 조회, opencode.json 작성, 대화·파일 작업 테스트, 키 영구 저장까지 순서대로 따라가면 된다.
OpenCode는 터미널에서 돌아가는 오픈소스 AI 코딩 에이전트이고, KIE는 여러 AI 모델을 크레딧 방식으로 쓰게 해 주는 API 서비스다. 둘을 잇는 핵심은 설정 파일 한 장이다. 기본 주소 한 글자, 인증 항목 이름 하나만 달라도 401이나 404가 나기 때문에 명령어를 원문 그대로 쓰는 편이 안전하다.
설치를 마친 뒤에는 PowerShell에서 opencode 한 단어만 입력해도 작업 폴더로 이동해 KIE 모델로 바로 실행되도록 프로필 함수를 등록한다. 안내 문구 자리에 키를 붙여 넣는 실수, 업데이트 창 때문에 버전 고정이 풀리는 상황, 401·404·503 대응, 키 교체 순서에 더해 여러 모델을 등록해 쓸 때 생기는 스크립트 인코딩 오류, 느린 시작, DeepSeek 두 번째 대화 오류와 작업장 선택 기준까지 함께 묶었다.
핵심 포인트: 설정 파일에는 실제 키 대신 {env:KIEAPIKEY} 참조만 넣고, 기본 주소는 https://api.kie.ai/anthropic/v1 에서 끝낸다. 키를 사용자 환경변수에 영구 저장하는 일은 대화와 파일 작업 테스트가 모두 끝난 뒤에 한다.
1. 설치 환경과 전체 진행 순서
예시 환경은 아래와 같다. 작업 폴더는 F드라이브의 001_opencode 폴더를 쓰며, 다른 위치를 쓰려면 이후 모든 코드의 경로를 같은 값으로 바꾸면 된다.
| 구분 | 설정 내용 |
|---|---|
| 운영체제 | Windows |
| 터미널 | PowerShell |
| 프로그램 | OpenCode CLI |
| 고정 버전 | OpenCode 1.18.25 |
| 모델 제공 서비스 | KIE |
| 사용 모델 | claude-haiku-5-5 |
| 작업 폴더 | F:\000Development\001opencode |
| 설정 파일 | 작업 폴더의 opencode.json |
| API 기본 주소 | https://api.kie.ai/anthropic/v1 |
| API 키 보관 | KIEAPIKEY 환경변수 |
| 이용 요금 | KIE 크레딧에서 차감 |
OpenCode 프로그램은 npm 전역 경로에 설치되고, 작업 파일과 프로젝트 설정은 지정한 작업 폴더에 둔다. 진행은 열 단계로 나뉜다.
| 단계 | 할 일 | 완료 기준 |
|---|---|---|
| 1 | KIE API 키·크레딧 준비 | 유효한 키와 잔액 확인 |
| 2 | Node.js 설치 확인 | Node.js·npm 버전 표시 |
| 3 | OpenCode 설치 | 1.18.25 표시 |
| 4 | 작업 폴더 생성 | 지정 경로로 이동 |
| 5 | API 키 입력 | 현재 PowerShell에 키 설정 |
| 6 | KIE 모델 조회 | Haiku 모델 ID 확인 |
| 7 | OpenCode 설정 작성 | JSON 검사 통과 |
| 8 | 대화 연결 테스트 | 정상 응답 |
| 9 | 파일 작업 테스트 | 읽기·생성·재확인 성공 |
| 10 | 키 저장 | 새 터미널에서도 실행 가능 |
그림 1. KIE 키 준비부터 키 영구 저장까지 열 단계 흐름
KIE 쪽 준비는 세 가지다.
- KIE에 로그인해 API 키 관리 페이지로 들어간다.
- 새 키를 만들거나 사용할 키를 준비한다.
- 계정 잔액과 사용할 모델의 요금을 확인한다. 대화 테스트와 파일 작업에도 사용료가 나갈 수 있다.
API 키는 채팅이나 스크린샷으로 공유하지 않고, 프로젝트 파일에도 적지 않는다.
2. Node.js 확인과 OpenCode 1.18.25 설치
시작 메뉴에서 PowerShell을 일반 권한으로 연다. 관리자 권한은 필요 없다. 먼저 Node.js와 npm이 있는지 본다.
node --version
npm.cmd --version
두 명령에서 버전이 나오면 다음으로 넘어간다. 명령을 찾을 수 없다면 Node.js 공식 사이트에서 LTS 버전을 설치하고, 설치 화면의 PATH 추가 옵션을 그대로 둔 채 PowerShell을 다시 연다. npm 대신 npm.cmd를 쓰는 이유는 Windows PowerShell의 스크립트 실행 정책 문제를 피하기 위해서다.
이어서 OpenCode를 1.18.25로 고정해 설치하고 버전을 확인한다.
npm.cmd install -g [email protected]
opencode.cmd --version
정상이라면 다음 값이 나온다.
1.18.25
명령을 찾지 못하면 PowerShell을 새로 연 뒤 다시 실행하고, 그래도 안 되면 설치 경로를 확인한다.
npm.cmd prefix -g
Get-Command opencode* -All -ErrorAction SilentlyContinue
그림 2. node v24.21.0, npm 11.19.0 확인 뒤 [email protected]를 설치하고 작업 폴더까지 만든 화면
설치 직후 npm이 install-scripts 경고를 띄울 수 있다. 최근 npm은 허용 목록(allowScripts)에 없는 패키지의 설치 스크립트를 바로 실행하지 않고 경고만 남긴다. 위 화면처럼 opencode.cmd --version에서 1.18.25가 나오면 그대로 진행해도 된다.
| 설치 화면에서 보이는 것 | 의미 | 할 일 |
|---|---|---|
| changed 3 packages | 설치 완료 | 버전 확인으로 이동 |
| install-scripts 경고 | postinstall 스크립트가 허용 목록 밖 | 버전이 나오면 무시해도 됨 |
| 버전 확인 실패 | 실행 파일 준비 안 됨 | 경고에 나온 --allow-scripts=opencode-ai 옵션으로 다시 설치 |
버전을 고정하는 이유도 짚어 둔다. OpenCode는 업데이트가 잦아 버전마다 설정 형식과 인증 동작이 바뀔 수 있다. npm에는 1.18.25가 2026년 8월 28일에, 1.19.3이 10월 16일에 올라왔고 10월 17일 현재 최신은 1.19.3이다. 여기서는 KIE 연결이 정상 동작한 1.18.25에 맞춰 모든 설정을 쓴다.
아래 영상은 OpenCode 설치부터 에이전트, 스킬, MCP 구성까지 입문자 눈높이로 보여 주는 영어 강의다. 설치 직후 전체 기능을 한 번 둘러보고 싶을 때 참고하면 된다.
3. 작업 폴더 만들기
작업 폴더를 만들고 그 위치로 이동한다.
New-Item -ItemType Directory -Force "F:\000_Development\001_opencode"
Set-Location "F:\000_Development\001_opencode"
Get-Location
Get-Location 결과가 아래와 같으면 정상이다. 폴더가 이미 있어도 New-Item의 -Force 옵션은 기존 파일을 지우지 않는다.
F:\000_Development\001_opencode
최종 폴더 구성은 단순하다.
F:\000_Development\001_opencode
├─ opencode.json
└─ 앞으로 생성할 프로젝트 파일
- opencode.json은 이 폴더 바로 아래에 둔다.
- 앞으로 OpenCode가 만드는 파일도 이 폴더에 생긴다.
- 다른 폴더에서 OpenCode를 실행하면 이 설정이 적용되지 않는다.
4. API 키 숨김 입력
키를 명령어에 직접 쓰면 PowerShell 기록에 남는다. 그래서 Read-Host의 숨김 입력으로 받아 현재 창의 환경변수에만 넣는다. 아래 전체를 복사해 한 번에 실행한다.
$secureKey = Read-Host "KIE API 키를 붙여넣고 Enter" -AsSecureString
$keyPointer = [IntPtr]::Zero
try {
$keyPointer = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureKey)
$env:KIE_API_KEY = (
[Runtime.InteropServices.Marshal]::PtrToStringBSTR($keyPointer)
).Trim()
}
finally {
if ($keyPointer -ne [IntPtr]::Zero) {
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($keyPointer)
}
$secureKey.Dispose()
}
if ([string]::IsNullOrWhiteSpace($env:KIE_API_KEY)) {
throw "API 키가 입력되지 않았습니다."
}
Write-Host "KIE API 키 설정 완료"
입력란이 뜨면 실제 키만 붙여 넣고 Enter를 누른다. 화면에 글자가 그대로 보이지 않는 것이 정상이다.
| 넣을 내용 | 넣지 않을 내용 |
|---|---|
| 실제 KIE API 키 | Bearer |
| 따옴표 | |
| 설명 문구 |
그림 3. Read-Host 숨김 입력, BSTR 변환, 빈 값 검사를 거쳐 설정 완료 문구가 나온 화면. 입력 길이가 드러나는 줄은 가렸다
값을 출력하지 않고 키가 들어갔는지만 확인하려면 다음을 쓴다.
if ([string]::IsNullOrWhiteSpace($env:KIE_API_KEY)) {
Write-Host "키가 설정되지 않았습니다."
}
else {
Write-Host "키가 설정되어 있습니다."
}
- 키를 확인한다고 값 자체를 출력하지 않는다.
- 이 방식은 키가 명령 기록에 남는 것을 막아 줄 뿐, 환경변수가 암호화되는 것은 아니다.
- 이 단계의 키는 현재 PowerShell 창에서만 유효하다. 영구 저장은 마지막 단계에서 한다.
5. KIE 모델 목록으로 인증 확인
OpenCode 설정 전에 키가 맞는지, 사용할 모델 ID가 실제로 있는지 KIE API로 먼저 확인한다.
$headers = @{
Authorization = "Bearer $env:KIE_API_KEY"
}
$models = Invoke-RestMethod `
-Uri "https://api.kie.ai/anthropic/v1/models" `
-Headers $headers `
-TimeoutSec 30 `
-ErrorAction Stop
$models.data | Select-Object id, display_name
목록에서 다음 ID를 찾는다.
claude-haiku-5-5
해당 모델만 보려면 아래처럼 거른다.
$models.data |
Where-Object id -EQ "claude-haiku-5-5" |
Select-Object id, display_name
그림 4. /anthropic/v1/models 조회로 모델 목록을 받은 뒤 claude-haiku-5-5만 걸러 낸 화면
| 결과 | 조치 |
|---|---|
| Haiku 모델 표시 | 다음 단계 진행 |
| 401 오류 | 키를 다시 확인 |
| 모델이 표시되지 않음 | 현재 제공 목록 확인 |
| has_more가 참 | 모델 목록에 추가 페이지가 있음 |
| 통신 오류 | 네트워크·서비스 상태 확인 |
모델 ID는 추측하지 말고 목록에 나온 값을 그대로 쓴다. KIE 문서도 모델 목록은 GET 방식의 /anthropic/v1/models, 실제 대화 요청은 /anthropic/v1/messages로 안내하며 인증은 Authorization 헤더의 Bearer 방식이다.
6. opencode.json 작성과 주소·인증 규칙
설정 파일 위치는 다음과 같다. 파일에는 API 키 대신 환경변수 참조만 넣는다.
F:\000_Development\001_opencode\opencode.json
기존 설정이 있으면 먼저 백업한다.
Set-Location "F:\000_Development\001_opencode"
if (Test-Path ".\opencode.json") {
$backupName = "opencode.json.backup-" + (Get-Date -Format "yyyyMMdd-HHmmss")
Copy-Item ".\opencode.json" $backupName
Write-Host "백업 완료: $backupName"
}
이제 설정을 쓴다. here-string으로 내용을 만든 뒤 BOM 없는 UTF-8로 저장하는 방식이다. 아래 전체를 실행한다.
$configText = @'
{
"autoupdate": false,
"enabled_providers": ["kie"],
"model": "kie/claude-haiku-5-5",
"small_model": "kie/claude-haiku-5-5",
"provider": {
"kie": {
"npm": "@ai-sdk/anthropic",
"name": "KIE",
"options": {
"baseURL": "https://api.kie.ai/anthropic/v1",
"authToken": "{env:KIE_API_KEY}",
"timeout": 60000
},
"models": {
"claude-haiku-5-5": {
"name": "KIE Haiku 5.5"
}
}
}
},
"permission": {
"edit": "ask",
"bash": "ask"
}
}
'@
$configPath = "F:\000_Development\001_opencode\opencode.json"
[System.IO.File]::WriteAllText(
$configPath,
$configText,
[System.Text.UTF8Encoding]::new($false)
)
Write-Host "설정 파일 생성 완료"
그림 5. here-string으로 설정 내용을 만들고 BOM 없는 UTF-8로 opencode.json을 저장한 화면
| 설정 | 역할 |
|---|---|
| autoupdate: false | 초기 설정 중 자동 버전 변경 방지 |
| enabled_providers | KIE 제공자만 활성화 |
| model | 기본 모델 |
| small_model | 보조 작업도 같은 모델 사용 |
| npm | Anthropic Messages SDK 사용 |
| baseURL | KIE API 주소 |
| authToken | 환경변수의 키를 Bearer 인증으로 전달 |
| timeout | 개별 요청 제한 시간 60초 |
| permission | 파일 수정·명령 실행 시 승인 요청 |
가장 많이 틀리는 곳은 주소와 인증 항목이다.
기본 주소:
https://api.kie.ai/anthropic/v1
최종 메시지 요청 경로:
https://api.kie.ai/anthropic/v1/messages
- 기본 주소에는 /messages를 넣지 않는다. SDK가 요청할 때 뒤에 붙인다.
- authToken 값 앞에 Bearer를 직접 붙이지 않는다. SDK가 인증 접두사를 처리한다.
- AI SDK의 Anthropic 제공자에서 authToken은 Authorization: Bearer 헤더로, apiKey는 x-api-key 헤더로 나간다. KIE는 Bearer를 받으므로 authToken을 쓴다.
- KIE 문서의 Claude Code 연결 예시는 기본 주소를 /anthropic까지만 쓴다. Claude Code가 /v1/messages를 직접 붙이기 때문이고, OpenCode가 쓰는 AI SDK는 /messages만 붙이므로 /anthropic/v1이 맞다.
- {env:KIEAPIKEY}는 환경변수가 비어 있으면 빈 문자열로 바뀐다. 이때는 설정이 아니라 키 입력 단계부터 다시 본다.
그림 6. opencode.json의 핵심 항목과 기본 주소·authToken 작성 규칙
저장한 파일의 JSON 문법을 검사한다.
Get-Content "F:\000_Development\001_opencode\opencode.json" -Raw |
ConvertFrom-Json |
Out-Null
Write-Host "JSON 문법 검사 통과"
이 검사는 문법만 본다. 프로그램 버전에 맞는 설정인지는 실제로 실행할 때 드러난다.
7. 첫 대화 테스트와 업데이트 창 주의
먼저 한 번만 요청하고 끝나는 run 명령으로 연결을 확인한다.
Set-Location "F:\000_Development\001_opencode"
opencode.cmd run --model "kie/claude-haiku-5-5" "파일 읽기, 수정, 명령 실행 없이 OK라고만 답해줘."
그림 7. JSON 문법 검사를 통과한 뒤 run 명령에 KIE Haiku가 OK로 답한 화면
| 성공 기준 | 내용 |
|---|---|
| 응답 | OK 또는 요청에 맞는 짧은 답변 |
| 종료 | 인증·서버 오류 없이 끝남 |
| KIE 로그 | 요청 기록이 남음 |
처음에는 제공자 패키지를 준비하느라 시간이 걸릴 수 있다. 제한 시간을 60초로 잡아도 내부 재시도가 있으면 전체 실행은 더 길어진다. 오류가 반복되거나 너무 오래 기다리면 Ctrl+C로 멈추고 아래 오류 해결 절을 본다.
첫 테스트가 성공하면 대화 화면(TUI)을 연다. 이제부터 자연어 요청과 슬래시 명령은 OpenCode 입력란에 넣는다.
opencode.cmd --model "kie/claude-haiku-5-5"
/models
/models에서 KIE Haiku 5.5가 선택돼 있는지 확인한다. 환경변수로 인증하는 구성이라 /connect 과정은 따로 필요 없다. 간단한 대화로 연결을 확인한다.
연결 확인용 테스트야.
파일을 읽거나 수정하지 말고 짧게 인사해줘.
그림 8. TUI에서 hello에 응답한 화면. 오른쪽에 컨텍스트 22,533토큰과 버전 1.19.3이 보인다
여기서 버전 고정이 풀리는 일이 생길 수 있다. 설정에 autoupdate: false를 넣었는데도 TUI를 처음 열 때 새 버전 안내 창이 뜨고, Confirm을 누르면 그 자리에서 1.19.3으로 업데이트된다. 공식 문서는 autoupdate를 false로 두면 자동 다운로드를 끈다고 설명하지만, 안내 창 자체는 이렇게 나타날 수 있다. 다른 위치의 전역 설정이 함께 적용되고 있을 가능성도 있다.


| 상황 | 대응 |
|---|---|
| 업데이트 안내 창이 뜸 | Skip 선택 |
| 이미 Confirm을 누름 | opencode.cmd --version으로 버전 확인 |
| 1.18.25로 되돌리려 함 | 설치 명령 npm.cmd install -g [email protected] 다시 실행 |
| 계속 안내 창이 뜸 | 사용자 설정 폴더의 전역 opencode.json 확인 |
위 화면에서는 1.19.3으로 올라간 뒤에도 hello 응답은 정상이었다. 다만 이후 버전에서 인증 처리나 설정 항목이 바뀌면 같은 설정이 그대로 통한다는 보장은 없으므로, 문제가 생기면 먼저 1.18.25로 돌아가 비교하는 편이 빠르다.
아래 영상은 OpenCode를 Codex·Claude Code의 오픈소스 대안으로 소개하며 주요 기능과 사용 흐름을 19분 남짓에 훑는 영어 단기 강의다. 대화 화면을 처음 연 뒤 보면 이해가 빠르다.
8. 파일 작업 테스트
대화만 되는 것과 파일 작업까지 되는 것은 다르다. 읽기, 생성, 다시 읽기 순서로 확인한다. 먼저 파일 읽기다. OpenCode 입력란에 넣는다.
현재 작업 폴더의 파일 목록을 확인하고,
opencode.json에 설정된 모델 ID와 API 기본 주소를 알려줘.
조건:
- 파일 수정 금지
- 환경변수 조회 금지
- API 키 출력 금지
다음 값이 답으로 나오면 된다.
모델:
kie/claude-haiku-5-5
기본 주소:
https://api.kie.ai/anthropic/v1
이어서 파일을 하나 만들게 한다.
현재 작업 폴더에 kie-opencode-test.html 파일을 만들어줘.
요구사항:
1. 제목은 “KIE + OpenCode 연결 성공”
2. 흰색 배경과 파란색 제목
3. 외부 라이브러리 사용 금지
4. 다른 파일 수정 금지
5. 동일한 파일이 이미 있으면 덮어쓰기 전에 확인
수정 승인 요청이 뜨면 대상 파일과 내용을 확인한 뒤 허용한다. 작업 폴더에 kie-opencode-test.html이 생기고, 탐색기에서 더블클릭하면 브라우저로 열린다. 마지막으로 만든 파일을 다시 읽게 한다.
kie-opencode-test.html을 다시 읽고
요구사항을 충족했는지 확인해줘.
파일은 수정하지 마.
| 단계 | 확인하는 것 | 실패하면 |
|---|---|---|
| 읽기 | 작업 폴더·설정 인식 | 실행 위치 확인 |
| 생성 | 수정 권한과 승인 흐름 | 승인 요청·도구 오류 확인 |
| 다시 읽기 | 생성 결과 반영 | 파일 경로 확인 |
대화, 읽기, 생성, 다시 읽기까지 모두 되면 기본적인 에이전트 작업 흐름이 정상이다.
9. API 키 영구 저장과 평소 실행
정상 동작을 확인했다면 키를 Windows 사용자 환경변수에 저장한다. OpenCode를 종료하고, 키를 입력했던 그 PowerShell 창에서 실행한다.
if ([string]::IsNullOrWhiteSpace($env:KIE_API_KEY)) {
throw "현재 창에 KIE_API_KEY가 없습니다. 먼저 키를 입력하세요."
}
[Environment]::SetEnvironmentVariable(
"KIE_API_KEY",
$env:KIE_API_KEY,
"User"
)
Write-Host "KIE API 키 사용자 환경변수 저장 완료"
| 구분 | 적용 |
|---|---|
| 현재 PowerShell | 현재 설정값 사용 |
| 이후 새 PowerShell | 저장한 사용자 환경변수 사용 |
| opencode.json | 키 자체는 저장되지 않음 |
| 다른 Windows 사용자 | 자동 적용되지 않음 |
새 창에서 반영되지 않으면 Windows Terminal이나 편집기처럼 터미널을 띄운 프로그램 전체를 종료했다가 다시 연다. 평소에는 다음 두 줄로 실행한다.
Set-Location "F:\000_Development\001_opencode"
opencode.cmd
첫 요청은 수정 없이 계획부터 받는 편이 안전하다.
현재 프로젝트 구조를 먼저 확인해줘.
아직 파일은 수정하지 말고,
작업 계획과 수정할 파일 목록부터 제안해줘.
- 프로젝트 분석용 AGENTS.md가 필요하면 연결 확인 뒤 OpenCode에서 /init을 실행한다.
- permission이 ask라서 파일 수정과 명령 실행은 매번 승인 요청이 뜬다.
- 키는 이 시점부터 새 창에서도 자동으로 읽힌다.
10. opencode 한 단어로 바로 실행하기
매번 폴더를 옮기고 모델을 지정하는 대신, PowerShell 프로필에 함수를 등록하면 어디서든 opencode만 입력해 KIE 연결 상태로 실행할 수 있다. 앞 단계의 설치·연결 테스트가 끝난 뒤에 추가하며, 적용 범위는 현재 Windows 사용자의 PowerShell이다. CMD에는 적용되지 않는다.
| 자동 처리 | 내용 |
|---|---|
| 작업 폴더 이동 | F:\000Development\001opencode |
| API 키 확인 | 저장된 KIEAPIKEY 사용 |
| 설정 파일 확인 | 작업 폴더의 opencode.json |
| 실행 모델 | kie/claude-haiku-5-5 |
| 실행 명령 | 어디서든 opencode |
먼저 키가 영구 저장돼 있는지 확인한다. 키 값은 화면에 출력하지 않는다.
$savedKey = [Environment]::GetEnvironmentVariable("KIE_API_KEY", "User")
if ([string]::IsNullOrWhiteSpace($savedKey)) {
if ([string]::IsNullOrWhiteSpace($env:KIE_API_KEY)) {
throw "KIE API 키가 없습니다. 먼저 매뉴얼의 API 키 입력 단계를 진행하세요."
}
[Environment]::SetEnvironmentVariable(
"KIE_API_KEY",
$env:KIE_API_KEY,
"User"
)
Write-Host "KIE API 키 저장 완료"
}
else {
Write-Host "저장된 KIE API 키가 있습니다."
}
Remove-Variable savedKey -ErrorAction SilentlyContinue
설정 파일과 실행 파일도 확인한다. 첫 결과는 True, 두 번째 결과는 opencode.cmd의 실행 경로가 나와야 한다.
Test-Path "F:\000_Development\001_opencode\opencode.json"
Get-Command opencode.cmd -ErrorAction Stop
등록할 함수의 동작은 이렇다.
opencode 입력
↓
저장된 KIE 키 확인
↓
F:\000_Development\001_opencode 이동
↓
KIE Haiku 모델로 OpenCode 실행
아래 전체를 한 번 실행한다. 기존 프로필이 있으면 백업하고, 다른 내용은 그대로 둔 채 함수만 추가한다.
$profilePath = $PROFILE.CurrentUserAllHosts
$profileDir = Split-Path -Parent $profilePath
New-Item -ItemType Directory -Force $profileDir | Out-Null
$existingText = ""
if (Test-Path $profilePath) {
$existingText = [System.IO.File]::ReadAllText($profilePath)
$backupPath = $profilePath + ".backup-" + (Get-Date -Format "yyyyMMdd-HHmmss")
Copy-Item $profilePath $backupPath
Write-Host "프로필 백업:" $backupPath
}
$marker = "# BEGIN KIE OPENCODE LAUNCHER"
if ($existingText.Contains($marker)) {
Write-Host "이미 KIE OpenCode 명령이 등록되어 있습니다."
}
else {
$launcher = @'
# BEGIN KIE OPENCODE LAUNCHER
function global:opencode {
$projectPath = "F:\000_Development\001_opencode"
$configPath = Join-Path $projectPath "opencode.json"
if (-not (Test-Path $projectPath -PathType Container)) {
throw "작업 폴더가 없습니다: $projectPath"
}
if (-not (Test-Path $configPath -PathType Leaf)) {
throw "OpenCode 설정 파일이 없습니다: $configPath"
}
if ([string]::IsNullOrWhiteSpace($env:KIE_API_KEY)) {
$env:KIE_API_KEY = [Environment]::GetEnvironmentVariable(
"KIE_API_KEY",
"User"
)
}
if ([string]::IsNullOrWhiteSpace($env:KIE_API_KEY)) {
throw "KIE_API_KEY가 없습니다. API 키를 먼저 설정하세요."
}
$launcherCommand = Get-Command opencode.cmd -ErrorAction Stop
Set-Location -LiteralPath $projectPath
& $launcherCommand.Source --model "kie/claude-haiku-5-5" @args
}
# END KIE OPENCODE LAUNCHER
'@
[System.IO.File]::WriteAllText(
$profilePath,
$existingText + [Environment]::NewLine + $launcher,
[System.Text.UTF8Encoding]::new($true)
)
Write-Host "KIE OpenCode 명령 등록 완료"
}
Write-Host "프로필 위치:" $profilePath
함수 안에서 opencode.cmd를 쓰는 이유가 있다. opencode 함수 안에서 다시 opencode를 부르면 자기 자신을 반복 호출할 수 있어서, 내부에서는 실제 프로그램인 opencode.cmd를 명시해 실행한다.
현재 창에 바로 적용하고 등록 결과를 본다.
. $PROFILE.CurrentUserAllHosts
Get-Command opencode
다음처럼 Function으로 나오면 정상이다.
CommandType Name
----------- ----
Function opencode
Alias로 나온다면 기존 별칭이 함수를 가리고 있는 것이다. 현재 창의 별칭을 지우고 다시 확인한다. 새 창에서도 같은 별칭이 생기면 프로필에 있는 기존 Set-Alias opencode 설정을 찾아 정리한다.
Remove-Item Alias:opencode -ErrorAction SilentlyContinue
Get-Command opencode
프로필을 적용할 때 스크립트를 실행할 수 없다는 오류가 날 때만 실행 정책을 손본다.
Get-ExecutionPolicy -List
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned
. $PROFILE.CurrentUserAllHosts
| 상황 | 처리 |
|---|---|
| 개인 PC | CurrentUser 범위에 RemoteSigned 허용 |
| 회사·기관 PC | 조직 정책은 우회하지 말고 관리자에게 문의 |
| Bypass·Unrestricted | 기본 설정으로 쓸 필요 없음 |
다른 폴더에서 실행해 본다.
Set-Location $HOME
opencode
| 확인 항목 | 정상 상태 |
|---|---|
| 작업 폴더 | F:\000Development\001opencode |
| 제공자 | KIE |
| 모델 | claude-haiku-5-5 |
OpenCode에서 다음을 입력해 OK가 오면 설정 완료다.
연결 테스트야. 파일이나 명령을 실행하지 말고 OK라고만 답해줘.
마지막으로 PowerShell을 닫고 새 창을 열어 opencode만 입력한다. 폴더 이동이나 키 재입력 없이 KIE 모델로 뜨면 끝이다.
- Windows PowerShell 5.1과 PowerShell 7은 프로필 위치가 다르다. 둘 다 쓴다면 각각 등록한다.
- 같은 PowerShell 버전의 여러 호스트에는 CurrentUserAllHosts 프로필이 함께 적용된다.
- 등록한 함수는 추가 인수를 실제 OpenCode 명령에 그대로 넘긴다.
| 용도 | 명령 |
|---|---|
| 일반 실행 | opencode |
| 한 번만 질문하고 종료 | opencode run 뒤에 요청 문장 |
| 디버그 모드 | opencode --log-level DEBUG |
| 폴더 이동 없이 원래 프로그램 실행 | opencode.cmd |
opencode run "파일을 수정하지 말고 현재 프로젝트 구조를 설명해줘."
opencode.cmd로 직접 실행하면 현재 폴더 기준으로 동작하므로 KIE 프로젝트 설정이 적용되는 위치인지 먼저 확인한다. 여러 모델을 등록해 쓰게 되면 이 함수 블록을 아래의 -RefreshModels 런처로 바꾸는 것이 최신 구성이다.
11. 흔한 실수와 해결: 안내 문구 자리에 키를 넣은 경우
숨김 입력 단계에서 자주 나오는 실수가 있다. Read-Host 뒤 따옴표 안에 API 키를 붙여 넣고 실행하는 경우다. 따옴표 안은 키를 저장하는 곳이 아니라 화면에 보여 줄 질문 문구다. 이렇게 하면 키가 화면과 명령 기록에 그대로 남고, 정작 입력란에서는 아무것도 넣지 않은 채 Enter를 누르게 된다.
| 증상 | 원인 |
|---|---|
| 입력란 앞에 키 문자열이 그대로 표시됨 | 키를 안내 문구 자리에 넣음 |
| API 키가 입력되지 않았습니다 오류 | 숨김 입력란이 비어 있음 |
| 오류 뒤에도 KIE API 키 설정 완료 출력 | 코드를 한 줄씩 붙여 넣어 마지막 Write-Host가 따로 실행됨 |
마지막 줄의 설정 완료 문구는 별도 출력문이 실행된 것일 뿐 실제 성공이 아니다. 키 문자열이 화면이나 채팅, 스크린샷에 한 번이라도 드러났다면 KIE에서 그 키를 폐기하고 새로 발급받는다.
해결은 두 번에 나눠 실행하는 것이다. 먼저 아래 한 줄만 실행한다. 따옴표 안 문구는 바꾸지 않는다.
$secureKey = Read-Host "여기에 새 KIE API 키를 붙여넣고 Enter" -AsSecureString
다음 입력란이 나타나면 콜론 뒤에 새 키를 붙여 넣고 Enter를 누른다. 키를 넣기 전에는 다음 코드를 붙여 넣지 않는다.
여기에 새 KIE API 키를 붙여넣고 Enter:
키 입력을 마친 뒤 아래 전체를 실행한다. 이번에는 값이 비어 있으면 오류로 멈추고, 입력과 저장이 모두 성공했을 때만 완료 문구가 나온다.
$keyPointer = [IntPtr]::Zero
try {
$keyPointer = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureKey)
$enteredKey = (
[Runtime.InteropServices.Marshal]::PtrToStringBSTR($keyPointer)
).Trim()
if ([string]::IsNullOrWhiteSpace($enteredKey)) {
throw "키가 비어 있습니다. 1단계에서 실제 키를 입력하세요."
}
$env:KIE_API_KEY = $enteredKey
[Environment]::SetEnvironmentVariable(
"KIE_API_KEY",
$enteredKey,
"User"
)
Write-Host "KIE API 키 입력 및 저장 완료"
}
finally {
if ($keyPointer -ne [IntPtr]::Zero) {
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($keyPointer)
}
if ($null -ne $secureKey) {
$secureKey.Dispose()
}
Remove-Variable enteredKey, secureKey -ErrorAction SilentlyContinue
}
마지막으로 키 값을 출력하지 않고 모델 목록을 조회해 실제 인증을 확인한다. 목록이 나오면 성공이고, 이어서 opencode를 실행하면 된다.
$headers = @{
Authorization = "Bearer $env:KIE_API_KEY"
}
Invoke-RestMethod `
-Uri "https://api.kie.ai/anthropic/v1/models" `
-Headers $headers `
-TimeoutSec 30 `
-ErrorAction Stop |
Select-Object -ExpandProperty data |
Select-Object id, display_name
- Read-Host 따옴표 안은 질문 문구 자리다.
- 키는 입력란이 뜬 뒤 콜론 뒤에 붙여 넣는다.
- 완료 문구보다 모델 목록 조회 성공이 실제 기준이다.
- 노출된 키는 즉시 폐기한다.
12. 다중 모델 동기화 스크립트 오류: 한글 깨짐과 변수 경계
Haiku 하나로 시작한 구성을 넓혀, KIE의 anthropic·openai·xai 모델 목록과 Gemini·GPT 계열 모델을 PowerShell 스크립트(Sync-KieModels.ps1)로 한꺼번에 받아 opencode.json에 등록하는 방식도 있다. 이 구성에서 자주 부딪히는 문제가 셋 있다. 스크립트 인코딩 오류, 실행할 때마다 느려지는 시작, 일부 모델의 두 번째 대화 실패다.
그림 11. 인코딩·변수 오류, 느린 시작, 2턴째 input.type 오류의 원인과 해결
첫 번째는 동기화 스크립트를 실행하거나 opencode를 입력했을 때 한글이 깨진 채 아래와 비슷한 오류가 나는 경우다.
| 화면에 보이는 것 | 의미 |
|---|---|
| 한글 안내 문구가 알아볼 수 없는 문자로 표시 | Windows PowerShell 5.1이 BOM 없는 UTF-8 파일을 다른 인코딩으로 읽음 |
| VariableIsUndefined | 변수 이름을 잘못 인식함 |
| '$geminiCount개 경로' 변수는 아직 설정되지 않았으므로 | $geminiCount 바로 뒤 한글까지 변수 이름으로 읽힘 |
원인은 두 가지가 겹친 것이다. Windows PowerShell 5.1은 BOM이 없는 UTF-8 스크립트를 시스템 기본 인코딩으로 읽어 한글이 깨지고, 문자열 안의 $geminiCount개처럼 변수 뒤에 글자가 붙으면 그 글자까지 변수 이름으로 해석한다. API 키나 KIE 연결과는 관계가 없고, 오류가 마지막 출력 줄에서 났다면 설정 저장은 이미 끝났을 수 있다.
아래 코드는 스크립트를 백업한 뒤, 변수 표기를 중괄호로 감싼 형태로 바꾸고 BOM이 있는 UTF-8로 다시 저장한다.
& {
$ErrorActionPreference = "Stop"
$path = "F:\000_Development\001_opencode\Sync-KieModels.ps1"
if (-not (Test-Path -LiteralPath $path)) {
throw "Sync-KieModels.ps1 not found."
}
$backup = $path + ".encoding-backup-" +
(Get-Date -Format "yyyyMMdd-HHmmss")
Copy-Item -LiteralPath $path -Destination $backup
# Read explicitly as UTF-8; existing BOMs are detected automatically.
$text = [System.IO.File]::ReadAllText(
$path,
[System.Text.Encoding]::UTF8
)
# Braces prevent adjacent text from becoming part of the variable name.
$text = $text.Replace(
'$geminiCount',
'${geminiCount}'
)
# Save as UTF-8 with BOM for Windows PowerShell compatibility.
[System.IO.File]::WriteAllText(
$path,
$text,
[System.Text.UTF8Encoding]::new($true)
)
Write-Host "Fixed: variable references and UTF-8 BOM."
Write-Host "Backup: $backup"
}
Fixed: variable references and UTF-8 BOM. 문구와 백업 경로가 나오면 성공이다. 이어서 opencode를 실행하고 /models에서 Gemini, DeepSeek 같은 이름으로 검색해 목록이 들어왔는지 본다.
- 한글이 들어간 .ps1 파일은 BOM 있는 UTF-8로 저장한다. PowerShell 7은 BOM 없는 UTF-8도 읽지만 5.1은 그렇지 않다.
- 문자열 안에서 변수 바로 뒤에 글자가 붙으면 ${변수} 형태로 감싼다.
- 이 오류 때문에 키를 다시 발급하거나 OpenCode를 재설치할 필요는 없다.
13. 시작이 느릴 때: -RefreshModels일 때만 갱신하는 런처
동기화 스크립트를 런처에 붙여 두면 opencode를 입력할 때마다 여러 모델 목록을 조회하느라 시작이 늦어진다. 모델 목록은 자주 바뀌지 않으므로 평소에는 저장된 목록으로 바로 띄우고, 필요할 때만 갱신하도록 나누는 편이 낫다.
| 명령어 | 동작 |
|---|---|
| opencode | 저장된 모델 목록으로 즉시 실행 |
| opencode -RefreshModels | KIE 모델 목록을 갱신한 뒤 실행 |
| OpenCode 내부 /models | 저장된 모델 중 선택 |
프로필을 열어 # BEGIN KIE OPENCODE LAUNCHER부터 # END KIE OPENCODE LAUNCHER까지의 블록만 아래 내용으로 바꾼다. 프로필에 있는 다른 함수는 그대로 둔다.
notepad $PROFILE.CurrentUserAllHosts
# BEGIN KIE OPENCODE LAUNCHER
function global:opencode {
$projectPath = "F:\000_Development\001_opencode"
$syncPath = Join-Path $projectPath "Sync-KieModels.ps1"
$configPath = Join-Path $projectPath "opencode.json"
# Remove the launcher's custom flag before forwarding arguments.
$refreshModels = $false
$forwardArgs = @()
foreach ($argument in $args) {
if ($argument -eq "-RefreshModels") {
$refreshModels = $true
}
else {
$forwardArgs += $argument
}
}
if (-not (Test-Path -LiteralPath $configPath)) {
throw "OpenCode config not found: $configPath"
}
$launcher = Get-Command `
opencode.cmd `
-CommandType Application `
-ErrorAction Stop
if ([string]::IsNullOrWhiteSpace($env:KIE_API_KEY)) {
$env:KIE_API_KEY = [Environment]::GetEnvironmentVariable(
"KIE_API_KEY", "User"
)
}
if ([string]::IsNullOrWhiteSpace($env:KIE_API_KEY)) {
throw "KIE_API_KEY is not configured."
}
# Refresh only when explicitly requested.
if ($refreshModels) {
if (-not (Test-Path -LiteralPath $syncPath)) {
throw "Model sync script not found: $syncPath"
}
try {
& $syncPath
}
catch {
Write-Error "KIE model refresh failed: $($_.Exception.Message)"
return
}
}
Set-Location -LiteralPath $projectPath
& $launcher.Source @forwardArgs
}
# END KIE OPENCODE LAUNCHER
저장한 뒤 현재 창에 적용한다.
. $PROFILE.CurrentUserAllHosts
- 런처 전용 옵션인 -RefreshModels는 OpenCode에 넘기기 전에 걸러지고, 나머지 인수는 그대로 전달된다.
- 이 런처는 --model을 강제로 붙이지 않으므로 opencode.json의 model 값으로 시작한다.
- 동기화 스크립트가 없어도 기본 실행은 되며, -RefreshModels를 붙였을 때만 스크립트 존재를 확인한다.
- 갱신에 실패하면 OpenCode를 띄우지 않고 오류만 보여 준다.
14. DeepSeek V4.1 Flash: 두 번째 대화부터 input.type 오류
동기화로 DeepSeek V4.1 Flash를 등록해 쓰면 첫 응답은 정상인데, 같은 대화에서 두 번째 질문을 보내는 순간 다음 오류가 날 수 있다.
| 항목 | 내용 |
|---|---|
| 오류 | Missing required parameter: input.type |
| 요청 주소 | POST https://api.kie.ai/openai/v1/responses |
| 모델 | deepseek-v4-1-flash |
| 첫 번째 요청 | 정상 응답 |
| 두 번째 요청부터 | 위 오류로 실패 |
첫 요청에는 사용자 질문만 들어가지만, 두 번째부터는 이전 질문과 답변, 추론·도구 기록까지 대화 이력이 함께 전송된다. 그 이력 가운데 어느 항목이 KIE 쪽 입력 검증에 걸리는지는 실제 요청 본문을 봐야 알 수 있다.
KIE의 DeepSeek V4.1 Flash 문서에는 두 가지가 명시돼 있다. 하나는 이 모델이 현재 채팅 요청만 지원하고 에이전트용으로는 아직 적응되지 않아, 에이전트에 연결하면 요청 오류나 예상치 못한 결과가 생길 수 있다는 경고(Chat only)다. 다른 하나는 입력 배열의 message 객체에서 type을 생략할 수 있고, 생략하면 message로 처리된다는 설명이다. 문서상 생략 가능한 값이 필수라고 거절되는 셈이라, KIE에 문의할 때 근거로 쓸 수 있다.
| 해 볼 만한 것 | 효과 |
|---|---|
| 재설치·키 교체 | 해결책 아님 |
| opencode.json에 type 값 추가 | 해결되는 문제 아님 |
| 같은 요청 반복 재시도 | 같은 오류 반복 |
| Esc로 중단 후 검증된 모델로 전환 | 작업 계속 가능 |
대응 순서는 다음과 같다.
- 오류가 반복되면 Esc로 요청을 멈춘다.
- /models에서 정상 동작이 확인된 KIE Haiku를 고른다.
- 새 대화에서 두 번 연속 질문하는 테스트를 한다.
내 이름은 테스트야. 기억했다고만 답해줘.
내 이름이 뭐라고 했지?
- Haiku는 두 번째 답이 정상인데 DeepSeek만 실패하면 해당 모델 경로의 문제다. Haiku도 두 번째에서 실패하면 DeepSeek만의 문제가 아니므로 설정과 로그부터 다시 본다.
- KIE 로그 화면에서 실패한 요청의 시간과 요청 ID를 찾아 지원 문의에 붙인다.
문의 내용은 아래 틀을 쓰면 된다. API 키는 어떤 경우에도 보내지 않는다.
[KIE 지원 문의]
엔드포인트: POST https://api.kie.ai/openai/v1/responses
모델: deepseek-v4-1-flash
클라이언트: OpenCode CLI
증상: 첫 요청은 정상, 같은 대화의 두 번째 요청부터 "Missing required parameter: input.type" 오류
문서 근거: 모델 문서에 message 객체의 type은 생략 가능하며 기본값이 message라고 되어 있음
요청 시간·요청 ID: (KIE 로그에서 확인한 값)
※ API 키는 첨부하지 않습니다.
모델이 /models 목록에 보인다고 해서 연속 대화나 파일 수정 같은 에이전트 작업까지 된다는 뜻은 아니다. 새 모델은 실제 작업에 쓰기 전에 두 번 연속 질문과 간단한 도구 사용부터 시험해 보는 편이 안전하다.
15. 오류 코드별 해결 (401·404·503)
증상별로 먼저 볼 곳을 정리하면 다음과 같다.
| 증상 | 먼저 확인할 것 | 해결 방향 |
|---|---|---|
| node를 찾을 수 없음 | Node.js 설치·PATH | LTS 설치 후 터미널 재시작 |
| opencode.cmd를 찾을 수 없음 | npm 전역 경로 | 설치 경로·중복 설치 확인 |
| 설정 항목 오류 | 프로그램 버전 | 1.18.25인지 확인 |
| JSON 오류 | 따옴표·쉼표·괄호 | 문법 검사 |
| 모델이 안 보임 | 설정 파일 위치 | 지정 폴더에서 실행 |
| 401 | 키·인증 설정 | 모델 목록 API 직접 검사 |
| 404 | 기본 주소 | /anthropic/v1 확인 |
| 400 | 요청 옵션·본문 | 오류 내용에 나온 필드 확인 |
| 429 | 호출 빈도·한도 | KIE 한도 확인 후 대기 |
| 503 | 개별 요청 실패 | 단순 API와 비교하고 로그 확인 |
| 계속 대기 | 재시도·연결·패키지 준비 | 중단 후 디버그 로그 확인 |
| 파일 수정이 안 됨 | 권한 승인 | 승인 요청·도구 오류 확인 |
| 새 창에서 인증 실패 | 환경변수 상속 | 저장 확인 후 터미널 전체 재시작 |
그림 12. 401·404·503과 400·429에서 먼저 확인할 곳
15.1. 401 인증 오류
- 키가 비어 있는지 확인한다. False면 값이 있고, True면 키를 다시 입력해야 한다.
[string]::IsNullOrWhiteSpace($env:KIE_API_KEY)
- 모델 목록을 직접 조회한다.
$headers = @{
Authorization = "Bearer $env:KIE_API_KEY"
}
Invoke-RestMethod `
-Uri "https://api.kie.ai/anthropic/v1/models" `
-Headers $headers `
-TimeoutSec 30 `
-ErrorAction Stop |
Select-Object -ExpandProperty data |
Select-Object id, display_name
- 직접 조회도 실패하면 키·인증 문제부터 풀고, 직접 조회는 되는데 OpenCode만 실패하면 버전·설정·환경변수 전달을 본다. 설정 파일의 인증 항목은 다음이어야 한다.
"authToken": "{env:KIE_API_KEY}"
15.2. 404 주소 오류
정상 기본 주소는 다음 하나다.
https://api.kie.ai/anthropic/v1
- 기본 주소에 /messages를 중복으로 넣지 않았는지 본다.
- /v1이 빠지지 않았는지 본다.
- 문서 URL이나 .md 주소를 넣지 않았는지 본다.
- Anthropic Messages가 아닌 다른 형식의 경로를 쓰지 않았는지 본다.
HTML 모양의 404 페이지가 나오면 API가 아니라 웹페이지 주소를 호출했을 가능성이 크다.
15.3. 503과 장시간 대기
- 반복 재시도 중이면 Ctrl+C로 멈춘다. 503 하나만으로 키 오류나 전체 서비스 장애라고 단정하지 않는다.
- 단순 메시지 API를 직접 호출해 본다. 실제 생성 요청이라 크레딧이 조금 쓰일 수 있다.
$headers = @{
Authorization = "Bearer $env:KIE_API_KEY"
"anthropic-version" = "2023-06-01"
}
$body = @{
model = "claude-haiku-5-5"
max_tokens = 64
stream = $false
messages = @(
@{
role = "user"
content = "Reply with OK only."
}
)
} | ConvertTo-Json -Depth 6
$result = Invoke-RestMethod `
-Method Post `
-Uri "https://api.kie.ai/anthropic/v1/messages" `
-Headers $headers `
-ContentType "application/json" `
-Body $body `
-TimeoutSec 90 `
-ErrorAction Stop
$result.content | Select-Object type, text
| 결과 | 해석 |
|---|---|
| OK | 단순 생성 요청은 정상 |
| 여기서도 503 | OpenCode 없이도 해당 요청이 실패 |
| 401 | 키·인증 재확인 |
| 타임아웃 | 네트워크·서비스 상태 확인 |
직접 API는 성공하고 OpenCode만 실패하면 로그로 요청 차이를 봐야 한다. 재설치나 키 재발급부터 반복하지 않는다.
16. 로그 확인과 설정 병합 위치
디버그 모드로 실행해 문제를 한 번 재현한 뒤 종료한다.
Set-Location "F:\000_Development\001_opencode"
opencode.cmd --log-level DEBUG --model "kie/claude-haiku-5-5"
기본 로그 폴더는 다음과 같다.
%USERPROFILE%\.local\share\opencode\log
가장 최근 로그의 끝부분 100줄을 보려면 PowerShell에서 실행한다.
$logDir = Join-Path $HOME ".local\share\opencode\log"
if (Test-Path $logDir) {
$latestLog = Get-ChildItem $logDir -File |
Sort-Object LastWriteTime -Descending |
Select-Object -First 1
if ($null -ne $latestLog) {
Write-Host "최신 로그:" $latestLog.FullName
Get-Content $latestLog.FullName -Tail 100
}
else {
Write-Host "로그 파일이 없습니다."
}
}
else {
Write-Host "로그 폴더가 없습니다."
}
로그에는 인증 정보, 프롬프트, 파일 경로가 들어갈 수 있다. 공유할 때는 키와 토큰을 가리고 오류 주변만 보낸다.
설정을 고쳤는데 반영되지 않으면 다른 위치의 설정이 함께 적용되고 있는지 본다.
사용자 설정:
%USERPROFILE%\.config\opencode\opencode.json
%USERPROFILE%\.config\opencode\opencode.jsonc
프로젝트 설정:
F:\000_Development\001_opencode\opencode.json
F:\000_Development\001_opencode\opencode.jsonc
추가 설정:
F:\000_Development\001_opencode\.opencode
OpenCode는 여러 설정을 덮어쓰지 않고 합쳐서 적용한다. 공식 문서 기준으로 원격 설정, 사용자 전역 설정, OPENCODE_CONFIG 환경변수로 지정한 파일, 프로젝트 opencode.json, .opencode 폴더, 인라인 설정, 관리자 설정 순서로 읽고 뒤에 오는 값이 앞의 값을 덮는다.
| 위치 | 확인할 것 |
|---|---|
| 사용자 전역 설정 | 다른 provider·model·autoupdate 값 |
| 프로젝트 opencode.json | 이 문서의 설정 |
| .opencode 폴더 | 추가 에이전트·명령 설정 |
| 실행 위치 | 작업 폴더에서 실행했는지 |
- 설정 파일을 통째로 지우지 않는다.
- 고치기 전에 기존 파일을 백업한다.
- 모델·제공자·API 주소처럼 충돌하는 항목부터 본다.
17. 키 보관 방식과 키 교체
개인 PC에서 opencode만 입력해 바로 쓰는 용도라면 지금의 사용자 환경변수 방식이 낫다. 프로젝트 .env.local로 바꿀 필요는 없다.
| 항목 | Windows 사용자 환경변수 | 프로젝트 .env.local |
|---|---|---|
| 적용 범위 | 같은 사용자로 실행하는 프로그램에 전달될 수 있음 | 직접 읽어 들인 프로그램·프로세스 |
| 여러 프로젝트 사용 | 편리함 | 프로젝트마다 관리 필요 |
| 프로젝트별 키 분리 | 별도 처리 필요 | 편리함 |
| Git에 키가 올라갈 위험 | 프로젝트 파일에 없으므로 낮음 | .gitignore 누락 시 유출 가능 |
| 저장 방식 | 암호화된 비밀 금고는 아님 | 일반 텍스트 파일 |
| OpenCode 적용 | 이 구성에서 동작 | 자동 로딩 보장 안 됨, 별도 로더 필요 |
| 추천 상황 | 개인 PC에서 같은 키로 계속 사용 | 프로젝트·고객사별로 키 분리 |
.env.local은 이름만으로 자동 적용되지 않는다. 설정 파일의 다음 항목은 OpenCode 프로세스에 전달된 환경변수를 읽는다는 뜻이지, .env.local 파일을 읽으라는 뜻이 아니다.
"authToken": "{env:KIE_API_KEY}"
이 구성은 다음처럼 유지한다.
Windows 사용자 환경변수
└─ KIE_API_KEY = 실제 키
프로젝트의 opencode.json
└─ authToken = {env:KIE_API_KEY}
PowerShell
└─ opencode 입력 → KIE 연결 실행
.env.local 방식이 나은 경우는 따로 있다.
- 프로젝트마다 다른 KIE 키를 써야 할 때
- 고객사별 사용량·과금을 나눌 때
- 개발용과 운영용 키를 구분할 때
- 키를 OpenCode 실행 때만 읽어 들이도록 관리하려 할 때
이때는 명시적인 파일 로딩 절차와 Git 제외 설정을 함께 만들고, 기존 사용자 환경변수도 정리해야 어느 키가 적용됐는지 헷갈리지 않는다.
그림 13. 사용자 환경변수와 .env.local 비교, 키 교체 4단계
키를 바꿀 때는 현재 PowerShell과 사용자 환경변수를 함께 갱신한다. opencode.json은 손대지 않는다.
| 변경 대상 | 처리 |
|---|---|
| 현재 PowerShell의 키 | 즉시 변경 |
| Windows 사용자 환경변수 | 새 창에서도 새 키 사용 |
| opencode.json | 변경 불필요 |
| 실행 중인 OpenCode | 종료 후 다시 실행 |
- 실행 중인 OpenCode를 종료한다.
/exit
- 아래 전체를 PowerShell에 실행한다. 입력 안내가 뜨면 새 키 자체만 붙여 넣는다. 새 키로 모델 목록 조회가 성공한 뒤에만 저장하고, 키 값은 출력하지 않는다.
& {
$secureKey = Read-Host "새 KIE API 키를 붙여넣고 Enter" -AsSecureString
$keyPointer = [IntPtr]::Zero
try {
$keyPointer = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureKey)
$newKey = (
[Runtime.InteropServices.Marshal]::PtrToStringBSTR($keyPointer)
).Trim()
if ([string]::IsNullOrWhiteSpace($newKey)) {
throw "키가 비어 있습니다. 기존 설정은 변경하지 않았습니다."
}
# 저장 전에 새 키의 인증 확인
$headers = @{
Authorization = "Bearer $newKey"
}
$null = Invoke-RestMethod `
-Uri "https://api.kie.ai/anthropic/v1/models" `
-Headers $headers `
-TimeoutSec 30 `
-ErrorAction Stop
# 인증 성공 후 저장
[Environment]::SetEnvironmentVariable(
"KIE_API_KEY",
$newKey,
"User"
)
$env:KIE_API_KEY = $newKey
Write-Host "새 키 인증 성공. 현재 창과 사용자 환경변수 변경 완료."
}
catch {
Write-Host "키 변경을 완료하지 못했습니다." -ForegroundColor Red
Write-Host "새 키와 네트워크 상태를 확인한 뒤 다시 시도하세요."
}
finally {
if ($keyPointer -ne [IntPtr]::Zero) {
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($keyPointer)
}
if ($null -ne $secureKey) {
$secureKey.Dispose()
}
}
}
- 같은 창에서 opencode를 실행하고 OK 응답을 확인한다.
파일이나 명령을 실행하지 말고 OK라고만 답해줘.
- 이미 열려 있던 다른 PowerShell·터미널은 이전 키를 쥐고 있을 수 있다. 완전히 닫았다 열거나, 그 창에서 새 값을 읽어 온다.
$env:KIE_API_KEY = [Environment]::GetEnvironmentVariable("KIE_API_KEY", "User")
- KIE API 키 관리 페이지에서 이전 키를 폐기한다. 정기 교체라면 새 키 동작 확인 뒤에, 유출된 키라면 즉시 폐기한다.
18. 기본 모델 바꾸기
모델은 지금 대화에서만 바꾸는 방법과 기본값을 바꾸는 방법이 있다.
| 목적 | 방법 |
|---|---|
| 지금 대화에서 다른 모델 사용 | OpenCode에서 /models |
| 앞으로 기본으로 쓸 모델 변경 | opencode.json 수정 |
| 등록하지 않은 새 모델 사용 | 설정에 모델을 먼저 추가 |
| API 키 변경 | 모델만 바꿀 때는 불필요 |
앞에서 등록한 프로필 함수에는 Haiku를 강제로 지정하는 줄이 있다.
& $launcherCommand.Source --model "kie/claude-haiku-5-5" @args
이 상태에서는 설정 파일의 기본 모델을 바꿔도 시작할 때 Haiku가 지정된다. 앞에서 소개한 -RefreshModels 런처로 이미 바꿨다면 강제 지정이 없으므로 이 단계는 건너뛴다. 처음 등록한 함수를 그대로 쓰고 있다면 프로필을 열어 그 줄을 아래처럼 바꾸고 다른 코드는 그대로 둔다.
notepad $PROFILE.CurrentUserAllHosts
& $launcherCommand.Source @args
그다음 모델 목록에서 실제 ID를 확인하고 provider → kie → models 부분에 추가한다. 예를 들어 목록에 claude-sonnet-5-5가 있다면 다음과 같이 쓴다. 파일 전체가 아니라 models 부분만 바꾼다.
"models": {
"claude-haiku-5-5": {
"name": "KIE Haiku 5.5"
},
"claude-sonnet-5-5": {
"name": "KIE Sonnet 5.5"
}
}
기본 모델을 바꾸려면 상단 model 값을 바꾼다. small_model은 제목 생성 같은 보조 작업용이라 Haiku로 두면 비용을 아낄 수 있다.
"model": "kie/claude-sonnet-5-5",
"small_model": "kie/claude-haiku-5-5",
- 저장 후 JSON 문법 검사를 다시 돌린다.
- OpenCode를 종료하고 다시 실행해야 반영된다.
- 모델 이름 선택 명령은 /model이 아니라 /models다.
19. KIE로 쓸 작업장 고르기
KIE 모델을 어디서 쓸지는 하려는 일에 따라 갈린다. KIE 에이전트 연결 문서는 에이전트와 모델이 같은 프로토콜을 쓸 때 별도 변환 없이 연결된다고 설명하며, 현재 정리된 에이전트는 Codex CLI, Claude Code, Grok Build다. 오래된 일부 모델은 채팅 요청만 지원해 Market 모델 페이지에 Chat only로 표시되고, 에이전트 기능에는 각 계열의 최신 모델을 쓰라고 권한다.
| 원하는 작업 | 현실적인 선택 | 근거 |
|---|---|---|
| KIE 모델로 일반 대화·코드 질문 | KIE 웹 Chat Playground | KIE가 직접 제공 |
| 내 PC 파일 수정·명령 실행 | Codex CLI + GPT 계열(OpenAI Responses) | KIE 에이전트 연결 문서에 설정 안내 있음 |
| Gemini·DeepSeek까지 한 코딩 작업장에서 | 공식 지원 조합 없음 | Chat only 모델은 에이전트 연결 시 오류 가능 경고 |
| OpenCode + KIE DeepSeek | 실사용 비권장 | 두 번째 요청부터 input.type 오류 |
| OpenCode + KIE Claude Haiku | 이 문서의 구성 | anthropic 엔드포인트로 대화·파일 작업 정상 |
KIE 문서 기준으로 프로토콜과 기본 주소는 이렇게 짝을 이룬다.
| 에이전트 | 프로토콜 | 기본 주소 |
|---|---|---|
| Claude Code | Anthropic Messages | https://api.kie.ai/anthropic |
| Codex CLI | OpenAI Responses | https://api.kie.ai/openai/v1 |
| Grok Build | Responses | https://api.kie.ai/xai/v1 |
| OpenCode(이 문서) | Anthropic Messages(AI SDK) | https://api.kie.ai/anthropic/v1 |
- 일반 대화와 모델 비교는 KIE Playground가 가장 간단하다. Playground 사용에도 크레딧이 들 수 있다.
- 파일을 고치는 코딩 작업장은 KIE가 에이전트 지원을 밝힌 모델로 좁힌다.
- 공식 경로가 있는 조합이라도 환경에 따라 실패할 수 있으니, 새 조합은 설치 직후 두 번 연속 대화와 도구 호출부터 시험한다.
- OpenCode는 KIE 문서의 에이전트 목록에 아직 없으므로, 검증된 OpenCode + KIE Haiku 조합을 기본으로 두고 다른 모델은 보조로 쓴다.
20. 최종 체크리스트
| 확인 항목 | 기준 |
|---|---|
| Node.js·npm | 버전이 표시됨 |
| OpenCode | 1.18.25 |
| 작업 폴더 | F:\000Development\001opencode |
| KIEAPIKEY | 설정되어 있음 |
| 모델 목록 | Haiku 모델 확인 |
| opencode.json | 실제 키 없음 |
| 선택 모델 | kie/claude-haiku-5-5 |
| 대화 테스트 | 성공 |
| 파일 읽기 | 성공 |
| 승인 후 파일 생성 | 성공 |
| 생성 파일 다시 읽기 | 성공 |
| KIE 로그 | 요청 기록 있음 |
| 새 PowerShell | 정상 실행 |
- 업데이트 안내 창은 Skip으로 넘긴다.
- 키는 채팅·스크린샷·설정 파일에 남기지 않는다.
- 문제가 생기면 직접 API 호출 결과와 OpenCode 결과를 비교하는 것부터 시작한다.
21. 출처
- OpenCode 설정 문서: https://opencode.ai/docs/config/
- OpenCode 문제 해결 문서: https://opencode.ai/docs/troubleshooting/
- OpenCode CLI 문서: https://opencode.ai/docs/cli/
- npm opencode-ai 패키지: https://www.npmjs.com/package/opencode-ai
- AI SDK Anthropic 제공자: https://ai-sdk.dev/providers/ai-sdk-providers/anthropic
- KIE Claude Code 연결 문서: https://docs.kie.ai/ai-agent/claude-code
- KIE 에이전트 연결 문서: https://docs.kie.ai/ai-agent/install-kie-chat-agents
- KIE DeepSeek V4.1 Flash 문서: https://docs.kie.ai/market/deepseek-v4-1-flash
- KIE Chat Playground: https://kie.ai/market/chat
22. 마무리
앞에서 다룬 KIE와 OpenCode 연결의 핵심만 짧게 정리한다.
- 버전은 1.18.25로 고정하고, TUI 업데이트 안내 창에서는 Skip을 고른다
- 기본 주소는 https://api.kie.ai/anthropic/v1, 인증은 authToken에 {env:KIEAPIKEY}
- 키는 Read-Host 숨김 입력으로 받고, 성공 기준은 완료 문구가 아니라 모델 목록 조회다
- 대화, 읽기, 생성, 다시 읽기까지 확인한 뒤에 키를 사용자 환경변수에 저장한다
- 프로필 런처로 opencode 한 단어 실행을 만들고, 모델 목록 갱신은 -RefreshModels일 때만, 한글이 든 .ps1은 BOM 있는 UTF-8로 저장한다
- 목록에 보이는 모델도 Chat only면 에이전트 작업에 쓰지 않으며, 검증된 조합은 OpenCode + KIE Haiku다
- 노출된 키는 즉시 폐기하며, 요금·모델 목록은 KIE 계정 화면이 최신이다
「설정 파일에는 참조만, 키는 환경변수에만, 주소는 /anthropic/v1에서 끝낸다.」 오류가 나면 재설치보다 모델 목록과 메시지 API를 직접 호출해 OpenCode 결과와 비교하는 것이 가장 빠른 길이다.
자주 묻는 질문
- OpenCode를 최신 버전이 아니라 1.18.25로 설치하는 이유는 무엇인가요?
OpenCode는 업데이트가 잦고 버전마다 설정 형식과 인증 동작이 달라질 수 있습니다. KIE 연결이 정상 동작한 1.18.25에 맞춰 설정을 쓰면 문제가 생겼을 때 원인을 좁히기 쉽습니다. 10월 17일 현재 npm 최신은 1.19.3입니다.
- autoupdate를 false로 했는데 업데이트 창이 뜨는 건 왜 그런가요?
공식 문서는 autoupdate false가 자동 다운로드를 끈다고 설명하지만, TUI 첫 실행 때 새 버전 안내 창이 뜰 수 있습니다. 이때 Confirm을 누르면 바로 업데이트되므로 Skip을 고르고, 이미 올라갔다면 opencode.cmd --version으로 확인한 뒤 1.18.25 설치 명령을 다시 실행합니다.
- baseURL은 /anthropic와 /anthropic/v1 중 무엇이 맞나요?
OpenCode가 쓰는 AI SDK의 Anthropic 제공자는 기본 주소 뒤에 /messages만 붙이므로 https://api.kie.ai/anthropic/v1 이 맞습니다. KIE 문서의 Claude Code 예시가 /anthropic까지만 쓰는 것은 Claude Code가 /v1/messages를 직접 붙이기 때문입니다.
- authToken 대신 apiKey를 쓰면 안 되나요?
AI SDK에서 apiKey는 x-api-key 헤더로, authToken은 Authorization: Bearer 헤더로 전송됩니다. KIE는 Bearer 방식으로 인증하므로 authToken에 {env:KIEAPIKEY}를 넣고, 값 앞에 Bearer를 직접 붙이지 않습니다.
- npm 설치 중 install-scripts 경고가 나오면 어떻게 하나요?
최근 npm은 허용 목록에 없는 패키지의 설치 스크립트를 바로 실행하지 않고 경고를 남깁니다. opencode.cmd --version에서 1.18.25가 나오면 그대로 진행해도 되고, 버전 확인이 실패하면 경고에 나온 --allow-scripts=opencode-ai 옵션으로 다시 설치합니다.
- API 키를 입력했는데 키가 입력되지 않았다는 오류와 설정 완료 문구가 같이 나왔습니다.
Read-Host 따옴표 안 안내 문구 자리에 키를 넣고 입력란은 비워 둔 경우입니다. 마지막 설정 완료 문구는 따로 실행된 출력문이라 성공이 아닙니다. 노출된 키는 KIE에서 폐기하고, Read-Host 한 줄을 먼저 실행해 입력란에 새 키를 넣은 뒤 나머지 코드를 실행합니다.
- 401 오류가 나면 무엇부터 확인하나요?
먼저 IsNullOrWhiteSpace로 KIEAPIKEY가 비어 있는지 보고, 모델 목록 API를 직접 조회합니다. 직접 조회도 실패하면 키 문제이고, 직접 조회는 되는데 OpenCode만 실패하면 버전, 설정의 authToken 항목, 환경변수 전달을 확인합니다.
- 503이 계속 나오면 키를 다시 발급받아야 하나요?
503 하나만으로 키 오류라고 단정하지 않습니다. Ctrl+C로 재시도를 멈추고 messages API에 짧은 요청을 직접 보내 봅니다. 직접 요청이 성공하고 OpenCode만 실패하면 --log-level DEBUG로 실행해 로그에서 요청 차이를 찾는 것이 먼저입니다.
- .env.local에 키를 넣으면 OpenCode가 자동으로 읽나요?
자동 로딩은 보장되지 않습니다. 설정의 {env:KIEAPIKEY}는 OpenCode 프로세스에 전달된 환경변수를 읽는다는 뜻입니다. 개인 PC에서 같은 키를 계속 쓴다면 Windows 사용자 환경변수 방식이 편하고, 프로젝트별로 키를 나눌 때만 별도 로더와 Git 제외 설정을 함께 만듭니다.
- KIE API 키를 바꿀 때 opencode.json도 수정해야 하나요?
수정할 필요가 없습니다. OpenCode를 /exit로 종료하고, 새 키로 모델 목록 조회가 성공했을 때만 사용자 환경변수와 현재 창을 갱신하는 코드를 실행합니다. 이미 열려 있던 다른 터미널은 새 값을 다시 읽어 오고, 마지막에 KIE에서 이전 키를 폐기합니다.
- Sync-KieModels.ps1 실행 중 한글이 깨지고 VariableIsUndefined 오류가 납니다.
Windows PowerShell 5.1이 BOM 없는 UTF-8 스크립트를 다른 인코딩으로 읽고, $geminiCount 뒤에 붙은 한글까지 변수 이름으로 해석해서 생기는 오류입니다. 변수를 ${geminiCount}로 감싸고 파일을 BOM 있는 UTF-8로 다시 저장하면 해결되며, 키나 KIE 연결과는 관계가 없습니다.
- opencode를 입력할 때마다 시작이 느린데 줄일 수 있나요?
런처가 실행할 때마다 모델 목록을 동기화하면 느려집니다. 런처 블록을 교체해 평소에는 저장된 목록으로 바로 실행하고, opencode -RefreshModels를 입력했을 때만 KIE 모델 목록을 갱신하도록 바꾸면 됩니다. 새 런처는 --model을 강제하지 않아 opencode.json의 기본 모델을 따릅니다.
- DeepSeek V4.1 Flash에서 두 번째 질문부터 Missing required parameter: input.type 오류가 납니다.
KIE 문서는 이 모델을 채팅 전용(Chat only)으로 표시하고 에이전트 연결 시 오류가 날 수 있다고 경고합니다. 재설치나 키 교체로는 풀리지 않으니 Esc로 멈추고 /models에서 KIE Haiku로 바꾼 뒤, 필요하면 KIE 로그의 요청 시간·ID를 붙여 지원 문의를 넣습니다.
- KIE 모델로 코딩 작업을 하려면 어떤 도구 조합이 안정적인가요?
일반 대화는 KIE 웹 Playground가 간단하고, 파일 수정까지 하는 작업장은 KIE가 에이전트 연결을 안내하는 Codex CLI·Claude Code·Grok Build나 이 문서의 OpenCode + KIE Claude Haiku 조합으로 좁히는 편이 안전합니다. Chat only로 표시된 모델은 에이전트용으로 쓰지 않습니다.
- opencode만 입력하면 바로 KIE 모델로 실행되게 하려면 어떻게 하나요?
PowerShell 사용자 프로필(CurrentUserAllHosts)에 opencode 함수를 등록합니다. 함수가 저장된 키를 확인하고 작업 폴더로 이동한 뒤 opencode.cmd를 KIE Haiku 모델로 실행합니다. Windows PowerShell 5.1과 PowerShell 7은 프로필 위치가 달라 각각 등록해야 합니다.
- opencode.json에서 기본 모델을 바꿨는데 계속 Haiku로 시작합니다.
프로필 함수 안에 --model로 Haiku를 강제 지정하는 줄이 있기 때문입니다. 그 줄을 & $launcherCommand.Source @args로 바꾸고 프로필을 다시 적용하면 opencode.json의 model 값을 따릅니다. 새 모델은 models 항목에 먼저 등록해야 /models에 나타납니다.
바이브 코딩