Open-source project
hanwen/go-mtpfs avatar
hanwen/go-mtpfs

go-mtpfs: mounting an Android phone over MTP with FUSE and partial reads

Mount MTP devices over FUSE

730 stars92 forksGoNOASSERTION

At a glance

What is it?
go-mtpfs is a Go FUSE filesystem that exposes an Android device over MTP as a directory tree, reading metadata only when needed so the mount appears instantly. It leans on the Android partial object extension to move large files without buffering them through /tmp, and it carries a short list of hard limitations worth reading first.
Who is it for?
go-mtpfs suits a Linux user who wants a phone to appear as a normal directory, wants to move one album or one large file, and can accept that the phone is not the source of truth while it is mounted. It is the wrong choice for syncing a media library, for anything that depends on rename, and for devices whose vendor stack lies about the partial object extension.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 96 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The mount reads metadata only as it is needed, so it appears instantly

An MTP device has no file system block structure, so a naive implementation walks the whole device and caches every directory entry before showing anything. go-mtpfs takes the other approach. The README states that it exposes all storage areas of a device in the mount and only reads file metadata as needed, which is what makes the mount quick on a phone holding tens of thousands of files. The consequence for a user is that the directory listing grows as you move through it rather than appearing complete and final at mount time. Metadata is fetched on demand through the same FUSE layer that serves the file contents. That design is the reason the tool feels responsive compared with a full scan, and it is also why a directory listing can change under you while you are looking at it.

Large files move through the Android partial object extension, not through /tmp

Copying a large file out of MTP normally means streaming it through a temporary location, which costs disk space and time on both ends. go-mtpfs uses the Android extensions for reading and writing partial data, so a file can be copied in pieces without any extra space in /tmp. The README calls this out as the reason manipulating large files requires no extra space in /tmp. It also means the tool depends on a vendor extension rather than the base MTP specification, and that is where the compatibility risk lives. Some devices advertise the extension and then fail the call, and the README records the symptom as AndroidGetPartialObject64 failed: OperationNotSupported, seen on some Sony Xperia hardware. The escape hatch is a flag that turns the Android extensions off, which trades the partial copy ability for broader device support.

The stack is a FUSE layer over a pure Go MTP implementation

The repository is small and split by responsibility: main.go at the top level, an fs directory for the filesystem side and an mtp directory for the protocol side. go.mod names the two direct dependencies. github.com/hanwen/go-fuse/v2 at version v2.11.0 provides the FUSE bindings, and github.com/hanwen/usb supplies the USB layer, pinned to a commit from 2014. The README notes that as of January 2013 the MTP implementation is pure Go and based on libusb, so there is no C library to install for the protocol itself, though libusb headers are still needed at build time. The module targets Go 1.21. Nothing in the repository listing suggests a bundled test suite for the protocol layer or a configuration file, which fits a tool whose behaviour is mostly determined by what the phone exposes.

Building it on Linux and making the first mount

Compilation needs a Go toolchain and the libusb headers. On Ubuntu the README gives these two commands, the second of which it introduces as the libmtp header files even though the package name is libusb1-devel.

bash
sudo apt-get install golang-go
bash
sudo apt-get install libusb1-devel

Then check out the repository and build it, which leaves a binary named go-mtpfs in the current directory. The README also warns that some tweaking may be needed for libusb to compile, pointing at the comment near the top of usb.go in the hanwen/usb repository.

bash
go build ./

Prebuilt 32-bit and 64-bit Linux x86 binaries are published on the project author's own site, which is the fastest way to find out whether your phone is supported before you touch a compiler. For the first run, create a mount point, start the daemon against it and copy something across.

bash
mkdir xoom
go-mtpfs xoom &
cp -a ~/Music/Some-Album xoom/Music/
fusermount -u xoom

The last command unmounts the filesystem when you are done. The daemon runs in the background for the life of the mount, and the sample copy moves a whole album directory, which is the kind of bulk operation the partial object extension is there to make cheap.

Rename and change notification are the two features the Android stack does not offer

The README lists the caveats bluntly. go-mtpfs does not implement rename between directories, because the Android stack does not implement it, so a file manager that relies on rename for safe moves will misbehave. It also does not implement event handling, which means it will not notice changes the phone makes to its media database while the device is connected. That second limitation is the more dangerous one in practice. If you take a photo on the phone or let a music app rewrite tags, the mounted view keeps showing the old state until something forces a refresh, and there is no notification path to tell you otherwise. The documentation does not describe a rescan or invalidate command, so the practical answer is to unmount and mount again when you need the phone's current state.

Unplugging is safe only after a file is closed

The README states that after a file is closed, for example when a copy finishes, it is safe to unplug the device, and that the filesystem will continue to function but generate I/O errors when it reads from or writes to the device. That is a better failure mode than a hung mount, but it is still a failure mode: a program that walks the tree after the cable comes out gets errors rather than a clean end of file. There is no mention of caching a file before the device disappears, so the copy you are in the middle of is the copy that fails. For a tool whose main purpose is transferring files, that ordering constraint is the one to design around: finish one transfer, then unplug, and keep the device plugged in for the next.

A mount against a pull-based copy, and when the mount loses

The alternative to mounting is a pull-based client that enumerates objects over MTP and copies the ones you name, without ever presenting a directory tree. The difference in approach is more than ergonomics. A mount makes the phone look like a disk, so tools that expect a path, a file size, a mtime or a directory can use it unchanged, and you can point a media indexer or a backup job at the mount point. A pull-based client touches only the files you select, needs no FUSE kernel module, works over a phone connected by Wi-Fi or USB tethering without a privileged mount, and never shows a stale directory listing because there is no listing. Against that, a mount gives you the whole tree in one interface, and the partial object extension that makes bulk transfers cheap is tied to the filesystem implementation rather than to a copy dialog. For a one-off album, the pull model is simpler. For a directory oriented workflow, the mount is the point.

A custom licence, an old compatibility list and a last push on 2026-07-20

The project uses a licence that GitHub cannot classify, so the LICENSE file in the repository is the only reliable statement of the terms. Read it before you redistribute a binary or ship the code in a product, and treat nothing here as legal advice. The compatibility notes are also old: the README says it has been tested on the Galaxy Nexus, the Xoom and the Nexus 7, and describes the pure Go rewrite as of January 2013. The last push was on 2026-07-20 and the repository has no GitHub releases, so there is no versioned artifact to install and no changelog to read; you track the master branch and rebuild when it changes. The dependency pin tells its own story: the USB library is fixed at a 2014 commit, which is deliberate for stability but means USB behaviour on current devices is unproven by the project itself.

Editorial conclusion

go-mtpfs suits a Linux user who wants a phone to appear as a normal directory, wants to move one album or one large file, and can accept that the phone is not the source of truth while it is mounted. It is the wrong choice for syncing a media library, for anything that depends on rename, and for devices whose vendor stack lies about the partial object extension. Before building it, read the LICENSE file, since the project uses a custom licence that GitHub cannot classify, and try the published Linux x86 binaries first to see whether your device answers the partial object call at all.

Frequently asked questions

What does go-mtpfs actually mount?

An Android device over MTP, exposed as a FUSE filesystem that shows all storage areas of the phone. It reads file metadata only as it is needed, so the mount completes quickly instead of walking the entire device first.

How do I build go-mtpfs on Linux?

Install the Go toolchain and the libusb headers, then build the repository with go build ./, which leaves a binary named go-mtpfs. The README also notes that libusb may need tweaking to compile, and that prebuilt 32-bit and 64-bit Linux x86 binaries are published on the author's site.

Does go-mtpfs support rename and live file change notifications?

No. It does not implement rename between directories because the Android stack does not implement it, and it does not implement event handling, so it will not notice changes the phone makes to its media database while the device is connected.

Can I unplug the phone while go-mtpfs is mounted?

Only once a file is closed. The README states that after a close, for example when a copy completes, it is safe to unplug, and that the filesystem keeps working but returns I/O errors when it tries to read from or write to the device.

Official sources

  1. hanwen/go-mtpfs on GitHub
  2. Issues
  3. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/hanwen-go-mtpfs.svg)](https://hysenlabs.com/projects/hanwen-go-mtpfs)

Was this useful?