Fork me on GitHub
vitunes is a curses-based music player and playlist manager whose goals are: a minimalistic appearance, strong vi-like bindings, and quick playlist creation/management. vitunes does not strive to be a feature-rich media player, but rather a quick, vi-like media indexer and playlist manager, that just happens to be able to play the music it indexes.


  • Doesn't need write-access to anything outside its storage directory
  • No junk files scattered everywhere
  • can create/modify/search/filter/sort playlists in a quick, vi-like fashion
  • uses mplayer or gstreamer to play media (can play almost anything)
  • uses TagLib for meta-data extraction (wide media/format support)
  • undo/redo
  • custom key-bindings
  • customizable display (format, color)
  • 256 color support
  • Can index non-files (things like URL's)...pretty much anything mplayer can play

Getting Started

Code / Files

Repository: GitHub
Latest: vitunes-2.3.tar.gz


mplayer ≥ 1.0rc3
gstreamer (optional)


Configure: $ ./
Build & install: $ make install
Uninstall: $ make uninstall

Default install locations for binary and man pages are /usr/local/{bin,man}. To tweak, edit relevant variables in Makefile.

Notes for Porters

vitunes is developed on OpenBSD, and makes use of a few OpenBSD-specific things such as err(3)/warn(3), fparseln(3), strlcat(3)/strlcpy(3), and strtonum(3).

Most of these are picked-up during the build on Linux & Mac OS X and will be added if needed. See the file config.h.


Man Pages

vitunes(1) - Thorough documentation of all features. Start with the “Getting Started” section. Additionally, for each e-command:

Mailing List

Search the archives for past questions & answers, or subscribe to ask new questions.

Open Issues

View open issues on GitHub. Add your gripe to an existing issue or open a new one. Or just say hello :D

Complete List of Keybindings

Key Scope Action
<ENTER> Library Load currently selected playlist for viewing & switch focus to playlist window
<ENTER> Playlist Begin playback of currently selected song
<TAB> Library Switch focus to playlist window
<TAB> Playlist Switch focus to library window
s Global stop playback
z Global pause/unpause playback
^p Global same as above
nb / nf Global Seek backwards/forwards n * 10 seconds in currently playing song
n[ / n] Global same as above
nB / nF Global Seek backwards/forwards n * 1 minute(s) in currently playing song
n{ / n} Global same as above
m Playlist Show/hide the filename & meta-info for the currently selected file.
ntregister Global Execute the nth next command in the toggle list associated with register register.
See the man page documentation for the :toggle command.
nTregister Global Execute the nth previous command in the toggle list associated with register register.
See the man page documentation for the :toggle command.
/ Global Get query from user and search forwards in current window for first playlist/file that matches the query. The structure of the query specified is identical to that of the :filter command below. See that for more info.
Note: In the Library window, only the playlist name is matched against.
? Global Get query from user and search backwards in current window for first playlist/file that matches the query. The structure of the query specified is identical to that of the :filter command below. See that for more info.
Note: In the Library window, only the playlist name is matched against.
n Global Jump to the next row in the current window matching the last provided query. If the last query made was done using '/', then this search is forwards, otherwise it is backwards.
N Global Jump to the next row in the current window matching the last provided query. If the last query made was done using '/', then this search is backwards, otherwise it is forwards.
nyy Playlist Yank the next n rows into the copy buffer
yG Playlist Yank the rest of the current playlist into the copy buffer
*y* Library Currently can't yank at all in library window.
Note: I don't really see a way of doing this in an intuitive way, so it will probably never be added.
ndd Playlist Delete the next n rows and copy them into the copy buffer
dG Playlist Delete the rest of the files in the current playlist after copying them into the copy buffer
dd Library Delete the currently selected playlist
Note: Currently, no n can be applied to this in the library window. I simply do not want to be able to delete all of my playlists accidentally.
p Playlist Paste the contents of the copy buffer after the currently selected row.
P Playlist Paste the contents of the copy buffer before the currently selected row.
p Library Paste the contents of the copy buffer at the end the currently selected playlist.
P Library Paste the contents of the copy buffer at the beginning the currently selected playlist.
u Playlist Un-do the previous cut/paste to the currently viewed playlist.
^r Playlist Re-do the previously undone cut/paste to the currently viewed playlist.
: Global Enter command mode. See vitunes(1) for list of all commands.
!cmd Global Exit curses-mode and execute external command cmd
^l Global Erase and redraw display
nj Global Move current row down n * 1 lines
n<KEY_DOWN> Global Move current row down n * 1 lines
nk Global Move current row up n * 1 lines
n<KEY_UP> Global Move current row up n * 1 lines
n- Global Move current row up n * 1 lines
nh Global Horizontally scroll left n * 1 columns
n<KEY_LEFT> Global Horizontally scroll left n * 1 columns
n<BACKSPACE> Global Horizontally scroll left n * 1 columns
nl Global Horizontally scroll right n * 1 columns
n<KEY_RIGHT> Global Horizontally scroll right n * 1 columns
n' ' Global Horizontally scroll right n * 1 columns
Note: that's a space.
$ Global Scroll all the way to the right
'^' Global Scroll all the way to the left
Note: that's a carrot, not a "CONTROL+"
0 Global Scroll all the way to the left
n^e Global Scroll screen down n * 1 line(s)
n^y Global Scroll screen up n * 1 line(s)
n^u Global Scroll screen up n * 1 half page(s)
n^d Global Scroll screen down n * 1 half page(s)
n^b Global Scroll screen up n * 1 full page(s)
n<PAGE_UP> Global Scroll screen up n * 1 full page(s)
n^f Global Scroll screen down n * 1 full page(s)
n<PAGE_DOWN> Global Scroll screen down n * 1 full page(s)
G Global Goto last row
nG Global Goto row n
n% Global Goto the row n% through the total number of rows
nH Global Goto the nth row from the top of current page
M Global Goto the middle row of the current page
nL Global Goto the nth row from the bottom of current page


256 colors, on OS X
256 colors, from @ok100
Default look
Smaller version of default
Library window hidden
On OSX, via Joshua Conner
Older version


  • 2015 Jan 15
    New website
    No news regarding vitunes itself, however I did refactor the site to use uikit, which I would highly recommend -- it's a great less-based, component framework that, imho, is much easier and more responsive than bootstrap et alia.
  • 2012 Jan 2
    Version 2.3 Released
    First release in over a year, consisting entirely of work over 6 months old (much by others) that I never got around to pushing out. Multiple new features, performance improvements, and bugfixes. Notable new features include toggle-lists, allowing one to quickly toggle through sets of commands, such as various sort or display schemas. One can now also control a running instance of vitunes remoltely, using the new -c command option, allowing vitunes to be controlled remotely.
    Complete changelog here. See man page for usage.
  • 2011 Jul 11
    Site back online
    New job, new city, and now finally the site is back up! Once I'm finished moving, I hope to push out some new work.
  • 2011 Mar 15
    Brief Hiatus
    With end-of-quarter grading, research, job-hunting, and dealing with my University closing my department (Computer Science.... !?!?!?), I'll be rather busy for the next few weeks and unable to contribute to the project.
    Keep an eye on the “Network” tab in the GitHub repo for some of the other contributor's work until I return.
  • 2011 Feb 16
    ArchLinux Port Updated!
    With many thanks, Peter Polacik has updated the ArchLinux port of vitunes.
  • 2011 Feb 10
    Linux Support Now Working out-of-the-box
    With much thanks to Daniel Walter and Peter Polacik, vitunes now compiles and runs on Linux! It requires a newer version of mplayer on Debian, and has some compile warnings (working on that), but it works!
    Mplayer version 1.0rc3 or later will do. Alternatively, any version built with a checkout of the source after December 27, 2009 should do.
  • 2011 Jan 9
    Version 2.2 Released: native Mac OS X Support
    This release adds no new functional features from version 2.1. It does include a much better man-page and a build that works on Mac OS X. That's it.
  • 2011 Jan 7
    Call for testing: Mac OS X Support
    In the past few days I have added support for a clean build on Mac OS X. That is, vitunes should build cleanly, as-is, on a Mac. Only the following needs addressing by any Mac users:
    • Update the install locations in the Makefile (PREFIX) appropriately.
    • Edit the LDFLAGS variable in the Makefile to include -lncursesw rather than -lncurses.
    • Either manually modify the DEFAULT_PLAYER_PATH variable in config.h, or simply run vitunes with the -m flag and a proper path to mplayer.
    With this, it should be rather trivial for a porter to get this into either MacPorts or similar.

    Thanks to Joshua Conner and André Berger for their help.

    NOTE: This isn't in any release yet, including the most recent, as it still needs heavy testing.
  • 2011 Jan 5
    Version 2.1 Released: Bugfix Release
    There were some rather nasty formatting errors with the man page that shipped with the 2.0 release a few days ago. They didn't show up during testing (e.g. with “mandoc vitunes.1 | less”), but did after installation (with “man vitunes”).
  • 2011 Jan 1
    Version 2.0 Released
    Version 2.0 is officially released. Many new features, including support for custom keybindings (via the bind and unbind commands), undo/redo support, vastly improved synchronization between vitunes and mplayer, new display elements that are colorable, and new keybindings.

    This brings vitunes almost to a completion, at least in terms of what I always wanted it to be. I'll be maintaining it indefinitely since I use it heavily, but I don't really foresee any major new features. If you have ideas, let me know.

    Happy 2011!
  • 2010 Dec 29
    Massive Re-Write Underway
    So my “minor clean-up and a few feature additions” has turned into a hackathon on my part. It rocks. Far better synchronization with mplayer (less skipping), undo/redo support, :map to create custom keybindings, more color-able stuff, support for the comment-field of media files, and cleaner syntax for all commands are all in the works.

    Unfortunately, these updates will either break compatability with previous versions of vitunes or require super-extra-massive effort on my part to make it backwards compatable by adding loads of goey goey c. Pondering...

    For the daring sort, you can use one of the repositories listed above to get a copy of the current development version and build yer own. And hey, if you just feel like contributing something back, that'd be sweet.
  • 2010 Dec 17
    Mailing List Up and New Stuff in the Works
    There is now a vitunes mailing list, hosted by You can subscribe to the mailing list by visiting this webpage, and searchable archives are available here.

    Now that school is out for the holiday break, I'm on a research binge during the day and a hacking binge during the night. New features in the works...
  • 2010 Apr 27
    1.0.5 Released (Documentation Cleanup)
    New release, 1.0.5 made today. A simple documentation cleanup. The man page and output of all vitunes -e help COMMAND have been made more complete. The man page is now the sole source of documentation (although the complete list of keybindings will remain here on the website, maintained, at least for now).
  • 2010 Feb 17
    Podcast Support?
    I'm contemplating adding podcast support. I don't wish to have vitunes automatically download any files within a podcast (a simple shell script, or any number of other existing utilities could be used for that). Rather, i'd like vitunes to just parse an RSS feed, extract info to view in vitunes, and pass the filenames to mplayer (mplayer handles URL's quite nicely).

    vitunes users: any good ideas on how to integrate this into the vitunes ui? Remember that a podcast is essentially a playlist, with multiple files. Just an informal “RFC.”
  • 2010 Jan 28
    FreeBSD Port!?
    Catching up on freshports yesterday, I noticed that vitunes has been ported (for some time now!) to FreeBSD by Dennis Herrmann. Many thanks to him!
  • 2010 Jan 20
    1.0.4 Released (Last one for a while)
    Last release for a while, baring any bug fixes. A few bugs fixed, documentation updated, and I finally re-wrote the player code (only stuff untouched from previous rewrite). Can now search in the library window. Command abbreviations supported. Can right-align columns in display. See complete changelog here.
  • 2010 Jan 14
    1.0.3 Released
    Big news... I removed the dependency on libid3tag, libvorbis, and libmp4v2. Now TagLib is used for all meta-extraction. Much cleaner. Some bug fixes also. This does, however, bump the version & format of the database, thus all vitunes databases will have to be re-built. It's much faster now though. See the full changelog here.
  • 2010 Jan 12
    Upcoming Release
    While browsing the intertubes today, I noticed that TagLib was updated recently and now includes MP4/AAC metadata including iTunes-style metadata. This is awesome, as TagLib is both way cleaner, faster, and overall better than the libraries I'm currently using. I'm updating vitunes now to use this new library. When finished, vitunes will also be able to tag files.
  • 2010 Jan 9
    1.0.2 Released
    A small bug-fix release with a few new features. See the changelog here.
  • 2010 Jan 3
    1.0.1 Released
    A simple bug-fix release, fixing an issue where “reload db” would sometimes segfault due to a use-after-free.
  • 2009 Dec 30
    1.0 Released!
    After much work, including a nearly complete re-write of everything, the initial 1.0 release has been made! There are many new features. See a complete changelog here.

Frequently Answered Questions

General Usage Questions

How do I change the meta-information of a file within vitunes?
Use the tag e-command (or another application) followed by an update.

The next time you launch vitunes you will see the changes (or you can issue a :reload db command within vitunes).
I moved a bunch of my music around. How do I update vitunes?
Use the update e-command to remove any moved files and then simply add your moved files again.
For some songs, the percent-complete in the player window is always negative?
When vitunes extracts the meta-information from songs, including playlength, it uses TagLib. If TagLib isn't able to determine the play length of the file, vitunes will attempt to determine the length when loading the file, but this isn't always possible either. In these cases, the percent will be negative.
How do I backup the vitunes database?
Just copy the ~/.vitunes/ directory. If you have your database/playlists stored elsewhere, just backup those.
Can I have my database/playlists/config-file stored elsewhere?
Yes. Use the -d, -p, and -f flags as described in the man page.
I have an old version of vitunes with an existing database. When I run the new version, it tells me to rebuild my database. How do I do this?
I had to slightly change the format of the database for this new version. Also, I never included any version information in the previous format. This has now been changed. To upgrade an existing setup, download the most recent version below and 1) remove the existing database, 2) re-init the database, then 3) re-add all of your files. e.g.
         $ rm ~/.vitunes/vitunes.db
         $ vitunes -e init
         $ vitunes -e add /path/to/music/ ...
Adding regular files to the database is easy, but adding URL's is somewhat painful. Is there an easy way to automate this?
Of course! You're using *nix, so use a shell script to add all of your URL's, like this one:
When exiting vitunes, it seems to hang for one half-second. Why?
This is intentional. The fork()'d mplayer child will fork() an instance of itself whenever it plays an internet radio stream (or similar) to handle the buffering. As such, vitunes needs to wait for this ‘grandchild’ instance of mplayer to exit before quitting.

Bugs & Other Questions

I think I found a bug... what should I do?
First, do the following, in this order:
  1. Read the man page (humor me)
  2. Read the FAQ
  3. Search the mailing list archives to see if your “bug” has popped-up before.
  4. Search the Bug/Issue database to see if your bug is already known, and if so, add a comment that you too are experiencing it. Provide as many details as possible.

If you've done the above and haven't found your bug/issue mentioned and resolved elsewhere, then email either the mailing list or me, and include an extremely detailed description of your bug and how to reproduce it.
After a song finishes playing, the next song isn't automatically started.
Most likely you're on a Linux distro with an older version of mplayer. You need mplayer version 1.0rc3 or greater. Alternatively, any version of mplayer built from a checkout of the source after December 29, 2009 will work.
The cursor is always visible, even when I'm not in command mode... what gives?
This is most likely a mis-configured $TERM environment variable. Specifically, it's set to something that does not support this particular feature. See the documentation for your OS & terminal emulator (e.g. xterm/rxvt/etc.) for what this should be set to. Note that “xterm-color” almost always has limitations (see here for more information).

On OpenBSD pre 4.7, your $TERM variable, when using xterm, should always be set to xterm-xfree86. After 4.7, just leave your $TERM variable alone.
Scrolling, redrawing, and resizing are all very slow. Is this normal?
If you're using an actual VT100 (or similar) or if you have 1,000,000,000,000+ songs in your library, then yes. Otherwise, no. This is mostly likely a misconfigured $TERM environment variable. See the previous FAQ entry.
What license is vitunes distributed under?


UTF8 Support
Now that OpenBSD supports UTF8, support that (waiting for ncurses(3) support)
256 Color Names
Support color names (not just IDs) when using 256 color support
ASCII-art audio viz
.... f' yeah!

P.S. if you like vitunes, then you might like...

vim plugin that allows you to control iTunes, by Daniel Choi.
An amazing browser using webkit with strong vi bindings and... tiling! It rocks. A little buggy still, but it looks promising.
Minimalistic browser using webkit with strong vi-like usage.
Another browser like vimprobable, based on webkit and with a srong vi-like usage. from the great devs of
Firefox plugin that make it more vi-like.
Another curses based music player similar to vitunes.
practical music search
Curses front-end for mpd.
play yer tunes... without the fluff
using html5 | css3 | uikit
by ryan flannery