Skip to main content
TurboADB

TurboADB

One pip package for driving Android over ADB + scrcpy — a Python API, a full CLI, and a desktop GUI. Built for Android Automotive / IVI head units and regular phones alike.

PyPI Python License: MIT

🌐 Website · ⤓ Download for Windows · 📦 PyPI


New in 2.5.0: a transfer history in Files with overall progress, speed, time left and every file's size and error; more than one Files tab on the same device; a second terminal session in one click; the system's own file icons; and a notification for every copy, paste, APK install and bulk file operation, plus fixes to the screencap view, streams and startup launchers. Full notes in the changelog.

TurboADB wraps adb and scrcpy so you don't have to remember their flags. The same engine powers all three front-ends, so every feature below works three ways — click it in the GUI, run it as a one-line CLI command, or call it from Python. It bundles its own adb/scrcpy (downloaded on first run), drives devices on another machine's adb server (handy over RDP / in a lab), and knows the quirks of Android Automotive head units.

The rest of this README is a hands-on guide: for each feature you get the GUI steps, the CLI command, and the Python call.

Contents

Install

Pick whichever fits — both give you the full GUI.

A · Windows app — no Python needed

  1. Download TurboADB-2.5.0-win64.exe from the latest GitHub Release (also linked from the website).
  2. Double-click it. On first launch it downloads adb + scrcpy automatically (about 20 seconds) and adds a desktop shortcut.

B · With pip — CLI, Python API, and GUI

pip install turboadb

On Windows this already includes the app: the package carries the same executable (which is why the download is about 59 MB), so turboadb-gui starts it even without PyQt5. To run the GUI from the Python code instead — on Linux or macOS, for example — add the GUI extra:

pip install "turboadb[gui]"

Then use any of: turboadb-gui (the app), turboadb <command> (the CLI), or import turboadb (the API). Other optional extras are:

pip install "turboadb[winrm]"  # remote 'serve' deploy over WinRM
pip install "turboadb[all]"    # GUI + WinRM support

Upgrade any time with pip install --upgrade turboadb.

adb and scrcpy download themselves into ~/.turboadb/tools on first use, so they never need to be on your PATH.

First, target a device

Everything operates on one device. How you point at it is the only thing that changes between local, network, and remote.

In the GUI — click Connect ▾ → Connect to a device… and choose how it is connected: USB, Network (IP and port) or Remote (a device on another PC's adb server). Attached devices also show live under Connected in the left sidebar; double-click one to open it in a tab. Connect ▾ also has Discover Wi-Fi devices and Pair device (Android 11+), and a USB device can switch itself to Wi-Fi with More ▾ → Go wireless (USB → Wi-Fi).

CLI — list first, then pass -s:

turboadb devices                                  # what's attached here
turboadb -s 10BE330KG9000AF info                  # a USB serial
turboadb -s 192.168.1.50:5555 info                # a network device
turboadb connect 192.168.1.50:5555                # adb connect first if needed
turboadb -s SERIAL wireless                       # USB device -> Wi-Fi adb in one step
turboadb discover                                 # find wireless-debugging devices
turboadb --adb-host lab-pc-01 devices             # devices on ANOTHER pc's server
turboadb --adb-host lab-pc-01 -s DEVICE info      # …and drive one of them

Python — build an ADBConfig, then connect():

from turboadb import ADBHandler, ADBConfig

# USB (omit serial if it's the only device)
dev = ADBHandler(ADBConfig(serial="10BE330KG9000AF"))

# network device
dev = ADBHandler(ADBConfig(host="192.168.1.50", port=5555))

# a device on a remote machine's adb server
dev = ADBHandler(ADBConfig(adb_server_host="lab-pc-01", adb_server_port=5037,
                           serial="DEVICE"))
dev.connect()

Pass safe=True to the handler (the GUI does) to get an OperationResult back instead of an exception on failure — handy when you don't want one bad call to abort a run.

The app at a glance

  • Top bar — Connect ▾ (connect, save a target, discover Wi-Fi devices, pair, restart ADB), ADB server ▾ (deploy to remote machines, share this PC's devices, stop sharing), Tools ▾ (check for updates, reinstall ADB and scrcpy, open the host webcam, create shortcuts), then icons for the theme, the log panel, settings and help.
  • Closing TurboADB closes ADB and scrcpy — any mirror window it opened is closed and the adb server is stopped, so nothing keeps the device busy after you quit. A server shared with other machines (turboadb serve) is left alone, and Settings → Startup turns this off.
  • Devices sidebar — Connected devices and Saved targets. Every device you connect is saved as a target automatically (named after the device, never twice; turn this off in Settings → Startup). Type in the search box to filter or quick-connect to a host; hide the sidebar with ‹ or Ctrl+B.
  • Device tabs — every device gets Terminal, Logcat, Files, Device Control, Apps, Phone and Webcam (plus IVI Displays on cars and multi-display devices). Screen ▾, Screenshot, Reboot ▾ and More ▾ sit at the right end of that row. More ▾ holds Split view (Terminal, Device Control, Files and Logcat side by side, stacked or in a grid), Device health…, Build details…, Root and mount, Go wireless (USB → Wi-Fi) and Capture bugreport….
  • Device type — TurboADB detects Android Automotive, an infotainment head unit, TV, watch, tablet or phone and shows it in the terminal's welcome banner. Cars get the IVI-compatible screen profile and the IVI Displays tab.
  • Themes — Graphite (dark) and Porcelain (light) by default, plus Black / White, Slate / Mist (cool blue-grey), Night / Paper (a warm reading pair) and Mocha / Latte — all with softened text and muted accents, never pure black or glaring white. The top-bar sun or moon switches between your last dark and your last light theme (pick Slate, and it toggles Slate ↔ Porcelain); its arrow, the Themes menu and Settings → Themes pick any theme directly.
  • Notifications — every action shows in the status bar and a small toast; errors show a red popup with a sound and a Copy button. The log panel (its top-bar icon) filters Normal, Verbose, Warnings + Errors or Errors only.
  • Settings — Appearance (terminal font), Tools (adb / scrcpy / ffmpeg paths), scrcpy (video and audio), Logcat, Themes and Startup.
  • Menu bar — File (new target, save output, export / import saved targets), View, Themes, Device (including Run a command on ALL devices…), Tools and Help.

Feature guide

Interactive shell

A real terminal, not a one-shot: history, Tab completion, copy/paste, and a Stop button that actually kills a runaway command like logcat (there's no PTY, so a plain Ctrl+C can't — Stop tears the shell down, kills the device-side process, and reopens, keeping your working directory). A bare ls is shown in columns.

In the GUI — open a device → Terminal tab → start typing. A boxed two-line banner at the top shows the connection, device type, Android version, CPU and serial. Right-click for Copy / Paste / Send key / Save full output to file…; Stop (or Ctrl+C) halts whatever is running. A− / A+ (or Ctrl + mouse wheel) resize every terminal together (12 pt by default).

The Android / PowerShell / CMD switcher at the left of the toolbar opens PowerShell or Command Prompt on this PC, with TurboADB's adb first on PATH and ANDROID_SERIAL set to the device. They behave like a normal console: Python, Node, Git, where and programs in the current folder all work. Stop ends the running command and opens a fresh shell in the same folder. Inside an adb shell typed there, Stop sends Ctrl+C to the device instead: only the device command stops and you stay in adb shell. If that command ignores it, Stop again reopens adb shell in the same device folder.

Need a second terminal on the same device? More ▾ → New terminal session, or right-click the Terminal tab, opens another terminal tab with its own Android shell, PowerShell and Command Prompt.

CLI — one-shot commands (everything after -- goes to the device):

turboadb -s SERIAL shell -- getprop ro.build.version.release
turboadb -s SERIAL shell --su -- "cat /data/misc/file"   # wrap in su -c

Python — shell() for one-shots, open_shell() for an interactive session:

r = dev.shell("getprop ro.product.model")
print(r.stdout, r.exit_code, r.ok)

sess = dev.open_shell()          # persistent ShellSession
sess.send("ls /sdcard\n")
print(sess.read())
sess.close()

Logcat

Filter by level, tag, or live regex; pause/clear; save the complete log (even under a flood the on-screen view trims to stay responsive, but every line is kept on disk).

In the GUI — Logcat tab → pick the level and how much history to include (Live from now, Last 1,000 + live, …), optionally a Tag, a live Filter regex or a Highlight pattern such as error|anr → Start. Crashes is a one-click preset, Pause / Clear do what they say, and Save… writes everything captured.

CLI:

turboadb -s SERIAL logcat --tag ActivityManager --priority W
turboadb -s SERIAL logcat --match "ANR|FATAL" --save crash.log
turboadb -s SERIAL logcat --dump                  # dump current buffer and exit
turboadb -s SERIAL logcat-clear                   # clear the buffers

Python — logcat() streams via an on_line callback (and tees to a file); iter_lines() is a plain generator if you'd rather loop:

dev.logcat(tag="ActivityManager", match="ANR", on_line=print, save_to="crash.log")

for line in dev.iter_lines(["logcat", "-v", "threadtime"]):
    if "FATAL" in line:
        break

Files (push/pull)

In the GUI — Files tab: This PC on one side, Device on the other. Select files and press Push or Pull, or drag and drop between the panes (also from Explorer). Both panes have New folder, New file, Edit (F4, a built-in editor), Copy / Paste, Rename (F2) and Delete, plus quick folders such as Downloads and /sdcard.

Selecting works like a file manager: drag beside the names for a block of files, Ctrl+A for all of them, Enter to open, Backspace to go up, Ctrl+Shift+N for a new folder. On Windows Delete moves local files to the Recycle Bin and Shift+Delete deletes them for good; device files always go for good. Each pane shows what it holds and what is selected. When the device refuses a change, TurboADB offers adb root, adb disable-verity and adb remount and retries afterwards (see Root & mount).

The Transfers panel under the panes follows every copy: an overall bar with the files and bytes done, the speed and the time left, and under Details a row per file with its size, progress, speed and adb's exact error if it failed. Retry failed, Clear finished and Copy / Save report… are in its menu; right-click a row to retry it or open its folder.

To browse two folders at once, press New tab (or Ctrl+Shift+T). The new Files tab starts in the same folders and has its own selection and transfers. You can open up to eight, and split view shows two side by side. Rows show the system's own file icons.

CLI:

turboadb -s SERIAL push app.apk /data/local/tmp/
turboadb -s SERIAL pull /sdcard/Download/log.txt .

Python:

dev.push("app.apk", "/data/local/tmp/")
dev.pull("/sdcard/Download/log.txt", "log.txt")

Apps

List, install (single or split APKs), uninstall, clear data, start/stop.

In the GUI — Apps tab: Install APK(s)…, or filter the package list (Third-party only) and select one for Start, Stop, Clear data or Uninstall.

CLI:

turboadb -s SERIAL packages --third-party
turboadb -s SERIAL install app.apk --grant            # grant all permissions
turboadb -s SERIAL install base.apk split_config.apk  # split install
turboadb -s SERIAL uninstall com.example.app
turboadb -s SERIAL clear com.example.app              # wipe app data
turboadb -s SERIAL start com.example.app
turboadb -s SERIAL stop com.example.app

Python:

for pkg in dev.list_packages(third_party=True):
    print(pkg)
dev.install("app.apk", grant_perms=True)
dev.install_multiple(["base.apk", "split_config.apk"])
dev.uninstall("com.example.app")
dev.clear_app("com.example.app")
dev.start_app("com.example.app")
dev.stop_app("com.example.app")

Device controls

The Device Control tab has a Device controls panel beside the screen with one-click actions. Each is also a CLI command and an API call.

Keys & input

GUI — Device controls → Navigation (Back, Home, Recents, Power, Notifications, Settings).

turboadb -s SERIAL key home          # back, home, recents, power, notifications…
turboadb -s SERIAL scroll down       # up | down | left | right
turboadb -s SERIAL tap                # tap the centre of the screen
dev.keyevent("home")
dev.scroll("down")
dev.tap_center()

Rapid taps (soak and stress testing)

Thousands of taps on one point, as one loop on the device — no tap waits for the PC. With --method events (what auto picks when the adb shell may write to the touchscreen) the taps go straight to the touch device and run several times faster than input tap, which starts a JVM per tap. --rate caps taps per second, and --duration taps for a while instead of counting.

GUI — not in the GUI: this is a command-line and API tool.

turboadb -s SERIAL tap-burst 540 1200 --count 5000
turboadb -s SERIAL tap-burst 540 1200 --rate 20 --duration 60
turboadb -s SERIAL touch-device        # which touchscreen, and may the shell write to it?
report = dev.tap_burst(540, 1200, count=5000)          # {'method': 'events', 'taps': 5000, …}
dev.tap_burst(540, 1200, rate=20, duration=60, on_progress=print)
dev.touch_device()

Media & connectivity

GUI — Device controls → Media & volume and Quick settings (Wi-Fi, Bluetooth, Mobile data, Airplane mode, Hotspot, each with On and Off).

turboadb -s SERIAL media play-pause   # previous | next | play-pause
turboadb -s SERIAL wifi on            # on | off
turboadb -s SERIAL bluetooth off
turboadb -s SERIAL airplane on
turboadb -s SERIAL hotspot on         # best-effort (see IVI tips)
dev.media("play-pause")
dev.set_wifi(True)
dev.set_bluetooth(False)
dev.set_airplane(True)
dev.set_hotspot(True)

Screen & app launchers

GUI — Device controls → Screen & power and Apps & web (a URL or search box plus Browser, YouTube, Spotify, Maps, Play Store, Gallery, Calculator and Camera tiles).

turboadb -s SERIAL screen off         # on | off
turboadb -s SERIAL settings           # open the Settings app
turboadb -s SERIAL open https://maps.google.com
turboadb -s SERIAL search "nearest charger"
turboadb -s SERIAL camera             # also: gallery, calculator
dev.screen_off()
dev.open_settings()
dev.open_url("https://maps.google.com")
dev.web_search("nearest charger")
dev.open_camera()        # open_gallery(), open_calculator()

On-screen keyboard

Type into the focused field (useful when the unit has no soft keyboard).

GUI — Device controls → Keyboard: type, then Send (Enter, Backspace, Space, Tab, Esc and Search keys are next to it). While the screen is showing you can also click it and type on your PC keyboard, or use Options → Type or paste text….

turboadb -s SERIAL text "hello world"
turboadb -s SERIAL key enter
dev.input_text("hello world")
dev.keyevent("enter")

Mirroring (scrcpy)

Mirror in its own window or embedded in the tab. A compatibility mode (software decode, forced tunnel host/port, UHID keyboard) handles IVI units that choke on the defaults, and it works through a remote adb server.

GUI — open Device Control, pick a display, then press Start screen to show it in the tab or Separate window (Screen ▾ beside the section tabs does the same from any tab). Click the screen and type on your PC keyboard. The toolbar also has Stop, a screenshot icon, Record…, Audio on / off, Options, Maximize view and Hide controls (hides the controls without stopping the screen; it works while maximized too). The controls sit beside the screen or in a strip below it, whichever shows the screen larger for your window and the screen's shape.

The display picker lists every display by number, name and size (for example Display 2 · Instrument cluster · 1920x720) as soon as the device connects. TurboADB asks Android over adb for them, so connecting never starts scrcpy. Options holds audio forwarding and its source, Compatibility mode (IVI / automotive), software rendering, the keyboard mode (Standard SDK or UHID hardware keyboard), Device camera with Back / Front — the device's own camera instead of its screen, needing scrcpy 2.2+ and Android 12+ — Manage displays… and All displays. Audio needs Android 11+; tune codec, bitrate and latency in Settings → scrcpy.

All displays at once — cars, and any device with several displays, get an IVI Displays tab (Displays on other devices) that shows every display live and controllable, side by side, each with its own Start / Stop, Separate window, screenshot and Record. The displays start one after another the first time you open the tab. Start all, Stop all and Rescan are at the top, and Maximize on a display shows only that one (Restore or Esc brings the grid back). Each display has its own Back, Home, Recents, volume, mute, power and screenshot buttons, sent to that display.

When scrcpy won't run — some builds can't run scrcpy at all. Settings → scrcpy → Screen renderer → ADB screencap (or Options → Renderer on one screen) shows the device through adb screencap instead: it finds the display through dumpsys display, streams frames over one adb connection (a few frames a second), and still supports tap, drag, long-press, scrolling and typing. Record records on the device with screenrecord instead, so it works without scrcpy too.

CLI:

turboadb -s SERIAL scrcpy --max-size 1280 --bit-rate 8M
turboadb -s SERIAL scrcpy --bit-rate 16M --audio-source playback --audio-dup
turboadb -s SERIAL scrcpy --no-control --turn-screen-off
turboadb -s SERIAL scrcpy --video-source camera --camera-facing front

Python:

from turboadb import ScrcpyOptions
sess = dev.mirror(ScrcpyOptions(max_size=1280, bit_rate="8M"))
sess.wait()          # blocks until the scrcpy window closes

Screenshots & recording

GUI — Screenshot at the right end of the section tabs (or the screenshot icon in Device Control); Record… in the Device Control screen toolbar. If the screen is already live, a second, windowless recorder runs beside it, so the view never restarts, and stopping saves a playable MP4.

CLI:

turboadb -s SERIAL screenshot shot.png
turboadb -s SERIAL record clip.mp4 --time-limit 20 --size 1280x720

Python:

dev.screenshot("shot.png")
dev.screen_record("clip.mp4", time_limit=20, size="1280x720")

The CLI record command and screen_record() use device-side screenrecord and pull the file back, so they work over RDP without a video tunnel.

Webcam (host camera)

Different from the device camera (scrcpy --video-source camera): the 📹 Webcam tab views a host webcam — a USB or laptop camera on the machine running TurboADB. Point one at the physical head unit / bench and watch it beside the scrcpy mirror.

GUI — choose Tools ▾ → Open host webcam (or View → Open webcam (host camera), or the Host webcam tile on the start page) to open it as a standalone tab — no device needed. Every device also has its own Webcam tab, handy beside the screen. Pick a Source:

  • Local — this PC — Scan cameras → pick a camera, resolution and frame rate → Start camera.
  • Remote — Windows PC — enter the RDP host, User, Domain and Password → Scan cameras → Start camera. No SSH: TurboADB uses the same WinRM/NTLM path as deploy-serve to run ffmpeg on the remote and stream its camera back over a direct TCP socket.

Then Snapshot, Record (clean H.264 MP4), Pause, Rotate, Flip, and View: Fit, Fill or Stretch. Right-click the video to copy the image.

Local works over RDP too. Capture is local DirectShow, so when TurboADB runs inside an RDP session it sees whatever camera that session exposes. If none shows up: enable camera redirection in the RDP client (Local Resources → More… → Cameras), turn on Windows camera privacy ("Let desktop apps access your camera"), and make sure nothing else is using it.

Remote needs WinRM on the target (Enable-PSRemoting -Force) and the account a local admin. ffmpeg is provisioned automatically: TurboADB first copies your local ffmpeg.exe to the remote over its admin share (\\host\C$, fast on a LAN and no internet needed there — like TurboSSH's push); if the share isn't reachable it falls back to the remote downloading ffmpeg itself, and failing that you can drop ffmpeg.exe in C:\Windows\Temp\turboadb-ffmpeg\ over RDP. The host / user / domain are remembered and the password is saved in the Windows Credential vault (keyring), never in a file. A physical USB camera works headlessly; a camera redirected into someone's RDP session is only visible inside that session.

ffmpeg powers the capture; locally it's downloaded once (~160 MB, cached under ~/.turboadb/ffmpeg) or set Settings → ffmpeg path to your own.

Telephony

GUI — open a device and pick its Phone tab. Calls and messages load the first time you open the tab, never while connecting.

  • Dialler — type or paste a number, or use the keypad (hold 0 for +). Call places the call, End hangs up or rejects, Answer picks up a ringing call, and Open in dialler (or Enter in the number field) only opens the device dialler pre-filled. The toolbar pill shows Idle, Ringing or In call, or No telephony on devices without it (e.g. IVI head units). Refresh reloads the call state, calls and messages.
  • Recent calls — incoming, outgoing, missed and rejected calls with their time and duration. Double-click a call or press Call back to put its number in the dialler (it never calls by itself); Message starts a message to it.
  • Messages — received and sent SMS with a one-line preview. Select one to address a reply, type under New message and press Compose in Messages: the device's Messages app opens with the draft, and you press Send there.

If the device refuses access to its call log or messages, the list says so in place of the rows and the log gets one warning.

Head units and other devices without a phone — the tab first checks what the device has, so nothing shows as an error. Without telephony the pill shows a grey No telephony; without a call log or SMS store the lists say so; and when no standard phone app exists, Call, Open in dialler and Compose are disabled. If the device has its own phone app (a customised head unit's Bluetooth phone, for example), an Open … button starts it.

CLI:

turboadb -s SERIAL dial 1800123456        # open dialer pre-filled
turboadb -s SERIAL call 1800123456        # place the call
turboadb -s SERIAL answer
turboadb -s SERIAL end-call
turboadb -s SERIAL call-log --limit 20
turboadb -s SERIAL sms --limit 20
turboadb -s SERIAL send-sms 1800123456 "on my way"
turboadb -s SERIAL phone-support          # telephony + dialler / call / SMS apps

Python:

dev.dial("1800123456"); dev.call("1800123456")
dev.answer_call(); dev.end_call()
for c in dev.call_log(20): print(c)
for m in dev.sms_list(20): print(m)
dev.send_sms("1800123456", "on my way")
print(dev.phone_support())  # which dialler / SMS / phone apps exist (calls no one)

Root & mount

For rooted / engineering builds.

GUI — More ▾ → Root and mount (at the right end of the section tabs). After adb root or adb unroot (from that menu, or typed in PowerShell or Command Prompt) every terminal follows: the Android shell reconnects with the new prompt (# as root), and a PowerShell or CMD tab that was inside adb shell opens it again in the same folder.

When the Files tab can't change a device file (permission denied or a read-only file system), it asks which of adb root, adb disable-verity and adb remount to run, runs them with any reboot they need, and then retries. More ▾ → Root and mount → Make files writable… opens the same choices at any time.

CLI:

turboadb -s SERIAL root            # restart adbd as root  (unroot to undo)
turboadb -s SERIAL remount         # adb remount
turboadb -s SERIAL mount-rw        # mount -o remount,rw /
turboadb -s SERIAL disable-verity  # syncs and offers the required reboot
turboadb -s SERIAL access          # root, build type, verity, bootloader
turboadb -s SERIAL make-writable   # root + remount, rebooting when needed

Python:

dev.root(); dev.unroot()
dev.remount(); dev.mount_rw()
dev.disable_verity(); dev.enable_verity()
dev.access_status()                        # {'root': True, 'verity': 'enforcing', …}
dev.make_writable(disable_verity=True)     # root, disable-verity, reboot, root, remount

Reboot

GUI — Reboot ▾ (System / Recovery / Bootloader / Sideload — the risky ones warn first, doubly so on automotive).

turboadb -s SERIAL reboot
turboadb -s SERIAL reboot recovery       # recovery | bootloader | sideload
dev.reboot()
dev.reboot("recovery")

Device info

GUI — the Android terminal's welcome banner shows the connection, device type, Android version, CPU and serial on connect. More ▾ → Device health… and Build details… show the rest, and Battery is in Device controls → Screen & power.

turboadb -s SERIAL info --json      # includes kind, kind_label, display_size, telephony
turboadb -s SERIAL build-info
turboadb -s SERIAL battery
turboadb -s SERIAL health           # battery, temperature, memory, CPU, uptime
turboadb -s SERIAL bugreport        # save a full bug report zip
d = dev.device_info()    # dict: manufacturer, model, android_version, sdk, abi, automotive, kind…
print(d["model"], d["android_version"], d["kind_label"])
kind = dev.device_kind() # {"kind": "phone" | "tablet" | "tv" | "watch" | "automotive" | "headunit", …}
print(kind["label"], "because", kind["reason"])
print(dev.battery())     # raw dumpsys battery text
print(dev.health())      # dict: battery, temperature, memory, CPU, uptime

The device type comes from the device itself: Android Automotive OS reports the android.hardware.type.automotive feature (or automotive in ro.build.characteristics); an infotainment head unit running ordinary Android has no telephony feature and a natively landscape display; TVs, watches and tablets report their own feature or characteristic. Both car kinds set automotive, which selects the IVI-compatible screen profile in the GUI.

Remote devices

Drive a device that's plugged into a different machine, over its adb server — exactly what you want for a lab unit reached by RDP. Add --adb-host to any CLI command, or set adb_server_host in the config. (The host machine has to be sharing its adb server — see the next two sections.)

turboadb --adb-host lab-pc-01 devices
turboadb --adb-host lab-pc-01 -s DEVICE shell -- pm list packages
turboadb --adb-host lab-pc-01 -s DEVICE scrcpy --max-size 1280
dev = ADBHandler(ADBConfig(adb_server_host="lab-pc-01", serial="DEVICE"))
dev.connect()

Share devices (serve)

Turn the machine a device is plugged into a host others can reach.

GUI — ADB server ▾ → Share THIS PC's devices… (Start once or **Start

  • run at login**; opening the firewall needs Administrator). ADB server ▾ → Stop sharing & remove auto-start undoes it.

CLI:

turboadb serve                    # start the shared server + open the firewall
turboadb serve --startup-task     # …and keep it running headless across reboots
turboadb serve --uninstall-startup

Python:

from turboadb.devices import start_shared_server, open_firewall, install_serve_task
print(start_shared_server())
print(open_firewall((5037, "27184-27199")))
install_serve_task()              # SYSTEM startup task, headless

Deploy serve over WinRM

Push serve onto remote Windows hosts from your machine — one host or a whole fleet — without logging into each. Uses pywinrm/NTLM, so domain credentials work over plain WinRM.

GUI — ADB server ▾ → Deploy to remote machine(s) (RDP / WinRM)…: enter the host(s) + admin credentials, Test connection, then Deploy.

CLI:

turboadb deploy-serve lab-pc-01 lab-pc-02 -u "DOMAIN\user"
turboadb deploy-serve lab-pc-01 -u "DOMAIN\user" --test   # just check WinRM first
turboadb deploy-serve lab-pc-01 -u "DOMAIN\user" --password-stdin < pw.txt  # never in argv

Python:

from turboadb.remote_deploy import deploy_serve
deploy_serve(["lab-pc-01", "lab-pc-02"], "DOMAIN\\user", "password",
             on_status=print)

Each target needs WinRM enabled (Enable-PSRemoting -Force once), your account a local admin, and Python + turboadb installed there.

Keep things up to date

GUI — Tools ▾ → Check for updates… checks PyPI for a newer TurboADB, updates it, refreshes adb/scrcpy, and restarts (with no newer TurboADB it still checks the tools). Tools ▾ → Download and reinstall ADB and scrcpy… refreshes only the tools.

turboadb self-update      # upgrade TurboADB itself, then adb/scrcpy
turboadb upgrade-tools    # only refresh adb/scrcpy
turboadb doctor           # report what's installed / missing

CLI cheatsheet

Every command with all its options and examples is in the CLI reference (also on the website, with search). turboadb -h lists everything; turboadb <command> -h details one. Every command takes --json. Target with -s SERIAL (or -s @NAME for a saved target); add --adb-host HOST for a remote server.

devices  info  state  serialno  ip  wait  targets  connect  disconnect  pair
tcpip  wireless  discover  restart-server  stop-server
shell  adb  logcat  logcat-clear  bugreport
push  pull  ls  mkdir  touch  rm  mv  cp  stat  edit
packages  install  uninstall  clear  start  start-activity  activity  stop
grant  revoke  close-apps
displays  screenshot  record  scrcpy  screen
key  text  tap  tap-burst  touch-device  swipe  scroll  media  brightness  notifications
wifi  bluetooth  airplane  hotspot  mobile-data
settings  open  search  camera  gallery  calculator
battery  health  build-info  getprop
dial  call  answer  end-call  call-state  call-log  sms  send-sms  phone-support
root  unroot  remount  access  make-writable  mount-rw  disable-verity  enable-verity  reboot
forward  reverse  serve  deploy-serve
doctor  fetch-tools  upgrade-tools  self-update  shortcut  gui

Python API notes

import turboadb exposes the engine and its types. Calls return small dataclasses — CommandResult (.stdout, .stderr, .exit_code, .ok), TransferResult, StreamResult. Construct a handler with safe=True for non-raising OperationResults, or leave it default to get exceptions you can catch (ADBError and friends). See examples/examples.py and ARCHITECTURE.md.

from turboadb import ADBHandler, ADBConfig, ScrcpyOptions

dev = ADBHandler(ADBConfig(serial="SERIAL"))
dev.connect()
assert dev.shell("getprop ro.build.version.release").ok
dev.install("app.apk", grant_perms=True)
dev.screenshot("after_install.png")

Android Automotive / IVI tips

  • device_info() flags automotive for Android Automotive OS and for head units running ordinary Android (see device_kind() in Device info); the GUI then uses the IVI-compatible screen profile and adds the IVI Displays tab, which shows every display (centre stack, cluster, passenger) live at once.
  • list_displays() names each display (Instrument cluster, Passenger) and asks Android over adb; pass method="scrcpy" for scrcpy's own list.
  • If the default mirror fails, use compatibility mode (software decode).
  • bootloader / sideload reboots warn hard — many head units have no on-screen recovery UI and can get stuck.
  • Calculator / Camera / Play Store are often absent; launchers fall back and the log says when nothing happened.
  • Hotspot can't always be toggled purely over adb (uid permissions) — TurboADB tries cmd wifi, then falls back to opening the tethering settings.

Build from source

git clone https://github.com/NVNKENNEDY/turboadb && cd turboadb
pip install -r requirements.txt
python -m turboadb.gui            # run the GUI from source
python scripts/build_exe.py       # build the versioned Windows exe in dist/
python tests/test_offline.py      # offline checks

See ARCHITECTURE.md and CHANGELOG.md.

License

MIT.

Metadata

Release files for turboadb 2.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for turboadb 2.5.0
File Size Uploaded
turboadb-2.5.0.tar.gz 60.2 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for turboadb 2.5.0
File Interpreter ABI Platform
turboadb-2.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 120.1 MB

Release files / turboadb-2.5.0.tar.gz

Download URL turboadb-2.5.0.tar.gz
Size 60.2 MB
Tags Source
SHA-256 checksum
How to use checksums
44f57711ac09954acc1a61a6de43b3219080aac6d66adaaf1ad6d7e4c568f897
BLAKE2b-256 checksum
How to use checksums
b9043b8ee088777394f6f5904384533456afff4acc5b80b0c54b4ec2f085cd67
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.9

Release files / turboadb-2.5.0-py3-none-any.whl

Download URL turboadb-2.5.0-py3-none-any.whl
Size 59.9 MB
Tags Python 3
SHA-256 checksum
How to use checksums
de7c8ee27e43d8f571b38a414dbfc34e1fc127733f67152e5addfac67491912f
BLAKE2b-256 checksum
How to use checksums
e9428e6841985ba0d0ad9665ee6cda09d8c4771ab8437c337a4b43740a8bca41
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.9

Release history Release notifications | RSS feed

4.0.0

2 release files

3.1.0

2 release files

3.0.0

2 release files

This release

2.5.0 This release

2 release files

2.3.0

2 release files

2.2.2

2 release files

2.1.0

2 release files

2.0.0

2 release files

1.1.15

2 release files

1.1.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page