CLI tool
baairon/soundcli avatar
baairon/soundcli

soundcli: a terminal music downloader and offline player, tested against its own README

Own your music. Download your YouTube, SoundCloud, and Spotify libraries to your computer and play them offline, all from your terminal.

514 stars46 forksTypeScriptMIT

At a glance

What is it?
soundcli (published as sndcli on npm) pulls YouTube, SoundCloud and Spotify libraries onto your disk and plays them back in an Ink terminal UI. The pitch is strong; the documentation is thinner than the pitch.
Who is it for?
soundcli suits people who already live in a terminal, want their music as files on their own disk, and accept that the first run depends on yt-dlp and mpv being installed and kept current. It is a poor fit if you need a documented Spotify account login, a scriptable non-interactive mode, or a guarantee that a given track will still resolve next year.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 43 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

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

Editorial analysis

What soundcli actually solves, and for whom

Streaming libraries are rented. soundcli's premise is that they should not be: it downloads tracks from YouTube, SoundCloud and Spotify to local files and plays them offline, all inside one terminal window. The README frames the output plainly: "Every song lands on your own drive as a real file, yours to keep." That is the whole value proposition, and it is a narrow one.

The intended user is someone comfortable with a terminal who wants a personal archive rather than a subscription. The README's own onboarding assumes no prior command-line experience: it walks through installing Node.js from nodejs.org, opening a terminal on Windows or macOS, and pasting a single command. That is a friendlier entry point than most TUI tools offer, though the interface that follows is still keyboard-driven.

It is not a streaming client and not a sync service. There is no account, no server, and according to the privacy section nothing tracks what you play. The three stated reasons it touches the network are downloading requested music, first-time setup, and keeping its own tools current.

Under the hood: Ink, yt-dlp and mpv

The contributing section is the most informative part of the repository for anyone evaluating the architecture. soundcli is "TypeScript with an Ink terminal UI, riding on yt-dlp and mpv." That sentence explains most of the behaviour you will observe.

Ink renders React components to a terminal, which is why the interface has a persistent footer and a `?` cheatsheet rather than a command prompt. yt-dlp does the actual extraction and downloading, which is why the project can accept YouTube, SoundCloud and Spotify links through one code path and why it can claim to keep tools current: the extractors live in yt-dlp, not in soundcli. mpv handles playback. package.json confirms the shape of the dependency graph: the runtime dependencies are env-paths, execa, ink, react and string-width. execa is the process-spawning layer that talks to the external binaries. Nothing in the dependency list is a media library, which means soundcli does not decode audio itself.

The practical consequence is that soundcli is a well-built control surface over two external programs it does not ship. The README says it downloads "the few tools it needs" on first run, so the setup step is automated, but the behaviour of your downloads is ultimately yt-dlp's behaviour. When a site changes its delivery, the fix arrives through yt-dlp, not through a soundcli release.

The repository layout is conventional for a TypeScript CLI: src/ for code, test/ with vitest, tsup.config.ts for bundling, and scripts/ containing a preview renderer and a dist-import checker that runs on prepublishOnly.

Installing soundcli and downloading your first track

The README's install path deliberately avoids package managers. Install Node.js from nodejs.org (package.json requires Node 22 or newer), open a terminal, and run the published package:

bash
npx sndcli

That single command downloads the package and starts it. The README states that from there soundcli "takes over, downloading the few tools it needs and setting everything up on its own." Expect a setup phase before the interface appears.

On first run, the README says soundcli shows where your music will be saved: a dedicated folder inside your computer's Music folder. It then asks for a source. Pick YouTube, SoundCloud or Spotify, then type a username or paste a link to a playlist, an album or a single track. Downloading starts immediately, and the README notes you can begin listening while the rest of the library finishes.

If you want to run it from source instead, the contributing section gives the developer path. Clone the repository, then:

bash
npm install
npm run dev

The README describes `npm run dev` as running straight from source. For a bundled build, use `npm run build` followed by `npm start`. Contributors are asked to run `npm test` and `npm run typecheck` before opening a pull request, and to write commits in Conventional Commits style.

Deduplication, resume and what happens when a download fails

Two behaviours matter more than the interface polish. The README states that soundcli "never downloads the same song twice", and that if you close it mid-download it "picks up where it left off next time." For a library of any size, that combination is the difference between a usable archive and a repeated waste of bandwidth. It also implies persistent state somewhere on disk tracking what has been fetched, though the README does not describe the format or location of that state.

What the README does not document is failure handling. There is no described retry policy, no error log, no way to inspect which tracks failed and why. Given that extraction is delegated to yt-dlp, failures are likely to be per-track and intermittent: a video removed, a region restriction, a changed extractor. The interface described in the README has a download key group, but nothing in the README explains what a failed item looks like afterwards, or whether it is retried on the next run. The README is silent on rollback and silent on partial-file cleanup.

A second gap is Spotify. The README says public Spotify playlists and albums work without signing in, which is the honest formulation: it does not claim account access. If your library lives in your Spotify likes rather than in public playlists, the README does not tell you whether that is reachable, and the first-run instructions say to type a username or paste a link, not to authenticate.

Where soundcli is the wrong tool

If you want a music player that is also a library manager for files you already own, soundcli is the wrong shape. It is built around acquiring tracks from three named services. The README describes renaming tracks and playlists from the interface, and sorting into folders, but it does not describe importing an existing collection, scanning a directory, or reading tags from files you did not download through it.

If you need unattended operation, the README offers nothing. There is no documented non-interactive mode, no subcommand to download a URL and exit, no configuration file mentioned anywhere in the README. Everything flows through the TUI: pick a source, type a username or paste a link. That rules out cron jobs and shell pipelines, at least on the evidence available.

If you are on a machine without the ability to install or run external binaries, soundcli's first run will not complete. The README says it downloads the tools it needs, but it does not say what happens when that download is blocked, and it does not document a way to point soundcli at binaries you installed yourself.

Finally, treating this as an archival guarantee is a mistake. The README says that once a track is saved "it's there for good", which is true of the file, not of your ability to obtain the next one. Extraction depends on yt-dlp keeping pace with the source sites.

How it differs from yt-dlp used directly

The obvious alternative is yt-dlp on its own, which is the tool soundcli already depends on. The difference is entirely in what sits on top.

yt-dlp is a command-line downloader with flags, output templates and a scripting surface. It does not play anything, it does not maintain a library view, and it does not deduplicate against a persistent catalogue by default. soundcli adds an Ink interface for browsing, a player via mpv, automatic folder sorting, artwork and artist metadata, and the deduplication and resume behaviour described above. It also adds a Spotify input path, which yt-dlp does not handle natively.

What you give up is control. With yt-dlp you choose formats, output paths and behaviour per invocation, and you can wrap it in a script. With soundcli the README describes a guided flow: choose a source, provide a username or link, watch it download. The contributing guidelines make this a stated design position rather than an oversight: contributors are told to keep the UI surface minimal, "one contextual footer plus the `?` cheatsheet, never a wall of commands." That is a deliberate trade of scriptability for approachability, and it is the single most consequential decision in the project.

Licence, maintenance and the cost of upgrading

soundcli is MIT licensed, and package.json confirms "license": "MIT" with a LICENSE file at the repository root. MIT is permissive: you can use, modify and redistribute the code, including commercially, provided the copyright notice and permission notice are preserved. The external tools it drives, yt-dlp and mpv, carry their own licences, and the README does not state what those are, so check them separately if redistribution matters to you. This is a description of the licence text, not legal advice.

The last push to the repository was on 2026-08-19, the same date as the v1.5.0 release. The two prior releases, v1.4.0 and v1.4.1, both landed on 2026-07-15. That is a steady cadence through the middle of 2026, and the repository is not archived. It is also a single-author project with one named author in package.json, which is the real maintenance consideration: there is no stated bus factor, no roadmap in the README, and no documented deprecation policy.

Upgrade cost is low by design. Installation is `npx sndcli`, which fetches the current published version each time you run it unless you pin one. The riskier upgrade path is not soundcli itself but yt-dlp, which soundcli keeps current on its own. A yt-dlp change can alter download behaviour without any soundcli release, and the README does not describe a way to pin or roll back that dependency. The repository does include a prepublishOnly script that builds and runs a dist-import check, which suggests some care about what actually ships.

Editorial conclusion

soundcli suits people who already live in a terminal, want their music as files on their own disk, and accept that the first run depends on yt-dlp and mpv being installed and kept current. It is a poor fit if you need a documented Spotify account login, a scriptable non-interactive mode, or a guarantee that a given track will still resolve next year. Before committing a large library, run npx sndcli once on a single track, confirm the file lands in the Music folder the first-run screen names, and check that mpv plays it back inside the interface.

Frequently asked questions

What is soundcli and what does it do?

soundcli is a terminal application that downloads music from YouTube, SoundCloud and Spotify to your computer and plays it offline. It is published on npm as sndcli and is written in TypeScript with an Ink terminal UI.

How do I install soundcli?

Install Node.js 22 or newer, open a terminal, and run npx sndcli. The README states that soundcli then downloads the few tools it needs and sets everything up on its own.

What are soundcli's dependencies?

The README says soundcli rides on yt-dlp and mpv, with a TypeScript and Ink front end. Its runtime npm dependencies are env-paths, execa, ink, react and string-width.

Does soundcli require a Spotify account?

The README states that public Spotify playlists and albums work without signing in. It does not describe signing in to a Spotify account, so it is unclear from the documentation whether private libraries such as your likes are reachable.

Does soundcli download the same song twice?

No. The README states that it never downloads the same song twice, and that if you close it mid-download it picks up where it left off next time.

Official sources

  1. baairon/soundcli on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
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/baairon-soundcli.svg)](https://hysenlabs.com/projects/baairon-soundcli)