adb-go is a pure-Go implementation of the ADB (Android Debug Bridge) protocol.
Note
Current adb-go implementation is not a full replacement for the official adb binary yet.
- Overview
- Install
- High-level client API
- Linux USB support
- Authentication helpers
- Experimental CLI
- adb-gos server foundation
- Low-level protocol package
- Implementation notes
- Current limitations
- Testing
History of changes is available in CHANGELOG.md.
adb-go is layered from low-level ADB protocol primitives up to high-level
library workflows, with the CLI and server built on top.
Most probably you are here for high-level client API.
block-beta
columns 2
cli["CMD/ADB-GO<br/>(experimental CLI)"]
server["CMD/ADB-GOS<br/>(server foundation)"]
root["GITHUB.COM/DECTOR/ADB-GO<br/>(stable high-level API)"]:2
workflows["CLIENT WORKFLOWS<br/>(shell · push/pull · install · logcat · screencap · reboot · forward · reverse)"]:2
client["CLIENT<br/>(connections, services, device operations)"]:2
auth["AUTH<br/>(RSA key loading and signing)"]
transports["TRANSPORTS<br/>(TCP · Linux USB)"]
protocol["PROTOCOL<br/>(ADB packets · handshake · streams)"]:2
| Feature | Notes |
|---|---|
| TCP connections | |
| USB connections | Linux only |
| USB device exploration | Linux only |
| Key authentication | Explicit existing RSA keys |
| Shell execution | |
| Shell streaming | |
| Service opening | |
| Android properties | |
| Logcat | Supports streaming and dump-and-exit modes |
| Screencap | |
| Reboot | Supports normal, bootloader, and recovery modes |
| Local TCP forwarding | Device TCP targets only |
| Server-owned TCP forwarding | Device TCP targets only |
| Reverse TCP forwarding | Foreground process-scoped, device TCP to host loopback TCP |
| File push/pull | |
| APK installation | Supports replace option |
| Sample CLI | Showcasing library |
| adb-gos server foundation | Unix-socket server |
go get github.com/dector/adb-goimport adb "github.com/dector/adb-go"Download latest binary (snapshot) or use mise:
mise u -g "github:dector/adb-go@snapshot"Use the root package for the high-level API. It re-exports the client
package for connecting to a device, opening services, running shell commands,
reading Android system properties, streaming Android logs, capturing screenshots,
rebooting into supported modes, forwarding local TCP connections to device TCP
ports, reverse forwarding device TCP connections to host loopback TCP ports,
pushing or pulling one file, and installing one APK.
ctx := context.Background()
c, err := adb.Connect(ctx, "127.0.0.1:5555")
defer c.Close()Use shell:
out, err := c.Shell(ctx, "echo hello")
fmt.Printf("%s", out)
Read Android system properties:
model, err := c.GetProp(ctx, adb.PropProductModel)
fmt.Println(model)
props, err := c.Properties(ctx)
fmt.Println(props[adb.PropBuildVersionSDK])Stream Android log output:
err := c.Logcat(ctx, os.Stdout, adb.LogcatOptions{})or use dump-and-exit mode:
err := c.Logcat(ctx, os.Stdout, adb.LogcatOptions{Dump: true})Capture PNG screenshot:
png, err := c.Screencap(ctx)
err = os.WriteFile("screen.png", png, 0o666)Or (file must not exist):
err := c.ScreencapFile(ctx, "screen.png")Request a reboot:
err := c.Reboot(ctx, adb.RebootNormal)Reboot is disruptive: a successful request affects the selected device
immediately and may close the ADB connection as the device restarts.
Forward local TCP connections to a TCP endpoint on the selected device:
remote, err := adb.ForwardTCP(8080)
forward, err := c.ForwardLocalTCP(ctx, "127.0.0.1:0", remote)
defer forward.Close()
fmt.Println("listening on", forward.LocalAddr())
err = forward.Wait()This is process-scoped foreground forwarding. It is useful for bridging local
clients to a service listening on the device, but it is not an adb-server-backed
persistent adb forward registration.
Reverse device TCP connections to a host loopback TCP endpoint:
remote, err := adb.ReverseDeviceTCP(8081)
local, err := adb.ReverseHostTCP(3000)
reverse, err := c.ReverseTCP(ctx, remote, local)
defer reverse.Close()
err = reverse.Wait()This creates a device-side tcp:8081 listener through adbd's reverse-forwarding
service. When device code connects to that port, adbd opens an ADB stream back
to adb-go and adb-go dials 127.0.0.1:3000 on the host. The reverse exists only
while the process owns the returned handle.
Install APK:
err := c.InstallAPKWithOptions(ctx, "./app.apk", adb.InstallOptions{Replace: true})The install helper intentionally is not a full clone of adb install; it pushes
the APK to /data/local/tmp, runs Android's package manager, and removes the
temporary file on a best-effort basis. More examples: client/README.md.
On Linux, adb-go can connect directly through /dev/bus/usb without libusb.
Select the only visible ADB-capable interface, or provide a USB selector when
multiple devices are connected.
c, err := adb.ConnectUSB(ctx, adb.USBOptions{
DevicePath: "/dev/bus/usb/001/002",
})Details and troubleshooting: client/README.md,
docs/linux-usb-transport.md.
Authenticated devices can use an explicitly supplied existing ADB RSA private
key. adb-go signs AUTH TOKEN challenges and can offer the matching public key
for the device authorization prompt. Key management remains explicit: adb-go
does not generate, discover, or persist keys in v0.
credential, err := adb.LoadPrivateKey("/home/me/.android/adbkey")
c, err := adb.ConnectTCPWithOptions(ctx, "127.0.0.1:5555", adb.ConnectOptions{
AuthCredentials: []adb.AuthCredential{credential},
})Package docs: auth/README.md. Protocol details:
docs/authentication.md.
The adb-go CLI is a thin wrapper around supported library workflows. It is not
a full clone of the official adb command.
go install github.com/dector/adb-go/cmd/adb-go@latest
adb-go version
adb-go --quiet shell --addr 127.0.0.1:5555 echo hello
adb-go push --addr 127.0.0.1:5555 ./local.txt /data/local/tmp/local.txt
adb-go pull --addr 127.0.0.1:5555 /data/local/tmp/remote.txt ./remote.txt
adb-go install-apk --addr 127.0.0.1:5555 ./app.apk
adb-go getprop --addr 127.0.0.1:5555 ro.product.model
adb-go getprop --addr 127.0.0.1:5555
adb-go logcat --addr 127.0.0.1:5555
adb-go logcat --dump --addr 127.0.0.1:5555
adb-go screencap --addr 127.0.0.1:5555 ./screen.png
adb-go reboot --addr 127.0.0.1:5555
adb-go reboot --addr 127.0.0.1:5555 recovery
adb-go forward --addr 127.0.0.1:5555 tcp:9000 tcp:9000
adb-go reverse --addr 127.0.0.1:5555 tcp:8081 tcp:3000Global --quiet suppresses non-error informational status messages while keeping
explicit command payloads on stdout. For example, adb-go --quiet shell ...
still prints the device command's stdout, logcat, getprop, targets,
--json/--plain, version, and screencap's chosen file path still emit their
requested output, and errors/warnings continue to use stderr. Status-only lines
such as foreground/background forwarding lifecycle messages are hidden.
adb-go version prints the adb-go build version, Go runtime version, target OS,
and target architecture. Development builds report dev; release builds can
inject a Git-derived value with Go's standard linker flags. The helper
./tools/git-version.sh prints the latest semantic vMAJOR.MINOR.PATCH tag
as-is when HEAD is exactly on that tag and the worktree is clean. For clean
commits after the tag, it bumps the patch component and appends the zero-padded
commit distance, for example v0.1.1-001. Dirty worktrees append -snapshot to
that calculated version, for example v0.1.1-001-snapshot:
version=$(./tools/git-version.sh)
go build -ldflags "-X main.version=${version}" ./cmd/adb-goCLI docs, including troubleshooting for common connection, authentication,
unsupported-platform, overwrite, and local-path errors:
cmd/adb-go/README.md.
adb-gos is the first adb-go server process. It listens on a Unix domain socket
and supports ping, status, graceful shutdown, service diagnostics, and
in-memory server-owned TCP forwarding registrations. It does not persist devices,
transports, forwards, shell sessions, authentication state, or other ADB workflow
state across server restarts yet.
go install github.com/dector/adb-go/cmd/adb-gos@latest
adb-gos
adb-go server doctor
adb-go server statusOn Linux with systemd user services, the CLI can install and manage adb-gos as
a per-user service:
adb-go server service install
adb-go server service status
adb-go server service logsServer design, socket selection, control protocol, troubleshooting, forwarding
health counters, and service management details:
docs/server-foundation.md. Server-backed
persistent forwarding behavior is described in
docs/persistent-forwarding-design.md.
Advanced callers can use protocol for direct ADB packet, handshake, and stream
access. Most applications should use the high-level client API instead.
conn := protocol.NewConnection(rw)
_, err := conn.Handshake(ctx)Package docs: protocol/README.md.
Architecture, package responsibilities, protocol flow, security model, and other
cross-cutting implementation notes live in docs/README.md.
adb-go intentionally supports only a small v0 subset:
- Transport support is limited to explicit TCP endpoints and Linux USB via
/dev/bus/usb; macOS and Windows USB are not implemented yet. - ADB authentication is implemented for explicitly supplied existing RSA key files; adb-go does not auto-discover, generate, or persist keys.
- No broad device discovery, server management, or official
adb devicescompatibility in v0. The CLI has an adb-go-specifictargetscommand. adb-goscan own in-memory TCP forwarding listeners, but it does not persist devices, transports, forwards, sessions, or authentication state across server restarts yet.- Incomplete command coverage: shell, shell streaming, generic service opening, Android property lookup, logcat streaming/dump, screenshot capture, reboot, foreground local TCP forwarding, single-file push/pull, and one-APK installation are the main supported workflows.
- APK installation is exposed as
install-apk, an adb-go-specific helper rather than officialadb installcompatibility. It currently supports one local APK and the replace-existing-app option only. - Property support intentionally covers common
getpropreads through adb-go'sGetProp/Propertieshelpers and CLIgetpropcommand. Property names and values come from the connected device and should be treated as remote data. - Logcat support intentionally covers only adb-go's
Logcathelper and CLIlogcatcommand with optional dump mode. It is not a full implementation of every officialadb logcatfilter, format, buffer, or output flag. - Screencap support captures one PNG image through Android's
screencap -pshell command. The CLI writes to a local PNG file and refuses to overwrite an existing path unless--overwriteis passed. - Reboot support is intentionally explicit and disruptive. It currently supports
normal, bootloader, and recovery modes through adb-go's
Reboothelper and CLIrebootcommand; a successful request may close the ADB connection while the selected device restarts. - Forwarding support covers foreground process-scoped TCP forwards/reverses and
server-owned in-memory TCP forwards/reverses through
adb-go forwardandadb-go reversebackground/list/remove commands. It does not emulate the official adb server's durable mapping store and does not support JDWP, Unix sockets, or other endpoint families yet.
More details are in the package READMEs and docs/README.md.
Run the default unit and example suite with:
go test ./...Optional integration tests are skipped by default. Set
ADB_GO_INTEGRATION_ADDR to run TCP tests against an already-running emulator,
TCP-enabled device, or manually started test server:
ADB_GO_INTEGRATION_ADDR=127.0.0.1:5555 go test ./...The repository also includes opt-in workflows for the containerized Linux
adbd fixture and Linux USB transport tests. Full setup, prerequisites, and
troubleshooting notes are in docs/integration-testing.md.
