Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?


Failed to load latest commit information.
Latest commit message
Commit time


Command line directory bookmarks with jumping to bookmarks, subdirectory tab completion, distant listing etc

Apparix is a tiny set of commands implementing directory bookmarking in bash and zsh. You just need the file .bourne-apparix. What apparix provides:

  • Bookmark the current directory by issuing bm foo. This takes effect instantly across all your sessions (it is stored in $HOME/.apparixrc).

  • Jump to foo by issuing
    to foo

  • Even better, jump to the subdirectory barzoodle of foo using
    to foo barzoodle

  • Even betterer, use cyclic tab completion with subdirectory jumping:
    to foo b<TAB> or just to foo <TAB>
    👆 This is the oomphiest bit.

  • This works at arbitrary levels:
    to foo barzoodle/ti<TAB>

  • No less excellent, there are several distant listing/editing commands. In all cases, tab completions work on subdirectories and files (below is the output of the apparix ahoy helper function):

When I mentioned that the set of commands is tiny, what I really meant was that the set of cd-related command is tiny; basically bm and to. It turns out that having bookmarks for directories is useful for other commands as well, such as distant listing, finding and editing, plus convenience queries such as the age old question: Am I a Bookmark?

Apparix functions, grouped and roughly ordered by expected use.
             Below all SUBDIR and FILE can be tab-completed.

  bm   MARK               Bookmark current directory as mark
  to   MARK [SUBDIR]      Jump to mark or a subdirectory of mark
  als  MARK [SUBDIR] [ls-options]  List mark dir or subdir
  ald  MARK [SUBDIR]      List subdirs of mark dir or subdir
                          ignores hidden directories
  aldr MARK [SUBDIR]      Like ald, recursively
  amd  MARK [SUBDIR] [mkdir options] Make dir in mark
  a    MARK [SUBDIR/]FILE Echo the true location of file, useful
                 e.g. in: cp file $(a mark dir)
  aget MARK [SUBDIR/]FILE Copy file to current directory
  aput MARK [SUBDIR] -- FiLE+   Copy files to mark (-- required)
  ae MARK [SUBDIR/]FILE [editor options] Edit file in mark
  av MARK [SUBDIR/]FILE [editor options] View file in mark
  amibm                   See if current directory is a bookmark
  bmgrep PATTERN          List all marks where target matches PATTERN
  agather MARK            List all targets for bookmark mark
  whence MARK             Menu selection for mark with multiple targets
  todo MARK [SUBDIR]      Edit TODO file in mark dir
  rme MARK [SUBDIR]       Edit README file
  portal                  current directory subdirs become mark names
  portal-expand           Re-expand all portals
  aghast MARK [SUBDIR/]FILE [dummy options] testing the apparix muxer
  Where options passing is indicated above:
   - The sequence has to start with a '-' or '+' character.
   - Multiple options with arguments can be passed.
   - -- occurrences are removed but will start a sequence.
   - FWIW Arguments with spaces in them seemed to work under limited
     testing, e.g. ae pl '+set paste'

Tab completion with apparix works best, IMHO, with cyclic tab completion. This is activated by the line TAB: menu-complete in the file $HOME/.inputrc (and you may need as well put INPUTRC=$HOME/.inputrc in $HOME/.bashrc), or the line bind '"\t":menu-complete' in $HOME/.bashrc.

Get it now:


Apparix allows the same mark to point to different directories. This can be useful e.g. for subsequent projects with a common theme or associated with the same collaborator, or simply using a now bookmark for the current project. The to jump command will use the last occurrence in the resource file as the destination to use (default target). I find it useful to keep the older destinations around as a trail of my activities. Use agather to view all associated targets, use whence to pick an older destination, or edit the resource file with via to change the default target.

I use amibm in PROMPT_COMMAND. It lists the marks under which the current directory $PWD is known. Let's call a mark mrk with multiple directories a multi-mark. Now mrk is listed by amibm as mrk- if it is a multi-mark and $PWD is not the default (last-listed) target, as mrk+ if it is a multimark and $PWD is the default target, and just as mrk if $PWD is the unique target. As a contrived example, suppose this is the location where apparix source code lives:

> /git/micans/apparix (main *%) (ax+ a- apx) pwd
> /git/micans/apparix (main *%) (ax+ a- apx) amibm 
ax+ a- apx

It shows that the location /home/stijn/git/micans/apparix (that is, $PWD) is associated with three bookmarks, two of which have this location as default target The mark apx is unique. The mark ax points to $PWD but has other (older) targets as well. The mark a points to another path and $PWD is an older target.

There are two asymmetries between aget and aput. The former can only retrieve a single file, but tab completion on the (distant) file to be copied works. The latter can copy over multiple files, but tab completion is bound to the target and hence does not work on the files to be copied. For other cases just work with $(a mark dir). This can be combined with globbing, as in

cp $(a mrk)/*.txt .

Many thanks to Sitaram Chamarty for the original idea of sub-directory completion and the first bash implementation thereof, and to Izaak van Dongen for the zsh completion code and complete overhaul and improvement of the bash completion code. Thanks to Martin Zuther there is a cool fish implementation, named appari-fish.

Apparix/apparish developments, past and ongoing

In the beginning (2005-ish) the system was called Apparix. It was implemented in C and shipped with bash wrapper functions and tab completion. Sitaram Chamarty got in touch, instigated subdirectory tab completion and contributed the bash code, adding pivotal oomph to apparix. The C code was, in hindsight, a slightly heavy hammer. A simple bash shell reimplementation was undertaken many years later, around 2018 and published in the micans/bash-utils repository. Izaak thought of the name apparish and added zsh code and additionally contributed a thorough rewrite of the bash completion layer (more about that below).

Martin added appari-fish to the family. The valley was peaceful for a while. Early 2021 I realised that I still think of the valley as apparix, so I've tweaked documentation and renamed files to revert back to apparix, followed by moving it to its own repository.

A bleeding edge fork of apparix lives in this repo, supporting among other things newlines in the directory name that a bookmark points to. For various reasons (my dinosaur habits among them) that code did not make it into this repository. The main reason you might want to use the dinosaur code here is that I'm a pretty heavy apparix user and live the distant directory experience every day. The bash helper functions occasionally receive little additions and improvements. When this happens the functionality is described and added to the list of example commands at the top. Happy to'ing!


Command line directory bookmarks with jumping to bookmarks, subdirectory tab completion, distant listing etc