relayax-cli 0.3.41 → 0.3.43
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/dist/commands/access.js +12 -12
- package/dist/commands/changelog.js +2 -2
- package/dist/commands/check-update.js +12 -12
- package/dist/commands/create.js +46 -19
- package/dist/commands/deploy-record.js +2 -2
- package/dist/commands/diff.js +2 -2
- package/dist/commands/grant.d.ts +33 -0
- package/dist/commands/grant.js +190 -0
- package/dist/commands/init.js +13 -15
- package/dist/commands/install.js +69 -68
- package/dist/commands/join.js +3 -3
- package/dist/commands/list.js +15 -15
- package/dist/commands/login.js +10 -3
- package/dist/commands/orgs.js +1 -1
- package/dist/commands/outdated.js +7 -7
- package/dist/commands/package.d.ts +18 -0
- package/dist/commands/package.js +355 -146
- package/dist/commands/ping.js +5 -5
- package/dist/commands/publish.d.ts +1 -1
- package/dist/commands/publish.js +56 -48
- package/dist/commands/search.js +2 -2
- package/dist/commands/status.js +11 -11
- package/dist/commands/uninstall.js +27 -9
- package/dist/commands/update.js +22 -22
- package/dist/commands/versions.js +2 -2
- package/dist/index.js +2 -0
- package/dist/lib/ai-tools.d.ts +15 -0
- package/dist/lib/ai-tools.js +48 -1
- package/dist/lib/api.d.ts +7 -7
- package/dist/lib/api.js +11 -11
- package/dist/lib/command-adapter.d.ts +4 -3
- package/dist/lib/command-adapter.js +37 -688
- package/dist/lib/config.d.ts +1 -1
- package/dist/lib/config.js +2 -2
- package/dist/lib/guide.js +34 -79
- package/dist/lib/installer.d.ts +2 -2
- package/dist/lib/installer.js +4 -4
- package/dist/lib/preamble.d.ts +4 -4
- package/dist/lib/preamble.js +14 -14
- package/dist/lib/slug.d.ts +5 -0
- package/dist/lib/slug.js +49 -2
- package/dist/lib/update-cache.js +4 -4
- package/dist/lib/version-check.d.ts +3 -3
- package/dist/lib/version-check.js +13 -13
- package/dist/prompts/_business-card.md +41 -0
- package/dist/prompts/_error-handling.md +38 -0
- package/dist/prompts/_requirements-check.md +59 -0
- package/dist/prompts/_setup-cli.md +19 -0
- package/dist/prompts/_setup-login.md +7 -0
- package/dist/prompts/_setup-org.md +27 -0
- package/dist/prompts/business-card.md +41 -0
- package/dist/prompts/error-handling.md +38 -0
- package/dist/prompts/index.d.ts +7 -0
- package/dist/prompts/index.js +28 -0
- package/dist/prompts/install.md +191 -0
- package/dist/prompts/publish.md +448 -0
- package/dist/prompts/requirements-check.md +59 -0
- package/dist/types.d.ts +9 -9
- package/package.json +3 -3
|
@@ -12,6 +12,7 @@ exports.getGlobalCommandPathForTool = getGlobalCommandPathForTool;
|
|
|
12
12
|
exports.formatCommandFile = formatCommandFile;
|
|
13
13
|
const os_1 = __importDefault(require("os"));
|
|
14
14
|
const path_1 = __importDefault(require("path"));
|
|
15
|
+
const index_js_1 = require("../prompts/index.js");
|
|
15
16
|
/**
|
|
16
17
|
* 로컬 어댑터 — 프로젝트 디렉토리 기준.
|
|
17
18
|
* {projectPath}/{skillsDir}/commands/relay/{id}.md
|
|
@@ -26,17 +27,18 @@ function createAdapter(tool) {
|
|
|
26
27
|
};
|
|
27
28
|
}
|
|
28
29
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
30
|
+
* @deprecated getGlobalCommandPathForTool(skillsDir, commandId)를 사용하세요.
|
|
31
|
+
* Claude Code 전용 경로. 멀티 에이전트 지원 시 ForTool 버전 사용 필요.
|
|
31
32
|
*/
|
|
32
33
|
function getGlobalCommandPath(commandId) {
|
|
33
|
-
return
|
|
34
|
+
return getGlobalCommandPathForTool('.claude', commandId);
|
|
34
35
|
}
|
|
35
36
|
/**
|
|
36
|
-
*
|
|
37
|
+
* @deprecated getGlobalCommandDirForTool(skillsDir)를 사용하세요.
|
|
38
|
+
* Claude Code 전용 경로. 멀티 에이전트 지원 시 ForTool 버전 사용 필요.
|
|
37
39
|
*/
|
|
38
40
|
function getGlobalCommandDir() {
|
|
39
|
-
return
|
|
41
|
+
return getGlobalCommandDirForTool('.claude');
|
|
40
42
|
}
|
|
41
43
|
/**
|
|
42
44
|
* 특정 AI 도구의 글로벌 커맨드 디렉토리.
|
|
@@ -57,348 +59,23 @@ function getGlobalCommandPathForTool(skillsDir, commandId) {
|
|
|
57
59
|
function formatCommandFile(content) {
|
|
58
60
|
return `---\ndescription: ${content.description}\n---\n\n${content.body}\n`;
|
|
59
61
|
}
|
|
60
|
-
// ───
|
|
61
|
-
|
|
62
|
-
### 에러 처리 가이드
|
|
63
|
-
|
|
64
|
-
CLI 명령 실행 후 JSON 에러가 반환되면 아래 기준에 따라 처리합니다.
|
|
65
|
-
**원칙: "되돌릴 수 없는 영향이 있는가?"로 판단합니다.**
|
|
66
|
-
|
|
67
|
-
#### 1. 자동 해결 (사용자에게 물어보지 않음)
|
|
68
|
-
되돌릴 수 있고, 부작용 없는 에러:
|
|
69
|
-
|
|
70
|
-
| 에러 코드 | 행동 |
|
|
71
|
-
|-----------|------|
|
|
72
|
-
| \`LOGIN_REQUIRED\` / \`NO_TOKEN\` | \`relay login\` 실행 (timeout 300초, 브라우저 자동 열림) → 성공 후 원래 명령 재시도 |
|
|
73
|
-
| \`NOT_INITIALIZED\` | \`relay init --all --json\` 실행 → 원래 명령 재시도 |
|
|
74
|
-
| \`FETCH_FAILED\` | 3초 대기 후 원래 명령 재시도 (최대 2회). 2회 실패 시 사용자에게 안내 |
|
|
75
|
-
|
|
76
|
-
#### 2. 사용자에게 선택지 제시 (AskUserQuestion)
|
|
77
|
-
\`options\` 필드가 있는 에러:
|
|
78
|
-
|
|
79
|
-
| 에러 코드 | 행동 |
|
|
80
|
-
|-----------|------|
|
|
81
|
-
| \`MISSING_VISIBILITY\` | options의 label을 선택지로 AskUserQuestion 호출 |
|
|
82
|
-
| \`MISSING_FIELD\` | fix 안내 + 사용자에게 값 입력 요청 |
|
|
83
|
-
| \`MISSING_TOOLS\` | options의 감지된 도구 목록을 선택지로 AskUserQuestion 호출 |
|
|
84
|
-
| \`MISSING_SPACE\` | options의 Space 목록을 선택지로 AskUserQuestion 호출 |
|
|
85
|
-
|
|
86
|
-
사용자가 선택하면, 선택된 값을 CLI 플래그에 반영하여 명령을 재호출합니다.
|
|
87
|
-
|
|
88
|
-
#### 3. 사용자에게 안내 (되돌릴 수 없는 에러)
|
|
89
|
-
구매, 접근 권한, 보안 관련:
|
|
90
|
-
|
|
91
|
-
| 에러 코드 | 행동 |
|
|
92
|
-
|-----------|------|
|
|
93
|
-
| \`GATED_ACCESS_REQUIRED\` | purchase_info의 message/url 표시 → "접근 코드가 있으신가요?" AskUserQuestion |
|
|
94
|
-
| \`SPACE_ONLY\` | Space 가입 필요 안내 → "초대 코드가 있으신가요?" AskUserQuestion |
|
|
95
|
-
| \`APPROVAL_REQUIRED\` | 승인 대기 안내 |
|
|
96
|
-
| \`NO_ACCESS\` | 접근 방법 안내 |
|
|
97
|
-
|
|
98
|
-
#### 4. 그 외 에러
|
|
99
|
-
\`fix\` 필드의 메시지를 사용자에게 전달하고, 필요하면 다음 행동을 제안합니다.`;
|
|
100
|
-
// ─── 명함 표시 포맷 ───
|
|
101
|
-
const BUSINESS_CARD_FORMAT = `
|
|
102
|
-
### 빌더 명함 표시
|
|
103
|
-
JSON 결과의 \`author\`, \`welcome\` 필드를 사용하여 명함을 표시합니다.
|
|
104
|
-
불릿 리스트(- 또는 *)로 나열하지 마세요. 반드시 인용 블록(>) 안에 넣어야 합니다.
|
|
105
|
-
|
|
106
|
-
**JSON 결과에서 사용할 필드:**
|
|
107
|
-
- \`author.display_name\` 또는 \`author.username\` → 명함 제목
|
|
108
|
-
- \`welcome\` → 환영 메시지 (💬)
|
|
109
|
-
- \`author.contact_links\` → 연락처 배열 (\`[{type, label, value}]\`)
|
|
110
|
-
- \`author.username\` → 프로필 링크 (👤)
|
|
111
|
-
|
|
112
|
-
**예시 (이 형태를 그대로 따르세요):**
|
|
113
|
-
|
|
114
|
-
JSON 결과 예시:
|
|
115
|
-
\`\`\`json
|
|
116
|
-
{
|
|
117
|
-
"author": { "username": "alice", "display_name": "Alice Kim", "contact_links": [
|
|
118
|
-
{"type": "email", "label": "이메일", "value": "alice@example.com"},
|
|
119
|
-
{"type": "website", "label": "블로그", "value": "https://alice.dev"},
|
|
120
|
-
{"type": "kakao", "label": "카카오", "value": "https://open.kakao.com/o/abc123"}
|
|
121
|
-
]},
|
|
122
|
-
"welcome": "안녕하세요!\\n에이전트 빌더 Alice입니다.\\n설치해주셔서 감사합니다."
|
|
123
|
-
}
|
|
124
|
-
\`\`\`
|
|
125
|
-
|
|
126
|
-
출력:
|
|
127
|
-
|
|
128
|
-
> **🪪 Alice Kim의 명함**
|
|
129
|
-
>
|
|
130
|
-
> 💬 "안녕하세요!
|
|
131
|
-
> 에이전트 빌더 Alice입니다.
|
|
132
|
-
> 설치해주셔서 감사합니다."
|
|
133
|
-
>
|
|
134
|
-
> 📧 alice@example.com
|
|
135
|
-
> 🔗 블로그: alice.dev
|
|
136
|
-
> 💬 카카오: open.kakao.com/o/abc123
|
|
137
|
-
> 👤 relayax.com/@alice
|
|
138
|
-
|
|
139
|
-
- \`welcome\`이 없으면 💬 줄을 생략합니다.
|
|
140
|
-
- 연락처의 type에 맞는 이모지: 📧 email, 💬 kakao, 🐦 x, 💼 linkedin, 💻 github, 🔗 website/custom
|
|
141
|
-
- 연락처가 여러 개면 각각 한 줄씩 표시합니다.
|
|
142
|
-
- \`author\`가 null이면 명함 블록 전체를 생략합니다.`;
|
|
62
|
+
// ─── 프롬프트 조각은 cli/src/prompts/*.md에서 관리 (SSOT) ───
|
|
63
|
+
// REQUIREMENTS_CHECK, ERROR_HANDLING_GUIDE, BUSINESS_CARD_FORMAT → import from '../prompts/index.js'
|
|
143
64
|
// ─── User Commands (글로벌 설치) ───
|
|
144
65
|
exports.USER_COMMANDS = [
|
|
145
66
|
{
|
|
146
67
|
id: 'relay-install',
|
|
147
|
-
description: 'relay
|
|
148
|
-
body:
|
|
149
|
-
인자 없이 호출하면 인터랙티브 탐색 모드로 진입합니다.
|
|
150
|
-
|
|
151
|
-
## 인터랙션 플로우
|
|
152
|
-
|
|
153
|
-
이 커맨드는 3단계 인터랙션으로 진행됩니다. 각 단계에서 반드시 AskUserQuestion 도구를 사용하세요.
|
|
154
|
-
|
|
155
|
-
### Step 1. Space 선택 & 팀 탐색 (slug가 없을 때만)
|
|
156
|
-
|
|
157
|
-
slug가 직접 주어지면 (\`/relay-install @alice/doc-writer\`) 이 단계를 건너뛰고 Step 2로 갑니다.
|
|
158
|
-
|
|
159
|
-
#### 1-1. Space 선택
|
|
160
|
-
\`relay spaces --json\` 을 실행하여 사용자의 Space 목록을 가져옵니다.
|
|
161
|
-
|
|
162
|
-
**AskUserQuestion 호출:**
|
|
163
|
-
- question: "어디서 팀을 찾을까요?"
|
|
164
|
-
- options: Space가 있으면 \`["<space1_name>", "<space2_name>", ...]\`, 없으면 이 단계를 건너뛰고 바로 내 Space 탐색으로 진행
|
|
165
|
-
|
|
166
|
-
**응답 처리:**
|
|
167
|
-
- Space 이름 선택 → 1-2. Space 팀 탐색으로 진행
|
|
168
|
-
|
|
169
|
-
#### 1-2. Space 팀 탐색
|
|
170
|
-
선택된 Space에서 팀을 검색합니다.
|
|
171
|
-
\`relay search <keyword>\` 명령어를 실행합니다 (필요하면 여러 키워드로 반복).
|
|
172
|
-
또는 \`relay list --space <space-slug> --json\`으로 전체 목록을 가져옵니다.
|
|
173
|
-
|
|
174
|
-
검색 결과를 번호 리스트로 보여줍니다:
|
|
175
|
-
|
|
176
|
-
\`\`\`
|
|
177
|
-
검색 결과 (3개)
|
|
178
|
-
|
|
179
|
-
1. @alice/doc-writer — 기술 문서 자동화
|
|
180
|
-
/write-doc, /api-doc
|
|
181
|
-
|
|
182
|
-
2. @bob/code-reviewer — PR 리뷰 자동화
|
|
183
|
-
/review, /suggest
|
|
184
|
-
|
|
185
|
-
3. @carol/test-gen — 테스트 코드 생성
|
|
186
|
-
/gen-test, /coverage
|
|
187
|
-
\`\`\`
|
|
188
|
-
|
|
189
|
-
**AskUserQuestion 호출:**
|
|
190
|
-
- question: "어떤 팀을 설치할까요?"
|
|
191
|
-
- options: \`["1", "2", "3", "다시 검색", "돌아가기"]\`
|
|
192
|
-
|
|
193
|
-
"다시 검색" → 새 키워드로 1-2 반복
|
|
194
|
-
"돌아가기" → 1-1로 돌아감
|
|
195
|
-
번호 선택 → 해당 팀의 slug로 설치 진행
|
|
196
|
-
|
|
197
|
-
#### 1-3. Space 팀 목록 (전체 보기)
|
|
198
|
-
\`relay list --space <space-slug> --json\` 을 실행합니다.
|
|
199
|
-
|
|
200
|
-
팀 목록을 번호 리스트로 보여줍니다 (1-2와 동일 형식).
|
|
201
|
-
|
|
202
|
-
**AskUserQuestion 호출:**
|
|
203
|
-
- question: "어떤 팀을 설치할까요?"
|
|
204
|
-
- options: \`["1", "2", ..., "돌아가기"]\`
|
|
205
|
-
|
|
206
|
-
"돌아가기" → 1-1로 돌아감
|
|
207
|
-
번호 선택 → 해당 팀의 slug로 설치 진행
|
|
208
|
-
|
|
209
|
-
### Step 2. 설치 & 배치 범위 선택
|
|
210
|
-
|
|
211
|
-
#### 2-1. 패키지 다운로드
|
|
212
|
-
\`relay install <@space/team> --json\` 명령어를 실행합니다.
|
|
213
|
-
- 공개 팀 (public): \`relay install <@space/team> --json\`
|
|
214
|
-
- 링크 공유 팀 (gated): \`relay install <slug> --json\`
|
|
215
|
-
- 접근 권한이 없으면 CLI가 **purchase_info** (구매 안내 메시지 + URL)를 표시합니다.
|
|
216
|
-
- 접근 링크 코드가 있으면: \`relay access <slug> --code <code>\` 로 접근 부여 + 자동 설치를 한번에 수행합니다.
|
|
217
|
-
- Space 멤버이면 접근 확인 없이 바로 설치됩니다.
|
|
218
|
-
- Space 팀 (비공개/private): \`relay install @<space-slug>/<team-slug> --json\`
|
|
219
|
-
- Space 가입이 필요하면: \`relay join <space-slug> --code <invite-code>\` 를 먼저 실행합니다.
|
|
220
|
-
- 또는 \`--join-code <code>\`로 가입+설치를 한번에 할 수 있습니다.
|
|
221
|
-
- CLI가 init과 login을 자동으로 처리합니다 (사용자가 별도 실행할 필요 없음).
|
|
222
|
-
- JSON 출력에서 \`install_path\` (패키지 경로)를 확인합니다.
|
|
223
|
-
|
|
224
|
-
**gated 팀 접근 거부 처리:**
|
|
225
|
-
- CLI가 403 + \`GATED_ACCESS_REQUIRED\` 에러를 반환하면:
|
|
226
|
-
1. purchase_info의 message와 url을 사용자에게 표시합니다.
|
|
227
|
-
2. "접근 링크 코드가 있으신가요?"라고 물어봅니다.
|
|
228
|
-
3. 코드가 있으면 \`relay access <slug> --code <code>\`를 실행합니다.
|
|
229
|
-
4. 코드가 없으면 purchase_info의 url로 구매 안내합니다.
|
|
230
|
-
|
|
231
|
-
#### 2-2. 배치 범위 선택 (추천 포함)
|
|
232
|
-
|
|
233
|
-
팀의 성격을 분석하여 글로벌/로컬 중 적합한 쪽을 추천합니다.
|
|
234
|
-
|
|
235
|
-
**추천 로직:**
|
|
236
|
-
- **글로벌 추천** — 범용 유틸리티 팀: 코드 리뷰, 문서 생성, 테스트, 번역 등 프로젝트에 무관하게 사용하는 도구성 팀
|
|
237
|
-
- **로컬 추천** — 프로젝트 특화 팀: 특정 프레임워크/스택 전용, 프로젝트별 워크플로우, 팀 내부 컨벤션에 의존하는 팀
|
|
238
|
-
|
|
239
|
-
판단 기준 (다운로드된 패키지의 relay.yaml과 콘텐츠를 분석):
|
|
240
|
-
1. \`tags\`에 특정 프레임워크/스택 키워드가 있으면 (nextjs, supabase, react 등) → 로컬 추천
|
|
241
|
-
2. \`requires\`에 프로젝트 종속 의존성이 있으면 (npm 패키지, 특정 파일 구조) → 로컬 추천
|
|
242
|
-
3. rules/ 파일이 있으면 (프로젝트 컨벤션 주입) → 로컬 추천
|
|
243
|
-
4. 범용 키워드 (utility, review, docs, testing 등) → 글로벌 추천
|
|
244
|
-
5. 판단이 어려우면 → 글로벌 추천 (기본값)
|
|
245
|
-
|
|
246
|
-
**AskUserQuestion 호출:**
|
|
247
|
-
- question: "{추천 이유}. {추천}에 설치할까요?"
|
|
248
|
-
- options: \`["글로벌 (모든 프로젝트) ✓ 추천", "로컬 (이 프로젝트만)"]\` 또는 \`["글로벌 (모든 프로젝트)", "로컬 (이 프로젝트만) ✓ 추천"]\`
|
|
249
|
-
|
|
250
|
-
예시:
|
|
251
|
-
- "범용 코드 리뷰 도구입니다. 글로벌에 설치할까요?" → \`["글로벌 (모든 프로젝트) ✓ 추천", "로컬 (이 프로젝트만)"]\`
|
|
252
|
-
- "Next.js + Supabase 전용 팀입니다. 이 프로젝트에 설치할까요?" → \`["글로벌 (모든 프로젝트)", "로컬 (이 프로젝트만) ✓ 추천"]\`
|
|
253
|
-
|
|
254
|
-
**응답 처리:**
|
|
255
|
-
- "글로벌" → \`~/.claude/\`에 배치
|
|
256
|
-
- "로컬" → 현재 프로젝트 \`.claude/\`에 배치
|
|
257
|
-
|
|
258
|
-
#### 2-3. 에이전트 환경에 맞게 배치
|
|
259
|
-
다운로드된 패키지(\`install_path\`)에서 파일을 읽고 선택된 범위에 배치합니다:
|
|
260
|
-
- 글로벌: \`<install_path>/commands/\` → \`~/.claude/commands/\`에 복사, skills/ 동일
|
|
261
|
-
- 로컬: \`<install_path>/commands/\` → \`.claude/commands/\`에 복사, skills/ 동일
|
|
262
|
-
- agents/, rules/ 파일도 같은 방식으로 배치합니다.
|
|
263
|
-
- **충돌 확인**: 같은 이름의 파일이 이미 있으면 사용자에게 덮어쓸지 물어봅니다.
|
|
264
|
-
|
|
265
|
-
#### 2-4. 배치 정보 기록 (필수)
|
|
266
|
-
배치 완료 후 반드시 \`relay deploy-record\`를 실행합니다:
|
|
267
|
-
\`\`\`
|
|
268
|
-
relay deploy-record <slug> --scope <global|local> --files <배치된_파일1> <배치된_파일2> ...
|
|
269
|
-
\`\`\`
|
|
270
|
-
|
|
271
|
-
#### 2-5. Requirements 체크리스트 (필수 — 항목이 있으면 반드시 수행)
|
|
272
|
-
|
|
273
|
-
\`<install_path>/relay.yaml\`의 \`requires\` 섹션을 읽고, **각 항목을 하나씩 확인하여 체크리스트로 표시**합니다.
|
|
274
|
-
requires 섹션이 없거나 비어있으면 이 단계를 건너뜁니다.
|
|
275
|
-
|
|
276
|
-
**출력 형식** (반드시 이 형식으로 사용자에게 보여줍니다):
|
|
277
|
-
\`\`\`
|
|
278
|
-
📋 Requirements 확인
|
|
279
|
-
|
|
280
|
-
[runtime]
|
|
281
|
-
✅ Node.js >=18 — v20.11.0 확인됨
|
|
282
|
-
❌ Python >=3.10 — v3.8.5 (업그레이드 필요)
|
|
283
|
-
|
|
284
|
-
[cli]
|
|
285
|
-
✅ playwright — 설치됨
|
|
286
|
-
❌ ffmpeg — 미설치 → 설치 명령: brew install ffmpeg
|
|
287
|
-
|
|
288
|
-
[npm]
|
|
289
|
-
✅ sharp — 설치됨
|
|
290
|
-
❌ puppeteer — 미설치 → 설치 중...
|
|
291
|
-
|
|
292
|
-
[env]
|
|
293
|
-
✅ OPENAI_API_KEY — 설정됨
|
|
294
|
-
❌ SLACK_WEBHOOK_URL (선택) — 미설정. 알림 전송에 필요
|
|
295
|
-
|
|
296
|
-
[mcp]
|
|
297
|
-
⚙️ supabase — MCP 서버 설정 필요 (아래 안내 참고)
|
|
298
|
-
|
|
299
|
-
[teams]
|
|
300
|
-
✅ @alice/doc-writer — 이미 설치됨
|
|
301
|
-
📦 @bob/utils — 미설치 → 설치 중...
|
|
302
|
-
\`\`\`
|
|
303
|
-
|
|
304
|
-
**처리 규칙 (각 카테고리별):**
|
|
305
|
-
|
|
306
|
-
1. **runtime**: \`node --version\`, \`python3 --version\`으로 확인. 버전 미달이면 ❌ 표시 후 업그레이드 안내.
|
|
307
|
-
2. **cli**: \`which <name>\`으로 확인.
|
|
308
|
-
- 설치됨 → ✅
|
|
309
|
-
- 미설치 + \`install\` 필드 있음 → 사용자에게 설치할지 물어본 후 실행
|
|
310
|
-
- 미설치 + \`install\` 필드 없음 → ❌ 표시 후 수동 설치 안내
|
|
311
|
-
3. **npm**: \`npm list <package> 2>/dev/null\`으로 확인.
|
|
312
|
-
- 설치됨 → ✅
|
|
313
|
-
- 미설치 + required → \`npm install <package>\` 실행
|
|
314
|
-
- 미설치 + optional → ❌ 표시 후 안내만
|
|
315
|
-
4. **env**: \`echo $<NAME>\`으로 확인.
|
|
316
|
-
- 설정됨 → ✅
|
|
317
|
-
- 미설정 + required → ❌ 표시 후 \`description\`과 함께 설정 방법 안내
|
|
318
|
-
- 미설정 + optional → ⚠️ 표시 후 용도 안내
|
|
319
|
-
5. **mcp**: MCP 서버 설정이 필요한 경우 ⚙️ 표시 후 설정 방법을 상세히 안내.
|
|
320
|
-
- \`config\` 필드가 있으면 settings.json에 추가할 JSON 블록을 보여줍니다.
|
|
321
|
-
- \`env\` 필드가 있으면 필요한 환경변수도 함께 안내합니다.
|
|
322
|
-
6. **teams**: \`relay list --json\`으로 설치 여부 확인.
|
|
323
|
-
- 설치됨 → ✅
|
|
324
|
-
- 미설치 → \`relay install <@author/team> --json\` 실행하여 재귀 설치
|
|
325
|
-
|
|
326
|
-
**중요**: 모든 required 항목이 ❌인 경우, 체크리스트 끝에 경고를 표시합니다:
|
|
327
|
-
\`\`\`
|
|
328
|
-
⚠️ 필수 요구사항이 충족되지 않았습니다. 팀 기능이 제한될 수 있습니다.
|
|
329
|
-
\`\`\`
|
|
330
|
-
${ERROR_HANDLING_GUIDE}
|
|
331
|
-
|
|
332
|
-
### Step 3. 완료 & 팔로우 제안
|
|
333
|
-
|
|
334
|
-
#### 3-1. 완료 안내
|
|
335
|
-
- 배치된 파일과 활성화된 커맨드 목록을 보여줍니다.
|
|
336
|
-
${BUSINESS_CARD_FORMAT}
|
|
337
|
-
|
|
338
|
-
#### 3-2. 팔로우 제안 (필수 — 이 단계를 절대 건너뛰지 마세요)
|
|
339
|
-
명함 표시 직후, 빌더의 username이 JSON 결과에 있으면 **반드시** AskUserQuestion 도구를 호출하세요.
|
|
340
|
-
|
|
341
|
-
**AskUserQuestion 호출:**
|
|
342
|
-
- question: \`@{username}을 팔로우할까요? 새 버전 알림을 받을 수 있습니다.\`
|
|
343
|
-
- options: \`["팔로우", "건너뛰기"]\`
|
|
344
|
-
|
|
345
|
-
**응답 처리:**
|
|
346
|
-
- "팔로우" → \`relay follow @{username}\` 실행. 로그인이 안 되어 있으면 \`relay login\` 먼저 실행 후 재시도.
|
|
347
|
-
- "건너뛰기" → 다음 단계로 진행
|
|
348
|
-
|
|
349
|
-
#### 3-3. 공유 가이드 (필수 — 설치 완료 시 반드시 표시)
|
|
350
|
-
설치 완료 후 아래 공유용 설치 가이드를 표시합니다. 복사 가능한 코드 블록으로 보여줍니다.
|
|
351
|
-
|
|
352
|
-
\`\`\`
|
|
353
|
-
주변인에게 공유하세요:
|
|
354
|
-
|
|
355
|
-
아래 가이드를 읽고 그대로 따라해줘:
|
|
356
|
-
https://relayax.com/api/registry/{owner}/{slug}/guide.md
|
|
357
|
-
\`\`\`
|
|
358
|
-
|
|
359
|
-
- \`{slug}\`가 \`@owner/team\` 형식이면 \`{owner}\`과 \`{slug}\`를 분리하여 URL을 구성합니다.
|
|
360
|
-
- CLI가 이미 설치된 사용자를 위한 짧은 버전도 함께 표시합니다: \`/relay:relay-install {slug}\`
|
|
361
|
-
|
|
362
|
-
#### 3-4. 사용 제안
|
|
363
|
-
- "바로 사용해볼까요?" 제안
|
|
364
|
-
|
|
365
|
-
#### 3-5. 업데이트 확인
|
|
366
|
-
- \`relay check-update\` 명령어를 실행합니다.
|
|
367
|
-
- CLI 업데이트가 있으면 안내합니다: "relay v{new} available. Run: npm update -g relayax-cli"
|
|
368
|
-
- 다른 팀 업데이트가 있으면 안내합니다.
|
|
369
|
-
|
|
370
|
-
## 예시
|
|
371
|
-
|
|
372
|
-
### 인터랙티브 모드 (/relay-install)
|
|
373
|
-
→ relay spaces --json 실행
|
|
374
|
-
→ AskUserQuestion: "어디서 팀을 찾을까요?" → ["Alice's Space (alice)", "Acme Corp"]
|
|
375
|
-
→ "Alice's Space" 선택 → "어떤 팀을 찾고 계세요?"
|
|
376
|
-
→ relay search "문서" 실행 → 결과 리스트 표시
|
|
377
|
-
→ AskUserQuestion: "어떤 팀을 설치할까요?" → ["1", "2", "3", "다시 검색"]
|
|
378
|
-
→ "1" 선택 (@alice/doc-writer)
|
|
379
|
-
→ AskUserQuestion: "어디에 설치할까요?" → ["글로벌 (모든 프로젝트)", "로컬 (이 프로젝트만)"]
|
|
380
|
-
→ "글로벌" 선택
|
|
381
|
-
→ 설치 + 배치 + deploy-record
|
|
382
|
-
→ 명함 표시
|
|
383
|
-
→ AskUserQuestion: "@alice을 팔로우할까요?" → ["팔로우", "건너뛰기"]
|
|
384
|
-
→ "✓ 설치 완료! /write-doc를 사용해볼까요?"
|
|
385
|
-
|
|
386
|
-
### 다이렉트 모드 (/relay-install @alice/doc-writer)
|
|
387
|
-
→ relay install @alice/doc-writer --json 실행 (Step 1 건너뜀)
|
|
388
|
-
→ AskUserQuestion: "어디에 설치할까요?" → ["글로벌 (모든 프로젝트)", "로컬 (이 프로젝트만)"]
|
|
389
|
-
→ 설치 + 배치 + deploy-record
|
|
390
|
-
→ 명함 표시
|
|
391
|
-
→ AskUserQuestion: "@alice을 팔로우할까요?" → ["팔로우", "건너뛰기"]
|
|
392
|
-
→ "✓ 설치 완료! /write-doc를 사용해볼까요?"`,
|
|
68
|
+
description: 'relay에서 에이전트를 설치합니다',
|
|
69
|
+
body: index_js_1.INSTALL_PROMPT,
|
|
393
70
|
},
|
|
394
71
|
{
|
|
395
72
|
id: 'relay-status',
|
|
396
|
-
description: '설치된
|
|
397
|
-
body: `현재 설치된
|
|
73
|
+
description: '설치된 에이전트와 Organization 현황을 확인합니다',
|
|
74
|
+
body: `현재 설치된 에이전트와 소속 Organization 현황을 한눈에 보여줍니다.
|
|
398
75
|
|
|
399
76
|
## 실행 방법
|
|
400
77
|
|
|
401
|
-
### 1. 설치된
|
|
78
|
+
### 1. 설치된 에이전트 목록
|
|
402
79
|
|
|
403
80
|
\`relay list --json\` 명령어를 실행합니다.
|
|
404
81
|
|
|
@@ -407,7 +84,7 @@ https://relayax.com/api/registry/{owner}/{slug}/guide.md
|
|
|
407
84
|
{
|
|
408
85
|
"installed": [
|
|
409
86
|
{
|
|
410
|
-
"slug": "@author/
|
|
87
|
+
"slug": "@author/agent-name",
|
|
411
88
|
"version": "1.2.0",
|
|
412
89
|
"installed_at": "2026-03-20T12:00:00.000Z",
|
|
413
90
|
"scope": "global",
|
|
@@ -418,11 +95,11 @@ https://relayax.com/api/registry/{owner}/{slug}/guide.md
|
|
|
418
95
|
}
|
|
419
96
|
\`\`\`
|
|
420
97
|
|
|
421
|
-
**각
|
|
98
|
+
**각 에이전트를 아래 형식으로 표시:**
|
|
422
99
|
|
|
423
|
-
|
|
|
100
|
+
| 에이전트 | 버전 | 배포 | 설치일 |
|
|
424
101
|
|---|---|---|---|
|
|
425
|
-
| @author/
|
|
102
|
+
| @author/agent-name | v1.2.0 | 글로벌 | 3/20 |
|
|
426
103
|
|
|
427
104
|
- \`deploy_scope\`가 \`"global"\` → 글로벌, \`"local"\` → 로컬, 없으면 → 미배치
|
|
428
105
|
- \`org_slug\`가 있으면 \`[Org: slug]\` 표시
|
|
@@ -447,16 +124,16 @@ https://relayax.com/api/registry/{owner}/{slug}/guide.md
|
|
|
447
124
|
|
|
448
125
|
**표시:**
|
|
449
126
|
- \`role\`: owner → 오너, admin → 관리자, builder → 빌더, member → 멤버
|
|
450
|
-
${ERROR_HANDLING_GUIDE}
|
|
451
|
-
- Org 조회 실패해도 설치된
|
|
127
|
+
${index_js_1.ERROR_HANDLING_GUIDE}
|
|
128
|
+
- Org 조회 실패해도 설치된 에이전트 목록은 정상 표시합니다 (로컬 데이터).
|
|
452
129
|
|
|
453
|
-
### 3. Org
|
|
454
|
-
- \`--org <slug>\` 인자가 있으면: \`relay list --org <org-slug> --json\`으로 해당 Organization의
|
|
130
|
+
### 3. Org 에이전트 목록 (옵션)
|
|
131
|
+
- \`--org <slug>\` 인자가 있으면: \`relay list --org <org-slug> --json\`으로 해당 Organization의 에이전트 목록도 보여줍니다.
|
|
455
132
|
|
|
456
133
|
### 4. 안내
|
|
457
|
-
- 설치된
|
|
134
|
+
- 설치된 에이전트가 없으면 \`/relay-install\`로 에이전트를 탐색·설치해보라고 안내합니다.
|
|
458
135
|
- Org가 있으면 활용법을 안내합니다:
|
|
459
|
-
- Org
|
|
136
|
+
- Org 에이전트 설치: \`relay install @<org-slug>/<agent>\`
|
|
460
137
|
- Org 관리: www.relayax.com/orgs/<slug>
|
|
461
138
|
|
|
462
139
|
## 예시
|
|
@@ -465,35 +142,35 @@ ${ERROR_HANDLING_GUIDE}
|
|
|
465
142
|
→ relay list --json 실행
|
|
466
143
|
→ relay orgs list --json 실행 (병렬 가능)
|
|
467
144
|
|
|
468
|
-
**설치된
|
|
145
|
+
**설치된 에이전트 (2개)**
|
|
469
146
|
|
|
470
|
-
|
|
|
147
|
+
| 에이전트 | 버전 | 배포 | 설치일 |
|
|
471
148
|
|---|---|---|---|
|
|
472
149
|
| @alice/doc-writer | v1.2.0 | 글로벌 | 3/20 |
|
|
473
150
|
| @bob/code-reviewer | v0.5.1 | 로컬 | 3/15 |
|
|
474
151
|
|
|
475
|
-
**내
|
|
152
|
+
**내 Organization (2개)**
|
|
476
153
|
- acme-corp — Acme Corp (소유자)
|
|
477
154
|
- dev-guild — Dev Guild (멤버)
|
|
478
155
|
|
|
479
|
-
사용자: /relay-status --
|
|
480
|
-
→ 위 정보 + \`relay list --
|
|
481
|
-
→ acme-corp
|
|
156
|
+
사용자: /relay-status --org acme-corp
|
|
157
|
+
→ 위 정보 + \`relay list --org acme-corp --json\` 실행
|
|
158
|
+
→ acme-corp Organization에서 설치 가능한 에이전트 목록 추가 표시`,
|
|
482
159
|
},
|
|
483
160
|
{
|
|
484
161
|
id: 'relay-uninstall',
|
|
485
|
-
description: '설치된
|
|
486
|
-
body: `설치된
|
|
162
|
+
description: '설치된 에이전트를 삭제합니다',
|
|
163
|
+
body: `설치된 에이전트를 제거합니다. CLI가 패키지와 배치된 파일을 모두 정리합니다.
|
|
487
164
|
|
|
488
165
|
## 실행 방법
|
|
489
166
|
|
|
490
167
|
1. \`relay uninstall <@author/slug> --json\` 명령어를 실행합니다.
|
|
491
168
|
2. CLI가 자동으로 처리하는 것:
|
|
492
|
-
- \`.relay/
|
|
493
|
-
- \`deployed_files\`에 기록된 배치 파일 삭제 (
|
|
169
|
+
- \`.relay/agents/\` 패키지 삭제
|
|
170
|
+
- \`deployed_files\`에 기록된 배치 파일 삭제 (에이전트 설정 디렉토리 내)
|
|
494
171
|
- 빈 상위 디렉토리 정리
|
|
495
172
|
- installed.json에서 항목 제거 (글로벌/로컬 양쪽)
|
|
496
|
-
3. 삭제 결과를 보여줍니다 (
|
|
173
|
+
3. 삭제 결과를 보여줍니다 (에이전트 이름, 제거된 파일 수).
|
|
497
174
|
|
|
498
175
|
## 예시
|
|
499
176
|
|
|
@@ -503,336 +180,8 @@ ${ERROR_HANDLING_GUIDE}
|
|
|
503
180
|
},
|
|
504
181
|
{
|
|
505
182
|
id: 'relay-publish',
|
|
506
|
-
description: '현재
|
|
507
|
-
body:
|
|
508
|
-
|
|
509
|
-
## 사전 준비
|
|
510
|
-
|
|
511
|
-
### 0-1. 인증 확인
|
|
512
|
-
|
|
513
|
-
- \`relay status --json\` 명령어를 실행하여 로그인 상태를 확인합니다.
|
|
514
|
-
- 인증되어 있으면 다음 단계로 진행합니다.
|
|
515
|
-
- 미인증이면 바로 로그인을 진행합니다:
|
|
516
|
-
1. \`relay login\` 실행 (timeout 300초)
|
|
517
|
-
- 브라우저가 자동으로 열리고, 사용자가 로그인을 완료하면 토큰이 자동 저장됩니다.
|
|
518
|
-
2. 완료 후 \`relay status --json\`으로 로그인 성공을 확인합니다.
|
|
519
|
-
|
|
520
|
-
### 0-2. 소스 패키징 (source → .relay/)
|
|
521
|
-
|
|
522
|
-
\`relay package\` CLI 명령을 사용하여 소스 디렉토리의 콘텐츠를 .relay/로 동기화합니다.
|
|
523
|
-
소스 탐색과 파일 비교는 CLI가 결정적으로 처리하고, 에이전트는 결과를 사용자에게 보여주고 흐름을 조율합니다.
|
|
524
|
-
|
|
525
|
-
#### A. 최초 배포 (.relay/relay.yaml이 없음)
|
|
526
|
-
|
|
527
|
-
##### 1단계: 소스 탐색
|
|
528
|
-
|
|
529
|
-
\`relay package --init --json\` 실행
|
|
530
|
-
- CLI가 프로젝트에서 에이전트 CLI 디렉토리(.claude/, .codex/, .gemini/ 등)를 자동 탐색합니다.
|
|
531
|
-
- JSON 결과의 \`detected\` 배열에 각 디렉토리별 콘텐츠 요약이 포함됩니다:
|
|
532
|
-
\`\`\`json
|
|
533
|
-
{
|
|
534
|
-
"status": "init_required",
|
|
535
|
-
"detected": [
|
|
536
|
-
{ "source": ".claude", "name": "Claude Code", "summary": { "skills": 2, "commands": 3 }, "fileCount": 8 },
|
|
537
|
-
{ "source": ".codex", "name": "Codex", "summary": { "agents": 1 }, "fileCount": 2 }
|
|
538
|
-
]
|
|
539
|
-
}
|
|
540
|
-
\`\`\`
|
|
541
|
-
|
|
542
|
-
- **detected가 0개** → "배포 가능한 에이전트 콘텐츠가 없습니다. skills/이나 commands/를 먼저 만들어주세요." 안내 후 중단
|
|
543
|
-
|
|
544
|
-
##### 2단계: 콘텐츠 분석 & 팀 포지셔닝
|
|
545
|
-
|
|
546
|
-
detected된 소스 디렉토리의 skills/, commands/, agents/, rules/ 파일 **내용을 직접 읽어** 팀의 정체성을 파악합니다.
|
|
547
|
-
|
|
548
|
-
**분석 관점:**
|
|
549
|
-
- 이 팀이 **무엇을 하는 팀**인지 (코드 리뷰? QA? 문서 생성? 데이터 분석?)
|
|
550
|
-
- 어떤 **기술 스택/도메인**에 특화되어 있는지 (Supabase? React? Python?)
|
|
551
|
-
- 설치자에게 **어떤 가치**를 제공하는지
|
|
552
|
-
|
|
553
|
-
이 분석을 기반으로 팀을 하나의 "제품"으로 포지셔닝합니다.
|
|
554
|
-
|
|
555
|
-
**중요: 소스 디렉토리 이름(.claude 등)은 인프라 디테일이므로 사용자에게 노출하지 않습니다.**
|
|
556
|
-
사용자에게는 팀의 기능과 정체성 중심으로 질문합니다.
|
|
557
|
-
|
|
558
|
-
##### 3단계: 배포 제안
|
|
559
|
-
|
|
560
|
-
분석 결과를 바탕으로 팀 배포를 제안합니다.
|
|
561
|
-
|
|
562
|
-
**detected가 1개일 때:**
|
|
563
|
-
|
|
564
|
-
**AskUserQuestion 호출:**
|
|
565
|
-
- question: 콘텐츠 분석 기반의 포지셔닝 질문
|
|
566
|
-
- 예시:
|
|
567
|
-
- "Supabase 웹 개발팀으로 배포할까요? (skills 2개, commands 3개)"
|
|
568
|
-
- "코드 리뷰 자동화 팀으로 배포할까요? (skills 1개, agents 2개)"
|
|
569
|
-
- "Next.js QA 테스트팀으로 배포할까요? (commands 5개)"
|
|
570
|
-
- options: \`["배포", "취소"]\`
|
|
571
|
-
|
|
572
|
-
**detected가 여러 개일 때:**
|
|
573
|
-
각 소스의 콘텐츠를 분석하여 서로 다른 팀으로 포지셔닝합니다.
|
|
574
|
-
|
|
575
|
-
**AskUserQuestion 호출:**
|
|
576
|
-
- question: "어떤 팀으로 배포할까요?"
|
|
577
|
-
- options: 콘텐츠 기반 설명 (예: \`["Supabase 웹 개발팀 (skills 2개, commands 3개)", "QA 자동화 에이전트 (agents 1개)"]\`)
|
|
578
|
-
- 디렉토리 이름은 내부적으로만 매핑하고, 사용자에게는 팀의 기능으로 보여줍니다.
|
|
579
|
-
|
|
580
|
-
##### 4단계: 팀 정보 확정
|
|
581
|
-
|
|
582
|
-
포지셔닝 분석을 기반으로 팀 이름과 설명을 제안합니다.
|
|
583
|
-
|
|
584
|
-
**AskUserQuestion 호출:**
|
|
585
|
-
- question: "팀 이름을 확인해주세요"
|
|
586
|
-
- 분석된 포지셔닝에서 자연스러운 팀 이름을 제안합니다 (예: "supabase-web-dev", "code-reviewer")
|
|
587
|
-
- 현재 디렉토리명이 아닌, **콘텐츠 기반** 이름을 기본값으로 제시합니다.
|
|
588
|
-
|
|
589
|
-
**AskUserQuestion 호출:**
|
|
590
|
-
- question: "팀 설명을 확인해주세요 (Space에 표시됩니다)"
|
|
591
|
-
- 분석한 콘텐츠를 기반으로 설치자 관점의 설명을 제안합니다.
|
|
592
|
-
- 좋은 예: "Supabase 기반 웹앱의 DB 마이그레이션, API 개발, 테스트를 자동화합니다"
|
|
593
|
-
- 나쁜 예: ".claude 디렉토리의 skills와 commands를 패키징한 팀"
|
|
594
|
-
|
|
595
|
-
##### 5단계: 초기화 & 패키징
|
|
596
|
-
|
|
597
|
-
자동 처리:
|
|
598
|
-
- \`.relay/relay.yaml\` 생성:
|
|
599
|
-
\`\`\`yaml
|
|
600
|
-
name: <확정된 이름>
|
|
601
|
-
slug: <이름에서 자동 생성 — 소문자, 특수문자→하이픈>
|
|
602
|
-
description: <확정된 설명>
|
|
603
|
-
source: <선택된 소스 디렉토리> # 예: .claude (내부용)
|
|
604
|
-
version: 1.0.0
|
|
605
|
-
tags: []
|
|
606
|
-
\`\`\`
|
|
607
|
-
- \`relay package --source <선택된 소스> --sync --json\` 실행하여 콘텐츠를 .relay/로 복사
|
|
608
|
-
- \`relay init --auto\` 실행하여 글로벌 커맨드 설치 보장
|
|
609
|
-
- 결과를 사용자에게 표시
|
|
610
|
-
|
|
611
|
-
#### B. 재배포 (.relay/relay.yaml이 있음)
|
|
612
|
-
|
|
613
|
-
1. \`relay package --json\` 실행
|
|
614
|
-
- CLI가 relay.yaml의 \`source\` 필드를 읽고, 소스 디렉토리와 .relay/를 파일 해시로 비교합니다.
|
|
615
|
-
- JSON 결과 예시:
|
|
616
|
-
\`\`\`json
|
|
617
|
-
{
|
|
618
|
-
"source": ".claude",
|
|
619
|
-
"sourceName": "Claude Code",
|
|
620
|
-
"synced": false,
|
|
621
|
-
"diff": [
|
|
622
|
-
{ "relPath": "skills/code-review/SKILL.md", "status": "modified" },
|
|
623
|
-
{ "relPath": "commands/deploy.md", "status": "added" },
|
|
624
|
-
{ "relPath": "commands/old-cmd.md", "status": "deleted" }
|
|
625
|
-
],
|
|
626
|
-
"summary": { "added": 1, "modified": 1, "deleted": 1, "unchanged": 5 }
|
|
627
|
-
}
|
|
628
|
-
\`\`\`
|
|
629
|
-
|
|
630
|
-
2. **변경이 있으면** (added + modified + deleted > 0) → diff를 사용자에게 보여줍니다:
|
|
631
|
-
\`\`\`
|
|
632
|
-
📦 소스 동기화 (.claude/ → .relay/)
|
|
633
|
-
변경: skills/code-review/SKILL.md
|
|
634
|
-
신규: commands/deploy.md
|
|
635
|
-
삭제: commands/old-cmd.md
|
|
636
|
-
유지: 5개 파일
|
|
637
|
-
\`\`\`
|
|
638
|
-
|
|
639
|
-
**AskUserQuestion 호출:**
|
|
640
|
-
- question: "소스 변경사항을 .relay/에 반영할까요?"
|
|
641
|
-
- options: \`["반영", "변경 확인", "건너뛰기"]\`
|
|
642
|
-
|
|
643
|
-
**응답 처리:**
|
|
644
|
-
- "반영" → \`relay package --sync --json\` 실행하여 동기화
|
|
645
|
-
- "변경 확인" → 변경된 파일의 내용을 직접 읽어 diff를 상세히 보여준 후 다시 AskUserQuestion
|
|
646
|
-
- "건너뛰기" → 현재 .relay/ 그대로 배포
|
|
647
|
-
|
|
648
|
-
3. **변경이 없으면** → "✓ 소스와 동기화 상태입니다." 표시 후 다음 단계로
|
|
649
|
-
|
|
650
|
-
4. \`source\` 필드가 없으면 → .relay/ 내 콘텐츠를 직접 편집하는 모드로 간주하고 동기화를 건너뜁니다.
|
|
651
|
-
|
|
652
|
-
## 인터랙션 플로우
|
|
653
|
-
|
|
654
|
-
이 커맨드는 4단계 인터랙션으로 진행됩니다. 각 단계에서 반드시 AskUserQuestion 도구를 사용하세요.
|
|
655
|
-
|
|
656
|
-
### Step 1. 버전 범프
|
|
657
|
-
|
|
658
|
-
relay.yaml의 현재 \`version\`을 읽고 semver 범프를 제안합니다.
|
|
659
|
-
|
|
660
|
-
**AskUserQuestion 호출:**
|
|
661
|
-
- question: "버전을 올릴까요? (현재 v{version})"
|
|
662
|
-
- options: \`["v{patch} — patch (버그 수정)", "v{minor} — minor (기능 추가)", "v{major} — major (큰 변경)", "v{version} — 유지"]\`
|
|
663
|
-
|
|
664
|
-
예시: 현재 v1.0.0이면 → \`["v1.0.1 — patch", "v1.1.0 — minor", "v2.0.0 — major", "v1.0.0 — 유지"]\`
|
|
665
|
-
|
|
666
|
-
**응답 처리:**
|
|
667
|
-
- 유지 외 선택 → relay.yaml의 version을 선택된 값으로 업데이트
|
|
668
|
-
- 유지 → 그대로 진행
|
|
669
|
-
|
|
670
|
-
### Step 1. 공개 범위 선택
|
|
671
|
-
|
|
672
|
-
relay.yaml의 \`visibility\` 설정을 확인합니다.
|
|
673
|
-
|
|
674
|
-
#### 신규 배포 (visibility 미설정)
|
|
675
|
-
|
|
676
|
-
**AskUserQuestion 호출:**
|
|
677
|
-
- question: "공개 범위를 선택하세요"
|
|
678
|
-
- options: \`["공개 — 누구나 설치", "링크 공유 — 접근 링크가 있는 사람만 설치", "비공개 — Space 멤버만"]\`
|
|
679
|
-
|
|
680
|
-
**응답 처리:**
|
|
681
|
-
- "공개" → relay.yaml에 \`visibility: public\` 저장
|
|
682
|
-
- "링크 공유" → relay.yaml에 \`visibility: gated\` 저장. 배포 후 웹 대시보드(/dashboard)에서 접근 링크를 생성하고 구매 안내를 설정할 수 있다고 안내.
|
|
683
|
-
- "비공개" → \`relay spaces --json\` 실행 후 Space 목록 표시
|
|
684
|
-
- Space가 0개이면: "비공개 배포하려면 Space가 필요합니다. www.relayax.com/spaces 에서 Space를 생성하세요."라고 안내하고 중단합니다.
|
|
685
|
-
|
|
686
|
-
**AskUserQuestion 호출 (Space가 1개여도 반드시 호출):**
|
|
687
|
-
- question: "어떤 Space에 배포할까요?"
|
|
688
|
-
- options: \`["<space1_name>", "<space2_name>", ...]\`
|
|
689
|
-
- **중요: Space가 1개라도 자동 선택하지 말고 반드시 사용자에게 확인받으세요.**
|
|
690
|
-
|
|
691
|
-
→ relay.yaml에 \`visibility: private\`, \`space: <selected_slug>\` 저장
|
|
692
|
-
|
|
693
|
-
#### 재배포 (visibility 이미 설정됨)
|
|
694
|
-
|
|
695
|
-
현재 설정을 확인합니다:
|
|
696
|
-
|
|
697
|
-
**AskUserQuestion 호출:**
|
|
698
|
-
- question: 공개일 때 "현재 **공개** 설정입니다. 유지할까요?", 링크공유일 때 "현재 **링크 공유** 설정입니다. 접근 링크가 있는 사람만 설치 가능합니다. 유지할까요?", 비공개일 때 "현재 **비공개** 설정입니다 (Space: {name}). 유지할까요?"
|
|
699
|
-
- options: \`["유지", "변경"]\`
|
|
700
|
-
|
|
701
|
-
"변경" → 신규 배포와 동일한 플로우
|
|
702
|
-
|
|
703
|
-
### Step 2. 보안 점검 & requires 확인
|
|
704
|
-
|
|
705
|
-
.relay/ 내 모든 파일을 자동 분석합니다.
|
|
706
|
-
|
|
707
|
-
#### 2-1. 시크릿 스캔 (자동)
|
|
708
|
-
- 하드코딩된 API 키, 토큰, 비밀번호, Private Key 등을 탐색합니다.
|
|
709
|
-
- 예: sk-..., ghp_..., AKIA..., Bearer 토큰, JWT, -----BEGIN PRIVATE KEY----- 등
|
|
710
|
-
- 발견 시 **즉시 사용자에게 경고**하고, 환경변수로 대체하도록 안내합니다.
|
|
711
|
-
- 시크릿이 제거되지 않으면 배포를 진행하지 않습니다.
|
|
712
|
-
|
|
713
|
-
#### 2-2. 환경변수 & 의존성 분석 (자동)
|
|
714
|
-
분석 대상:
|
|
715
|
-
- **env**: 환경변수 참조 (process.env.*, \${VAR}, os.environ 등)
|
|
716
|
-
- **cli**: 참조하는 CLI 도구 (playwright, ffmpeg, sharp 등)
|
|
717
|
-
- **npm**: import/require되는 npm 패키지
|
|
718
|
-
- **mcp**: MCP 서버 설정
|
|
719
|
-
- **runtime**: Node.js/Python 등 최소 버전
|
|
720
|
-
- **teams**: 의존하는 다른 relay 팀
|
|
721
|
-
|
|
722
|
-
분석 결과를 요약 표시합니다:
|
|
723
|
-
|
|
724
|
-
\`\`\`
|
|
725
|
-
requires 분석 결과
|
|
726
|
-
|
|
727
|
-
환경변수:
|
|
728
|
-
OPENAI_API_KEY — 필수 (LLM API 호출)
|
|
729
|
-
SLACK_WEBHOOK_URL — 선택 (알림 전송)
|
|
730
|
-
|
|
731
|
-
CLI: playwright (필수)
|
|
732
|
-
npm: sharp (필수)
|
|
733
|
-
MCP: supabase (선택)
|
|
734
|
-
\`\`\`
|
|
735
|
-
|
|
736
|
-
**AskUserQuestion 호출:**
|
|
737
|
-
- question: "requires 설정이 맞나요?"
|
|
738
|
-
- options: \`["확인", "수정"]\`
|
|
739
|
-
|
|
740
|
-
**응답 처리:**
|
|
741
|
-
- "확인" → .relay/relay.yaml에 requires 섹션 저장, 다음 단계로
|
|
742
|
-
- "수정" → 사용자와 텍스트 대화로 수정 후 다시 확인
|
|
743
|
-
|
|
744
|
-
\`\`\`yaml
|
|
745
|
-
# .relay/relay.yaml requires 구조
|
|
746
|
-
requires:
|
|
747
|
-
env:
|
|
748
|
-
- name: OPENAI_API_KEY
|
|
749
|
-
required: true
|
|
750
|
-
description: "LLM API 호출에 필요"
|
|
751
|
-
- name: SLACK_WEBHOOK_URL
|
|
752
|
-
required: false
|
|
753
|
-
description: "알림 전송 (선택)"
|
|
754
|
-
cli:
|
|
755
|
-
- name: playwright
|
|
756
|
-
install: "npx playwright install"
|
|
757
|
-
required: true
|
|
758
|
-
npm:
|
|
759
|
-
- name: sharp
|
|
760
|
-
required: true
|
|
761
|
-
mcp:
|
|
762
|
-
- name: supabase
|
|
763
|
-
package: "@supabase/mcp-server"
|
|
764
|
-
required: false
|
|
765
|
-
config:
|
|
766
|
-
command: "npx"
|
|
767
|
-
args: ["-y", "@supabase/mcp-server"]
|
|
768
|
-
env: [SUPABASE_URL, SUPABASE_SECRET_KEY]
|
|
769
|
-
runtime:
|
|
770
|
-
node: ">=18"
|
|
771
|
-
permissions:
|
|
772
|
-
- filesystem
|
|
773
|
-
- network
|
|
774
|
-
teams:
|
|
775
|
-
- @alice/doc-writer
|
|
776
|
-
\`\`\`
|
|
777
|
-
|
|
778
|
-
### Step 3. 최종 확인 & 배포
|
|
779
|
-
|
|
780
|
-
#### 3-1. 메타데이터 생성 (자동)
|
|
781
|
-
- description: skills 내용 기반으로 자동 생성합니다.
|
|
782
|
-
- long_description: 팀 소개 마크다운을 자동 생성합니다 (README.md가 있으면 활용).
|
|
783
|
-
- tags: 팀 특성에 맞는 태그를 추천합니다.
|
|
784
|
-
|
|
785
|
-
#### 3-2. 배포 요약 + 최종 확인
|
|
786
|
-
배포할 내용을 요약 표시합니다:
|
|
787
|
-
|
|
788
|
-
\`\`\`
|
|
789
|
-
배포 요약
|
|
790
|
-
|
|
791
|
-
팀: my-team v1.0.0
|
|
792
|
-
공개: Space 공개
|
|
793
|
-
Skills: 3개, Commands: 5개
|
|
794
|
-
requires: env 2개, cli 1개
|
|
795
|
-
\`\`\`
|
|
796
|
-
|
|
797
|
-
**AskUserQuestion 호출:**
|
|
798
|
-
- question: "이대로 배포할까요?"
|
|
799
|
-
- options: \`["배포", "취소"]\`
|
|
800
|
-
|
|
801
|
-
**응답 처리:**
|
|
802
|
-
- "배포" → \`relay publish --json\` 실행 (슬래시 커맨드에서 이미 버전/visibility를 relay.yaml에 저장했으므로 --json으로 인터랙티브 프롬프트 생략)
|
|
803
|
-
- "취소" → 중단
|
|
804
|
-
|
|
805
|
-
#### 3-3. 배포 완료 & 온보딩 가이드
|
|
806
|
-
- 배포 결과와 Space URL을 보여줍니다.
|
|
807
|
-
- \`relay publish\` 출력 끝에 코드블록 형태의 온보딩 가이드가 포함됩니다.
|
|
808
|
-
- 이 코드블록을 사용자에게 그대로 보여줍니다.
|
|
809
|
-
- 출력에 코드블록이 없으면 아래 형태로 직접 생성합니다:
|
|
810
|
-
|
|
811
|
-
\\\`\\\`\\\`
|
|
812
|
-
아래 가이드를 읽고 그대로 따라해줘:
|
|
813
|
-
https://relayax.com/api/registry/{owner}/{slug}/guide.md
|
|
814
|
-
\\\`\\\`\\\`
|
|
815
|
-
|
|
816
|
-
- \`{owner}\`과 \`{slug}\`는 배포된 팀의 실제 슬러그에서 추출합니다 (\`@owner/slug\` → \`owner\`, \`slug\`).
|
|
817
|
-
- "이 블록을 팀원에게 공유하면 Claude가 환경 체크부터 설치까지 자동으로 해줍니다"라고 안내합니다.
|
|
818
|
-
- CLI가 이미 설치된 사용자를 위한 짧은 버전도 함께 표시: \`/relay:relay-install <slug>\`
|
|
819
|
-
${BUSINESS_CARD_FORMAT}
|
|
820
|
-
|
|
821
|
-
## 예시
|
|
822
|
-
|
|
823
|
-
사용자: /relay-publish
|
|
824
|
-
→ 인증 확인 ✓, 팀 구조 분석 (skills 3개, commands 5개)
|
|
825
|
-
→ AskUserQuestion: "어디에 배포할까요?" → ["공개 (Space 공개)", "비공개 (Space 전용)"]
|
|
826
|
-
→ "공개" 선택
|
|
827
|
-
→ 보안 스캔 ✓ 시크릿 없음 → requires 분석 결과 표시
|
|
828
|
-
→ AskUserQuestion: "requires 설정이 맞나요?" → ["확인", "수정"]
|
|
829
|
-
→ "확인"
|
|
830
|
-
→ 배포 요약 표시
|
|
831
|
-
→ AskUserQuestion: "이대로 배포할까요?" → ["배포", "취소"]
|
|
832
|
-
→ "배포" → relay publish 실행
|
|
833
|
-
→ "배포 완료! URL: https://relayax.com/@my-space/my-team"
|
|
834
|
-
→ 온보딩 가이드 코드블록 표시
|
|
835
|
-
${ERROR_HANDLING_GUIDE}`,
|
|
183
|
+
description: '현재 에이전트 패키지를 relay에 배포합니다',
|
|
184
|
+
body: index_js_1.PUBLISH_PROMPT,
|
|
836
185
|
},
|
|
837
186
|
];
|
|
838
187
|
// ─── Builder Commands (로컬 설치) ───
|