| name | bettermode-sdk |
| description | SDK 스크립트 기반 Bettermode 포스트 CRUD 및 Space 멤버 관리. 게시글 생성/조회/수정/삭제, 게시판 멤버 초대/내보내기. "베터모드", "bettermode", "포스트", "게시글", "게시판 초대", "멤버 초대/내보내기" 등 언급 시 사용. BETTERMODE_CLIENT_ID + BETTERMODE_CLIENT_SECRET 필수. |
Bettermode SDK Skill
SDK 스크립트로 Bettermode 포스트 CRUD. GraphQL 기반으로 GPTers 프록시 API와 통신합니다.
주요 기능
- ✅ Post 생성 (Create) - 제목, HTML 본문, 커스텀 필드로 게시글 작성 + 작성자 자동 설정
- ✅ Post 조회 (Read) - 목록 조회, 단건 조회 (커스텀 필드 포함), 검색
- ✅ Post 수정 (Update) - 제목, 본문, 커스텀 필드, 작성자 변경
- ✅ Post 삭제 (Delete) -
--confirm 안전장치 포함
- ✅ Post Type 동기화 - 사용 가능한 포스트 타입 스키마 캐싱
- ✅ Space 조회 - 게시판 정보, Role 목록 조회
- ✅ Space 멤버 관리 - 게시판 멤버 초대/내보내기
- ✅ 멤버 조회 - 이름/닉네임/이메일/전화번호로 bettermodeUserId 조회 (로컬 + Airtable fallback)
⚠️ 필수: 게시글 생성 전 반드시 확인할 3가지
포스트 생성 요청을 받으면 아래 3가지를 반드시 사용자에게 확인하세요:
1. 작성자 (누구 이름으로 올릴지)
bun run ~/.claude/skills/bettermode-sdk/scripts/lookup-member.ts --list
- 사용자가 명시적으로 작성자를 지정하지 않으면 → 현재 대화 중인 사용자 본인이 작성자
- 사용자를 이름/별칭으로 식별:
bun run lookup-member.ts --name "다혜"
- 식별 안 되면 전화번호 요청:
bun run lookup-member.ts --phone "01012345678"
- 조회된
bettermodeUserId를 create-post.ts --ownerId에 전달
2. 게시판 (어떤 Space에 올릴지)
cat ~/.claude/skills/bettermode-sdk/references/config.json
사용자에게 어떤 게시판에 올릴지 물어보세요. --spaceId 또는 --space 별칭으로 지정합니다.
3. 게시글 유형 (어떤 Post Type으로 올릴지)
cat ~/.claude/skills/bettermode-sdk/references/post-types.json
주요 Post Type:
ysHbSWVC5pKKZ0K — 스터디
KLxSodedLeDUiTj — 사례게시글
70cQB70yFjV8o9X — 포스트 (일반)
PQi3CLXSRYqO9uD — 질문
빠른 시작 워크플로우
1. 크레덴셜 설정
스킬 내부에 references/.env 파일이 있으면 자동으로 로드됩니다 (별도 설정 불필요).
최초 설치 시 .env 파일이 없는 경우:
cp ~/.claude/skills/bettermode-sdk/references/.env.example \
~/.claude/skills/bettermode-sdk/references/.env
우선순위: process.env (export/프로젝트 .env) > references/.env (스킬 내부)
2. Post Type 동기화 (최초 1회)
bun run ~/.claude/skills/bettermode-sdk/scripts/sync-post-types.ts
3. 포스트 생성 (작성자 자동 설정)
bun run ~/.claude/skills/bettermode-sdk/scripts/lookup-member.ts --name "다혜"
bun run ~/.claude/skills/bettermode-sdk/scripts/create-post.ts \
--title "첫 게시글" \
--content "<p>안녕하세요</p>" \
--spaceId "DpzZo3dmHTGH" \
--postTypeId "ysHbSWVC5pKKZ0K" \
--ownerId "pxKBUPj6EE"
4. 포스트 조회
bun run ~/.claude/skills/bettermode-sdk/scripts/list-posts.ts --limit 10
bun run ~/.claude/skills/bettermode-sdk/scripts/get-post.ts --id "postId"
스크립트
모든 스크립트는 ~/.claude/skills/bettermode-sdk/scripts/ 경로에 있습니다.
| 스크립트 | 목적 | 주요 옵션 |
|---|
lookup-member.ts | 멤버 조회 (이름/닉네임/이메일/전화번호→bettermodeUserId) | --name, --nickname, --email, --phone, --list |
create-post.ts | 새 포스트 생성 | --title, --content, --spaceId, --postTypeId, --ownerId, --publish, --fields |
update-post.ts | 포스트 수정 | --id, --title, --content, --content-file, --ownerId, --publish, --fields, --postTypeId |
delete-post.ts | 포스트 삭제 | --id, --confirm |
list-posts.ts | 포스트 목록 조회 | --limit, --offset, --spaceId, --query |
get-post.ts | 단일 포스트 조회 | --id |
sync-post-types.ts | Post Type 스키마 동기화 | --help |
get-space.ts | Space(게시판) 정보 조회 | --id, --ids |
get-space-roles.ts | Space Role 목록 조회 + type 필터 | --spaceId, --type |
invite-members.ts | Space에 멤버 초대 | --spaceId, --memberIds, --roleId |
remove-members.ts | Space에서 멤버 내보내기 | --spaceId, --memberIds, --validate |
작성자 조회 (lookup-member.ts)
bun run lookup-member.ts --list
bun run lookup-member.ts --name "다혜"
bun run lookup-member.ts --name "눈오지"
bun run lookup-member.ts --nickname "눈오지"
bun run lookup-member.ts --email "dahye@gpters.org"
bun run lookup-member.ts --email "cpuxp11@gmail.com"
bun run lookup-member.ts --phone "01044535752"
조회 우선순위: 모든 옵션(name/email/phone)이 로컬 team-members.json → Airtable 멤버(Sync) → Airtable 결제(Sync) 순서로 fallback
포스트 생성 (create-post.ts)
bun run create-post.ts \
--title "제목" \
--content "<p>본문</p>" \
--spaceId "DpzZo3dmHTGH" \
--postTypeId "ysHbSWVC5pKKZ0K" \
--ownerId "pxKBUPj6EE"
bun run create-post.ts --title "제목" --content-file ./post.html --spaceId "abc123"
bun run create-post.ts --title "초안" --content "<p>내용</p>" --publish false
bun run create-post.ts \
--title "AI 스터디" \
--content "<p>소개</p>" \
--spaceId "DpzZo3dmHTGH" \
--postTypeId "ysHbSWVC5pKKZ0K" \
--fields '{"partner":"홍길동","recruit_start":"2026-03-01","study_order":5}'
포스트 수정 (update-post.ts)
bun run update-post.ts --id "postId" --title "수정된 제목"
bun run update-post.ts --id "postId" --content "<p>수정된 본문</p>"
bun run update-post.ts --id "postId" --title "새 제목" --content-file ./updated.html
bun run update-post.ts --id "postId" --ownerId "newUserId"
bun run update-post.ts --id "postId" \
--postTypeId "ysHbSWVC5pKKZ0K" \
--fields '{"partner":"김철수","recruit_end":"2026-04-01"}'
포스트 삭제 (delete-post.ts)
bun run delete-post.ts --id "postId" --confirm
⚠️ 삭제는 soft delete — API로 조회는 가능하지만 웹 UI에서 숨겨집니다. undoPostsDeletion mutation으로 복구 가능.
포스트 조회 (list-posts.ts, get-post.ts)
bun run list-posts.ts --limit 10
bun run list-posts.ts --space "작성중" --limit 20
bun run get-post.ts --id "postId"
Space 관리 (get-space.ts, get-space-roles.ts, invite-members.ts, remove-members.ts)
bun run get-space.ts --id "DpzZo3dmHTGH"
bun run get-space-roles.ts --spaceId "DpzZo3dmHTGH" --type "member"
bun run invite-members.ts --spaceId "DpzZo3dmHTGH" --memberIds "userId1,userId2" --roleId "roleId"
bun run remove-members.ts --spaceId "DpzZo3dmHTGH" --memberIds "userId1,userId2"
bun run remove-members.ts --spaceId "DpzZo3dmHTGH" --memberIds "userId1" --validate
Space 지정 방법
우선순위 (높은 순):
--spaceId "직접ID" (CLI 인자)
--space "별칭" (config.json의 spaces 매핑)
config.json의 defaultSpaceId
- 미지정 시 에러
bun run create-post.ts --spaceId "abc123" --title "Test"
bun run create-post.ts --space "event" --title "Test"
커스텀 필드 (Custom Fields)
Post Type별로 정의된 커스텀 필드를 --fields 옵션으로 전달합니다.
사용법
bun run create-post.ts \
--title "제목" --content "<p>내용</p>" \
--postTypeId "ysHbSWVC5pKKZ0K" \
--fields '{"partner":"홍길동","recruit_start":"2026-03-01","study_order":5}'
지원 타입
| postFields 타입 | mappingFields 타입 | 값 예시 |
|---|
text | text | "홍길동" |
richText | html | "<p>소개</p>" |
date | date | "2026-03-01" |
number | number | 5 |
boolean | boolean | true |
커스텀 필드 key 확인
cat ~/.claude/skills/bettermode-sdk/references/post-types.json
각 PostType의 postFields.fields[] 배열에 사용 가능한 key, type, name이 정의되어 있습니다.
주요 PostType 커스텀 필드 예시
스터디 (ysHbSWVC5pKKZ0K): partner(text), recruit_start(date), recruit_end_time(date), study_start(date), study_end(date), study_order(number), time(text), category(text), 등 43개
커뮤니티 이벤트 (NR49kR6XEqUbEEr): date_time(date), end_date(date), location(text), speaker(text), event_link(text), category(text), 등 13개
조회 시 커스텀 필드 확인
get-post.ts로 조회하면 fields 배열에 모든 커스텀 필드 key/value가 포함됩니다.
Anti-Patterns (절대 하지 말 것)
| 금지 항목 | 올바른 방법 |
|---|
| curl로 GraphQL 직접 호출 | SDK 스크립트 사용 (list-posts.ts 등) |
| mappingFields 수동 구성 | prepareMappingFields() 사용 (lib/bettermode.ts) |
| 환경변수 검증 생략 | validateEnv() 호출 필수 |
| bettermodeUserId 추측/하드코딩 | lookup-member.ts로 조회 후 사용 |
| 작성자/게시판/유형 확인 생략 | 3가지 반드시 사용자에게 확인 |
| 삭제 시 사용자 확인 생략 | get-post.ts로 확인 → 사용자 동의 → 삭제 |
| spaceId 하드코딩 | config.json 별칭 또는 --spaceId 사용 |
| Post Type ID 추측 | sync-post-types.ts 실행 후 확인 |
콘텐츠 작성 규칙
지원 HTML
- 기본 태그:
<p>, <strong>, <em>, <a>, <ul>, <ol>, <li>, <br>
미지원 (사용 금지)
- 이미지/비디오 임베딩 (
<img>, <video>, <iframe>)
- 복잡한 레이아웃 (
<div>, <table>)
- 인라인 스타일 (
style="...")
긴 HTML 처리
bun run create-post.ts --content "<p>Very long...</p>"
echo "<p>Very long...</p>" > /tmp/content.html
bun run create-post.ts --content-file /tmp/content.html
에러 복구 절차
| 에러 | 원인 | 복구 방법 |
|---|
AUTHENTICATION_REQUIRED | 크레덴셜 누락/오류 | echo $BETTERMODE_CLIENT_ID $BETTERMODE_CLIENT_SECRET 확인 → 재설정 |
Invalid postTypeId | 잘못된 Post Type ID | bun run sync-post-types.ts → post-types.json 확인 → 재시도 |
Space not found | Space ID 오류 | config.json 확인 → --spaceId 직접 지정 |
Rate limited (429) | API 호출 과다 | 스크립트가 자동 지수 백오프 재시도 (최대 5회). 지속 실패 시 대기 |
GraphQL errors | 필수 필드 누락, 잘못된 타입, 권한 부족 | 에러 메시지 확인 → 필드/타입 수정 |
| Airtable 크레덴셜 누락 | .env에 AIRTABLE_API_KEY 없음 | references/.env 확인 → 값 채우기 |
| 멤버 조회 실패 | 3단계 fallback 모두 실패 | 전화번호 재확인 → --ownerId 없이 진행 (API 기본 작성자) |
체크리스트
게시글 생성 전 (MANDATORY)
게시글 삭제 전 (MANDATORY)
참조 문서
시나리오 예시, 작성자 식별 흐름도, 상세 워크플로우는 references/llm-rules.md 참조.
제약사항
구현됨 (Full CRUD + Custom Fields)
- ✅ Post 생성 (Create - 제목, 본문, 커스텀 필드)
- ✅ Post 조회 (Read - 목록, 단건, 커스텀 필드 포함)
- ✅ Post 수정 (Update - 제목, 본문, 커스텀 필드, 작성자)
- ✅ Post 삭제 (Delete - soft delete,
--confirm 필수)
- ✅ Post Type 동기화
- ✅ Space 조회 (게시판 정보, Role 목록)
- ✅ Space 멤버 관리 (초대, 내보내기)
미구현 (향후 범위)
- ❌ Reply/Comment 관리
- ❌ 파일 업로드 / 이미지 임베딩
- ❌
undoPostsDeletion (삭제 복구)
미구현 작업 시도 시:
- 명확히 "미구현" 안내
- 수동 작업 또는 Bettermode 웹 UI 사용 권장
필수 규칙
- 게시글 생성 전 3가지 확인: 작성자(누구) + 게시판(어디) + 유형(어떤 타입) — 반드시 사용자에게 물어보기
- 작성자 자동 설정: 명시적 지정 없으면 현재 사용자 본인.
lookup-member.ts로 bettermodeUserId 조회 → --ownerId에 전달
- 작성자 미식별 시:
--name이 자동으로 Airtable 닉네임도 검색. 그래도 못 찾으면 전화번호/이메일을 물어보기
- 삭제 시 반드시 확인:
delete-post.ts는 --confirm 필수. 삭제 전 사용자에게 "정말 삭제할까요?" 확인
- SDK 스크립트 사용: curl 직접 호출 금지
- 긴 HTML:
--content-file 옵션 사용하여 파일로 전달
시나리오별 워크플로우 예시는 references/llm-rules.md 참조.