A terminal-based music player (TUI) for streaming services, currently supporting Subsonic-compatible APIs, YouTube Music, and SoundCloud. Spotify, Apple Music, and other services are future features.
Note
This project is not supported or endorsed by any streaming music service or major company. It is a hobby project and has no affiliation with Spotify, Apple, Google, or YouTube. The same warnings and disclaimers for the well-known yt-dlp project apply here.
- TUI Interface: Built with Terminal.Gui for a rich console experience.
- Cross-Platform Audio: Powered by SoundFlow.
- YouTube Music Integration: Powered by YouTubeMusicAPI. Search, stream, and manage your library.
- Subsonic API Integration: Streaming client for any Subsonic-compatible server. For instance, Navidrome, Airsonic Advanced, Gonic, or Madsonic.
- SoundCloud Integration: Search and stream tracks, artists, and playlists from SoundCloud.
- Session Persistence: Automatically saves and restores your playback queue, active track, playback position, and volume across restarts.
- Visuals: Displays album art using Sixel graphics (requires a compatible terminal) and a beautiful real-time audio frequency spectrum visualizer.
While most basic functionality is available and SMoC is totally usable, there's a lot left to do.
Feature Plan (Click to expand)
- UI
- Search Support
- Command Bar (with Command History & Tab Completion)
- Incremental Table Filtering (
/) - Song Table
- Now Playing Bar
- Album Art (Sixel)
- Status Bar
- Visualizations
- Now Playing Screen
- Playback
- Play
- Pause
- Stop
- Skip
- Previous
- Start Over
- Repeat Track
- Volume (0–200% with Loudness Normalization)
- Playback Device Selection
- Gapless Playback (Next-Track Preloading)
- Session State Persistence
- Queue
- Add to End of Queue
- Queue Next (after current song)
- Remove
- Advance to Next at End of Song
- Repeat Queue
- Shuffle
- Search
- Artist
- Track
- Playlist
- URL
- YouTube Music
- Authentication
- POToken
- VisitorData
- Metadata
- Searching
- Play Audio Stream
- Album Art
- Caching
- History Tracking
- Like
- Dislike
- Subsonic API-compatible Servers
- Authentication
- Metadata
- Searching
- Play Audio Stream
- Album Art
- Caching
- History Tracking
- Like
- Dislike
- SoundCloud
- Authentication
- Metadata
- Searching
- Play Audio Stream
- Album Art
- Caching
- History Tracking
- Like
- Dislike
- Apple Music (gamdl as a reference)
- Authentication
- Play Audio Stream
- Metadata
- Searching
- Play Audio Stream
- Album Art
- Caching
- History Tracking
- Like
- Dislike
- Spotify (librespot as a reference)
- Authentication
- Play Audio Stream
- Metadata
- Searching
- Play Audio Stream
- Album Art
- Caching
- History Tracking
- Like
- Dislike
Once installed some setup is required to use SMoC. See the Configuration and Setup section for more information.
Current release is v0.6.0.
Available for Windows x64, Linux x64, and MacOS ARM64.
SMoC is available via my overlay. To install, add my overlay and emerge it.
eselect repository add razza git https://github.com/mrazza/razza-overlay.git
emerge media-sound/smoc
# Clone the repository
git clone https://github.com/mrazza/smoc.git
cd smoc
# Build and run
dotnet run --project smoc/smoc.csprojSMoC operates with a Vim-style command bar. Press : to enter command mode (supports Up/Down command history and Tab command completion) or / to filter the active view incrementally.
| Command | Description |
|---|---|
:a |
Switch to Artist mode |
:a/<artist> |
Switch to Artist mode and search for <artist> |
:t |
Switch to Track mode |
:t/<track> |
Switch to Track mode and search for <track> |
:p |
Switch to Playlist mode |
:p/<playlist> |
Switch to Playlist mode and search for <playlist> |
:likes |
Load your Liked Songs playlist |
:url |
Switch to Playlist mode from URL |
:url/<url> |
Load songs from a specific streaming URL |
:pq |
View the Playback Queue |
:np |
View Now Playing screen |
:np-vis |
Toggle real-time frequency visualizer in Now Playing |
:np-vis-fps/<1-60> |
Set real-time frequency visualizer refresh rate in FPS |
:v/<0-200> |
Set volume percentage (0–200%, e.g., :v/80 or :v/150) |
:devices |
List available audio playback devices (* marks the active device) |
:device/<name-or-idx> |
Switch active audio output device by name, substring, or index |
/<query> |
Incrementally filter the active table view (Enter keeps, Esc clears) |
:q |
Quit application (automatically saves session state) |
| Hotkey | Action |
|---|---|
Space |
Play / Pause |
Ctrl+Space |
Stop |
, (Comma) |
Previous Track (Restart if > 10s played) |
. (Period) |
Next Track |
[ |
Seek Backward 10s |
] |
Seek Forward 10s |
Up/Down/Left/Right |
Navigate Tables |
h/j/k/l |
Navigate Tables (Vim style) |
Shift + Nav Key |
Select multiple items |
Tab |
Switch active pane (or autocomplete command in : mode) |
/ |
Enter incremental filter mode for the active view |
v / V (Shift+v) |
Toggle real-time frequency visualizer (on Now Playing screen) |
Enter |
Open Song Context Menu for selected item |
The Song Context Menu provides options for playback and queue management. It appears when pressing Enter while a song is selected in any song table.
| Hotkey | Action | Details |
|---|---|---|
p |
Play all from here | Clears the playback queue and queues the track listing in its entirety. Then starts playback at the selected track. |
o |
Play selection only | Clears the playback queue and queues only the selected tracks. Then starts playback at the first selected track. |
n |
Queue next | Adds the selected tracks to the playback queue after the current track. |
q |
Queue last | Adds the selected tracks to the end of the playback queue. |
Up/Down/j/k |
Navigate menu | Moves the selection through the menu items. |
Enter |
Execute selected action | Executes the highlighted action and closes the menu. |
Esc |
Close menu | Dismisses the context menu without taking any action. |
SMoC stores configuration and authentication data in ~/.config/smoc/ (on Linux).
SMoC provides a dedicated smoc auth CLI suite to manage service credentials securely using your operating system's native credential store:
- Linux: Secret Service API via D-Bus (GNOME Keyring, KWallet)
- macOS: Keychain Services
- Windows: Windows Credential Manager and Data Protection API (DPAPI)
When connecting to streaming services, SMoC resolves authentication credentials in the following order:
- OS Secure Keyring: Credentials saved via
smoc auth login,smoc auth import-cookies, orsmoc auth migrate. - Environment Variables: Ideal for headless systems, CI, or containerized environments:
SMOC_SUBSONIC_PASSWORD(orSMOC_SUBSONIC_<USERNAME>_PASSWORD)SMOC_SOUNDCLOUD_CLIENT_IDandSMOC_SOUNDCLOUD_AUTH_TOKENSMOC_YTM_COOKIESandSMOC_YTM_TOKENS
- Configuration & Legacy Files:
config.json(Password/AuthToken) or legacycookies.txtandtokens.json.
Important
If credentials exist in the OS Keyring, they take precedence over config.json. Editing Password in config.json will have no effect until the keyring entry is cleared using smoc auth logout <service>.
- Interactive Login:
Prompts interactively for credentials and securely stores secrets in the OS keyring.
smoc auth login subsonic smoc auth login soundcloud
- Inspect Status:
Displays authentication status for all supported services and indicates whether credentials are sourced from the secure Keyring or Environment.
smoc auth status
- Import YouTube Music Cookies:
Imports cookies into the secure credential store and automatically generates session tokens.
smoc auth import-cookies [path/to/cookies.txt]
- Regenerate YouTube Music Tokens:
Regenerates visitor and Proof-of-Origin (PO) session tokens using your stored YouTube Music cookies.
smoc auth gentokens
- Migrate Existing Plaintext Credentials:
Migrates plaintext passwords from
smoc auth migrate
config.jsonand legacycookies.txt/tokens.jsonfiles into the secure OS keyring and sanitizes plaintext files. Use--keep-backupto retain.bakbackup copies. - Logout:
Removes stored credentials from the secure OS keyring.
smoc auth logout <service> # subsonic, soundcloud, ytm, or all
YouTube Music is the default streaming service in SMoC. Setting ActiveService to YouTubeMusic under SmocConfiguration is optional unless you need to switch back from another service.
Unlike other services where credentials are saved directly in config.json, YouTube Music authenticates using session cookies and tokens.
Note
You need a YouTube Music Premium subscription to play most content.
To access your YouTube Music account (these steps are copied from YouTube.js):
- Open YouTube Music in your browser (Incognito recommended).
- Open Developer Tools (
F12) -> Network tab. - Find a
POSTrequest tomusic.youtube.com. - Copy the value of the
cookierequest header. - Save it to
~/.config/smoc/cookies.txtor import directly into the keyring:smoc auth import-cookies
Tip
It is recommended to open an incognito window or separate browser profile when getting your cookie information to avoid other browser sessions from invalidating the tokens. Once cookies are retrieved, close the session without logging out.
More recently, additional tokens beyond just cookies are often needed (Proof-of-Origin and Visitor Data). smoc auth import-cookies automatically generates these tokens and stores them securely. If those tokens later expire while your cookies are still valid, you can regenerate them with smoc auth gentokens.
To use a Subsonic-compatible service (like Navidrome, Gonic, or Airsonic):
- Ensure your server has the Subsonic API enabled.
- Set
ActiveServicetoSubsonicunderSmocConfigurationinconfig.json. - Configure your server hostname, port, and credentials using
smoc auth login subsonic(recommended) or underSubsonicConfiginconfig.json(see below).
To use SoundCloud:
- Set
ActiveServicetoSoundCloudunderSmocConfigurationinconfig.json. - Configure credentials using
smoc auth login soundcloud(recommended) or underSoundCloudConfiginconfig.json(see below).
Create or edit ~/.config/smoc/config.json to customize settings.
Example Configuration (Click to expand)
{
"SmocConfiguration": {
"LogLevel": "Information",
"ActiveService": "YouTubeMusic",
"SongCacheSizeBytes": 536870912,
"SongCacheMaxElements": 0,
"AlbumCoverCacheSizeBytes": 104857600,
"AlbumCoverCacheMaxElements": 0,
"VisualizerFps": 24,
"EnableLoudnessNormalization": true,
"LoudnessNormalizationMode": "Full",
"AudioDevice": null,
"DeduplicateArtistSingles": true
},
"SubsonicConfig": {
"ServerScheme": "https",
"ServerHost": "subsonic.example.com",
"ServerPort": 443,
"Username": "username",
"Password": "password",
"UseToken": true
},
"ListenHistoryConfig": {
"Enabled": true,
"MinimumPositionSeconds": 30,
"MinimumFraction": 0.5
},
"SoundCloudConfig": {
"ClientId": "your-client-id",
"AuthToken": "your-auth-token"
},
"YouTubeMusicConfig": {
"PlayerId": "your-player-id"
}
}| Section | Key | Type | Default | Description |
|---|---|---|---|---|
SmocConfiguration |
ActiveService |
StreamingService |
YouTubeMusic |
Active service (YouTubeMusic, Subsonic, SoundCloud) |
SmocConfiguration |
LogLevel |
LogLevel |
Information |
Minimum log level (Trace, Debug, Information, Warning, Error, Critical, None) |
SmocConfiguration |
SongCacheSizeBytes |
long |
536870912 |
Max song cache size in bytes (0 = no limit, default 512MB) |
SmocConfiguration |
SongCacheMaxElements |
int |
0 |
Max songs to cache (0 = no limit) |
SmocConfiguration |
AlbumCoverCacheSizeBytes |
long |
104857600 |
Max album cover cache size in bytes (0 = no limit, default 100MB) |
SmocConfiguration |
AlbumCoverCacheMaxElements |
int |
0 |
Max album covers to cache (0 = no limit) |
SmocConfiguration |
VisualizerFps |
int |
24 |
Refresh rate for the audio frequency spectrum visualizer (FPS) |
SmocConfiguration |
EnableLoudnessNormalization |
bool |
true |
Enable track loudness normalization |
SmocConfiguration |
LoudnessNormalizationMode |
LoudnessNormalizationMode |
Full |
Loudness normalization mode (Full, AttenuateOnly) |
SmocConfiguration |
AudioDevice |
string |
null |
Preferred audio output device name or index (null = system default) |
SmocConfiguration |
DeduplicateArtistSingles |
bool |
true |
Filter out duplicate teaser singles already on an album in Artist mode |
SubsonicConfig |
ServerScheme |
string |
http |
Subsonic API URI scheme (http, https) |
SubsonicConfig |
ServerHost |
string |
null |
Subsonic server hostname |
SubsonicConfig |
ServerPort |
int |
80 |
Subsonic server port |
SubsonicConfig |
Username |
string |
null |
Subsonic username |
SubsonicConfig |
Password |
string |
null |
Subsonic password |
SubsonicConfig |
UseToken |
bool |
true |
Use token auth instead of password |
ListenHistoryConfig |
Enabled |
bool |
true |
Enable listen history tracking |
ListenHistoryConfig |
MinimumPositionSeconds |
int |
30 |
Min seconds for 'listened' status |
ListenHistoryConfig |
MinimumFraction |
double |
0.5 |
Min fraction for 'listened' status |
SoundCloudConfig |
ClientId |
string |
null |
SoundCloud client ID |
SoundCloudConfig |
AuthToken |
string |
null |
SoundCloud authentication token |
YouTubeMusicConfig |
PlayerId |
string |
null |
Custom YouTube Music player ID |
SMoC supports custom themes and color schemes via Terminal.Gui's configuration format. You can customize colors globally or define theme-specific scheme overrides in ~/.config/smoc/config.json.
Custom Theme Configuration Example (Click to expand)
{
"Theme": "CustomDark",
"Themes": {
"CustomDark": {
"Schemes": {
"Accent": {
"Normal": { "Foreground": "#ebdbb2", "Background": "None" },
"Focus": { "Foreground": "#ebdbb2", "Background": "#639494" },
"Active": { "Foreground": "#ebdbb2", "Background": "#394e4e" }
},
"ProgressBar": {
"Normal": { "Foreground": "#ebdbb2", "Background": "#394e4e" }
}
}
}
}
}You can override individual schemes either at the root level ("Schemes": { ... }) or scoped within a theme ("Themes": { "<ThemeName>": { "Schemes": { ... } } }). Any unspecified schemes automatically fall back to SMoC's default values:
| Scheme Key | Description |
|---|---|
Accent |
Accent highlights across views |
ProgressBar |
Audio playback progress bars |
TableCurrentTrack |
Currently playing track in playlist and track tables |
TableHeaders |
Column headers in tables |
TableNormalTracks |
Normal track rows in tables |
Menu |
Navigation menus and dropdowns |
StatusBar |
Main status bar container |
StatusBar_State |
Playback state label within the status bar |
CommandLine |
Command line input prompt (:) |
CommandLineError |
Command line error messages and alerts |
Contributions are welcome!
- Code Style: We follow the Google C# Style Guide.
- Commits: Please use Conventional Commits.
Distributed under the Apache-2.0 License. See LICENSE for more information.

