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

divecmd is a suite of open source command-line UNIX tools to extract and manipulate dives from dive computers. Why use it 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) piped into groff(1) or LaTeX.

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

dcmd 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.

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

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

dcmd2pdf -m summary daily.xml > daily.summary.pdf dcmd2pdf -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 dcmdfind(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:

dcmdfind -ldate=today daily.xml | dcmdls dcmdfind -ldate=today daily.xml | dcmdterm

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

dcmdfind -ldate=today daily.xml | dcmd2pdf -a -m all >daily.pdf

To use divecmd, you'll need a reasonably up-to-date UNIX system (OpenBSD, Linux, Mac OSX, etc.). You'll also need the excellent libdivecomputer, which does the heavy lifting to interface with your device. Just run ./configure, sudo make install (or doas).

printable graphs

The dcmd2grap(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 dcmd2pdf(1), which manages the groff pipeline.

There are a number of graphing modes available to dcmd2grap(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 dcmdterm(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 dcmd(1) was exporting reasonable data.

dcmdterm(1) doesn't have as many fancy modes as dcmd2grap(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: dcmd2json(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 dcmd(1) output directly and use an XML-to-JSON formatter in the client, but this is easier.

As much as I use dcmd2grap(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 dcmd2csv(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 dcmdfind(1) utility, which is able to pull together a lot of files, de-duplicate entries, and print them out again. Some dive computers, like the HW OSTC 2c, put all free dives into a single dive sequence. The dcmdedit(1) lets you split those apart for analysis. (You can also merge them back together with the same tool.)

The helpful dcmdls(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!

For integration with Subsurface, I also provide dcmd2ssrf(1) and ssrf2dcmd(1), which convert into and out of the Subsurface native XML format.

version notes