진행 중 · 2026년 5월 26일
ScreenBridge
AI가 시키는 추상적 지시('VS Code 열고 X 수정해')를 실제 화면 위의 구체적 포인터 액션으로 실시간 번역하는 macOS 도구. ScreenCaptureKit + Accessibility API + 비전 LLM.
- 역할
- Solo
- 스택
- Swift 6.3 · SwiftUI + AppKit · ScreenCaptureKit · AXUIElement · Vision OCR · Anthropic Claude Sonnet 4.6 (vision) · Gemini 2.5 Flash
프로젝트 로그
이 프로젝트를 만들면서 남긴 트러블슈팅 · 회고 · 업데이트의 시간순 기록.
2026년 6월 1일 주9 개 · 2 트러블슈팅 · 6 기술 회고 · 1 사용성 회고
GitHub Actions CI + Release — v0.3 Beta DMG 자동 build/sign/notarize pipeline
기술 회고2026년 6월 2일 · 4 분
v0.3 Beta DMG ship 자동화. ci.yml (push/PR → swift test) + release.yml (tag v* → Notarized DMG + GitHub Release). secret-driven (cert.p12 base64 + notarytool store-credentials). 박힌 거 macOS app distribution pipeline transferable.
Qwen AppDelegate 끼움 — Phase 9 박혔는데 호출 path 빠진 2일 (사용자 좌절 신호)
기술 회고2026년 6월 2일 · 4 분
Phase 9.0 Week 1 skeleton (26a1286) + Week 2-3 wire (59cc0cb) 박혀있는데 AppDelegate가 Qwen 호출 안 함 — 사용자 'Phase 9인데 안 됨' 좌절. env var SCREENBRIDGE_USE_LOCAL=1 toggle 박음. 3-step (skeleton → wire → wire AppDelegate)의 3번째 빠뜨림 pattern.
Layer 3 Region drag UI — NSPanel canBecomeKey + NSView drag handler
기술 회고2026년 6월 2일 · 6 분
Layer 3 API (commit ae07cec) 박은 후 사용자 박는 UI 박힘. NSPanel borderless + NSView mouseDown/Dragged/Up + keyDown. ESC/Return 종료 / Delete 마지막 제거. canBecomeKey override 박는 게 핵심. SettingsView regionsSection + menu-bar ⌥⌘R.
SensitivityRouter (Layer 2) 박음 — 19 bundle ID + fail-closed + 한국 PII 5개
기술 회고2026년 6월 2일 · 6 분
Workflow w99oanivx 박힌 v0.3 ship 4주 plan의 Week 3 task를 Week 1에 합쳐 박음. SensitivityRouter Layer 2 (19 bundleID deny-list + fail-closed) + 한국 PII 5개 (휴대폰/계좌/사업자/면허/여권). 5-layer 보안 4/5 박힘 (Layer 3 region opt-out만 남음).
Session Inspector — 별도 NSPanel + SwiftUI + actor→MainActor publish
기술 회고2026년 6월 2일 · 6 분
사용자 요청 '병렬로 문맥 트래킹 새로 띄워서'. 별도 floating NSPanel + SwiftUI ObservableObject + actor→MainActor publish 박음. 3 가치: 자녀가 어머님 옆에서 봄 / 기업 audit / 본인 디버그. ⌥⌘I hotkey + menu-bar item.
SettingsWindow blank content fix — NSHostingView + init-time styleMask
트러블슈팅2026년 6월 2일 · 5 분
사용자 dogfooding (2026-06-02) ⌘, 박은 후 Settings window 박혔는데 *content blank*. NSWindow init *후* styleMask 갱신이 NSHostingController layout invalidate. NSHostingView + win.contentView 직접 박은 거 + init 시점 styleMask + Autolayout 4 constraint로 fix.
v0.3 Week 1+2+3 task 연쇄 박음 — publish wire / ContentMasker / Settings / Probe scaffold
기술 회고2026년 6월 2일 · 5 분
사용자 '전부다 해라 계속 될떄까지 가보자' 신호 — Workflow w99oanivx 박힌 4주 plan의 Week 1+2+3 task 4 commit 연쇄 박음. publish wire (Inspector 갱신) + ContentMasker (Layer 2.5) + Settings (Privacy mode toggle) + Probe D-prime scaffold. 5-layer 보안 4/5 + Phase 9 measure 박힘 + setting UI 박힘.
Landing page 박음 — Apple-style + 어머님 + 빅테크 비교 + 5-layer 보안 표
사용성 회고2026년 6월 1일 · 5 분
사용자 요청 'landing 디렉토리 안에 컨셉에 맞게 박아줘' — single-page static HTML 박음 (995 lines, 외부 dep 0). Pretendard 한국어 + Apple-style minimal + 박힌 product identity (번역기 + user-in-the-loop + local-first + 어머님).
MAX_TOKENS hit + 스크롤 영역 visible-only — 사용자 dogfooding 첫 진짜 발견
트러블슈팅2026년 6월 1일 · 6 분
사용자 'github 알림 끄기' multi-step prompt 시도 중 step 5에서 응답 끊김 + '화면 안에서만 찾는다' 좌절. log 분석으로 maxOutputTokens 2048 부족 (Phase 7.0 schema 추가 후 갱신 안 됨) + SYSTEM_PROMPT에 스크롤 안내 clause 없음 발견. 2 fix 박음.
2026년 5월 25일 주31 개 · 1 업데이트 · 2 트러블슈팅 · 27 기술 회고 · 1 사용성 회고
Local-first 로드맵 — Apple FM 대기 + Qwen2.5-VL hybrid + 5-layer 보안 (출시 가능 path 확정)
기술 회고2026년 5월 31일 · 8 분
사용자 우려 정당. cloud only는 Operator/Manus 자리, 차별 lose. Workflow 5-agent local-vision-LLM survey로 path 확정: v0.2 SensitivityRouter (deny-list) → v0.3 Qwen2.5-VL-3B local → v0.4 Apple FM (WWDC26 dependent). 3-tier hybrid가 senior + enterprise + global 동시 만족하는 유일 path.
Qwen2.5-VL-3B MLXVLM wire — research synthesis vs pinned source 6 errors
트러블슈팅2026년 5월 31일 · 6 분
Phase 9.0 Week 2-3 QwenLocalDispatcher.analyze() wire 박는 동안 Workflow research synthesis가 박은 code sketch가 *최신 mlx-swift-lm 2026*에 맞춰져 있어 *pinned mlx-swift-examples 2.21*과 6개 API 충돌. .build/checkouts에서 pinned source 직접 grep하여 4 API drift + 2 Swift 6 strict concurrency fix. 결국 6.62s build pass + 133/133 tests.
스크린 LLM 에이전트 보안 — 사용자 우려부터 Local-first 결정까지 (ScreenBridge 회고)
기술 회고2026년 5월 31일 · 33 분
ScreenBridge 박는 1개월 동안 사용자가 박은 보안 우려 8개, 빅테크 사고 분석 (Manus SilentBridge CVE / Microsoft Recall plaintext SQLite / Claude CU 'not production-ready'), 5-layer 보안 architecture, Local-first 결정 흐름. 다른 사람이 비슷한 vision-LLM agent 박을 때 reference.
Image 1568→1024 downscale — 30% latency / 40% token, ship-mode pragmatic trade-off
기술 회고2026년 5월 30일 · 3 분
Vision LLM 호출 비용 dominate한 image payload. 1568px → 1024px downscale로 30% latency 단축 + 40% token 절감, 작은 텍스트 정확도 ~5% 손실 trade. ship-mode pragmatic 결정 — 완벽 X, ship 우선.
Intent-Aware AX Role Inference — instruction "켜기" → AXDockItem keyword inference
기술 회고2026년 5월 30일 · 6 분
Chrome이 화면 여러 위치 (Dock + MenuBar)에 동시 존재 시 substring tiebreaker 비결정적. 사용자 instruction "켜기/열기"에서 intent 추출 → AXDockItem 우선 sort. 16 keyword pattern (한국어 + 영어) ElementMatcher.inferPreferredRole() 추가로 dispatch 시점에 disambiguate.
Latency Optimization Playbook (612 lines, 25 tricks) — story behind the asset
기술 회고2026년 5월 30일 · 5 분
ScreenBridge Vision LLM 호출 9.5s → 6.5s 가는 동안 학습한 25 trick을 6 dimension으로 정리한 612-line playbook. 사용자가 '메커니즘 배워서 앞으로도 써먹어야지'라 했고, transferable knowledge 박는 게 임시 fix보다 가치 큼.
Multi-Target Overlay — user-in-the-loop으로 95% effective accuracy (Vision LLM 천장 인정)
기술 회고2026년 5월 30일 · 5 분
Vision LLM 정확도 ~80-90% 본질 천장 인정 후, top 2 distinct 박스 (빨강 + 회색 dashed + 번호 라벨)로 사용자가 1초만에 시각 선택. Operator/Computer Use의 자동 클릭 대비 결정적 차별 — guide 자동화 OK, action 자동화 X.
Phase 6.1 spatial fusion — LLM coords hint + OCR proximity로 wrong-box 차단
기술 회고2026년 5월 30일 · 4 분
사용자 dogfooding이 wrong-box 발견 — 'Slack 어디?' 시도 시 OCR matcher가 Dock 아이콘 아닌 어시스턴트 응답 텍스트의 'slack 못 찾았어'에 박스. 화면 여러 영역에 같은 텍스트가 있을 때 substring 매칭이 사용자 intent 무시. 해법: LLM coords를 *대략적 영역 hint*로 활용 + OCR proximity filter. SYSTEM_PROMPT 권장 (강제 X — 본질 일관).
Phase 6.2 — AXUIElement matcher: icon-only UI 풀이 (Dock 아이콘, Slack 케이스)
기술 회고2026년 5월 30일 · 4 분
OCR이 visible text만 잡는 한계 — Dock 아이콘 같은 icon-only UI 못 풀음. macOS Accessibility tree로 AXTitle/AXDescription/AXPosition 메타데이터 추출 → ElementMatcher가 OCR + AX 합집합 candidate. Slack 케이스 풀음. 번역기 본질 도달 — 모든 clickable UI deterministic.
Phase 7.0 — Jarvis 5-stage evolution scaffold (continuation mode 시작)
기술 회고2026년 5월 30일 · 4 분
Single-shot ScreenBridge가 multi-step continuation으로 진화. Workflow 8-agent design (research + 4 design + synthesis)으로 4 trigger model 비교 → Hybrid X (v0.2) + W (v0.3) + Y (v0.4 opt-in) 선택. Phase 7.0은 *scaffold only* — additive 필드 + SessionState enum + IrreversibleActions keyword filter, behavior change X.
Phase 7.1 Continuation Wire — state machine + hotkey 분기 + idle timeout + irreversible filter
기술 회고2026년 5월 30일 · 5 분
Phase 7.0 scaffold (additive 필드 + SessionState enum)를 *진짜 wire*. AnalyzeCoordinator state transition + currentInstruction 저장 + continueSession + idle timeout. AppDelegate hotkey mode-aware 분기 (idle → panel, waitingForUserClick → continueSession). 사용자 'Chrome 켜고 Naver 가기' 같은 multi-step task를 매 step 재입력 X 진행 가능.
URLSession Cold-Start Optimization — Dispatcher.prewarm() Pattern
기술 회고2026년 5월 30일 · 4 분
URLSession의 첫 호출 cold start (TLS 핸드셰이크 + DNS = 1-2초) 최적화. 앱 launch 시 dispatcher.prewarm()으로 경량 GET 요청 (응답 1KB, cost 0) 미리 실행 — 실제 analyze 호출 시 1-2초 단축.
Non-ASCII Language Traps — Unicode NFC/NFD silent mismatch + short-text fuzzy threshold
기술 회고2026년 5월 29일 · 6 분
ElementMatcher fuzzy 매칭이 한국어 도파민 테스트는 통과했는데 실제 dogfooding에서 실패 — NFC/NFD 정규화 누락 + 짧은 텍스트 threshold 0.7이 너무 관대. 박은 fix: normalize()에 NFC explicit + ≤6자 threshold 0.85 + punctuation strip.
Phase 2.1 — AnalysisResult Codable struct: raw 분리 + coordinates optional
기술 회고2026년 5월 29일 · 4 분
Swift 본격 Phase 2 시작. LLM dispatcher 응답 contract를 가장 먼저 박았다 — coordinates는 LLM fallback only (OCR이 source of truth), raw는 Codable 분리 (responseSchema 1:1 보존). sweep workflow 12분 후 첫 atomic commit.
Phase 2.2 — SYSTEM_PROMPT에 번역기 본질 4개 박기 + .env parser 직접
기술 회고2026년 5월 29일 · 4 분
ScreenBridge가 추상 지시를 화면에 박는 *번역기*인데, 그 정체성은 SYSTEM_PROMPT 상수에서 결정된다. target_text 룰 + 친화 톤 + 한 화면 한 동작 + coordinates fallback — 4개를 ✗/✓ 페어 직역으로 박았다. .env parser는 dep 0 직접 구현.
Phase 2.3 — GeminiDispatcher + os.Logger swap: 사용자가 로그 볼 수 있게
기술 회고2026년 5월 29일 · 4 분
Gemini 2.5 Flash dispatcher (URLSession async + responseSchema 강제 + exp backoff retry + image FIRST/text AFTER). 동시에 NSLog → os.Logger 전체 swap — 사용자가 'log stream' 한 명령으로 별도 terminal에 줄줄. JSONSchema는 indirect enum (Swift 6 struct 자기참조 함정).
Phase 3.1 — ScreenCaptureKit + Permissions + cursor 시점 capture + 4-layer 좌표 변환
기술 회고2026년 5월 29일 · 6 분
사용자 화면 PNG 캡처 단계. ScreenCaptureKit(SCShareableContent + SCScreenshotManager) + 권한 startup eager trigger + LastTriggerContext static (hotkey 시점 cursor 저장 = Layer 10 회피) + DisplayGeometry 4-layer 좌표 변환 캡슐화 (Layer 6/9 회피). dev.sh에 codesign 추가로 TCC 매 빌드 재요청 차단.
Phase 3.1 verify — adversarial workflow가 BLOCKER 3개 잡았다
기술 회고2026년 5월 29일 · 6 분
Phase 3.1 commit 후 ultracode 정신으로 adversarial verify workflow (5 dimensions × 1 synth). 4개 review가 CRITICAL — verdict FIX_FIRST. SCContentFilter empty array bug + NSScreen.main 자기 모순 + screenFrame.origin 미반영 함정 3개 BLOCKER fix. Sweep plan이 implementation 후 review로만 catch되는 함정 입증.
Phase 4.2 — AnalyzeCoordinator: 진짜 LLM 호출 + 한국어 에러 + HUD 3 case
기술 회고2026년 5월 29일 · 6 분
Phase 5.0의 빨간 박스 hardcode를 *진짜 동작*으로 교체. AnalyzeCoordinator actor (capture → Gemini → DisplayGeometry → HUD), UserMessage 한국어 매핑 (jargon 금지), HUDContent enum (loading/annotated/error). LLM coordinates ~70% — Phase 6.1 OCR matcher로 99% 도달 계획.
Phase 5.0 — HUDOverlayWindow 빈 골격: 안경 메타포 첫 시각화
기술 회고2026년 5월 29일 · 5 분
사용자가 처음으로 *눈으로 보는* 단계. NSPanel borderless + transparent + click-through 영구 + level=.screenSaver + collectionBehavior 3개. 화면 중앙 빨간 박스 1개 hardcode — dispatcher 정확도와 분리해 NSWindow 본질 5개 검증. Phase 5.x/6.x에서 진짜 LLM 좌표 연결.
Phase 6.1 — Vision OCR + ElementMatcher: LLM 추정 ~70% → deterministic 99%
기술 회고2026년 5월 29일 · 5 분
사용자 dogfooding이 명확히 보여줬다: LLM target_text는 perfect (CLAUDE.md 정확), coordinates는 ~70% 빗나감. Phase 6.1이 그 gap을 OCR + fuzzy matching으로 메움. 정책 swap back lock-in — 본질 '99% 좌표는 OCR이 source' 일관.
학습 자산 강제: R8/R9 + git pre-commit hook으로 troubleshoot/decision 의무화
사용성 회고2026년 5월 27일 · 5 분
ScreenBridge dogfooding 중 16 layer trial-and-error를 commit 메시지에만 묻히게 두지 않고 TROUBLESHOOTING.md / DECISIONS.md로 강제 기록. R8/R9 룰 + .claude/settings.json Stop hook + .git/hooks/pre-commit 차단으로 4단 강제. 매 commit에 학습 자산 동반 의무.
Vision LLM 좌표 추정 ~70%를 OCR + element matching으로 99%로 — deterministic source 도입
기술 회고2026년 5월 27일 · 4 분
ScreenBridge의 빨간 박스가 ±50-100px 어긋나는 fundamental — vision LLM의 픽셀 좌표 추정 한계. LLM에게 element identification만 시키고 좌표는 macocr OCR list에서 fuzzy 매칭하는 deterministic source architecture 도입. 정확도 ~70% → ~95-99%.
Swift Phase 0.2: menu-bar shell + global hotkey + trigger panel — Tauri 일주일치를 한 commit으로
업데이트2026년 5월 27일 · 3 분
Swift native rewrite 첫 기능 commit. NSApp.setActivationPolicy(.accessory)로 dock 숨김 + NSStatusItem 트레이 + Carbon RegisterEventHotKey ⌥+Space + NSPanel trigger panel. Tauri attempt에서 일주일 박은 menu-bar / hotkey / 윈도우 layer가 Swift SDK 표준으로 한 commit (2.26s 빌드).
Tauri 2로 macOS HUD overlay 박은 진실 — 16개 native layer를 매번 trial-and-error로
트러블슈팅2026년 5월 27일 · 11 분
Tauri 2 React/Rust로 ScreenBridge의 transparent click-through HUD overlay를 박는 동안 macOS-native API가 한 줄로 해결하는 16개의 layer를 매번 발견. capability scoping / macOSPrivateApi / collectionBehavior / DPR 4-layer / setIgnoreCursorEvents / multi-monitor / cursor timing 등 각 사건을 시간순으로.
Tauri에서 Swift macOS native로 stack swap — 16 layer trial-and-error의 결말
기술 회고2026년 5월 27일 · 5 분
ScreenBridge v0.1을 Tauri로 박는 동안 macOS HUD overlay의 16개 native layer를 매번 trial-and-error로 발견했다. 'macOS HUD = Apple SDK 표준 use case'라는 단순한 진실을 dogfooding signal로 확인하고 Swift native로 rewrite 결정. 학습 자산은 stack 무관 보존.
Vendor-Specific JSON Contract — Gemini responseSchema vs Anthropic tool_use
기술 회고2026년 5월 27일 · 4 분
Vision LLM에서 JSON 강제 출력 메커니즘이 vendor마다 다름. Anthropic은 SYSTEM_PROMPT 텍스트로 충분하지만, Gemini는 명시적 responseSchema 필수 — Phase 7.2의 vendor swap 시 이 패턴을 layer화하는 결정 기록.
Vision LLM dispatcher 4종 실측 — Claude CLI 41s / Groq 76s / Gemini 8-15s
기술 회고2026년 5월 27일 · 3 분
ScreenBridge dispatcher 4종 (Claude CLI subprocess / Anthropic API / Groq Llama 4 Scout / Gemini 2.5 Flash) 같은 fixture로 실측. WebSearch 추정 무너지고 vendor 공식 docs 직접 확인이 결국 가장 빠른 진실. Gemini Flash 채택 + responseSchema 강제.
99% Accuracy Architecture — Deterministic OCR + AX + LLM hint hybrid
기술 회고2026년 5월 27일 · 5 분
Vision LLM 좌표 추정 ~70% 성능 한계 인식 후, deterministic source (macOS Vision OCR + Accessibility tree) + LLM element identification 하이브리드로 99% 정확도 달성. LLM에게 픽셀 추정 안 시킴.
macocr Subprocess vs objc2-Vision Direct — build-vs-bind trade-off
기술 회고2026년 5월 27일 · 5 분
OCR 구현 경로 선택 — macocr CLI subprocess (2-3h, zero deps, 패턴 일관) vs objc2-vision direct binding (8-10h, 새 interop 5-6개 crate). Pragmatic ship-mode: 시간 ROI + fail loud + v0.2에서 trait swap 가능한 reversibility.
ScreenBridge v0.1 Tauri stack — 6 Phase 한 세션 완성 (1세션 30 commits)
기술 회고2026년 5월 26일 · 3 분
ScreenBridge v0.1을 Tauri 2 + Rust + React/TS로 한 세션에 6 Phase (bootstrap → foundation → dispatcher → system integration → trigger panel → overlay → polish) 완성. 30 commits, BUILD_REPORT.md. 자율 빌드 룰 R1-R7 따라 atomic commit + 매 phase verify.