Skip to content

feat: rn-mcp CLI with Snapshot + Refs pattern#125

Merged
ohah merged 17 commits intomainfrom
feat/cli-snapshot-refs
Mar 21, 2026
Merged

feat: rn-mcp CLI with Snapshot + Refs pattern#125
ohah merged 17 commits intomainfrom
feat/cli-snapshot-refs

Conversation

@ohah
Copy link
Owner

@ohah ohah commented Mar 20, 2026

Summary

  • agent-browser 스타일의 Snapshot + Refs 패턴을 React Native에 적용한 CLI 도구 (rn-mcp)
  • AI 에이전트(Claude Code, Codex 등)가 셸에서 직접 앱을 제어 — MCP 도구 대비 토큰 50~70% 절감
  • init-agent 명령으로 AGENTS.md/CLAUDE.md에 CLI 가이드 자동 추가 (한영 지원)

주요 명령어

rn-mcp snapshot -i           # interactive 요소를 @e1, @e2 refs로 반환
rn-mcp tap @e3               # ref로 탭 (좌표 자동 변환)
rn-mcp type @e5 "텍스트"      # TextInput에 입력
rn-mcp assert text "..."     # 텍스트 검증 (exit 0/1)
rn-mcp init-agent --lang ko  # AGENTS.md/CLAUDE.md 가이드 추가

아키텍처

  • WebSocket extension client로 기존 MCP 서버에 연결 (별도 서버 불필요)
  • ~/.rn-mcp/session.json에 refs 매핑 저장 (CLI 호출 간 상태 공유)
  • idb/adb 직접 실행 (기존 유틸 재사용)
  • bin: rn-mcp → dist/cli.js (기존 패키지에 entry point 추가)

파일 구조

파일 역할
src/cli.ts CLI entry point + --help + 라우팅
src/cli/ws-client.ts WebSocket extension client
src/cli/session.ts ~/.rn-mcp/session.json 세션 관리
src/cli/ref-map.ts Snapshot → @ref 할당
src/cli/commands.ts 명령어 구현 (status, snapshot, tap, type, assert, query, swipe, key, screenshot, init-agent)
src/cli/agent-guide.ts AGENTS.md/CLAUDE.md 가이드 텍스트 (한영)
src/shared/interactive-types.ts INTERACTIVE_TYPES 공유 상수 (take-snapshot + ref-map)
docs/cli-spec.md CLI 설계 스펙 문서

CI 변경

  • test.yml: CLI smoke test + init-agent 통합 테스트 추가
  • e2e-ios.yml: YAML E2E 후 CLI smoke test 실행
  • e2e-android.yml: YAML E2E 후 CLI smoke test 실행 + adb PATH 설정 + libgl1-mesa-dri 삭제 제거
  • cli-smoke.sh: 10단계 CLI 통합 테스트 (status, snapshot, tap, assert, query, init-agent)

코드 리뷰 반영 (/simplify)

  • eval 코드 빌더 중복 제거 → buildQuerySelectorEvalCode 등 기존 export 재사용
  • INTERACTIVE_TYPES 중복 → shared/interactive-types.ts로 추출
  • assert text false-positive 수정 → :text() 셀렉터 기반
  • loadSession() 3회 호출 → 1회로
  • Android screencap 이중 실행 제거
  • WebSocket close 핸들러 추가
  • 죽은 코드/import 제거

Test plan

  • 유닛 테스트 24개 (ref-map, session, agent-guide, CLI help)
  • CI smoke test (--help, --version, init-agent)
  • E2E iOS — CLI smoke test 10단계 통과
  • E2E Android — CLI smoke test 10단계 통과
  • 린트 (oxlint + oxfmt) 통과
  • 전체 CI 통과 확인

🤖 Generated with Claude Code

ohah and others added 4 commits March 21, 2026 04:54
agent-browser 스타일의 Snapshot + Refs 패턴을 React Native에 적용한 CLI 도구.
AI 에이전트(Claude Code, Codex 등)가 셸에서 직접 앱을 제어할 수 있도록 함.

주요 기능:
- snapshot -i: Fiber 트리에서 interactive 요소를 @e1, @e2 refs로 반환
- tap/type/swipe: refs로 요소 조작 (좌표 자동 변환, iOS orientation 자동 처리)
- assert: 텍스트/가시성 검증 (exit code 0/1)
- init-agent: AGENTS.md/CLAUDE.md에 CLI 가이드 자동 추가 (한영 지원)
- query: 셀렉터 직접 사용 가능

구현:
- WebSocket extension client로 기존 MCP 서버에 연결 (별도 서버 불필요)
- ~/.rn-mcp/session.json에 refs 매핑 저장 (CLI 호출 간 상태 공유)
- idb/adb 직접 실행 (기존 유틸 재사용)
- bin: rn-mcp → dist/cli.js (기존 react-native-mcp-server와 같은 패키지)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CI에서 기존 YAML E2E 후 CLI smoke test를 실행:
- MCP 서버 백그라운드 시작 → 앱 연결 대기
- snapshot -i, tap @ref, assert text, query, init-agent 검증
- iOS/Android 양쪽 워크플로우에 추가

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- eval 코드 빌더: 인라인 중복 → buildQuerySelectorEvalCode 등 기존 export 재사용
- buildEvalCall() 헬퍼: __REACT_NATIVE_MCP__ 가드 패턴 통합
- INTERACTIVE_TYPES: take-snapshot + ref-map 중복 → shared/interactive-types.ts로 추출
- cmdTap: loadSession() 3회 호출 → 1회로 수정 (디스크 읽기 3→1)
- cmdScreenshot: Android screencap 이중 실행 + 죽은 dynamic import 제거
- assert text: JSON.stringify false-positive → :text() 셀렉터 기반으로 수정
- cmdQuery: 요소 포맷 중복 → formatElementLine() 헬퍼 추출
- ws-client: WebSocket close 핸들러 추가 (연결 끊김 시 pending reject)
- 죽은 코드 제거: evalAssertText, 미사용 existsSync import
- 인라인 상수 → 모듈 레벨 (ANDROID_KEYCODES, VALID_DIRECTIONS)
- cmdInitAgent: TOCTOU (existsSync→readFileSync) → try/catch로 수정

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@ohah ohah self-assigned this Mar 20, 2026
@ohah ohah added the enhancement New feature or request label Mar 20, 2026
ohah and others added 13 commits March 21, 2026 05:31
- MCP 서버 백그라운드 시작 시 stdin을 /dev/null로 리다이렉트 (stdin EOF로 인한 즉시 종료 방지)
- resolveUdid/resolveSerial에 MCP 내부 deviceId("ios-1") 대신 undefined 전달 (자동 감지)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
MCP 서버는 stdio transport를 사용하므로 stdin EOF 시 즉시 종료됨.
sleep infinity를 파이프로 연결하여 stdin을 열어둔 상태로 유지.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
COUNT_REF 추출 시 grep 매칭 실패 → pipefail → 스크립트 종료.
|| true 추가로 grep 실패를 허용 (빈 결과 시 셀렉터 fallback 사용).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
cd $(mktemp -d) 후 상대 경로가 깨지는 문제.
SCRIPT_DIR 기반 절대 경로로 수정.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Android SDK platform-tools/emulator PATH를 명시적으로 추가
- adb start-server를 에뮬레이터 부팅 전에 실행 (adb daemon 연결 실패 방지)
- emulator-boot-timeout: 600 명시적 설정

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
libgl1-mesa-dri 삭제 시 libgl1, libglx0, libglx-mesa0이 연쇄 제거되어
에뮬레이터가 그래픽 라이브러리를 찾지 못해 부팅 무한 대기 발생.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
이전 libgl1-mesa-dri 삭제 환경에서 생성된 깨진 AVD 스냅샷 무효화.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
sleep infinity 파이프 방식은 cleanup 시 프로세스 그룹이 남아서 타임아웃.
FIFO(named pipe) + fd 3으로 stdin을 열어두고, cleanup 시 fd 닫기 → EOF → 정상 종료.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
FIFO 방식은 macOS CI에서 exec 3>fifo 블로킹 문제 발생.
tail -f /dev/null | node 방식으로 단순화:
- tail이 stdin을 영구히 열어둠
- node kill → tail broken pipe → 자동 종료
- macOS/Linux 모두 동작

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
tail -f /dev/null이 node kill 후에도 살아남아 5분 타임아웃 발생.
서브셸로 감싸고 pkill -P로 자식 프로세스까지 확실히 종료.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
pkill -P로 자식 kill 후에도 tail -f /dev/null이 남아서 emulator-runner가
script 종료를 못 함 → 1시간 타임아웃.
pkill -f "tail -f /dev/null"로 잔여 프로세스까지 확실히 정리.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- en/mcp/cli.md, ko/mcp/cli.md 추가
- _meta.json 사이드바에 "rn-mcp CLI (Snapshot + Refs)" 항목 추가
- 워크플로우, 명령어 레퍼런스, refs 시스템, 예시 포함

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- snapshot --max-depth 기본값(30) 명시
- swipe --dist 단위를 dp로 명시 (JSDoc px→dp 수정 포함)
- 전역 옵션에 -h/--help, -v/--version 추가

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@ohah ohah merged commit 71af491 into main Mar 21, 2026
4 checks passed
@ohah ohah deleted the feat/cli-snapshot-refs branch March 21, 2026 13:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant