<p align="center">
<img src="https://raw.githubusercontent.com/mpiton/tauri-pilot/HEAD/assets/logo.jpeg" alt="tauri-pilot logo" width="200">
</p>
<p align="center">
<a href="https://github.com/mpiton/tauri-pilot/actions/workflows/ci.yml"><img src="https://github.com/mpiton/tauri-pilot/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
<a href="https://crates.io/crates/tauri-plugin-pilot"><img src="https://img.shields.io/crates/v/tauri-plugin-pilot.svg" alt="crates.io"></a>
<a href="https://github.com/mpiton/tauri-pilot/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License: MIT"></a>
<img src="https://img.shields.io/badge/rust-1.95.0+-orange.svg" alt="Rust 1.95.0+">
<img src="https://img.shields.io/badge/platform-linux%20%7C%20macOS%20%7C%20Windows-lightgrey.svg" alt="Platform: Linux | macOS | Windows">
<img src="https://img.shields.io/badge/tauri-v2-24C8D8.svg" alt="Tauri v2">
</p>
tauri-pilot
Tauri v2 앱을 위한 대화형 테스트 CLI (Interactive testing CLI for Tauri v2 apps) — AI 에이전트(Claude Code)와 개발자가 Tauri 애플리케이션을 실시간으로 검사하고, 상호 작용하며, 디버깅할 수 있게 해줍니다.
<p align="center">
<img src="https://raw.githubusercontent.com/mpiton/tauri-pilot/HEAD/assets/demo.gif" alt="tauri-pilot demo" width="700">
</p>
$ tauri-pilot snapshot -i
- heading "PR Dashboard" [ref=e1]
- textbox "Search PRs" [ref=e2] value=""
...
왜 필요한가요?
AI 에이전트가 Tauri 앱 UI와 상호 작용할 수 있는 도구가 없습니다. Playwright는 작동하지 않습니다 (Tauri는 Chromium이 아닌 시스템 WebView를 사용합니다 — Linux에서는 WebKitGTK, macOS에서는 WebKit, Windows에서는 WebView2). tauri-pilot은 LLM(대규모 언어 모델) 소비에 최적화된 프로토콜을 사용하는 경량 플러그인과 CLI로 이 격차를 해소합니다.
작동 방식
<p align="center">
<img src="https://raw.githubusercontent.com/mpiton/tauri-pilot/HEAD/assets/architecture.png" alt="tauri-pilot 아키텍처: CLI가 Unix 소켓 / Named Pipe를 통해 임베디드 플러그인에 JSON-RPC로 연결하고, 플러그인이 WebView에 JS 브릿지를 주입함" width="700">
</p>
- **플러그인(Plugin)**은 Tauri 앱에 내장되며 (디버그 빌드에서만), Unix 소켓/Named Pipe 서버를 시작합니다.
- CLI는 해당 소켓에 연결하여 JSON-RPC 명령을 전송합니다.
- **JS 브릿지(JS Bridge)**는 WebView에 주입되어 DOM 검사 및 상호 작용을 처리합니다.
빠른 시작 (Quick Start)
1. 플러그인을 Tauri 앱에 추가하기
[dependencies]
tauri-plugin-pilot = { git = "https://github.com/mpiton/tauri-pilot" }
fn main() {
let mut builder = tauri::Builder::default();
...
필수 기능(Required capability) — 앱의 capability 파일에 pilot:default를 추가하세요.
(예: src-tauri/capabilities/default.json):
{
"remote": {
"urls": ["https://allowed.example/*"]
...
>
> `pilot:default`가 없으면 다음 오류와 함께 eval 명령이 실패합니다: `eval timed out after 10s`. 해당 오리진을 구동해야 하는 경우, 동일한 capability에 `remote.urls`를 통해 외부 오리진을 나열하세요.
### 2. CLI 설치하기
```bash
cargo install tauri-pilot-cli
선택적으로 Agent가 사용할 수 있도록 설정할 수 있습니다:
npx skills add https://github.com/mpiton/tauri-pilot
3. 사용하기
복잡하거나 여러 줄로 된 스크립트에는 tauri-pilot eval -을 사용하세요. 단일 따옴표를 사용한 heredoc 구분자(<<'EOF')는 쉘 확장을 비활성화하므로, JavaScript 내부의 $, 백틱(``), 따옴표는 이스케이프할 필요가 없습니다.
명령어 (Commands)
| 명령어 | 설명 |
|---|
ping | 상태 확인 (Health check) |
| ... | |
AI 에이전트를 위해 (For AI Agents)
tauri-pilot은 AI 에이전트의 사용을 염두에 두고 설계되었습니다. 워크플로우는 다음과 같습니다:
tauri-pilot snapshot -i — 접근성 트리(accessibility tree)를 참조와 함께 가져옵니다.
- 출력에서 참조(
@e1, @e2, ...)를 읽습니다.
tauri-pilot click @e3 — 참조를 사용하여 상호작용합니다.
tauri-pilot assert text @e1 "Dashboard" — 단일 단계에서 상태를 검증합니다 (종료 코드 0 = 성공, 종료 코드 1 = 실패).
tauri-pilot diff -i — 변경된 내용만 확인합니다 (전체 재스냅샷 대비 토큰 절약).
tauri-pilot logs --level error — JS 오류를 확인합니다.
assert 명령어는 수동적인 text @ref + 파싱 + 비교 패턴을 대체하여 왕복 횟수(round-trips)와 토큰 사용량을 줄입니다.
프로그램적으로 파싱할 때는 구조화된 출력을 위해 --json을 사용하십시오.
MCP 서버
네이티브 MCP 지원 기능을 갖춘 에이전트의 경우, 각 명령어마다 셸 아웃(shelling out)하는 대신 tauri-pilot을 stdio MCP 서버로 실행하십시오:
{
"mcpServers": {
"tauri-pilot": {
...
MCP 서버는 CLI와 동일한 앱 검사 및 상호작용 인터페이스를 노출하며, 이는 pilot.* 아래에 네임스페이스됩니다: pilot.snapshot, pilot.click, pilot.fill,
pilot.logs, pilot.network, pilot.eval, pilot.ipc, pilot.assert_*,
pilot.run, 그리고 다른 테스트 도구들입니다. pilot.run은 path 또는 인라인 content에서 TOML 시나리오를 실행하고 JSON 보고서(ok, 카운트, summary, steps)를 반환합니다. ok를 확인하십시오. 실패한 단계가 있는 완료된 실행이라도 성공적인 도구 결과입니다. 도구 오류는 파싱, I/O, 연결, 타임아웃 실패만 해당합니다. tools/list
이 접두사화된 이름을 광고하며; 베어 이름(예: snapshot)은 여전히 tools/call을 통해 해결되므로 기존 설정이 작동합니다.
전역 플래그를 사용하여 특정 앱 소켓 또는 창에 고정하려면 mcp 앞에 사용하십시오:
{
"mcpServers": {
"tauri-pilot": {
...
경로는 리눅스 데스크톱의 기본값입니다: 1000을 사용자 ID(id -u)로, com.myapp.dev를 앱 식별자(app's identifier)로 대체하십시오. macOS에서는 $XDG_RUNTIME_DIR가 보통 설정되어 있지 않으므로 /tmp/tauri-pilot-com.myapp.dev.sock을 사용하십시오. Windows에서는 명명된 파이프(Named Pipe)를 사용하며, JSON에서 백슬래시( ext{})는 각각 두 번씩 이스케이프해야 합니다: "\\.\pipe\tauri-pilot-com.myapp.dev".
요구사항
알려진 제한 사항
-
Windows 호스트의 Android 연결: Windows CLI는 이름 있는 파이프(named pipes)를 사용하며, 이 Android 설정에서 사용되는 유닉스 소켓 포워딩을 통해 연결할 수 없습니다.
-
실제 iOS 기기: 기기의 앱 샌드박스는 해당 장치에서 소켓 파일을 숨기므로, CLI가 열 경로를 찾을 수 없습니다. 현재는 시뮬레이터만 가능합니다.
-
X11에서의 press 및 전역 단축키: press에서 발생하는 합성 키 이벤트(enigo의 XTestFakeKeyEvent 백엔드를 통해)는 tauri-plugin-global-shortcut에 등록된 핸들러를 트리거하는 데 자주 실패합니다.
상위 레벨의 global-hotkey 크레이트는 Linux/X11 백엔드에서 XGrabKey 수동 가로채기(passive grabs)를 사용하며, 이는 X 서버의 논리적 수정자 상태와 일치합니다. enigo가 각 수정자와 주 키코드에 대해 별도의 가짜 입력 호출을 수행할 경우 해당 상태가 동기화되지 않을 수 있어, 가로채기의 정확한 수정자 마스크 매치가 실패하게 됩니다. DOM 리스너 및 Tauri 액셀러레이터는 계속해서 isTrusted=true 이벤트를 받습니다.
해결 방법: 핸들러 본문을 #[tauri::command]로 분리하고 tauri-pilot ipc <command>를 통해 호출하거나, 핸들러가 Tauri 이벤트를 방출하여 테스트가 이를 재방출할 수 있도록 해야 합니다. 프로세스 외부에서 on_shortcut(...)에 전달된 임의의 클로저(closure)를 직접 호출하는 방법은 없습니다. #75 참조.
누가 사용하나요?
tauri-pilot을 사용하고 계신가요? 여기에 프로젝트를 추가하려면 PR 열기를 해주세요!
<!-- Add your project below -->
<!-- | [Project Name](https://github.com/...) | Short description | -->
라이선스
MIT — [LICENSE] 참조