CLI 사용하기
reopt-data CLI를 설치하고 브라우저 로그인, 계정 조회, 프로젝트 관리, 분석 조회, 카탈로그·프로젝트 정의·소스맵 자동화를 사용합니다.
reopt-data는 사람, CI, 에이전트가 같은 방식으로 리옵트 데이터를 다루는 CLI입니다.
브라우저에서 개인 세션을 승인하면 내 계정을 조회할 수 있고, 배포 자격증명을 설정하면 프로젝트·카탈로그·쿼리·소스맵을 다룰 수 있습니다.
설치하고 로그인하기
Node.js 22 이상에서 전역으로 설치하거나 npx로 바로 실행하세요.
npm install -g @reopt-ai/data-cli
reopt-data --help
# 설치 없이 확인
npx -y @reopt-ai/data-cli --help개인 계정으로는 다음 네 명령을 씁니다.
reopt-data login
reopt-data status --format text
reopt-data account show --format table
reopt-data logout목적별 자격증명
개인 로그인과 배포 자격증명은 권한도 보관 방식도 다릅니다.
| 목적 | 자격증명 | 사용하는 명령 |
|---|---|---|
| 내 계정과 접근 범위 확인 | 브라우저에서 승인한 사용자 세션 | status, account show, logout |
| 프로젝트·카탈로그 운영 | REOPT_DATA_ORG_KEY | project *, event *(init·types 제외), pull·push·diff·verify·import·unlink, 소스맵 |
| 분석 쿼리와 세그먼트 | REOPT_DATA_CLIENT_ID + REOPT_DATA_CLIENT_SECRET | query *, segment * |
| 자격증명 없이 실행 | 없음 | link, config show, event init, event types, sourcemap inject |
개인 CLI 세션의 현재 scope는 account:read뿐입니다.
그래서 reopt-data login으로 얻은 세션은 프로젝트 관리나 분석 쿼리에 필요한 조직 키·클라이언트 자격증명을 대신하지 않습니다.
반대로 배포 키만 설정해서는 account show를 실행할 수 없습니다.
조직 키와 client secret은 처음 만들 때 한 번만 내려옵니다.
- 조직 키는 콘솔에서 발급하지 않습니다. 필요하면 문의 창구로 요청하세요. 잃어버린 키는 다시 볼 수 없고 새로 발급받아야 합니다.
project create의 응답에는 서버용 client의 ID(clients.server.id)가 들어 있고,clientSecret은 처음 만들 때만 함께 내려옵니다. 잃어버린 secret은project rotate-secret으로 다시 발급합니다.
브라우저 로그인 과정
- CLI가 짧은 확인 코드와 브라우저 URL을 발급받습니다.
- 브라우저가 열리면 로그인된 Reopt 계정으로, 표시된 코드가 같은지 확인하고 승인합니다.
- CLI가 승인 상태를 기다렸다가 한 번만 세션으로 교환합니다.
- 세션을
~/.reopt/data/auth.json에 원자적으로 저장합니다.
비밀번호와 브라우저 쿠키는 터미널로 전달되지 않습니다. 브라우저 URL에는 사람이 확인할 코드만 들어가고, 별도의 device secret은 CLI 메모리에만 둡니다. 브라우저 쿠키와 CLI bearer는 서버에서 audience가 분리되어 있어 서로 대신 사용할 수 없습니다.
원격 서버나 브라우저를 열 수 없는 환경에서는 URL만 출력하세요.
reopt-data login --no-browser이미 유효한 로그인이 있으면 login은 그 세션을 재사용합니다.
새 세션으로 바꾸려면 --force를 사용하세요. 새 세션이 안전하게 저장된 뒤 이전 서버 세션을 해제합니다.
reopt-data login --forcePOSIX 환경에서 인증 디렉터리는 0700, 파일은 0600으로 유지됩니다.
테스트나 격리된 실행에서는 REOPT_DATA_AUTH_FILE로 경로를 바꿀 수 있습니다.
로그인 상태 확인하기
status는 로컬 파일이 있는지만 보지 않고 서버에서 세션을 검증합니다.
토큰 값은 출력하지 않으며, 서버가 만료 시각을 연장했다면 로컬 파일에도 새 시각을 저장합니다.
reopt-data status
reopt-data status --format textsession 필드는 다음처럼 해석하세요.
| 값 | 의미 | 다음 행동 |
|---|---|---|
valid | 서버 검증까지 통과했습니다. | 그대로 사용합니다. |
missing | 저장된 사용자 세션이 없습니다. | reopt-data login을 실행합니다. |
invalid | 서버가 만료되거나 해제된 세션으로 판정했습니다. | login --force로 교체합니다. |
corrupt | 인증 파일 형식이나 서버 origin이 올바르지 않습니다. | login --force로 교체합니다. |
unreachable | 세션은 있지만 서버에 연결할 수 없어 판정하지 못합니다. | URL과 네트워크를 먼저 확인합니다. |
status는 조직 키와 클라이언트 자격증명의 설정 여부도 함께 보여줍니다. 값은 출력하지 않습니다.
계정과 접근 가능한 프로젝트 확인하기
reopt-data account show
reopt-data account show --format table응답에는 로그인 사용자, CLI 세션의 scope·만료·최근 사용 시각, 사용자가 멤버인 조직과 활성 프로젝트가 들어갑니다. 조직 키, write key, client secret 같은 배포 자격증명은 반환하지 않습니다.
account show는 먼저 서버에서 사용자 세션을 다시 검증하고 account:read scope를 확인합니다.
브라우저 세션 쿠키를 bearer로 보내거나 CLI 토큰을 브라우저 쿠키로 사용하면 모두 거절됩니다.
로그아웃과 세션 폐기
reopt-data logoutlogout은 저장된 서버 세션을 폐기한 뒤 로컬 인증 파일을 지웁니다.
서버에 연결하지 못해 폐기를 확인하지 못해도 로컬 파일은 제거하고 경고를 출력합니다.
REOPT_DATA_USER_TOKEN으로 주입한 세션은 실행 환경이 소유하므로 CLI가 폐기하거나 지우지 않습니다.
로그아웃 뒤에도 이 변수가 설정되어 있으면 계속 사용되므로 secret manager나 셸 환경에서 직접 제거하세요.
배포 자격증명 설정하기
반복 실행과 CI에서는 플래그보다 환경변수를 사용하세요. 플래그 값은 셸 히스토리와 프로세스 목록에 남을 수 있습니다.
export REOPT_DATA_ORG_KEY="..."
export REOPT_DATA_CLIENT_ID="..."
export REOPT_DATA_CLIENT_SECRET="..."필요한 자격증명이 없으면 CLI는 네트워크 요청 전에 종료 코드 2로 실패하고 설정할 변수 이름을 알려줍니다.
CI secret store에는 실제 값만 넣고 로그, 저장소, reopt-data.config.*에는 기록하지 마세요.
출력과 입력 형식
기본 출력은 JSON입니다. stdout에는 결과만 쓰고, 진행 상황과 오류 envelope는 stderr에 씁니다.
reopt-data project list --format json
reopt-data project list --format table
reopt-data project list --format csv
reopt-data account show --format yamlproject list는 --organization-id가 필요합니다. 이 문서의 예시는 아래 저장소를 프로젝트에 연결하기로 조직과 프로젝트를 연결해 둔 저장소를 가정합니다.
필드 선택과 cursor 전체 순회를 조합할 수 있습니다.
reopt-data project list --fields id,name --page-all --page-limit 20JSON에서 --page-all을 쓰면 배열 하나가 아니라 레코드당 한 줄인 NDJSON을 출력합니다.
--page-limit의 기본값은 10입니다. 다음 cursor가 남아 있는데 --page-limit에 도달하면 종료 코드 6으로 끝나 결과가 잘렸음을 알립니다.
login --format json도 진행 중 결과를 전달해야 하므로 verification_uri, polling, success 이벤트를 NDJSON으로 출력합니다.
세션 토큰과 device secret은 포함하지 않습니다.
입력은 플래그, JSON 문자열, 파일, stdin으로 줍니다. --input과 플래그를 함께 주면 플래그의 값이 --input의 같은 필드를 덮어씁니다.
reopt-data query funnel --input @funnel.json
echo '{"projectId":"prj_123"}' | reopt-data project get --input @-모든 옵션은 실행 코드와 같은 schema에서 생성되는 help로 확인하세요.
reopt-data project create --help
reopt-data query funnel --help안전한 변경 명령
삭제와 secret 회전 같은 파괴적 명령은 --yes가 없으면 요청을 보내지 않고 종료 코드 7로 멈춥니다.
reopt-data project delete prj_123 --external-id brand_9 --yes
reopt-data project rotate-secret prj_123 <serverClientId> --yesproject delete는 프로젝트와 그 프로젝트의 모든 데이터를 지우며 되돌릴 수 없습니다.--external-id가 프로젝트에 기록된 값과 다르면 거절합니다. 콘솔에서 만든 프로젝트는 external-id가 없어서 이 명령으로 지울 수 없습니다.project rotate-secret은 서버용 client의 ID를 두 번째 인자로 받습니다. 이전 secret은 즉시 동작을 멈춥니다.
입력 검증, 자격증명 설정 여부 확인, --yes 확인은 모두 네트워크 요청 전에 끝납니다. --yes가 없어서 7로 끝났다면 서버에는 아무것도 보내지 않은 것입니다.
7은 서버가 파괴적 변경을 막았을 때도 나옵니다. 예를 들어 project update로 보존 기간을 줄이면서 --allow-destructive를 빼면, 요청이 나간 뒤 서버가 거절하고 7로 끝납니다.
서버가 돌려준 401·403은 2로, 그 밖의 400·404·409·422는 3으로 끝납니다. 이 두 코드는 요청 전과 후 양쪽에서 나올 수 있습니다. sourcemap upload도 같은 규칙을 따릅니다. 업로드를 시작하는 단계에서 400·404가 오면(프록시나 예전 배포가 답한 경우 포함) 다시 시도하지 않고 3으로 끝납니다.
sourcemap inject와 sourcemap upload는 --dry-run으로 파일 탐색과 계획을 먼저 확인할 수 있습니다.
지원하지 않는 명령에 --dry-run을 주면 무시하지 않고 종료 코드 3으로 실패합니다.
저장소를 프로젝트에 연결하기
reopt-data link는 저장소에 reopt-data.config.mjs를 만들어 프로젝트와 조직 ID를 기록합니다. 연결해 두면 --project-id와 --organization-id를 매번 주지 않아도 됩니다.
reopt-data link --project-id prj_123 --organization-id org_abc
reopt-data config show- 이 파일에는 ID와 경로만 넣습니다. 커밋되는 파일이라 키를 넣으면 종료 코드
4로 거절합니다. - 값이 정해지는 순서는 플래그, 환경변수, config 순입니다.
config show는 해석된 설정과 각 자격증명의 설정 여부만 보여주고 값은 출력하지 않습니다.--config <path>로 다른 위치의 config를 지정합니다. 기본은 현재 디렉터리에서 위로 올라가며 찾은 가장 가까운reopt-data.config.{mjs,js,json}입니다.
프로젝트 만들고 관리하기
조직 키로 프로젝트를 만들고 설정을 바꿉니다.
reopt-data project create --external-id brand_9 --name "Acme Shop" --domain shop.acme.com --timezone Asia/Seoul
reopt-data project get prj_123
reopt-data project update prj_123 --symbol-host-app studio-web--external-id가 멱등성 키입니다. 같은 값으로 다시 실행하면 새로 만들지 않고created: false로 답합니다. 이때writeKey와 서버 client ID는 다시 내려오고clientSecret만 빠집니다.- 같은
--external-id에 시간대나 보존 기간을 다르게 주면409 external_id_conflict로 거절합니다. project create의 응답에는 브라우저용writeKey와 서버용 client ID·secret이 들어 있습니다.project update에서 생략한 필드는 그대로 둡니다. 비울 수 있는 필드는null을 주면 값을 지우고, 시간대처럼 비울 수 없는 필드에null을 주면 거절합니다. 보존 기간을 줄일 수 있는 변경은--allow-destructive --yes가 함께 필요합니다.
분석 쿼리와 세그먼트 조회하기
클라이언트 자격증명으로 계산된 분석 결과를 읽습니다. 모두 읽기 전용입니다.
reopt-data query timeseries --start-date 2026-08-01 --end-date 2026-08-31 --event-name purchase
reopt-data query funnel --start-date 2026-08-01 --end-date 2026-08-31 --steps view_item --steps add_to_cart --steps purchase
reopt-data query retention --help
reopt-data query traffic-overview --start-date 2026-08-01 --end-date 2026-08-31
reopt-data query traffic-sources --help
reopt-data segment list --format table
reopt-data segment preview --segment-id seg_123- 날짜는
YYYY-MM-DD이고--timezone을 주지 않으면 프로젝트 시간대로 자릅니다. query funnel의 단계는 순서대로--steps를 반복해 2~10개를 줍니다.query timeseries에서--breakdown과--segment-id는 함께 쓸 수 없습니다.- 세그먼트는 조회만 합니다.
segment list의deviceCount가null이면 0명이 아니라 아직 계산된 적이 없는 상태입니다.
이벤트 카탈로그를 코드로 관리하기
프로젝트 저장소의 reopt-data.events.json을 기준으로 서버 카탈로그를 동기화합니다.
reopt-data event init --project-id prj_123
reopt-data event pull
reopt-data event diff --format text
reopt-data event push # 계획만 출력
reopt-data event push --apply --yes # 실제 반영
reopt-data event verify # drift가 있으면 exit 8
reopt-data event types --out src/reopt-events.d.ts파일에서 생략한 필드는 기존 값을 유지하지 않고 계약의 기본값이 됩니다.
파일에서 뺀 이벤트는 삭제되지 않고 archived가 됩니다.
event push는 마지막 동기화 시각으로 전체 배치를 비교합니다. 콘솔 변경과 충돌하면 일부만 반영하지 않고 전부 거절합니다.
동기화 지점은 파일 옆의 reopt-data.events.lock.json에 기록되니 함께 커밋하세요.
변경에는 등급이 있습니다. 표시 필드만 바뀌는 safe는 --apply만으로 반영됩니다. conversion·status처럼 숫자가 달라지는 metric-changing과 롤업 재계산을 부르는 expensive(rollupProperties)는 --yes가 필요합니다.
파일 없이 이벤트 하나만 고치거나 이력을 볼 수도 있습니다.
reopt-data event set-meta prj_123 purchase --conversion --rollup-properties plan --rollup-properties currency
reopt-data event history purchase --limit 20event types는 파일만으로 오프라인에서 동작하고 속성 값의 타입은 unknown으로 둡니다. --with-types를 주면 프로젝트의 속성 카탈로그에서 타입을 읽어 오며, 이때는 조직 키가 필요합니다.
event pull은 사람이 설명을 달았거나 숨긴 속성만 파일에 씁니다. 관측된 속성을 전부 쓰려면 --include-discovered를 주세요. 이때는 배포마다 파일이 달라질 수 있습니다.
version: 2 파일은 properties 절에 속성의 의미(타입·설명·숨김)도 함께 씁니다.
이벤트와 달리 파일에 없는 속성은 관측된 그대로 둡니다. 속성은 수집으로 생기는 것이라 파일로는 없앨 수 없기 때문입니다.
그래서 verify는 기본으로 미선언 속성을 지적하지 않습니다. 저장소가 카탈로그를 소유한다면 아래 둘 중 골라 켜세요.
reopt-data event verify --strict-properties # 콘솔에서 손댔는데 파일에 없는 속성
reopt-data event verify --strict-observed # 수집이 관측만 했는데 파일에 없는 속성두 옵션은 서로를 포함하지 않고 보고 대상도 겹치지 않습니다. 둘 다 필요하면 함께 주세요.
--strict-observed는 SDK 소유 키($ 예약 키와 자동 이벤트 속성)를 제외합니다.
--strict-observed는 속성을 추가한 PR에서는 실패하지 않습니다. 그 시점에는 서버가 그 키를 본 적이 없기 때문입니다.
배포 뒤 첫 이벤트가 들어와야 행이 생기므로, 실패는 관계없는 다음 PR에서 납니다. 이 점을 감수할 저장소에서만 켜세요.
프로젝트 설정·룰·알림을 코드로 관리하기
프로젝트 설정, 에러 트래킹 룰, 알림도 카탈로그와 같은 규칙으로 저장소의 reopt-data/ 디렉터리에 선언할 수 있습니다.
여섯 동사는 모두 최상위 명령입니다. 표를 출력하는 명령은 diff입니다. status는 로그인 상태를 보여줍니다.
reopt-data pull # 서버 → reopt-data/*.json + reopt-data.lock.json
reopt-data diff --format text # 종류 / key / 작업 / 등급
reopt-data verify # CI 게이트. 어긋나면 exit 8
reopt-data push --apply --yes # 반영. 보존 기간을 줄일 수 있는 변경은 --allow-destructive도 필요
reopt-data import error-rule <id> --key ignore-vendor
reopt-data unlink alert purchase-drop
reopt-data --env staging pull # config `environments`로 프로젝트를 고르고 lock을 환경별로파일은 key가 있는 룰·알림만 관리하고, 콘솔에서 만든 항목은 건드리지 않습니다. 웹훅 URL은 "${env:SLACK_ALERTS_URL}"처럼 환경 변수 이름으로 적으면 push 시점에 치환됩니다.
파일 형식, 등급, 충돌 해결, 환경 설정은 프로젝트를 코드로 관리하기에서 자세히 다룹니다.
소스맵을 CI에서 업로드하기
reopt-data sourcemap inject --dir .next/static
reopt-data sourcemap upload \
--dir .next/static \
--url-prefix https://shop.example.com/_next/static \
--project-id "$REOPT_DATA_PROJECT_ID" \
--release "$GIT_SHA" \
--delete-after-upload먼저 --dry-run으로 대상 파일과 업로드 계획을 확인하세요. dry run은 아무것도 바꾸지 않고 키도 필요 없습니다.
sourcemap inject는 빌드된 .js마다 내용에서 유도한 chunk ID를 새겨, URL이 바뀌어도 맵을 찾을 수 있게 합니다. 여러 번 실행해도 결과가 같습니다.
업로드 대상은 두 가지입니다.
| 대상 | 플래그 | 자격증명 |
|---|---|---|
| 프로젝트 하나 | --url-prefix + --project-id | 조직 키 |
| 여러 프로젝트를 그리는 한 번들 | --path-prefix + --host-app + --organization-id | 조직 키 |
일부 맵이 실패하면 종료 코드 6으로 끝나고 결과에 실패한 항목이 나옵니다. skipped가 0보다 큰데 종료 코드가 0이면 서버가 이미 가진 맵을 건너뛴 것입니다.
--delete-after-upload는 서버에 저장된 것이 확인된 .map(이번에 올렸거나 이미 같은 내용이 있는 것)을 지웁니다. 업로드에 실패했거나 너무 커서 건너뛴 .map은 남기고, dry run에서는 지우지 않습니다.
프로젝트와 조직 host app 범위의 symbol set은 sourcemap list와 sourcemap delete로 조회하고 폐기합니다.
reopt-data sourcemap list --project-id prj_123
reopt-data sourcemap delete sym_123 --project-id prj_123 --yes
reopt-data sourcemap list --scope host --organization-id org_abc --host-app studio-web셸 completion과 에이전트 연동
현재 셸에 completion을 적용합니다.
# bash / zsh
source <(reopt-data completion bash)
source <(reopt-data completion zsh)
# fish
reopt-data completion fish | source에이전트가 명령 계약을 탐색해야 하면 실행 가능한 schema catalog를 사용하세요.
reopt-data tools --jsonMCP client에는 같은 도구 registry를 stdio 서버로 연결합니다.
{
"mcpServers": {
"reopt-data": {
"command": "npx",
"args": ["-y", "@reopt-ai/data-cli", "mcp"],
"env": {
"REOPT_DATA_ORG_KEY": "..."
}
}
}
}도구 이름은 reopt_data_<group>_<command> 형식입니다. 예: reopt_data_project_create, reopt_data_query_funnel.
login, status, logout은 MCP 도구로 노출되지 않습니다.
account show MCP 도구는 저장된 사용자 로그인 또는 REOPT_DATA_USER_TOKEN을 사용합니다.
배포 도구는 MCP process에 주입한 환경변수와 repository config를 사용합니다. 환경은 REOPT_DATA_ENV로만 고를 수 있습니다.
파괴적 도구는 CLI의 --yes 대신 confirmed: true가 필요합니다. event push처럼 계획에 따라 위험해지는 도구는 계획이 확인을 요구할 때만 confirmed: true가 필요합니다.
0이 아닌 종료 코드는 모두 MCP 오류 결과로 돌아옵니다.
종료 코드
| 코드 | 의미 | 처리 방법 |
|---|---|---|
0 | 성공 | 다음 단계로 진행합니다. |
1 | API·네트워크 오류 | retryAfterMs와 서버 상태를 확인합니다. |
2 | 인증 오류 | 필요한 자격증명을 설정하거나 회전합니다. |
3 | 입력 검증 오류·없는 리소스·충돌 | 인자와 details.issues를 수정합니다. |
4 | 환경·설정 오류 | URL, 파일, 선택 dependency를 확인합니다. |
5 | CLI 내부 오류 | request ID와 함께 버그로 보고합니다. |
6 | 부분 실패·잘린 pagination | stdout 결과와 stderr를 함께 확인합니다. |
7 | 확인 필요 | 영향을 확인한 뒤 --yes를 명시합니다. |
8 | 드리프트(카탈로그·프로젝트 정의) | pull, diff, push로 해소합니다. |
자주 막히는 지점
| 증상 | 확인할 것 |
|---|---|
| 브라우저가 열리지 않음 | login --no-browser의 URL을 복사하고 코드가 같은지 확인하세요. |
session: invalid | login --force로 서버 세션을 새로 발급하세요. |
session: unreachable | 네트워크 연결, DNS와 방화벽을 확인하세요. |
로그인했지만 project create가 실패함 | 개인 세션은 조직 키를 대신하지 않습니다. REOPT_DATA_ORG_KEY를 설정하세요. |
account show가 인증 오류로 실패함 | 사용자 세션이 있고 account:read scope로 발급됐는지 확인하세요. |
JSON parser가 login에서 실패함 | 로그인 출력은 JSON 문서 하나가 아니라 NDJSON 이벤트 stream입니다. |
| logout 뒤에도 로그인으로 표시됨 | REOPT_DATA_USER_TOKEN이 남았는지 확인하고 실행 환경에서 제거하세요. |
다음 단계
- 프로젝트에 첫 이벤트를 붙이려면 빠른 연동
- 카탈로그 의미와 변경 등급은 데이터 카탈로그
- 설정·룰·알림을 파일로 두는 흐름은 프로젝트를 코드로 관리하기
- 같은 기능의 HTTP API는 HTTP API