Open · Transparent · Honest

How DeepSix Dive Log works.
And why it works that way.

DeepSix Dive Log isn't open source. But the problems it solves, the data formats it uses, and the principles behind its data model are documented here. No black boxes. No proprietary lock-in. No surprises when you export your data.

Open Contributions

What we've put back.

The diving software ecosystem is small. Jef Driesen has maintained libdivecomputer for years — a free, open library that lets hundreds of dive computer models talk to third-party software. Without it, none of this exists. UDDF is an open standard. The tools divers rely on are mostly built by people who dive and care.

DeepSix benefits from all of that. These are our contributions back.

⭐
Shearwater GPS Extractor
rbollar/macdive-swiftai-gps · MIT License

138 lines of Python. No dependencies. No network. No account. Reads a MacDive SQLite database, decompresses Shearwater binary records, extracts entry and exit GPS coordinates, writes them back to the dive site. Works on any Mac with Python 3.

Released before DeepSix Dive Log existed and still maintained. Early adopters of the Shearwater Swift AI transmitter use it to backfill GPS coordinates into their MacDive databases.

github.com/rbollar/macdive-swiftai-gps ↗
📐
deepsix: UDDF Schema Extensions
GPS coordinates · clock reconciliation · proposed upstream

UDDF is the open standard for dive log exchange. It doesn't have fields for entry/exit GPS pairs, clock reconciliation deltas, or photo depth metadata. Rather than inventing a proprietary format, DeepSix extends UDDF with a declared XML namespace.

These extensions are proposed for upstream adoption. Until then, any parser that understands XML namespaces can read them. Any parser that doesn't will skip them cleanly — the base UDDF record is always intact.

Schema documentation ↓
🔧
libdivecomputer Exit GPS
Shearwater Swift AI · location sample · in discussion

libdivecomputer captures entry GPS via DC_FIELD_LOCATION. There was no standard way to expose exit GPS. The Shearwater Swift AI records it in a closing record. Every app using libdivecomputer was silently discarding half the data.

We raised this with Jef Driesen, who has been maintaining libdivecomputer for years. He's already designed a better solution: reporting GPS as sample data on the first and last sample of the dive, rather than as a dedicated header field. This generalises cleanly across manufacturers — Halcyon, Divesoft, Ratio, and Shearwater all store location data differently, and the sample approach handles all of them. We're following his lead. When he pushes the implementation, we'll test against it with a corpus of real Swift AI dives.

📸
DeepSix Photo Sidecar Spec IN DEVELOPMENT
Underwater photo metadata standard · in development

Underwater photos contain metadata no existing standard captures: depth at the moment of the shot, GPS interpolated from dive track, position on the dive profile, species identifications. We're documenting a sidecar format that any dive app could read.

Not finished. Not submitted anywhere yet. Published here for comment.

The Shearwater Exit GPS Problem

The data was there.
Every app threw it away.

The Shearwater Swift AI GPS transmitter locks a fix before you descend and again when you surface. Those coordinates are stored in the compressed binary memory of your dive computer. Both of them. Every dive.

libdivecomputer — the open library that powers dive computer communication in Subsurface, MacDive, and most other apps — captures entry GPS via DC_FIELD_LOCATION. Exit GPS had no standard field. The exit coordinate was read, decoded, and discarded.

Until late 2025, exit GPS had no standard field in libdivecomputer. The Shearwater Swift AI binary protocol stores it, but the dedicated DC_FIELD_LOCATION API only exposed entry GPS. Apps built on libdivecomputer — including some of the best dive logs on Mac and Linux — didn't have a path to surface exit coordinates.

Shearwater binary record format (compressed, LRE+XOR):
Opening Record 9  (0x19) → entry GPS
  offset 0x00: latitude  (int32, degrees × 100,000)
  offset 0x04: longitude (int32, degrees × 100,000)

Closing Record 9  (0x29) → exit GPS
  offset 0x00: latitude  (int32, degrees × 100,000)
  offset 0x04: longitude (int32, degrees × 100,000)

Precision: ±1.1 meters
Condition: aimode == 6 (AI_ON_GPS)

DeepSix Dive Log extracts both records on every BLE import via a Shearwater-specific code path that runs alongside libdivecomputer's generic parser. For historical dives in MacDive databases, the open-source Python script does the same extraction from the stored binary blobs. We raised the gap with Jef Driesen, who has designed a more general solution: reporting GPS as sample data on the first and last sample of a dive, which generalises across Halcyon, Divesoft, Ratio, and Shearwater. When his implementation lands, we'll test against it with a corpus of real Swift AI dives.

Data Immutability

Your dive computer recorded something.
We don't change it.

The raw data from your dive computer is a recording of what happened. It's not a draft. It doesn't need to be "corrected" — it needs to be interpreted correctly.

DeepSix never overwrites raw dive computer data. Every adjustment — time corrections, GPS assignments, clock offsets, depth calibrations — is stored as a separate delta and applied at display time. The original record is always intact.

This matters for one specific reason: you might want to reinterpret the data in 2030 with better algorithms, better maps, or information you didn't have at import time. If we'd overwritten the original, that's gone. If we stored the delta, you can throw it away and start over.

Raw data is immutable
The binary blob from your dive computer is stored exactly as received. Depth samples, temperature, gas mixes, CNS values — unmodified. The display layer transforms; the storage layer doesn't.
Corrections are deltas
Your camera clock was 133 seconds fast. That's stored as camera-offset-s="-133" — not applied to every photo timestamp. When you decide the offset was actually -127 seconds, you change one number. Every photo moves. Nothing was destroyed.
Display authority hierarchy
When multiple sources disagree on a value, DeepSix applies a priority order rather than picking one arbitrarily:
  1. Apple Watch (GPS-synced clock)
  2. GPS-tagged photo EXIF
  3. Explicit user correction
  4. Dive computer clock
  5. Computer-relative timestamps
The source of every displayed value is trackable. Nothing is silently resolved.
Backup & Transfer

Your whole log,
in a file you hold.

Backup & Transfer, in Settings, writes a complete, lossless .deepsixarchive — every dive, site, trip, photo link, raw dive-computer blob, correction delta, and identification — and restores it on any device. The screen shows when the last backup was taken and warns, in orange, when a device has no cloud copy at all. Moving to a new phone or Mac is three steps: back up, restore, done.

iCloud sync itself is optional. The Sync Mode switch puts a device in local-only mode, with no CloudKit traffic until you turn it back on — the right answer for a diver who wants nothing in any cloud, or for keeping an ailing sync out of the way while you sort it out. UDDF and Subsurface export stay free and unconditional either way.

Time Reconciliation

Three clocks.
None of them agreed.

Your dive computer runs on its own clock, set manually, drifting slightly over time. Your camera has a clock you set once when you bought it and haven't touched since. Your phone is GPS-synced and accurate to the millisecond.

When you match a photo to a dive, you're asking which timestamp to trust. The answer isn't obvious.

DeepSix measures the offset between clocks rather than picking a winner. You identify one reference point — a photo taken at a known moment — and the system calculates the offset between your camera clock and the dive computer clock. That offset applies to every photo from every camera you've ever used with that dive computer, until you tell it otherwise.

Clock reconciliation:
Apple Watch time (GPS-synced):       14:32:07.000
Dive computer entry time:            14:31:20.000
Observed offset:                     +47 seconds

Camera EXIF time (first photo):      14:33:15.000
Known moment (dive entry on watch):  14:32:07.000
Camera offset:                       -68 seconds

All camera timestamps shift by -68s.
Dive computer timestamps shift by +47s.
Photos match to profile with sub-minute precision.

Photos already matched to another dive show orange conflict badges when you scan a new one — the system tracks what it's already claimed and won't silently steal a photo from one dive to assign it to another.

The reconciled offsets are stored in the deepsix: UDDF namespace and exported with your dive log. If you move to a different app, the work isn't lost.

External Data Sources

What your dive log
should already know.

A dive log is a set of coordinates and a timestamp. Everything else — the reef health, the species, the wreck history, the current weather — has to come from somewhere. These are the sources DeepSix uses, why each one was chosen, and what it contributes.

SOURCE WHAT IT PROVIDES WHY THIS ONE
NOAA Coral Reef Watch ERDDAP Bleaching alert level, degree heating weeks, SST anomaly at dive date Only authoritative global bleaching dataset. Time-specific — records the alert level at the time of your dive, not just current.
Allen Coral Atlas Reef geomorphic zone, benthic habitat, MultiPolygon boundaries 5m resolution. The entry GPS puts you on the correct zone — back reef, fore reef, lagoon — not the nearest named location.
Marine Regions Gazetteer Ecoregion name, EEZ, MRGID identifier Structured marine geography. "Coral Sea" instead of coordinates. Persistent identifiers that don't change when place names do.
Wikidata SPARQL + Wikipedia REST Wreck vessel history, tonnage, sinking date, war grave status Structured wreck data from Wikidata, readable summaries from Wikipedia. Falls back to keyword detection on site name when no match.
Cloud AI — Anthropic or OpenAI (your key) Marine life identification, reef narrative, wreck narrative, travelogue Requires image input for critter ID. A local vision model you run yourself (Ollama, LM Studio, MLX) can take the pre-identification role. BYOK only — no credits, no markup.
Open-Meteo Historical weather and marine conditions at dive date/location Free, no API key, offline-capable for historical queries. Records surface conditions at the time of the dive.

All network calls are guarded by a connectivity monitor. Every feature that depends on external data degrades gracefully when offline — which is most of the time, for most divers, at most dive sites. The dive log works without a network connection. The enrichment happens when one is available.

A note on AI

DeepSix uses your configured AI provider — Anthropic, OpenAI, or a model on your own hardware — for tasks that require reasoning about images or generating readable prose. It is not used for data storage, user profiling, or any purpose beyond the specific task you invoke it for. The critter ID pipeline sends a photo and a species candidate list. The narrative pipeline sends dive metadata. That's the extent of it.

If you don't want to use AI features, they're off by default and nothing breaks.

Schema Reference

deepsix: namespace extensions

These XML elements extend standard UDDF records. The namespace declaration is required. Elements are designed to degrade cleanly — a UDDF parser that doesn't recognize the namespace skips them without error.

Namespace URI: https://deepsixdive.com/ns/uddf/1.0

<?xml version="1.0" encoding="UTF-8"?>
<uddf version="3.2.2"
  xmlns="http://www.streit.cc/uddf/3.2/"
  xmlns:deepsix="https://deepsixdive.com/ns/uddf/1.0">

  <dive ref="dive247">

    <!-- GPS coordinates from Shearwater Swift AI transmitter.
         source: shearwater-swift | photo-exif | user | estimated
         Both entry and exit stored. Entry used for all geo lookups.
         Exit used for drift calculation and photo interpolation. -->
    <deepsix:gps
      entry-lat="-23.4521"
      entry-lon="152.0834"
      exit-lat="-23.4489"
      exit-lon="152.0851"
      source="shearwater-swift"
    />

    <!-- Clock offsets relative to GPS-synced reference (Apple Watch).
         authority: apple-watch | gps-photo | user | dive-computer
         computer-offset-s: dive computer clock ahead of true time
         camera-offset-s: camera clock ahead of true time
         Positive = source clock is ahead. Negative = behind.
         Applied at display time. Raw timestamps never modified. -->
    <deepsix:clock-reconciliation
      authority="apple-watch"
      computer-offset-s="47"
      camera-offset-s="-133"
    />

    <!-- Per-photo metadata. One element per matched photo.
         local-identifier: PHAsset localIdentifier (Photos.app)
         depth-m: interpolated from dive profile at photo timestamp
         minutes-into-dive: position on profile timeline
         interpolated-lat/lon: GPS interpolated from entry/exit track
         context: underwater | surface -->
    <deepsix:photo
      local-identifier="AE7F2C19-4B8A-..."
      depth-m="11.5"
      minutes-into-dive="41.53"
      interpolated-lat="-23.4512"
      interpolated-lon="152.0844"
      context="underwater"
    />

    <!-- Reef context snapshot at dive date.
         bleaching-alert: NOAA CRW alert level (0–4) at dive date
         dhw: degree heating weeks at dive date
         ecoregion: Marine Regions Gazetteer name
         mrgid: Marine Regions persistent identifier
         aca-zone: Allen Coral Atlas geomorphic zone
         aca-habitat: Allen Coral Atlas benthic class -->
    <deepsix:reef
      bleaching-alert="1"
      dhw="4.2"
      ecoregion="Coral Sea"
      mrgid="21917"
      aca-zone="Outer Reef Flat"
      aca-habitat="Coral/Algae"
    />

  </dive>

</uddf>

The deepsix: elements are always written alongside standard UDDF fields — depth, duration, temperature, gas mixes, and all other data appear in the base record as per the UDDF 3.2.2 specification. The extensions add what the standard doesn't cover. They don't replace anything.

UDDF export, including all deepsix: extensions, is always free.

Questions about the data model or schemas? Discord or [email protected]