A TUI music player written in Rust.
- File system navigation and playback (MP3, WAV, OGG, FLAC)
- Audio visualization (Spectrum Analyzer)
- Internet Radio and Subsonic/Navidrome support
- AudioBookshelf podcast support (browse, filter, resume, autoplay)
- Supports MPRIS (media playback controls on a system-wide level)
- Built-in management for Radio Stations and Sources
I'm happy to hear your feedback and feature requests! I'm also very open to PRs that add or enhance functionality. But, please, know that I created this application for myself and my friends, our feedback and needs come before any others.
| Key | Action |
|---|---|
q |
Quit Application |
TAB |
Toggle Mode (Files / Radio / Favorites / Subsonic / AudioBookshelf) |
/ |
Search / Filter |
? |
Toggle Help / About |
j / ↓ |
Move Selection Down |
k / ↑ |
Move Selection Up |
Enter |
Play Selection / Enter Directory |
Backspace |
Go Up / Delete Station or Source |
Delete |
Delete Station/Source |
Space |
Toggle Pause / Resume |
+ / = |
Volume Up |
- |
Volume Down |
→ |
Next Track |
← |
Previous Track |
l |
Toggle Loop Mode (Off / Track / Folder) |
h |
Toggle hidden files in File View Mode |
x |
Export selected radio station to config |
a |
Add Station/Source/Server |
e |
Edit Station/Source/Server |
f |
Toggle Favorite |
| Key | Action |
|---|---|
p |
Toggle hide finished/played episodes |
s |
Toggle episode sort order (newest-first / oldest-first) |
cohors [OPTIONS] [PATH]
| Argument | Description |
|---|---|
-v, --volume <0-100> |
(Optional) Set the initial volume (default: 100) |
-r, --radio |
(Optional) Start in Radio mode |
--invalidate-cache |
Force the station list to be re-downloaded |
-h, --help |
Print help information |
-V, --version |
Print version information |
[PATH] |
(Optional) Path to a file or directory to play on startup |
You can manage your radio stations and sources directly within the application without manually editing the JSON configuration file.
Press a to open the Add menu. You will be prompted to choose what to add:
- Press
sto add a Single Station. - Press
rto add a Source (a dynamic list of stations from a JSON URL).
-
Visit www.radio-browser.info and craft your search there. When finished, click the JSON button and copy the URL provided, for example:
https://de2.api.radio-browser.info/json/stations/search?limit=10&name=80s&hidebroken=true&order=clickcount&reverse=true -
Open Cohors.
-
Press
tabuntil you reach theRadio Stationstab. -
Press
ato add a new station/source. -
Press
rto add a radio source and use these fields:- Title: Anything you want
- JSON URL: The above URL
- Container: Leave empty, no mapping override is needed, the default matches.
- Map: Name - "name"
- Map: URL - "url"
- Map: Desc - "description"
- Map: Home - "homepage"
- Map: Tags - "tags"
-
Press
Enterto save and your category and stations should show up in the Radio Stations list
To edit an existing item, navigate to it in the Radio list and press e.
- Custom Stations: You can edit any station that you've added manually (under "Custom Stations").
- Sources: Select the source header (the group title) to edit the source configuration.
To delete an existing item, navigate to it in the Radio list and press backspace or delete.
- Custom Stations: You can delete any station that you've added manually (under "Custom Stations").
- Sources: Select the source header (the group title) to delete the source configuration.
When adding or editing, a dialog will appear with several fields.
- Navigation: Use
Tab/Downto move to the next field, andShift+Tab/Upto move back. - Saving: Press
Enterto save your changes. - Canceling: Press
Escto close the dialog without saving.
Changes are automatically saved to your config.json file.
While the built-in UI handles most tasks, you can still manually configure sources in config.json. The station data is downloaded and cached for one week. To invalidate the cache and force a re-download, use the --invalidate-cache argument.
The application looks for the configuration file in the following order:
$XDG_CONFIG_HOME/cohors/config.json~/.config/cohors/config.json./config.json
The configuration file is a JSON object containing an optional radio object, which holds lists of stations and/or sources.
Each station defines an individual station you want to list while each source defines where to fetch the data and how to map the JSON fields to Cohors' internal station structure.
Stations support the following fields:
name: Display name of the stationstation_url: The URL to stream fromdescription(Optional): A description of the station.homepage(Optional): The station's home page.
Radio stations can be export to your individual station list by pressing x. This is useful if you're using a JSON link that could have rotating results based on properties.
Sources support the following fields:
title: Display name for this group of stations in the UI.json_url: The URL to fetch the JSON data from.container(Optional): If the station list is inside a property of the root JSON object, specify the key here. If the root is an array, omit this field.mapping: Maps the API's field names to Cohors' fields. Nested fields can be accessed using dot notation (e.g.,playlists.0.url).
{
"radio": {
"stations": [
{
"name": "My Favorite Station",
"station_url": "http://stream.example.com/radio",
"description": "Best hits 24/7",
"homepage": "http://example.com"
}
],
"sources": [
{
"title": "Example Radio Source",
"json_url": "https://api.example.com/stations.json",
"container": "stations",
"mapping": {
"station_name": "name",
"station_url": "stream_url",
"description": "desc",
"homepage": "website",
"tags": "genre",
"lastPlaying": "current_song"
}
}
]
}
}For the configuration above, the json_url (https://api.example.com/stations.json) would be expected to return a JSON structure similar to this:
{
"stations": [
{
"name": "Cool Radio",
"stream_url": "http://stream.example.com/cool",
"desc": "The coolest beats",
"website": "https://coolradio.example.com",
"genre": "Jazz, Funk",
"logo_url": "https://coolradio.examplecom/logo.png",
"current_song": "Miles Davis - So What"
},
{
"name": "News FM",
"stream_url": "http://stream.example.com/news",
"desc": "24/7 News",
"website": "https://newsfm.example.com",
"genre": "News, Talk",
"logo_url": null,
"current_song": "Breaking News"
}
]
}The container field is set to "stations", telling Cohors to look inside that property for the list. The mapping then connects fields like name to station_name and stream_url to station_url.
Cohors can connect to an AudioBookshelf server to browse and play podcasts.
- Press
TABuntil you reach the AudioBookshelf mode. - Press
ato open the Add menu, then pressbto add an AudioBookshelf server. - Enter your server URL, username, and password. The password is used only to obtain an API token and is never saved.
Navigation follows the same pattern as the rest of the app:
- Servers → Libraries → Podcasts → Episodes: Press
Enterto drill down,Backspaceto go back. - Selecting an episode starts playback. In-progress episodes resume from where you left off.
- When an episode finishes, the next episode plays automatically.
While viewing an episode list:
- Press
pto toggle hiding episodes you have already finished. - Press
sto toggle between newest-first and oldest-first order (useful for starting a podcast from episode 1).
The server token is stored in config.json under audiobookshelf. You can manage servers directly from the UI; there is no need to edit this manually.
{
"audiobookshelf": {
"sources": [
{
"server_url": "http://my-abs-server:13378",
"username": "myuser",
"api_token": "<token obtained at login>"
}
]
}
}

