User Guide

Basic Interface Overview

Mepo is a fast, simple, and hackable OSM map viewer for desktop & mobile Linux devices (like the PinePhone, Librem 5 etc.) and both environment's various user interfaces (Wayland & X inclusive). Its interface presents an SDL interactive application and auxiliary features are built out in scripts. The basic interface is essentially a OSM map that can be panned, zoomed, manipulated, and overlaid via 'pins' which are arbitrary points on the map which can be added by the user to mark locations (see below for a diagram of the general user-interface). Being a good unix citizen, the core application does one thing well, only focusing on displaying the map and visual overlays, and has no extra functionality; however mepo plays well with other applications and is scriptable and very customizable through mepolang.

For end-users not interested in customizing the behavior of mepo, the application is bundled with sensible defaults including a default set of keybindings, touch-compatible configuration, and scripts written in plain shell which enable features such as POI searches, routing, and more. Throughout the rest of this guide it will be assumed the user is making use of the default configuration and has done no customization; but its important to realize there is a hard distinction between the core SDL application, mepo, and its default base configuration and scripts which are bundled by default. See the install guide for information on installation and ensure you have both the mepo binary and mepo_* scripts installed before continuing.


The Bottombar

The UI feature a diagnostic bottombar which indicates a number of numerical values based on the application state. Shorthand lettering is used to save visual screenspace. The background color of the bottombar changes based on tile downloading state. While in offline mode (tile_cache_network as 0), the bar will be red, while in online mode and idle the bar is white, while downloading UI tiles the bar turns green, and while downloading background cache / queued tiles the bar turns blue. See below for a visual labeling overview of the bottom bar and explanation of each item.


  • Lat/lon: Indicates latitude & longitude at left start of bar
  • Z#: Indicates the current zoom level (0-16)
  • O#: Indicates if tile_cache_network is set to 1 or 0 for online or offline respectively
  • P#: Indicates current pingroup (0-9)
  • Q#: Indicates number of queued UI tiles for downloading
  • B#: Indicates number of queued BG tiles for downloading
  • D#: Indicates number of current network transfers
  • M#: Indicates number of tiles loaded to GPU/Memory cache
  • S#: Indicates number of active async_shellpipe threads
  • Dl: #: Indicates number of megabytes downloaded since boot

The UI Button Bar

The UI feature a bar of buttons in the default configuration indicated as text aligned in a bar at the bottom righthand of the screen. Under the hood this is actually built out using the bind_button mepolang command; so if you want to add your own custom buttons (tied to userscripts, etc.) this is doable.


  • Purge: Purge pins (only visible when there is >1 pin)
  • <: Switch to the previous pin (only visible when there is >1 pin)
  • >: Switch to the next pin (only visible when there is >1 pin)
  • Menu: Launch the central menu
  • Center: Reposition the map based on userposition
  • Relocate: Relocate the map via Nominatim
  • Nm: Search the current bounding box via Nominatim
  • Op: Search the current bounding box via Overpass
  • Dl: Download current viewport (all tiles in current/higher zoom levels)

Touch & Mobile support

Using mepo on mobile linux devices such as the Pinephone, Librem 5, and postmarketOS devices and similar is a primary usecase. Take note of the following shortcuts:

  • One finger drag: Pan the map
  • One finger double tap: Zoom in
  • One finger triple tap: Zoom out
  • Two fingers pan gesture in: Zoom in
  • Two fingers pan gesture out: Zoom out
  • Three fingers rotate gesture clockwise: Increase UI fontsize
  • Three fingers rotate gesture counterclockwise: Decrease UI fontsize
  • One finger hold: Launch the central menu

Keyboard & Desktop support

Ordinary desktop usage is supported. Ordinary one finger gestures referenced in the touch & mobile section also apply on the desktop; and in addition numerous hotkeys exist to allow functionality such as panning with vim-style keys and direct hotkeys to launch various scripts.

You can reference the default hotkeys by studying the default configuration. Take note of the bind_key commands to determine the applications' default keybindings.

The Central Menu

Since most auxiliary features such as routing, POI searches, etc. are built out in shellscripts (which utilize dmenu, bemenu, zenity, etc. for menuing); the central menu provides a central way to launch different scripts on mobile via touch or on the desktop without having to remember numerous hotkeys.

Below is an image of how the central menu may appear when using zenity (note depending on which menuing program you are using / which package you have installed this may look slightly different):


Here's an explanation of each options available in the central menu. Within parenthesis after the script name is the associated hotkey for desktop users. Also note clicking on each item will show the the mepolang script source:

  • Download: clear download queue (w): Clears the current download cache (background downloading of tiles).
  • Download: custom region (interactive) (q): Queues the current bounding box / viewport of the map to be downloaded in the background. Interactive, in that user is prompted for the minimum and maximum zoom-level to be downloaded.
  • Download: current bounding-box (non-interactive) (Q): Queues the current bounding box / viewport of the map to be downloaded in the background. Non-interactive, in that user is not prompted for zoom-level etc. All zoomlevels equal to and higher then the current zoom level are downloaded.
  • Pin editor: Edit, save, and restore pin metadata (f): Provides comprehensive pin editing via interactive menuing, allowing the user to add and remove pins,as well as edit pin metadata. Uses the filedump command functionality to extract pin data. Script is designed to be used asychronously via shellpipe_async.
  • Update: Fontsize (Z): Updates the fontsize of the UI prompting the user for the input size. Presents menuing prefilled between sizes 12 and 30.
  • Update: Online/Offline toggle (m): Toggles the UI between offline and online mode (e.g. flipping the preference tile_cache_network).
  • Update: Tilesource (u): Updates the tilesource for the map to pull from. Note %1$d, %2$d, and %3$d are used to indicate X, Y, and Z variables respectively. Presents menuing with presets for OSM Maps, Stamen, OpenCycleMap etc.
  • Update: Zoom (z): Updates the zoom level based on users input. Presents menuing to pick from zoom levels between 1 and 16.
  • Relocate map: via search (g): Repositions the map latitude and longitude based on a Nominatim search query. Presents menuing to prompt user for input location and pick from Nominatim results.
  • Route: via GraphHopper (r): Allows user to determine a route between two points via the publicly accessible GraphHopper instance. Presents menuing to prompt user for origin and destination points. The cursor (e.g. the position of the mouse or on mobile the last clicked point - e.g. in case of click-hold functionality) and the centerpoint (where the crosshair is) may be used as origin or destination points as an alternative to named entries. Named entry searches use Nominatim to lookup the user input query. Resulting route is placed into pin group 1 as an ordered pin group wherein instructional pins show each direction in the route.
  • Route: via OSM Relation / Public Transit (R): Drops pins on the map in pin group 1 for the given OSM relation ID. This can be used for general routing for any OSM relation (such as a subway, bus route, or similar). Presents menuing to prompt for the input OSM relation ID.
  • POI Search: via Nominatim (G): Searches for points of interest via the publicly accessible Nominatim API based on the current viewport. Presents menuing to prompt for input overpass query. Drops pins on the map for the resulting found points of interest in pin group 0; purging any previous pins in in group 0.
  • POI Search: via Overpass (b): Searches for points of interest via the publicly accessible Overpass API based on the current viewport. Presents menuing to prompt for input overpass query. Drops pins on the map for the resulting found points of interest in pin group 0; purging any previous pins in in group 0.
  • Location Pin: Center on user location (x): Determines the user location via GPSD, Geoclue, or Mozilla Location services. When provided with no argument runs the function droppinactivateandcenter which both drops a pin on the map and centers the map. Meanwhile the function droppin can be used in isolation to only drop a pin on the map. This script may be used synchronously or asynchronously; within the default config droppin is used asynchronously via shellpipe_async.

POI Searches

Points of interest within the current viewport (bounding-box) can be searched both via Nominatim or via Overpass using the default included scripts. Each of these methods has its advantages and disadvantages. Generally speaking, for specific name-based searches within a region, you should use Nominatim; while for flexible OSM-tag-based searches you should use Overpass.

As described above, Nominatim excels at name based searches. For example if you wanted to find a restaurant called "Joe's Pizza" you could type this directly into the Nominatim POI search script prompt. Or similarly to find a starbucks, you could just type in "starbucks" in the Nominatim prompt. Either select the Nm UI button to launch a Nominatim POI search or select POI Search: via Nominatim from the central menu.

Meanwhile, Overpass is more powerful and suited then Nominatim for POI searches based on OSM tags; for example if you wanted to find all coffeshops, (rather then just a specific name of a coffeshop such as "starbucks" in the previous example) you could search for the general OSM tag [amenity=cafe]. This will find all OSM relations matching this tag within the current bounding box. A number of prepopulated OSM tags are available within the provided Overpass script; however if you want to search any custom OSM tag, simply enter it and this will work just the same. Either select the Op UI button to launch a Overpass POI search or select POI Search: via Overpass from the central menu.


Routing can be accomplished via two mechanisms: either via the bundled script which provides routing via the public GraphHopper instance or via the OSM relation / public transit script.

The GraphHopper script mentioned allows you to route from one location to another. The locations may be determined either via from a Nominatim search or via cursor or centerpoint. Cursor means that the position of the cursor is used as the start/end location; meanwhile centerpoint is the center of the screen indicated by the crosshair. If you type directly, a Nominatim search is used which is appropriate for terms like things like '10 Milbury St, Anchorage, Alaska' and similar. Nominatim can also detect common points of interest, for example Grand Central, NY. The resulting route is added to the map as an ordered pin group which you may step through with information from GraphHopper determining timing etc. Select the Route: via GraphHopper entry from the central menu to create a GraphHopper route.

Meanwhile, the OSM relation script allows you to place an arbitrary OSM relation indicated by the OSM relation ID on the map as an ordered pin group. Simply enter the OSM relation ID or enter a labeled relation from the pre-selected list. Relation IDs can be referenced on the OSM Website. Select the Route: via OSM Relation / Public Transit entry from the central menu to create a route via OSM relation ID.

Repositioning the map

The map view starts wherever the position was last saved from, for more details on this see the next section on save state. During runtime if you want to reposition the map beyond just panning, you primarily have three options through the provided default configuration. The first option is relocate the map via Nominatim, the second option is to relocate the map based on your geopositioning, and the third option relocate the map based on to geocoordinates coordinates pasted from the clipboard.

As for the first option, to reposition the map based on a Nominatim query select from the central menu the entry entitled Relocate map: via Nominatim. You may also press the button in the button bar entitled Relocate to launch this script as well. You will be presented with menuing to prompt for a Nominatim query. You may enter a region (e.g. like Vancouver Canada), a street address (like 20 Jay street), or a point of interest (like Washington DC capitol). Nominatim will be queried and you may pick from the resulting list to reposition the map.

As for the second option, to reposition the map based on geolocation select from the central menu the entry entitled Location Pin: center on user location. You may also press the button in the button bar entitled Center to run this script as well. This script uses either Geoclue2, GPSd, or MLS to determine the user's position and both drops a pin on the map at that location and repositions the map as well to center on that pin.

The third option is to use the clipboard pasting functionality described in the next section.

Clipboard functionality

The clipboard may be used to run arbitrary mepolang code or relocate the map to an specific geocordinate. Currently in the default configuration clipboard functionality is only accessible via keybindings.

The keybinding y yanks the current coordinates of the map into the clipboard in the format of lat, lon.

Meanwhile, the keybinding Shift-y can either restore geocoordinates (such as in the form lat, lon as yanked with y); or alternatively may run mepolang code if not fitting the lat, lon pattern. Using Shift-y you may thus simply recall a previous location yanked with y (which is vaguely reminiscent of vim marks). If the pattern in the clipboard does not look like geocoordinates, what's in the clipboard on pressing Shift-y will be run as mepolang code. For example you might put in your clipboard prefset_n crosshair_size 200; and press Shift-y to run this code. This is a quick way to debug mepolang code.

Save state and Autoloading preferences (via config file)

Within the default config, the mepolang command bind_quit is used along with filedump to write out save state of the application on quitting. Then on boot, fileload is used to restore this save state. As such, after quitting mepo, reopening the application will restore location, pins, and all preferences. Note save state is saved to $XDG_CACHE_HOME/mepo/savestate, so for most users if you wish to temporarily delete any saved state you could run rm ~/.config/mepo/savestate.

In regards to using a config file; while for most users restoring the old state is preferable, you may want to automatically always start the map in a specific location, or with a given set of pins (or bookmarks), or customized in a different way. For this functionality you can use the file at $XDG_CONFIG_HOME/mepo/config, likely ~/.config/mepo/config to store mepolang to run; reference the mepolang guide for more details. The config file mentioned always gets loaded after savestate so it will be applied ontop of any given savestate in all cases.

A simple configuration file for mepo to store in ~/.config/mepo/config to reposition the map to Boston, MA, US and have an arbitrary bookmark pin named foopin placed on the map, might look like:

prefset_n lat 42.3608;
prefset_n lon -71.0573;
pin_add 3 0 42.355 -71.0780 [foopin] [foopin];
prefset_n zoom 15;

Below is a screencast covering savestate and configuration:

Offline Usage

Mepo prioritizes offline usage as a first-class usecase. The mepo application itself presents an SDL2 view of OSM tiles on the map along with a background thread that interfaces with curl for downloading tiles. This background downloading thread has the ability to be completely disabled through a mepolang preference named tile_cache_network which you may read about below. Do note however, tile_cache_network does not effect any scripts called.. if you wish to use scripts utilizing Nominatim or Overpass etc. offline for example for running your own instances locally, these ENV parameters are customizable; see the Overridable Script ENV variables section for more details.

Using the tile_cache_network parameter

If you have already used mepo to download tiles, either interactively or through the script as described below; you may use mepo entirely offline by setting the preference tile_cache_network to 0. When the tile_cache_network property is 0, you'll see the bottom bar turn red and O0. This mode is helpful if you have bandwidth limitations (e.g. for your data plan or similar) and want to make sure mepo does not make any network requests. As mentioned above this does not cover external scripts called through the shellpipe mechanism.

echo "prefset tile_cache_network 0;" | mepo -i

Downloading tiles interactively (via UI)

The buttonbar entry labeled Dl will download all tiles in the current viewport (current zoom level and higher) to the filesystem cache. You may also select Download: current bounding-box (non-interactive) from the central menu for the same functionality. The entry Download: custom region (interactive) in the central menu allows you to download a custom region via Nominatim search query.

Once background downloading is started you can view the bottom bar for diagnostics on download progress. You may use the Download: clear download queue entry from the central menu to cancel in-progress downloading.

Downloading tiles non-interactively (via commandline)

It's a common use case to need to download an entire block / bounding box of tiles while online before going offline. For example, say if you want to use your phone with mepo but are not sure you'll not have internet access at your destination. To facilitate downloading of tiles, you may do this from the UI using the Dl button as described above, but mepo additionally features a non-interactive tile downloading CLI accessible through using the -d flag. This flag should be suffixed with a list of 6 comma separate parameters (no whitespaces) in the form of lat_a,lon_a,lat_b,lon_b,zoom_min,zoom_max. Zoom min and max can range from 0-16. For example, to download a bounding box:

mepo -d40.74946,-74.04673,40.818358,-73.88211,3,16

This may be a bit more involved then you would like to get, so as an alternative you can use the provided script which provides a prompt-driven dialog which queries Nominatim to determine the bounding box to download and then feeds this into mepo -d. Run this script as:

Overridable Script ENV variables

By default the scripts in the central menu (used for the buttonbar and also called by keybindings) that call out to Nominatim, Overpass, and Graphhopper all use the publicly available instances of each service respectively. For privacy purposes, if you wish to run your own instances of these services, updating mepo's scripts to use your local or custom instance is just a matter of updating the appropriate ENV variables. All public endpoints & API keys which are overridable by setting ENV variables are listed below respectively:

  • MEPO_ENDPOINT_NOMINATIM_SEARCH: The Nominatim search endpoint to use
    • (Default:
    • See Nominatim Install Guide for details on using your own custom Nominatim instance offline.
  • MEPO_ENDPOINT_GRAPHHOPPER_ROUTE: The Graphopper route endpoint to use
    • (Default:
    • See GraphHopper Install Guide for detail on using your own custom GraphHopper instance offline.
  • MEPO_ENDPOINT_OVERPASS: The Overpass interpreter endpoint to use
    • (Default:
    • See Overpass Install Guide for details on using your own custom Overpass instance offline.
  • MEPO_ENDPOINT_MLS: The Mozilla Location Services geolocate endpoint to use
    • (Default :
  • MEPO_ENDPOINT_OSM_WIKI_SPECIALPHRASES: The OSM wiki endpoint to retrieve special phrases from
    • (Default:
  • MEPO_APIKEY_GRAPHHOPPER: The API key for Graphopper to use
  • MEPO_APIKEY_MLS: The API key for Mozilla Location Services to use
  • MEPO_USERPIN_ENABLED: Determines whether to enable the user geolocate pin updating script. Set to 1 to enable, set to 0 to disable.
    • (Default: 1)
  • MEPO_MENUING: Determines menuing to use, can be auto, inputzenity, inputbemenu, inputdmenu, or a custom script, see menuing script
    • (Default: auto)
  • MEPO_MENUING_FONT: Font used for inputbemenu or inputdmenu
    • (Default: Inconsolata)
  • MEPO_MENUING_NLINES: Number of lines passed to bemenu/dmenu for inputbemenu or inputdmenu
    • (Default: 17)


Mepolang is mepo's command language API for IPC & configuration. See the mepolang page and scripting guide for more information on mepolang usage.

CLI Options

  • mepo -docmd: Print markdown documentation for the mepolang API to STDOUT.
  • mepo -docman: Print manpage documentation for the mepolang API to STDOUT. Can be viewed with man via: mepo -docman | man -l.
  • mepo -i: Read mepolang from STDIN continually. Can be used for interactive debugging or scripting via: tee | mepo -i or ./myscript | mepo -i.
  • mepo -e: Enable debug mode to log messages to STDERR.
  • mepo -ndc: Disable default/base config, this is useful if you have a custom config and don't wish to use the default bindings, etc.. for example: cat my_config | mepo -ndc -i.
  • mepo -sw: Use software renderer rather then default GPU/hardware based renderer.
  • mepo -v: Print version number.
  • mepo -h: Print this help text.
  • mepo -dlat_a,lon_a,lat_b,lon_b,zoom_min,zoom_max: Non-interactively download tiles for given range.