{"id":41009384,"url":"https://github.com/codeskyblue/go-adbkit","last_synced_at":"2026-01-22T09:01:18.498Z","repository":{"id":330247173,"uuid":"1122096447","full_name":"codeskyblue/go-adbkit","owner":"codeskyblue","description":"Golang implementation of https://github.com/openstf/adbkit","archived":false,"fork":false,"pushed_at":"2026-01-01T01:24:41.000Z","size":102,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-01-02T09:45:21.806Z","etag":null,"topics":["adb","golang"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/codeskyblue.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-24T05:14:59.000Z","updated_at":"2025-12-31T13:55:16.000Z","dependencies_parsed_at":null,"dependency_job_id":"2b5f0b43-1d90-4050-9d1f-76c691c87742","html_url":"https://github.com/codeskyblue/go-adbkit","commit_stats":null,"previous_names":["codeskyblue/go-adbkit"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/codeskyblue/go-adbkit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codeskyblue%2Fgo-adbkit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codeskyblue%2Fgo-adbkit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codeskyblue%2Fgo-adbkit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codeskyblue%2Fgo-adbkit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/codeskyblue","download_url":"https://codeload.github.com/codeskyblue/go-adbkit/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codeskyblue%2Fgo-adbkit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28659868,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-22T01:17:37.254Z","status":"online","status_checked_at":"2026-01-22T02:00:07.137Z","response_time":144,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["adb","golang"],"created_at":"2026-01-22T09:01:17.839Z","updated_at":"2026-01-22T09:01:18.483Z","avatar_url":"https://github.com/codeskyblue.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# go-adbkit\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/codeskyblue/go-adbkit.svg)](https://pkg.go.dev/github.com/codeskyblue/go-adbkit)\n[![codecov](https://codecov.io/gh/codeskyblue/go-adbkit/graph/badge.svg?token=YkCKmO9TUs)](https://codecov.io/gh/codeskyblue/go-adbkit)\n\nA pure Go client library for the Android Debug Bridge (ADB) protocol.\n\n## Features\n\n- **Pure Go Implementation**: No external dependencies on ADB binaries\n- **Comprehensive API Support**:\n  - Host commands: version, devices, connect, disconnect, kill server\n  - Device commands: shell, properties, reboot, screenshot, screen orientation\n  - Package management: list, install, uninstall, clear data, check installation\n  - Intent management: start activities, start services\n  - Network operations: TCP/IP mode, USB mode, socket connections\n  - File operations: stat, readdir, pull, push (sync service)\n  - Port forwarding: forward, reverse, list forwards\n  - Screen capture: framebuffer, screencap with fallback\n  - Logcat: real-time log streaming\n- **Simple \u0026 Clean API**: Easy to use and integrate into your Go projects\n- **Testable**: Mock-friendly design with connector interface for testing\n\n## Installation\n\n```bash\ngo get github.com/codeskyblue/go-adbkit\n```\n\n## Quick Start\n\n### Basic Usage\n\n```go\npackage main\n\nimport (\n    \"fmt\"\n    \"log\"\n    \"github.com/codeskyblue/go-adbkit/adb\"\n)\n\nfunc main() {\n    // Create a new ADB client (connects to localhost:5037 by default)\n    client := adb.NewClient()\n\n    // Get ADB server version\n    version, err := client.Version()\n    if err != nil {\n        log.Fatal(err)\n    }\n    fmt.Printf(\"ADB version: %d\\n\", version)\n\n    // List connected devices\n    devices, err := client.ListDevices()\n    if err != nil {\n        log.Fatal(err)\n    }\n    for _, device := range devices {\n        fmt.Printf(\"Device: %s (%s)\\n\", device.Serial, device.State)\n    }\n}\n```\n\n### Running Shell Commands\n\n```go\n// Get a device\ndevice := client.Device(\"device-serial\")\n\n// Run a shell command\noutput, err := device.RunCommand(\"getprop ro.product.model\")\nif err != nil {\n    log.Fatal(err)\n}\nfmt.Printf(\"Device model: %s\\n\", output)\n\n// Run with context and timeout\nctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)\ndefer cancel()\n\noutput, err = device.RunCommandContext(ctx, \"getprop ro.product.model\")\nif err != nil {\n    log.Fatal(err)\n}\nfmt.Printf(\"Device model: %s\\n\", output)\n```\n\n### File Operations\n\n```go\ndevice := client.Device(\"device-serial\")\n\n// List files\nentries, err := device.Readdir(\"/sdcard/\")\nif err != nil {\n    log.Fatal(err)\n}\nfor _, entry := range entries {\n    fmt.Printf(\"File: %s\\n\", entry)\n}\n\n// Get file info\nstat, err := device.Stat(\"/sdcard/file.txt\")\nif err != nil {\n    log.Fatal(err)\n}\nfmt.Printf(\"Size: %d, Mode: %d\\n\", stat.Size, stat.Mode)\n\n// Pull file from device\nreader, err := device.Pull(\"/sdcard/file.txt\")\nif err != nil {\n    log.Fatal(err)\n}\ndefer reader.Close()\n\n// Write to local file\nlocalFile, err := os.Create(\"local_file.txt\")\nif err != nil {\n    log.Fatal(err)\n}\ndefer localFile.Close()\n_, err = io.Copy(localFile, reader)\n\n// Push file to device\nfile, err := os.Open(\"local_file.txt\")\nif err != nil {\n    log.Fatal(err)\n}\ndefer file.Close()\n\nerr = device.Push(file, \"/sdcard/file.txt\", 0644)\nif err != nil {\n    log.Fatal(err)\n}\n```\n\n### Port Forwarding\n\n```go\ndevice := client.Device(\"device-serial\")\n\n// Forward local port to device\nsuccess, err := device.Forward(\"tcp:8080\", \"tcp:8080\")\nif err != nil {\n    log.Fatal(err)\n}\n\n// Reverse forward (device to local)\nsuccess, err = device.Reverse(\"tcp:8080\", \"tcp:8080\")\nif err != nil {\n    log.Fatal(err)\n}\n\n// List reverse forwards\nrevs, err := device.ListReverses()\nif err != nil {\n    log.Fatal(err)\n}\nfor _, rev := range revs {\n    fmt.Printf(\"%s -\u003e %s\\n\", rev.Remote, rev.Local)\n}\n\n// List all forwards (from client)\nforwards, err := client.ListForwards()\nif err != nil {\n    log.Fatal(err)\n}\nfor _, fwd := range forwards {\n    fmt.Printf(\"%s: %s -\u003e %s\\n\", fwd.Serial, fwd.Local, fwd.Remote)\n}\n```\n\n### Device Tracking\n\n```go\n// Track device changes with callback\nerr := client.TrackDevicesWithCallback(func(devices []adb.Device) {\n    fmt.Printf(\"Devices changed: %d devices\\n\", len(devices))\n    for _, dev := range devices {\n        fmt.Printf(\"  %s: %s\\n\", dev.Serial, dev.State)\n    }\n})\nif err != nil {\n    log.Fatal(err)\n}\n```\n\n### Package Management\n\n```go\n// Using Device methods\ndevice := client.Device(\"device-serial\")\n\n// List installed packages\npackages, err := device.GetPackages()\nif err != nil {\n    log.Fatal(err)\n}\nfor _, pkg := range packages {\n    fmt.Printf(\"Package: %s\\n\", pkg)\n}\n\n// Check if package is installed\ninstalled, err := device.IsInstalled(\"com.example.app\")\nif err != nil {\n    log.Fatal(err)\n}\nfmt.Printf(\"Installed: %v\\n\", installed)\n\n// Clear app data\nsuccess, err := device.ClearPackageData(\"com.example.app\")\nif err != nil {\n    log.Fatal(err)\n}\n\n// Install APK\nsuccess, err = device.Install(\"/path/to/app.apk\")\nif err != nil {\n    log.Fatal(err)\n}\n\n// Uninstall package\nsuccess, err = device.Uninstall(\"com.example.app\")\nif err != nil {\n    log.Fatal(err)\n}\n```\n\n### Intent Management\n\n```go\ndevice := client.Device(\"device-serial\")\n\n// Start an activity\nerr := device.StartActivity(adb.StartActivityOptions{\n    Action:    \"android.intent.action.VIEW\",\n    Data:      \"https://example.com\",\n    Component: \"com.example.app/.MainActivity\",\n})\nif err != nil {\n    log.Fatal(err)\n}\n\n// Start a service\nerr = device.StartService(adb.StartServiceOptions{\n    Action:    \"com.example.app.ACTION_SYNC\",\n    Component: \"com.example.app/.SyncService\",\n    Extras: map[string]string{\n        \"param1\": \"value1\",\n        \"param2\": \"value2\",\n    },\n})\nif err != nil {\n    log.Fatal(err)\n}\n```\n\n### Network Operations\n\n```go\ndevice := client.Device(\"device-serial\")\n\n// Switch to TCP/IP mode\nsuccess, err := device.TcpIp(5555)\nif err != nil {\n    log.Fatal(err)\n}\n\n// Connect to device over TCP\nmsg, err := client.Connect(\"192.168.1.100:5555\")\nif err != nil {\n    log.Fatal(err)\n}\n\n// Switch back to USB mode\nsuccess, err = device.Usb()\nif err != nil {\n    log.Fatal(err)\n}\n\n// Open socket connection\nconn, err := device.OpenSocket(\"tcp:8080\")\nif err != nil {\n    log.Fatal(err)\n}\ndefer conn.Close()\n\n// Open local abstract socket (e.g., for scrcpy)\nconn, err = device.OpenSocket(\"localabstract:scrcpy\")\nif err != nil {\n    log.Fatal(err)\n}\ndefer conn.Close()\n```\n\n### Screen Capture\n\n```go\ndevice := client.Device(\"device-serial\")\n\n// Capture screen using screencap (faster, recommended)\nimg, err := device.Screencap()\nif err != nil {\n    log.Fatal(err)\n}\n\n// Save screenshot to file\nf, err := os.Create(\"screenshot.png\")\nif err != nil {\n    log.Fatal(err)\n}\ndefer f.Close()\nerr = png.Encode(f, img)\n\n// Or use framebuffer (slower, works on older devices)\nimg, err = device.Framebuffer()\nif err != nil {\n    log.Fatal(err)\n}\n```\n\n## API Reference\n\n### Client\n\n#### Creating a Client\n\n```go\n// Default client (localhost:5037)\nclient := adb.NewClient()\n\n// With options (auto-starts ADB server if needed)\nclient := adb.NewClientWithOptions(adb.ClientOptions{\n    Host: \"127.0.0.1\",\n    Port: 5037,\n    Bin:  \"adb\", // Path to adb binary\n})\n\n// With custom connector (useful for testing)\nclient := adb.NewClientWithConnector(customConnector)\n```\n\n#### Host Commands\n\n```go\n// Get ADB server version\nversion, err := client.Version()\n\n// List connected devices\ndevices, err := client.ListDevices()\n// Returns: []Device{Serial: \"xxx\", State: \"device\"}\n\n// List devices with paths\ndevices, err := client.ListDevicesWithPaths()\n// Returns: []DeviceWithPath{Serial, State, Model, Device}\n\n// Connect to remote device\nmsg, err := client.Connect(\"192.168.1.100:5555\")\n\n// Disconnect from remote device\nmsg, err := client.Disconnect(\"192.168.1.100:5555\")\n\n// Kill ADB server\nok, err := client.KillServer()\n```\n\n#### Device Commands\n\n```go\n// Get a device\ndevice := client.Device(\"device-serial\")\n\n// Get device information\nserial, err := device.Serial()\nstate, err := device.State()\nprops, err := device.Properties()\npath, err := device.DevicePath()\n\n// Run shell command (simple version without context)\noutput, err := device.RunCommand(\"ls /sdcard\")\n\n// Run shell command with context support\nctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)\ndefer cancel()\noutput, err = device.RunCommandContext(ctx, \"ls /sdcard\")\nif err != nil {\n    log.Fatal(err)\n}\nfmt.Printf(\"Output: %s\\n\", output)\n```\n\n#### Port Forwarding\n\n```go\ndevice := client.Device(\"device-serial\")\n\n// Forward local port to device\nsuccess, err := device.Forward(\"tcp:8080\", \"tcp:8080\")\n\n// Reverse forward (device to local)\nsuccess, err = device.Reverse(\"tcp:8080\", \"tcp:8080\")\n\n// List reverse forwards for a device\nrevs, err := device.ListReverses()\n\n// List all forwards (from client)\nforwards, err := client.ListForwards()\n```\n\n#### Screen Capture\n\n```go\ndevice := client.Device(\"device-serial\")\n\n// Get framebuffer as image.Image\nimg, err := device.Framebuffer()\nif err != nil {\n    log.Fatal(err)\n}\n// img can be used directly with standard image operations\n// For example, save to file:\n// f, _ := os.Create(\"screenshot.png\")\n// defer f.Close()\n// png.Encode(f, img)\n\n// Screencap (returns image.Image)\nimg, err = device.Screencap()\nif err != nil {\n    log.Fatal(err)\n}\n```\n\n### Device\n\nFor device-specific operations, use `Device`:\n\n```go\ndevice := client.Device(\"device-serial\")\n\n// Device Information\nserial, err := device.Serial()\nstate, err := device.State()\nprops, err := device.Properties()\npath, err := device.DevicePath()\n\n// Device Control\nerr := device.Reboot()\nerr = device.Remount()\nok, err := device.Root()\n\n// Shell Commands\nconn, err := device.Shell(\"ls /sdcard\")\ndefer conn.Close()\ndata, err := adb.ReadAllFromConn(conn)\n\n// Or run command and get output directly\noutput, err := device.RunCommand(\"ls /sdcard\")\n\n// File Operations\nstat, err := device.Stat(\"/sdcard/file.txt\")\nentries, err := device.Readdir(\"/sdcard/\")\nreader, err := device.Pull(\"/sdcard/file.txt\")\n// Push requires io.Reader and file mode\nfile, _ := os.Open(\"local.txt\")\nerr = device.Push(file, \"/sdcard/file.txt\", 0644)\n\n// Screen Operations\nimg, err := device.Screencap()\nimg, err = device.Framebuffer()\n\n// Logcat\nconn, err = device.OpenLogcat(\"main\")\ndefer conn.Close()\n// Stream logs from conn\n\n// Package Management\npackages, err := device.GetPackages()\ninstalled, err := device.IsInstalled(\"com.example.app\")\nsuccess, err := device.ClearPackageData(\"com.example.app\")\nsuccess, err = device.Install(\"/path/to/app.apk\")\nsuccess, err = device.InstallRemote(\"/sdcard/app.apk\")\nsuccess, err = device.Uninstall(\"com.example.app\")\n\n// Intent Management\nerr = device.StartActivity(adb.StartActivityOptions{\n    Action:    \"android.intent.action.VIEW\",\n    Component: \"com.example.app/.MainActivity\",\n})\nerr = device.StartService(adb.StartServiceOptions{\n    Component: \"com.example.app/.MyService\",\n})\n\n// Network Operations\nsuccess, err := device.TcpIp(5555)\nsuccess, err = device.Usb()\nconn, err = device.OpenSocket(\"tcp:8080\")\nconn, err = device.OpenLocal(\"/dev/socket/adb\")\nconn, err = device.OpenLog(\"main\")\nconn, err = device.OpenSocketContext(ctx, \"localabstract:scrcpy\")\n```\n\n### Sync Service\n\nFor advanced file operations, use the Sync service:\n\n```go\ndevice := client.Device(\"device-serial\")\n\n// Create a new sync service\nsync, err := device.NewSyncService()\nif err != nil {\n    log.Fatal(err)\n}\ndefer sync.Close()\n\n// List files\nentries, err := sync.List(\"/sdcard/\")\nif err != nil {\n    log.Fatal(err)\n}\nfor _, entry := range entries {\n    fmt.Printf(\"%s %d %s\\n\", entry.Name, entry.Size, entry.Mode)\n}\n\n// Pull file with progress\nreader, err := sync.Pull(\"/sdcard/file.txt\")\nif err != nil {\n    log.Fatal(err)\n}\ndefer reader.Close()\n\n// Push file with options\nfile, _ := os.Open(\"local.txt\")\ndefer file.Close()\n\nerr = sync.Push(file, \"/sdcard/file.txt\", adb.SyncPushOptions{\n    Mode: 0644,\n})\nif err != nil {\n    log.Fatal(err)\n}\n\n// Get file stat\nstat, err := sync.Stat(\"/sdcard/file.txt\")\nif err != nil {\n    log.Fatal(err)\n}\nfmt.Printf(\"Size: %d, Mode: %d\\n\", stat.Size, stat.Mode)\n```\n\n## Testing\n\nThe library includes comprehensive test coverage using mock connections. See [DEVELOP.md](DEVELOP.md) for how to write tests.\n\n```bash\n# Run tests\ngo test ./adb/...\n\n# Run with coverage\ngo test -cover ./adb/...\n```\n\n## Architecture\n\nThe library implements the ADB protocol as specified in [AOSP](https://android.googlesource.com/platform/system/core/+/master/adb/PROTOCOL.TXT):\n\n1. **Connection Layer**: Manages TCP connections to ADB server\n2. **Protocol Layer**: Handles ADB wire protocol (length-prefixed messages)\n3. **Command Layer**: Implements host and device commands\n4. **Transport Layer**: Manages device-specific transports\n\n```\nYour App -\u003e Client -\u003e ADB Protocol -\u003e ADB Server -\u003e Device\n```\n\n## Requirements\n\n- Go 1.22 or later\n- ADB server running (usually started by Android SDK Platform Tools)\n\n## Troubleshooting\n\n**Connection refused:**\n- Start ADB server: `adb start-server`\n- Check if ADB server is running: `adb devices`\n\n**Device not found:**\n- Check if device is connected: `adb devices`\n- Verify device serial is correct\n\n**Permission denied:**\n- Make sure your user has permission to access ADB\n- On Linux, you may need to configure udev rules\n\n## Contributing\n\nContributions are welcome! Please see [DEVELOP.md](DEVELOP.md) for development guidelines.\n\n## License\n\nMIT License - see LICENSE file for details\n\n## Credits\n\nBased on the Node.js implementation from [openstf/adbkit](https://github.com/openstf/adbkit)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodeskyblue%2Fgo-adbkit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodeskyblue%2Fgo-adbkit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodeskyblue%2Fgo-adbkit/lists"}