# music-dl: a PHP command line music searcher with parallel download drivers

> music-dl searches tencent, netease and kugou from one command line and downloads what it finds, and it ships as a single executable file or as a Composer package. The interesting engineering is not the search but the plumbing: a self-update command, a lock so two instances cannot collide, driver modes that trade processes for forks, and a repository configured with nearly every PHP quality tool in existence.

**guanguans/music-dl** — Music Searcher and Downloader. - 音乐搜索下载器。

- Repository: https://github.com/guanguans/music-dl
- Website: https://guanguans.github.io/music-dl
- Stars: 764 · Forks: 71
- Language: PHP
- License: MIT
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/guanguans-music-dl

## What it does, and the warning the author puts at the top

music-dl is described as a Music Searcher and Downloader, with the Chinese description 音乐搜索下载器, and the homepage is a documentation site at guanguans.github.io/music-dl.

The first thing in the README after the badges is a warning, and it is worth reading before anything else: the tool is only used for learning and communication, it is forbidden to use this tool for commercial purposes, and if a legal dispute arises it has nothing to do with the author. That is the author's own framing of the tool, and it is the licence equivalent of saying read the terms before you rely on it.

The stated requirement is PHP 8.5, which is a high floor and tells you something about the age of the project and the runtime it is written for. The release history is dense and recent: 7.1.13, 7.1.12 and 7.1.11 all published on 2026-09-21 within a few hours of each other, and the last push to the repository was on 2026-10-22.

The repository top level is a full PHP project with a lot of tooling in it. There is an app/ directory, a config/ directory, a bootstrap/ directory, tests/, resources/, a music-dl file at the root, a music-dl.tape file, box.json for the build, a monorepo-builder.php, and a set of tool configs:.php-cs-fixer.dist.php, ecs.php, phpstan.neon.dist, rector.dist.php, phpunit.xml.dist,.zhlintrc,.typos.toml,.yamlfmt.yml,.lintmdrc,.gitleaksignore and.chglog/.

The licence is the MIT License, which is worth holding next to the non-commercial warning, since they are not the same thing.

## Installing it: one curl, or Composer if you want it in a project

There are two install routes, and the first one is unusual enough to be worth reading twice.

The recommended way is to download the built music-dl file from the builds directory in the repository and make it executable:

```shell
curl 'https://raw.githubusercontent.com/guanguans/music-dl/master/builds/music-dl' -o music-dl --progress-bar
chmod +x music-dl
```

So the primary distribution is a single file fetched over https from the repository itself, and the box.json in the repository root is the build configuration for producing it. There is no separate release asset step in this flow, which means the file you run comes from the master branch of the repository rather than from a tagged release, and that is worth remembering when you think about what you are executing.

The Composer route is for people who want it as a project dependency. The command includes a flag to skip the platform requirement check for the pcntl extension, which tells you that the extension is required but that the author expects it to be missing on some platforms:

```shell
composer global require guanguans/music-dl:dev-master --dev -v --ignore-platform-req=ext-pcntl # global
composer require guanguans/music-dl:dev-master --dev -v --ignore-platform-req=ext-pcntl # local
```

Note that both pins are dev-master, and the --dev flag on a global install is unusual, so this is a tool meant to live in a development environment rather than in a production dependency graph.

The GitHub releases and Packagist are both linked from the badges, so tagged versions exist on Packagist even though the primary install path is the raw file.

## The command surface, and the small features that show how it is actually used

The list command shows a small application with a personality, which is more informative than it looks.

```shell
  completion  Dump the shell completion script
  inspire     Display an inspiring quote
  music       Search and download music
  self-update Self-update the installed application
  thanks      Thanks for using this tool.
```

There is a completion command, which dumps a shell completion script, and a self-update command, which updates the installed application. The self-update matters because of the install method: if you downloaded a single file from a branch, you have no package manager to update you, so the tool updates itself.

The music command is the real one, and its options are where the design shows.

The -s and --sources option takes multiple values, and the default set is tencent, netease and kugou, so a plain run searches three services. The -D and --driver option chooses between sync, fork and process modes, and the spelling with the Chinese comma in the help text suggests the option list was written with a Chinese locale in mind, since the default locale is zh_CN.

The --isolated option is the one that shows careful thinking. It means do not run the command if another instance of the command is already running, and it defaults to false. For a tool that downloads files to a shared directory from several services at once, a lock that prevents two runs from writing over each other is the kind of detail that gets added after someone lost a file to it.

The rest is standard Symfony Console behaviour: -b to break after download, -d for the download directory, -l for locale, -N to disable desktop notification, -p for page number and -P for per-page count, with a default of 30, plus the usual --quiet, --silent, --verbose and --no-interaction flags. There is also a --configuration option for passing key-value pairs dynamically, and a --xdebug flag.

## The repository is the interesting part: a PHP project with every quality tool wired up

Look at the top level of the repository rather than at the downloader, because the tooling is extensive and it is the more transferable part.

The code quality stack includes PHPStan through phpstan.neon.dist, Rector through rector.dist.php for automated refactoring, PHP-CS-Fixer through .php-cs-fixer.dist.php and ECS through ecs.php, which are two different style fixers configured side by side, PHPUnit through phpunit.xml.dist, and a composer-dependency-analyser.php, which is a tool for finding unused dependencies.

There are also linters for the non-PHP files. .zhlintrc is for Chinese text, which makes sense for a project with a Chinese locale default and a Chinese README, .typos.toml catches typos, .yamlfmt.yml formats YAML, .lintmdrc configures markdown linting, and .gitleaksignore is a gitleaks exclusion list for secret scanning. The .chglog/ directory holds changelog generation configuration, and the CHANGELOG.md is generated from it.

The build and release side has box.json, which is the PHAR build configuration, a monorepo-builder.php, and the music-dl.tape file, which is a VHS tape definition, a format for scripting terminal recordings. That last one explains the animated usage gif in the resources directory: it is generated by running the tool in a recorded terminal session rather than by hand-editing a video.

The composer scripts are the public face of all that:

```shell
composer checks:required
composer php-cs-fixer:fix
composer ecs:fix
composer test
```

So the intended developer loop is a static analysis pass, then a style fix, then the test suite. A project that ships its own quality gate as composer commands is telling you it expects contributions, and the CHANGELOG and CONTRIBUTING links in the README point the same way.

## Where the limits are, and who should not reach for this

The limitations are real and mostly implicit in the design, so it is worth making them explicit.

The service list is fixed at three Chinese music services, and the sources option takes those three names. The library is not an abstraction over a pluggable provider interface, so adding a source means changing the application, not writing a plugin. The --locale option changes the language of the results, and the default is zh_CN, so the tool is aimed at Chinese catalogues rather than at a general international search.

The binary is downloaded from a branch of the repository rather than from a signed release, and the self-update command has the same property, so trusting the tool means trusting the master branch. For a script someone runs casually that is a reasonable trade, and for anything in a pipeline it is worth a second look.

The PHP requirement of 8.5 narrows the audience too, and the pcntl extension is required with the platform check explicitly disabled in the install command, which means on Windows you are relying on something the author has not fully accounted for.

The legal restriction is the biggest constraint of all, and it is the author's own statement rather than an inference. The tool searches and downloads music, the author says it is for learning and communication only, and forbids commercial use. Whatever the copyright position of a given download in your jurisdiction, the project is telling you it does not support commercial use, and the MIT licence on the code does not settle the question of the music itself.

So the sensible use is personal, for music you have the right to listen to, as a demonstration of a multi-source search CLI. It is not a component to build a product around.

## Conclusion

Adopt music-dl if you want a single command that searches several music services at once and you are comfortable with PHP 8.5, since that is the stated requirement and the version floor is high. Do not adopt it for commercial use, because the README states the tool is only for learning and communication and forbids commercial use. Before you run it, read the licence and the usage restriction yourself, and check the --sources and --driver options to understand which services and which concurrency mode you are turning on, since a default run searches three services at once.

## FAQ

### How do I install music-dl?

Download the built file from the builds directory with curl and make it executable with chmod +x music-dl, or install it through Composer with composer global require guanguans/music-dl:dev-master, which needs the --ignore-platform-req=ext-pcntl flag because the pcntl extension is required.

### Which music sources does music-dl search?

Tencent, netease and kugou, by default. The -s or --sources option takes multiple values, so you can narrow the search to one service. The --locale option sets the language, defaulting to zh_CN.

### What does the --isolated option do?

It stops the command from running if another instance of it is already running, and it defaults to false. It exists so two concurrent runs do not collide when writing downloads.

### Can I use music-dl commercially?

The README states the tool is only for learning and communication and forbids commercial use, and adds that any legal dispute has nothing to do with the author. The project code is MIT licensed, but that licence covers the code rather than the music it retrieves.

## Sources

- [guanguans/music-dl on GitHub](https://github.com/guanguans/music-dl)
- [License: MIT](https://github.com/guanguans/music-dl/blob/master/LICENSE)
- [Project website](https://guanguans.github.io/music-dl)
- [README](https://github.com/guanguans/music-dl/blob/master/README.md)
- [Releases](https://github.com/guanguans/music-dl/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/guanguans-music-dl
