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
scripts installed before continuing.
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
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.
tile_cache_networkis set to 1 or 0 for online or offline respectively
The UI features 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
The UI features a bar of buttons in the default configuration indicated
as text aligned in a bar at the top lefthand of the screen similar to the
bottom button bar. The difference between
this bar and the bottom bar is that this button bar only appears
when there is a currently activated pin (this built out using the
bind_button mepolang command with the
first argument set to
1). Additionally the items in the top bar utilze
bind_button's group number functionality
0-9 buttons to show a bar of color for each group transfer
button associated with the group's color (and also the currently active pingroup
will show as highlighted).
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:
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.
Since most auxiliary features such as routing, POI searches, etc. are built out in shellscripts (which utilize zenity for menuing & user input); 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:
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:
filedumpcommand functionality to extract pin data. Script is designed to be used asychronously via
droppinactivateandcenterwhich both drops a pin on the map and centers the map. Meanwhile the function
droppincan be used in isolation to only drop a pin on the map in pingroup 6. This script may be used synchronously or asynchronously; within the default config
droppinis used asynchronously via
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
[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.
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
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.
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.
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.
y yanks the current coordinates of the map into the
clipboard in the format of
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
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;
Shift-y to run this code. This is a quick way to debug
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
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
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
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:
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
tile_cache_network which you may read about below. Do
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.
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
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
echo "prefset tile_cache_network 0;" | mepo -i
The button bar 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
Download: clear download queue entry from the central
menu to cancel in-progress downloading.
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
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:
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:
By default the scripts in the central menu (used for the button bar 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
MEPO_ENDPOINT_GRAPHHOPPER_ROUTE: The Graphopper route endpoint to use
MEPO_ENDPOINT_OVERPASS: The Overpass interpreter endpoint to use
MEPO_ENDPOINT_MLS: The Mozilla Location Services geolocate endpoint to use
MEPO_ENDPOINT_OSM_WIKI_SPECIALPHRASES: The OSM wiki endpoint to retrieve special phrases from
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
1to enable, set to
MEPO_MENUING: Determines menuing / user input function or script to use, can be
autoor the name of a custom script in
$PATHto use a custom script for mening, see menuing script. Prior versions of mepo supported
bemenu, however now only
auto(which uses zenity), or a custom script.
MEPO_MENUING_FONT: Font used for
MEPO_MENUING_NLINES: Number of lines passed to bemenu/dmenu for
MEPO_TIMEOUT_GEOCLUE: Number of seconds used for the geoclue timeout in the
where-am-iexecutable (e.g. the
-toption) used in geolocate script
MEPO_GEOLOCATE_COORDSVIAMETHOD: Name of function (either
coordsviagpsdfor gps, or
coordviamlsfor MLS via curl) or a custom script to use in
$PATHto determine coordinates see geolocation script
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 -ior
./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.