Automate real Android phones from code: test your apps, script the tasks you repeat, run a shelf of phones, or let an AI agent use one. Open source. No ADB, no USB cable, no root.
翻訳待ち
開発ツールGo · TypeScriptGitHub @KnifeLemonオンライン所有者未確認
Have you tried it? One tap is enough. No sign-in needed.
Android automation from code. Test your apps on real phones, script the tasks you repeat, run a shelf of phones, or let an AI agent use one, from Python, Node.js, the CLI, HTTP or Appium clients. No ADB, no USB cable, no root.
翻訳待ち
Loading the full README.
Read the full README ↗Droidline uses only permissions an ordinary app can get, so a few things are out of reach: see What it cannot do.
You need a PC (Windows, macOS or Linux) and an Android phone with Android 9 or later, on the same Wi-Fi for a first try. The installation guide walks through each step with screenshots.
Run the server on your PC. Download the droidline archive for your system from Releases, put droidline on your PATH, and start it. Leave it running.
droidline serve
Install the app on the phone. Download droidline-agent.apk from the same release page and open it. On the app's Setup tab, turn on the accessibility service, the Droidline keyboard, notifications and unrestricted battery use. On Android 13 and later, allow restricted settings for the app first; the app shows where.
Pair them. Run this on the PC and scan the QR code with the app's Pair tab:
droidline pair
No camera? Tap Pair on this Wi-Fi in the app and type the 6-digit code it shows: droidline pair 482913.
Send a command.
droidline launch com.android.settings
droidline touch text "Network & internet"
No phone at hand? droidline-fakephone, included in every release, simulates one with a small demo app. The first-script tutorial builds a complete login script against it.
Every interface talks to droidline serve on localhost:8780 and uses the same command names.
Python (pip install droidline, Python 3.9+)
from droidline import connect
d = connect() # the phone paired with this PC
d.launch("dev.droidline.demo")
if d.exists("text", "Close ad"): # conditions never wait and never fail
d.touch("text", "Close ad")
d.input("id", "email", "knife") # waits up to 10 s for the element
d.touch("text", "Log in")
print(d.get_text("id", "greeting"))
Node.js and TypeScript (npm install droidline, Node.js 18+)
import { connect } from "droidline";
const d = await connect();
await d.launch("dev.droidline.demo");
await d.input("id", "email", "knife");
await d.touch("text", "Log in", { timeout: 15 });
console.log(await d.getText("id", "greeting"));
C# and .NET (dotnet add package Droidline, .NET 8+ or .NET Framework 4.6.2+)
using Droidline;
await using var d = await DroidlineClient.ConnectAsync();
await d.LaunchAsync("dev.droidline.demo");
await d.InputAsync("id", "email", "knife");
await d.TouchAsync("text", "Log in", timeout: 15);
Console.WriteLine(await d.GetTextAsync("id", "greeting"));
Command line (comes with the server)
droidline touch text "Log in"
droidline which text="Log in" id=main_tab --timeout 15
droidline screenshot shot.png
HTTP (any language, any tool)
curl -s -X POST localhost:8780/devices/_/touch \
-H 'content-type: application/json' -d '{"by":"text","value":"Log in"}'
AI agents over MCP (Claude, Cursor, VS Code and others)
{ "mcpServers": { "droidline": { "command": "droidline", "args": ["mcp"] } } }
With Claude Code: claude mcp add droidline -- droidline mcp. In Claude Desktop you can instead open droidline.mcpb from Releases, which carries its own droidline; it is also listed in the MCP Registry as io.github.KnifeLemon/droidline. To give an agent fewer tools, add --tools dump,screenshot,touch or --read-only to the args; see Limit what an agent can use. Other languages can open a TCP socket and send one JSON line per command; see Other languages for Go, Java and PHP.
This is the beginning of the README. Read the rest at the original. Read the full README ↗