download and process dive computer data
Image from divelog.blue's Kittiwake.

divecmd is a suite of command-line UNIX tools (OpenBSD, Linux, Mac OS X) to extract dives from dive computers. It wraps thinly around the excellent libdivecomputer, which does the heavy lifting to interface with your device.

Why use divecmd instead of, say, Subsurface? Because it's built to work in a command-line workflow with other command-line tools for processing, such as grap(1) (or any other grap implementation) piped into groff(1) (or other troff) or LaTeX (or other TeX). Plus, it has much better support and analysis tools for free diving.

My workflow usually begins with divecmd(1) on the day of my dive. First, I extract the dives from my Suunto D6i into an XML file for the day. divecmd(1) keeps track of my last extracted dive, so it will only extract new dives (presumably from the current day):

divecmd d6i > daily.xml

In reality, I usually archive my dives after each day of diving to prevent me from overrunning the computer's internal memory and losing dives.

divecmd d6i > daily-`date +%F`.xml

Following that, I'll analyse my dives by plotting them with divecmd2grap(1) via divecmd2pdf(1). In the case of free diving, for example, I might do this:

divecmd2pdf -m summary daily.xml > daily.summary.pdf divecmd2pdf -m restscatter daily.xml > daily.restscatter.pdf

These graphs let me see my dive depths and times, and also see whether I'm following the surface-time rule of thumb, where rest is twice the prior dive. Note: if you're free diving and using a dive computer that lumps all free dives into one huge dive without splitting them up by surface time, use divecmd2divecmd(1) to canonicalise the dives. My HW OSTC 2C does this. Or I'll take a sneak peak only at the day's dives on my terminal:

divecmd2divecmd -ldate=`date +%F` daily.xml | divecmd2list divecmd2divecmd -ldate=`date +%F` daily.xml | divecmd2term

Want to see a full analysis of these dives in PDF?

divecmd2divecmd -ldate=`date +%F` daily.xml | divecmd2pdf -a -m all >daily.pdf

There are a number of ways to export from the native divecmd(1) XML file without needing to parse the file yourself.

printable graphs

The divecmd2grap(1) utility converts from XML into the grap(1) format. Aside: why grap(1)? Because it fits into the standard piped UNIX workflow. I can send the output directly into groff(1) without needing to manage the intermediary files of gnuplot or LaTeX. I use these other tools all of the time, but prefer to avoid them for that reason. See also divecmd2pdf(1), which manages the groff pipeline.

There are a number of graphing modes available to divecmd2grap(1). In all of them, I use daily.xml, multiday.xml, day1.xml, and/or day2.xml, as input. The graph names (e.g., aggr) are used in the -m argument.


Stacked dives (multiple dives) split by date with -sdate and showing ascent and descent velocities with -d.


Line graph connecting (aggregating) subsequent dives with real time (relative to the beginning of the first dive) on the x-axis and depth on the y-xais. See stack for how this looks when dive profiles are super-imposed instead of laid side-by-side.

Note: this also has a derivative mode for viewing descent and ascent velocities.


Also available as stacktemp, for stacked dives. This shows the temperature recorded by your dive computer, either as an aggregate or stacked.


Impulse graph with each dive's rest time (surface interval) on the positive y-axis and dive time on the negative y-axis. The recommended rest time (twice the prior dive) is also shown when at least one dive profile is in free dive mode. See restscatter for how this looks in a scatter graph.


Scatter graph with points corresponding to dive time and rest time. A line with minimum suggested free diving interval is shown (twice the dive time) if any of the dives are free dives. See rest for how this looks in an impulse graph.


Same as restscatter but with -sdate specified. Here we're looking at two dive dates coloured differently.


Scatter graph with points at the intersection of dives' maximum depth and time. See summary for how this looks in an impulse graph.


Default line graph with dives layered over one other, dive time on the x-axis, depth on the y-axis. See aggr for how this looks when dive profiles are laid side-by-side instead of stacked.

Note: this also has a derivative mode for viewing descent and ascent velocities.


Version of stack split (with the -sdate argument) for multiple days' diving.


Each independent dive is shown on the x-axis with the maximum depth and time above and below, respectively, the y-axis. See scatter for how this looks in a scatter graph.


Like summary, except dives are shown on an x-axis of their start time relative to the first dive in a grouped sequence. This example shows two dives sequences split by -sdate.


Each independent dive is shown on the x-axis with the minimum tepmerature and time above and below, respectively, the y-axis. This is shown with -a to de-linearise the temperature values so that they don't cluster.

terminal graphs

The divecmd suite also has divecmd2term(1), which formats graphs on a UNIX terminal. This is useful for a quick peek at one's dives. It was the first output mode I wrote, just to test that divecmd(1) was exporting reasonable data.

divecmd2term(1) doesn't have as many fancy modes as divecmd2grap(1), but it's still a quick and easy way to see one's dives. Especially when setting up a groff(1) pipeline takes too many characters.

Screenshot of the terminal mode. The temperature of a longer dive is shown on the top frame; depth, in the lower frame.

Three consecutive free dives in -a mode. The temperature isn't particular granular with this dive computer…

other utilities

The arguably most-used output mode is also the simplest: divecmd2json(1), which converts graphs to JSON. I use it constantly for divelog.blue, specifically to show the dive profiles. Technically, I could simply bundle the native divecmd(1) output directly and use an XML-to-JSON formatter in the client, but this is easier.

As much as I use divecmd2grap(1) and friends for my needs, others prefer using tools like Subsurface To do so, one needs to be able to export into a format used by Subsurface. The divecmd suite has divecmd2csv(1), which exports a (for the time being minimal) set of information in CSV format. This can then be imported into Subsurface using the import utility.

If you have lots of dive files and want to consolidate, you can use the divecmd2divecmd(1) utility, which is able to pull together a lot of files, de-duplicate entries, and print them out again. This tool is also able to split and join dive sequences for analysis in different ways: some dive computers export free dives as a single dive including surface time, while others don't. Sometimes you may want a single sequence (for example, when analysing with Subsurface), other times (like with the divecmd2grap(1) graphing tool) you want them separated.

Lastly, the divecmd2list(1) tool accepts a set of files, groups them by dive computer and diver, and lists their contents. This makes browsing through a lot of dives much easier!

version notes