iDevice AFC File Transfer and App Management Methods in the ipsw Go Library

The ipsw library provides native Go implementations for iDevice interaction through two primary packages: pkg/usb/afc for AFC file transfer operations and pkg/usb/apps for app management, both communicating via lockdownd services without external dependencies.

The blacktop/ipsw repository offers a complete Go-based toolkit for communicating with iOS devices over USB. Understanding the iDevice interaction methods for file system access and application lifecycle management enables developers to automate deployment workflows entirely within Go programs, eliminating the need for external binaries like ideviceinstaller or ifuse.

AFC File Transfer Architecture

The AFC (Apple File Conduit) implementation in pkg/usb/afc provides POSIX-like file operations by connecting to the lockdownd service com.apple.afc. This service allows sandboxed access to the device's filesystem, enabling both single-file and recursive directory transfers.

Establishing the AFC Connection

According to the source code in pkg/usb/afc/afc.go, the NewClient function initializes a session by negotiating with lockdownd using the target device's UDID:

afcClient, err := afc.NewClient("<UDID>")
if err != nil {
    log.Fatalf("AFC client error: %v", err)
}
defer afcClient.Close()

This creates an afc.Client that wraps the raw USB connection (usb.Client) and manages the binary AFC protocol encoding, including operation codes and argument marshaling.

Single File Operations

The helper methods in pkg/usb/afc/helper.go abstract the low-level FileRefOpen calls. Use CopyFileToDevice and CopyFileFromDevice for streaming single files via io.Copy:

// Copy local file to device Documents folder
err = afcClient.CopyFileToDevice("/Documents/myfile.txt", "./myfile.txt")
if err != nil {
    log.Fatalf("Copy error: %v", err)
}

These functions handle opening remote file references, streaming data chunks, and closing handles automatically.

Recursive Directory Transfer

For directory operations, CopyToDevice and CopyFromDevice handle recursive transfers by walking the filesystem tree. The implementation creates remote subdirectories via MakeDir and traverses structures using the Walk method:

// Recursively copy local directory to device
err = afcClient.CopyToDevice("/Documents/remoteFolder", "./localFolder", nil)
if err != nil {
    log.Fatalf("Recursive copy failed: %v", err)
}

The RemoveAll method provides depth-first recursive deletion of remote directory trees, complementing the copy operations.

App Management via Installation Proxy

The pkg/usb/apps package implements the Installation Proxy protocol (com.apple.mobile.installation_proxy) for comprehensive application lifecycle management, including querying, installation, upgrading, and removal.

Querying Installed Applications

The InstalledApps method in pkg/usb/apps/installation.go returns metadata for all applications as a slice of app structures:

appsClient, err := apps.NewClient("<UDID>")
if err != nil {
    log.Fatalf("Apps client error: %v", err)
}
defer appsClient.Close()

list, err := appsClient.InstalledApps()
if err != nil {
    log.Fatalf("Failed to fetch apps: %v", err)
}

Additional lookup methods include Lookup for raw metadata, LookupExePath for binary locations, LookupDisplayName for user-facing names, and LookupContainer for app sandbox paths.

Installing and Upgrading Packages

The Install and Upgrade methods accept IPA or ZIP archives and provide progress callbacks via ProgressFunc. As implemented in installation.go, these methods send PLIST-encoded commands and parse ProgressEvent responses:

err = appCli.Install("./MyApp.ipa", func(ev *apps.ProgressEvent) {
    log.Printf("Install %s – %d%%", ev.Status, ev.PercentComplete)
})
if err != nil {
    log.Fatalf("Install error: %v", err)
}

The CopyAndInstall convenience method combines local file copying with installation for streamlined deployment workflows.

Uninstallation and Archiving

For removal operations, Uninstall accepts a bundle identifier and optional progress callback:

bundleID := "com.example.myapp"
if err = cli.Uninstall(bundleID, nil); err != nil {
    log.Fatalf("Uninstall failed: %v", err)
}

The package also supports Archive and RestoreArchive for creating and restoring application backups, along with Upgrade for in-place app updates.

Core Implementation Files

  • pkg/usb/afc/afc.go: Low-level AFC protocol request/response handling and error mapping.
  • pkg/usb/afc/helper.go: High-level file copy and directory walk utilities including CopyToDevice and RemoveAll.
  • pkg/usb/apps/installation.go: Installation Proxy client implementing Install, Upgrade, Uninstall, and lookup methods.
  • pkg/usb/lockdownd/: Service negotiation layer used by both AFC and apps clients to establish sessions.
  • pkg/usb/usb.go: Generic USB transport abstraction for socket handling and device discovery.

Summary

  • AFC file transfer uses the com.apple.afc service via pkg/usb/afc, providing CopyFileToDevice, CopyToDevice, and RemoveAll operations for both single files and recursive directories.
  • App management leverages the Installation Proxy (com.apple.mobile.installation_proxy) through pkg/usb/apps for installing, upgrading, querying, and removing applications.
  • Both clients initialize through lockdownd sessions identified by device UDID and support progress callbacks for monitoring long-running operations.
  • The pure-Go implementation requires no external binaries, communicating directly with iOS devices over USB using the AFC and Installation Proxy protocols.

Frequently Asked Questions

What is AFC in the context of iDevice file transfer?

AFC (Apple File Conduit) is a binary protocol that provides sandboxed file system access to iOS devices. In the ipsw library, the pkg/usb/afc package implements this protocol to enable POSIX-like file operations including copying, walking directories, and recursive deletion without requiring jailbreak or external tools like ifuse.

How does the ipsw library handle app installation progress?

The apps.Client methods accept a ProgressFunc callback that receives ProgressEvent structures containing Status strings and PercentComplete integers. This allows real-time monitoring of installation, upgrade, and uninstallation operations as the device reports progress via the Installation Proxy service (com.apple.mobile.installation_proxy).

Can I transfer entire directories using the AFC client?

Yes. While CopyFileToDevice handles single files, the CopyToDevice and CopyFromDevice methods in pkg/usb/afc/helper.go recursively traverse directory trees, automatically creating remote subdirectories with MakeDir and handling nested file transfers via the Walk method.

What dependencies are required to use these iDevice interaction methods?

The ipsw library requires only Go standard libraries and its internal USB transport layer (pkg/usb). It communicates directly with the device's lockdownd daemon over USB using native protocols, eliminating dependencies on external binaries like ideviceinstaller for app management or ifuse for file transfer.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →