SAIR
ใช้ทำอะไรได้
ยังไม่มีคำอธิบายภาษาไทย ดูข้อเท็จจริงด้านล่าง หรือเปิดคำอธิบายต้นฉบับจากผู้ทำ
- ต่อแบบ ติดตั้งในเครื่อง
- บัญชีหรือคีย์ ต้องมี SAIR_API_KEY
- หมวด เครื่องมือนักพัฒนา
คำอธิบายต้นฉบับจากผู้ทำ (อังกฤษ)
Run Android tests on real phones, or lease one: install, shell, screenshot, logcat.ติดตั้ง
เลือกโปรแกรม AI ที่คุณใช้ แล้วคัดลอกค่าตั้งไปวาง
ผลตรวจผ่าน 3/3 · ทำงานบนเครื่องคุณ
ขั้นแรก: คุณใช้ AI ตัวไหน
เลือกแอปที่คุณใช้ ขั้นตอนจะขึ้นด้านล่าง
ต่อกับ Claude ได้ แต่ต้องเตรียมก่อน
ไม่ต้องใช้คีย์ ไม่ต้องลงโปรแกรม · ใช้ได้เฉพาะแอป Claude บนคอม (Windows หรือ Mac) ไม่ใช่บนเว็บหรือมือถือ
ดาวน์โหลดไฟล์ติดตั้งของผู้ทำ
ไฟล์ .mcpb มาจากผู้ทำโดยตรง เราไม่ได้แก้ไฟล์
ดับเบิลคลิกไฟล์ แล้วกด Install ในแอป Claude บนคอม
ลองเลย
ใช้ SAIR บอกหน่อยว่าทำอะไรให้ฉันได้บ้าง แล้วลองทำให้ดูหนึ่งอย่าง✓ ถ้า Claude บอกว่ากำลังใช้ SAIR หรือมีชื่อเครื่องมือของ SAIR ขึ้นในคำตอบ แปลว่าต่อสำเร็จ
ชื่อเมนูตรวจกับหน้าช่วยเหลือของ Anthropic เมื่อ 11 พ.ย. 2569 · หน้าจอของคุณอาจต่างเล็กน้อยตามรุ่นของแอป
ChatGPT ยังต่อ SAIR ไม่ได้
SAIR ต้องติดตั้งในเครื่องคุณ แต่ ChatGPT ต่อได้เฉพาะตัวที่ทำงานบนเว็บ
คุณทำแบบนี้แทนได้
ก · ใช้แอปที่ต่อ SAIR ได้
- ไม่ต้องใช้คีย์ ไม่ต้องลงโปรแกรม · ใช้ได้เฉพาะแอป Claude บนคอม (Windows หรือ Mac) ไม่ใช่บนเว็บหรือมือถือ
ข · ตัวอื่นในหมวด เครื่องมือนักพัฒนา ที่ต่อกับ ChatGPT ได้
เลือกจากตัวที่ใช้มากในหมวดเดียวกัน เฉพาะตัวที่ต่อด้วยที่อยู่ได้โดยไม่ต้องใส่คีย์
- Sentry✓ ChatGPT
- Compiler Explorer✓ ChatGPT
- GitDiagram✓ ChatGPT
Claude Code ยังต่อ SAIR ไม่ได้
ผู้ทำมีแต่ไฟล์ติดตั้งสำหรับแอป Claude บนคอม
คุณทำแบบนี้แทนได้
ก · ใช้แอปที่ต่อ SAIR ได้
- ไม่ต้องใช้คีย์ ไม่ต้องลงโปรแกรม · ใช้ได้เฉพาะแอป Claude บนคอม (Windows หรือ Mac) ไม่ใช่บนเว็บหรือมือถือ
Cursor ยังต่อ SAIR ไม่ได้
ผู้ทำมีแต่ไฟล์ติดตั้งสำหรับแอป Claude บนคอม
คุณทำแบบนี้แทนได้
ก · ใช้แอปที่ต่อ SAIR ได้
- ไม่ต้องใช้คีย์ ไม่ต้องลงโปรแกรม · ใช้ได้เฉพาะแอป Claude บนคอม (Windows หรือ Mac) ไม่ใช่บนเว็บหรือมือถือ
VS Code ยังต่อ SAIR ไม่ได้
ผู้ทำมีแต่ไฟล์ติดตั้งสำหรับแอป Claude บนคอม
คุณทำแบบนี้แทนได้
ก · ใช้แอปที่ต่อ SAIR ได้
- ไม่ต้องใช้คีย์ ไม่ต้องลงโปรแกรม · ใช้ได้เฉพาะแอป Claude บนคอม (Windows หรือ Mac) ไม่ใช่บนเว็บหรือมือถือ
สำหรับคนเขียนโค้ด: คำสั่ง Terminal และค่าตั้ง JSON
ค่าที่ต้องใส่เอง
SAIR_API_KEYความลับ จำเป็น envAn API key from https://sair.run/dashboardSAIR_API_URLenvAgent API base URL (default: https://api.sair.run)
คำอธิบายยังเป็นภาษาอังกฤษตามต้นฉบับ
ค่าตั้งนี้สร้างจากข้อมูลใน registry ของผู้ทำ ถ้าไม่ตรงกับ README ให้เชื่อ README
สรุป
ใช้กับโปรแกรมไหนได้
ดูจากแบบการต่อของ server ตัวนี้ และเอกสารของผู้ทำโปรแกรมแต่ละตัว ตรวจเมื่อ 10 พ.ย. 2569
ติดตั้งบนเครื่องได้ใน
ClaudeGooseLM StudioMsty StudioCherry StudioVisual StudioWindsurf (Devin Desktop)ZedKiroClineContinueJetBrains AI AssistantCodex CLIGemini CLIOpenCodenodecodeWarpLibreChatRaycast
คู่มือที่เกี่ยวข้อง
ทำอะไรได้บ้าง
รันในเครื่องคุณ รายการเครื่องมือจะขึ้นในแอป AI หลังติดตั้ง
ผลตรวจเบื้องต้นi
เราตรวจจากข้อมูลที่ใครก็เปิดดูได้ ยังไม่ได้อ่านโค้ด ข้อที่ไม่เกี่ยวกับตัวนี้ไม่นับในตัวหาร · ตรวจเมื่อ 14 พ.ย. 2569
- ✓ ผ่าน
ตัวตนผู้ทำตรงกับ repo
ชื่อใน registry ยืนยันด้วยบัญชี GitHub compscidr ซึ่งเป็นเจ้าของ repo
- ✓ ผ่าน
ยังมีคนดูแล
มีการแก้โค้ดล่าสุด 9 วันที่ผ่านมา
- ✓ ผ่าน
มีสัญญาอนุญาต (license)
ใช้ Apache-2.0
- – ไม่เกี่ยว
endpoint ตอบ
ตัวนี้รันบนเครื่องคุณ ไม่มี endpoint บนอินเทอร์เน็ต
- – ไม่เกี่ยว
ล็อกอินแบบ OAuth
ตัวนี้รันบนเครื่อง ใช้ค่าที่ตั้งในเครื่องแทน
- … ยังไม่ตรวจ
คำอธิบายเครื่องมือไม่มีคำสั่งแอบแฝง
รันในเครื่องคุณ เราอ่านรายการเครื่องมือได้เฉพาะตัวที่มี endpoint บนอินเทอร์เน็ต
พูดคุย
ถาม แชร์เคล็ดลับ หรือแจ้งว่าใช้ไม่ได้ เรียงตามที่คนกดว่ามีประโยชน์
ยังไม่มีใครโพสต์ ถามหรือแชร์เป็นคนแรกได้เลย
ข้อความในส่วนนี้เขียนโดยผู้ใช้ ไม่ใช่ทีม PopNx
รีวิวจากผู้ใช้
ยังไม่มีรีวิว
เทียบกับตัวอื่นในหมวด เครื่องมือนักพัฒนาi
- ดาวมากกว่า 69% ของอีก 5884 ตัวในหมวดนี้
- ส่งรุ่นใหม่เข้า registry ล่าสุดกว่า 71% ของอีก 5884 ตัวในหมวดนี้
- ผลตรวจเบื้องต้นดีกว่าหรือเท่ากับ 100% ของอีก 5884 ตัวในหมวดนี้
เทียบกับทุก server ที่ยังใช้งานในหมวดนี้ทั้งทะเบียน ดาวนับเฉพาะเมื่อผู้ลงทะเบียนเป็นเจ้าของ repo
คำถามที่พบบ่อย
SAIR ปลอดภัยไหม?
จากการตรวจเบื้องต้นของเรา ผ่าน 3 จาก 3 ข้อที่ตรวจได้ เรายังไม่ได้อ่านโค้ด ก่อนใส่กุญแจหรือ token ให้ดูว่า server ขอสิทธิ์อะไร และเลือกกุญแจที่ทำได้เท่าที่จำเป็น
ต้องใช้กุญแจหรือรหัสอะไรบ้าง?
ต้องใส่ค่าเหล่านี้: SAIR_API_KEY
ตัวนี้รันบนเครื่องหรือบนคลาวด์?
รันบนเครื่องของคุณ โปรแกรม AI จะเปิด server ขึ้นมาเองเมื่อใช้ ข้อมูลไม่ต้องผ่านเซิร์ฟเวอร์ของผู้ทำ (ยกเว้นตัวที่ไปเรียกบริการออนไลน์ต่อ)
ยังมีคนดูแลอยู่ไหม?
repo บน GitHub มีการแก้โค้ดล่าสุด 9 วันที่ผ่านมา และส่งรุ่นล่าสุด (0.1.36) เข้า registry 9 วันที่ผ่านมา
ใช้กับโปรแกรมไหนได้บ้าง?
โปรแกรมที่รองรับ MCP เช่น Claude Desktop, Claude Code, Cursor และ VS Code ตัวนี้ต้องมี MCPB ในเครื่องด้วย
ตัวอื่นในหมวดเดียวกัน
server หมวดเดียวกันจากผู้ทำคนอื่น เรียงตามดาว
อ่านการ์ด:↓ ดาวน์โหลดต่อสัปดาห์i★ ดาว GitHubiสามเสา: รีวิว · ผลตรวจ · การใช้งานiอัปเดต = วันที่ส่งรุ่นล่าสุดเข้า registryi
Serena MCP: the IDE for your agent
A powerful toolkit for coding, providing semantic retrieval and editing capabilities.
README จากผู้ทำ
เปิดอ่าน README
ส่วนนี้คัดจาก repo ของผู้ทำตามต้นฉบับ PopNx MCP ไม่ได้ตรวจหรือรับรองเนื้อหา ตัด HTML รูปภาพ และสคริปต์ออกแล้ว ลิงก์จะพาออกนอกเว็บ
SAIR — Shared Android Instrumented Runner
SAIR lets CI pipelines safely share physical Android devices. It provides device locking, ADB protocol translation, and per-runner isolation so multiple jobs never collide on the same device.
Why
Without SAIR, every CI job that can see a phone uses it at the same time:
CI job 1 ──┐
├──▶ adb ──▶ Phone ✗ both jobs install / uninstall the same APK CI job 2 ──┘ ✗ one job's reboot or settings change breaks the other's tests mid-run ✗ connectedCheck runs on every attached phone, including ones another job is using
With SAIR, a job must hold a lock before it sees a device, and waiting jobs queue:
CI job 1 ──┐ ┌──▶ Phone A (locked by job 1)
├──▶ Proxy ───────┤ CI job 2 ──┘ ▲ └──▶ Phone B (locked by job 2) │ locks CI job 3 ··· Orchestrator: job 3 waits in the queue until a phone is released
GitHub Action
This repo is also a GitHub Action that puts sair-acquire, sair-release, sair-wifi, sair-bluetooth, sair-locks and sair-label on PATH. The tools need an orchestrator account: sign up at sair.run to get an API key, store it as the repository secret SAIR_API_KEY, and set the repository variable SAIR_PROXY_URL to your bench's proxy (see Run). Then:
steps:
- uses: actions/checkout@v4
- uses: compscidr/sair@v0.1.18
- run: sair-acquire --count 1 > /dev/null env: SAIR_PROXY_URL: ${{ vars.SAIR_PROXY_URL }} SAIR_API_KEY: ${{ secrets.SAIR_API_KEY }}
- run: ./gradlew connectedCheck
- if: always() run: sair-release --status ${{ job.status }} env: SAIR_API_KEY: ${{ secrets.SAIR_API_KEY }}
The full workflow example explains each step.
A runner with no proxy of its own (e.g. GitHub-hosted, using phones other accounts share) can have the action start one, at the same release as the action. Leave SAIR_PROXY_URL unset; the proxy listens on the default localhost:8550, and its log is at $RUNNER_TEMP/sair-proxy.log:
- uses: compscidr/sair@v0.1.18
with: proxy: true env: SAIR_API_KEY: ${{ secrets.SAIR_API_KEY }}
Used at a branch or SHA rather than a release tag, the action warns and starts the latest release instead.
AI agents (MCP)
sair-mcp is an MCP server (stdio) for coding agents. It can run an app's instrumented tests on a real phone in one call, or lease a phone and install APKs, run shell commands, take screenshots and read logcat on it. It talks to the orchestrator's agent API with an API key from sair.run. The agent's machine needs no proxy or adb.
Install it with go install github.com/compscidr/sair/cmd/sair-mcp@latest, take sair-mcp from a release tarball, or use sair-mcp.mcpb from a release (an MCP Bundle for clients such as Claude Desktop). Then add it to your agent, e.g. Claude Code:
claude mcp add sair -e SAIR_API_KEY=sair_... -- sair-mcp
or any client's JSON config:
{ "mcpServers": { "sair": { "command": "sair-mcp", "env": { "SAIR_API_KEY": "sair_..." } } } }
| Tool | Does |
|---|---|
run_tests | Uploads app_apk and test_apk (paths on the agent's machine), waits for the run, returns per-test results, instrument output and a logcat tail |
list_devices | Lists the phones the key may use: serial, model, sdk (API level), shared, in use |
lease_device | Takes a phone (serial, wait_s optional) and returns the lease id |
install_apk | Installs an APK on the leased phone, returns its package |
shell | Runs a command, returns output and exit code |
screenshot | Returns a PNG of the screen |
logcat | Returns the most recent lines (default 500) |
release_device | Ends the lease: uninstalls what it installed and frees the phone |
The server heartbeats the leases it takes, so an agent that thinks for a while between calls keeps its phone. A lease still ends at the plan's maximum (free 15 min, solo 1 h, team 2 h, enterprise 4 h). On a phone shared by another user, shell commands are limited to a safe set (see the orchestrator README). SAIR_API_URL points it at another orchestrator (default https://api.sair.run).
It is listed in the official MCP registry as io.github.compscidr/sair. Every release publishes it: the release workflow builds sair-mcp.mcpb, fills server.json's version, download URL and SHA-256 (the values in the repo are placeholders), and publishes it with mcp-publisher, logged in through GitHub OIDC. Check it with curl "https://registry.modelcontextprotocol.io/v0/servers?search=io.github.compscidr/sair".
Quick Start
Install
curl -fsSL https://raw.githubusercontent.com/compscidr/sair/main/install.sh | bash
This detects your OS and architecture, downloads the latest release, and installs all binaries to ~/.local/bin.
Prerequisites
adbinstalled on the machine with Android devices- One or more Android devices connected via USB with USB debugging enabled (don't sign them in to a personal account: see Securing a bench)
Run
# 1. Start a real ADB server on a non-default port (5038), so it doesn't
conflict with the proxy which will own the standard port (5037).
adb -P 5038 start-server
2. Set your API key (shared by proxy and device-source)
export SAIR_API_KEY=your-api-key
3. Start the proxy and device source
sair-proxy & sair-device-source
The proxy connects to the hosted orchestrator at orchestrator.sair.run by default (with TLS). Override with ORCHESTRATOR_ADDR for local development.
Use
Acquire a device lock (blocks until one is available), run your tests, then release:
ACQUIRE_OUTPUT=$(sair-acquire)
eval "$ACQUIRE_OUTPUT" ./gradlew connectedCheck sair-release
After eval, stock adb automatically talks to the proxy through the scoped port and only sees the locked devices.
When the bench sets WIFI_SSID on the device source, Wi-Fi is managed for you:
- On acquire each phone joins the bench Wi-Fi and the acquire returns only once the phone is *online* (below); it fails otherwise.
--no-wifihands it over *offline* instead, verified the same way rather than trusting the previous release.--wifi-band 2.4|5|6(alsosair-wifi on --band) joins on that GHz band: the phone scans, the suggestion is pinned to the strongest BSSID ofWIFI_SSIDit sees in the band, and the join fails if it sees none. The phone'scmd wifi statusshows the BSSID and frequency it joined. - On release, and when a lock expires or is cancelled, each phone is reset: every suggestion added through
adb shelland every saved network is forgotten and the radio is toggled, and the reset waits until the phone is offline with the radio back on. The next job never inherits the last one's network. The phone then rejoins the bench Wi-Fi, so it is online between leases and app updates can install (see the Play Store below); the next acquire puts it in the state that job asked for either way. - Also on release, every third-party package the phone did not have when the device source first saw it is uninstalled (test APKs and
.testpackages included, with their app data and signed-in accounts), and the browser and mail apps are force-stopped; seeBASELINE_PACKAGES,RESET_FORCE_STOPandRESET_CLEAR_PACKAGES. What was removed is written to the proxy log and the lock's log on the orchestrator, naming any Wi-Fi suggestion that went with a package. This runs before the Wi-Fi reset, so a suggestion a test app leaked for the bench network is gone before the reset waits for the phone to be offline. - A phone relayed to a borrower resets differently: the first relay under a lock lists its third-party packages, and when the lock ends only what is not on that list is uninstalled, for the primary user only. An app on the phone before a lock's first relay stays; one installed during the lock goes, whoever installed it.
BASELINE_PACKAGEShas no effect on this reset, but a local or guest-key lock on the same phone still resets to the baseline, so list apps to keep inBASELINE_PACKAGES. What was removed goes to the proxy log and the bench events, not the lock's log, which is on the holder's proxy. Without that list (it could not be read, the device source is older than the proxy, or no relay got that far) nothing is uninstalled: the proxy logs a warning and reports a failed package reset. Leftovers can then survive until a local lock, because the next borrower's list includes them, as it does when a relay under a new lock arrives before the previous lock's reset (the proxy warns, naming what it suspects). - On acquire the same cleanup runs first (reverse forwards, packages), before the Wi-Fi check. A job that never released, because it had no
if: always()release step, its runner died, or the proxy was down when the lock expired, is cleaned up by the next job, whose lock log then showssair: uninstalled … (left by an earlier job). This is local locks only: a relayed lock's next job cleans up nothing. - No leaked UiAutomation, on release and on acquire: a killed
am instrumentor a leftover uiautomator server can leave a UiAutomation registered, failing every later instrumentation withUiAutomationService … already registered!. Auiautomator dumpprobe detects it; sair then kills the shell user'sapp_process/uiautomatorprocesses, which unregisters it, and reboots only if the probe still fails (never a phone with a secure lock). The lock log getssair: cleared a leaked UiAutomation registration (killed … | rebooted). - Awake and unlocked, on acquire and again after the release reset: the screen is woken and the keyguard dismissed, then verified (
dumpsys powersaysAwake,dumpsys window policysays the keyguard is not showing), with up to three attempts since a one-shot dismiss can race on some phones. A phone whose keyguard stays up fails the acquire withscreen locked; that means a PIN, pattern or password is set, which sair cannot dismiss, so set the phone's screen lock to Swipe or None. The reason is also reported as the device'swarning(proxy/status, device report) until a wake succeeds. A phone withstay_on_while_plugged_inoff is logged as a warning, since it will sleep and re-lock between steps. Android 4.x phones (nowm) are verified through their ownmShowingLockscreenfield; a dump in a format sair does not know is logged once and treated as unlocked. - Rebooted on release once its uptime is over
REBOOT_UPTIME_HOURS(24 by default), while the phone is unacquired: the reset waits for the boot and the wake above before the next acquire of that phone can proceed, and the phone is not offered while it is down. The lock log getssair: rebooted after release (uptime …)and the proxy's/statuslists each phone'slast_reboot. This runs before the Wi-Fi reset, so the offline wait is not spent twice. A phone with a PIN, pattern or password is never rebooted this way, since it would come back on "unlock to start" and need a human; the device source logs that with the fix. The wake and the reboot run whether or not the bench manages Wi-Fi. - Bluetooth cycled on release, after the Wi-Fi reset:
svc bluetooth disable, wait untildumpsys bluetooth_managersays the adapter is fullyOFF,svc bluetooth enable, wait until it saysON(30 s each). A BLE stack an earlier job wedged (stuck advertisers, a scanner that neve