Divedex
Identify and profile any aquatic organism — saltwater or freshwater — from a name, a description, or a photo. Resolves the correct accepted scientific name and taxonomy, maps where it's found (range, depth, habitat), explains ID features / diet / behavior / lookalikes, pulls a license-clean reference photo (or uses the diver's own), and builds a printable species card. Built for the "what did I just see on that dive?" question. Nudibranchs get a dedicated specialist path. Triggers: "/divedex", "เจอตัวนี้ตอนดำน้ำ", "ตัวนี้คืออะไร", "นี่ทากอะไร", "what is this critter", "ID this nudibranch", "เจอได้ที่ไหน", "ชื่อวิทยาศาสตร์", "found this diving", "ปลาอะไร", "มีในไทยไหม", "identify sea slug / fish / coral / shrimp".From its SKILL.md
npx -y skills add killernay/DiveDEX --skill divedexAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
18.6 KB, ~4.5k tokens by cl100k_base, as published. Nobody here has run it
DiveDex
The dive-buddy reference. You surface, you saw something, you want the real answer — not a confident guess. This skill turns "ตัวอะไรวะ" into a clean species card backed by authoritative registers.
Core principle
AI proposes, the register confirms. Never assert taxonomy, distribution, or a locality record from memory. A name recalled from training is a lead to verify, not an answer — the
Tapania → Trapania scurracase is the standing reminder.But the register only confirms the name exists — never that it's your animal. A photo ID passes the register whether it's right or wrong; recall a famous species, look it up, and the register says "yes, real name." That check is nomenclature, not identification. The
Plakobranchus → Costasiellacase is the standing reminder here.
Four rules that never bend:
- Resolve to the accepted name + authority, not the first name you recall. Synonyms, misspellings, and "sp." placeholders all get run through the register.
- Every claim is sourced. Range, depth, diet, and any locality claim come from WoRMS / FishBase / GBIF / OBIS / iNaturalist, never asserted.
- Uncertainty is stated, not hidden. If a photo ID is only genus-level or has lookalikes, say so and list the confusion species — a wrong species ID is worse than an honest "genus X, one of these three."
- A photo ID is never committed on a name lookup alone. Find the nearest lookalike and the feature that separates it, check that feature in the photo, and — when it's the user's own animal — let them confirm it. See Phase 1's discriminator check.
When to use / not use
Use when the user wants to identify, name, locate, or understand any aquatic organism — reef fish, nudibranch, coral, shrimp, crab, echinoderm, or a freshwater fish/invert from a river, lake, or paddy — seen while diving, snorkeling, fishing, or in a photo.
Not for aquarium husbandry advice, dive-site logistics (that's a trip-planning job), or medical/first-aid on stings & bites (hand off; this skill IDs the animal, it doesn't treat the injury).
Input modes
| Input | What happens |
|---|---|
| A name (even misspelled) | Straight to Phase 1. Tapania → check Trapania. |
| A description ("purple slug, blue horns, Tulamben, 18 m") | Phase 1 builds candidates from features + locality, then verifies each in the register. Expect genus-level confidence — that's fine, say so. |
| An attached photo | Read the visible features off the photo, then treat as a description (above). The candidate must survive the discriminator check and the confirm gate before it becomes a species. The user's photo is the card photo — see Phase 4. |
A photo plus a locality is the strongest input. A photo alone is often genus-only; don't inflate it to a species to look helpful.
Output language
Default: English. Not a preference — English is simply cheaper in tokens, and the user pays for their own. Scientific names are Latin regardless.
The user can ask for any language, any time, and it applies to the whole card:
/divedex Trapania scurra — ตอบเป็นภาษาไทย · … in Japanese · … auf Deutsch.
Honor it for the prose fields (Look for / Field notes / Lookalikes) and the labels.
Keep the accepted name, authority, and AphiaID untranslated — those are identifiers.
How to run it
Four phases. The inline path is the baseline and works in every harness — run the phases in order, in one context, and build the same card. If your harness supports subagents, phases 2–4 run in parallel instead; that's a speed win, not a different result.
The gate
Phase 1 runs first, alone. Phases 2–4 all key off the accepted name, so nothing starts until it lands (or is explicitly left at genus level). When the input was a photo or a description, the gate also includes the confirm step — the card is not built on an unconfirmed guess.
Then
Phases 2, 3, 4 are independent. Inline: run them in order. With subagents:
dispatch divedex-location, divedex-detail, divedex-images in one parallel round.
Then merge + build
You (the orchestrator) collect the return blocks, fill assets/species-card.html,
and run assets/build_card.py.
Subagents (Claude Code / Cowork). agents/ holds four agent definitions
with locked-down toolsets — the research agents get only WebSearch, WebFetch so they
cannot guess, only look up; the images agent also gets Bash to curl the photo.
Copy agents/divedex-*.md into .claude/agents/ (project) or ~/.claude/agents/
(user-wide) for auto-discovery. Other harnesses: use the inline path — same output.
One level of nesting. A subagent can't spawn a subagent. You dispatch and merge; the four agents are leaves. That's exactly one level, which is allowed.
Phase 1 — Taxonomy (the gate)
Resolve the raw input to the accepted name.
- Route by water first — it decides the register:
- Marine → WoRMS (
marinespecies.org). Molluscs → MolluscaBase. Fish → cross-check FishBase. - Freshwater → FishBase for fish (it covers freshwater), Eschmeyer's Catalog of Fishes for contested fish names, GBIF backbone for non-fish. WoRMS is marine-only — a freshwater species legitimately has no WoRMS record. Its absence is not evidence of a bad name.
- Brackish / unsure (gobies, archerfish, scats, mangrove species) → check both; say which register the accepted name came from.
- Marine → WoRMS (
- Normalize the string; check it as written and as the nearest real genus
(
Tapania→Trapania). Note any correction; don't accept a spelling silently. - Read the
acceptedvsunaccepted/synonymstatus; if a synonym, follow it to the accepted name and report both. - Capture Author, Year and the AphiaID (marine) or the FishBase/GBIF key (freshwater). Build the chain Phylum > Class > Order > Family > Genus.
- Grab the common name if the register carries one — many nudibranchs have none, and "—" is the honest answer. Don't invent a friendly name.
- Never invent an AphiaID or author string — flag "unverified" and pass it on.
The discriminator check — mandatory when the input is a photo or a description.
A register hit proves the name is real. It does not look at the photo. So before a
species name is committed, name the nearest lookalike(s) and the single feature that
separates them, then score that feature against the actual animal:
matches / conflicts / not visible.
- Look the separating feature up. Never recall it. Rule 2 (
every claim is sourced) governs the ruler, not just the measurement. A trait pulled from memory is the same failure as a name pulled from memory, one layer deeper — it feels like verification while scoring the photo against something half-remembered, and a trait remembered backwards makes the check confidently kill the right answer. Quote it from the register, the description paper, or Sea Slug Forum. - One
conflictskills the candidate — however good the colour match is. not visibleis not a pass. Discriminator unreadable → genus-only + confusion set.- A photo can't be re-interrogated; the diver can. Anything the frame doesn't carry (size, host, behaviour, depth) is a question for the confirm gate, not a guess.
- Check body plan, then host/substrate, then size — all before colour. Colour convergence is the entire trap: Plakobranchus ocellatus (40–60 mm, dorsum is one fused parapodial flap, sits on sand/rubble) and Costasiella sp. (5–10 mm, dorsum is rows of discrete swollen cerata, lives on its algal host, e.g. Avrainvillea) are both green with blue ocelli, and the register cheerfully confirms either name.
- Prefer discriminators the photo can actually settle. Body plan and host are read
straight off the frame; size usually is not — a photo rarely carries a ruler, and
"small next to the blade" is a guess, not a measurement. An unrulered size impression
is
not visible, nevermatches. Ask the diver for size at the confirm gate instead of eyeballing it (they know how big it was; the photo doesn't). what the register says it eatsis a discriminator. An obligate host pins the substrate, so a wrong-substrate candidate is a killed candidate.- This is Phase 3's lookalike work pulled in front of the gate. Phase 3 still writes the list for the card; Phase 1 uses it to decide whether the species name is earned at all. Running it after the gate is how a wrong name gets a beautiful card built on it.
Confidence is earned, not declared. It is a verdict on evidence, never a feeling:
| Level | Earned when |
|---|---|
| species | Register-accepted and every discriminator against the nearest lookalikes scores matches. From a photo alone this is rare — if you land here easily, you skipped a lookalike. |
| genus-only | Genus features clear; species discriminator not visible, unresolvable, or needs radula / dissection / DNA. Carry the shortlist. This is the honest default for a photo. |
| needs-photo | Description too thin to place even the genus. Ask for a photo. |
Nothing downstream runs until Phase 1 lands (or is explicitly left at genus level).
The confirm gate — photo / description input only
If the ID came off a photo or a description, you ask. Every time — including when you
feel certain. Confidence is not an exemption; a confident wrong species is the exact
failure this gate exists to catch, and the moment you feel sure is the moment nothing
else is checking you. Only a plain name lookup (/divedex Trapania scurra) skips it —
don't nag someone who already told you the name.
What you ask scales with what's at stake, but you always surface the deciding feature:
- species — one-line check, not an interrogation: "Called it on the ear-like rhinophores and separate cerata — that match your animal?" Cheap to answer, and it catches the confident miss.
- genus-only — the real question below: give them the branch and let them decide.
Ask about what they can check on their own animal. Never "is this X?" beside a reference photo: they came here because they don't know the name, and a plausible green blob gets a false yes. Names are yours to resolve; features are theirs to confirm.
Best fit is Costasiella sp. Two things on your animal decide it: Size — grain-of-rice tiny (5–10 mm), or finger-length (40–60 mm)? Its back — separate lobes you could count one by one, or one continuous flap? Tiny + countable lobes fits Costasiella. Big + one flap is a different animal entirely, and I'd start over rather than force this one.
- Features, not names. The diver knows what they saw, not the Latin.
- Two questions max — only the ones that actually decide it. Don't interrogate.
- Never hang a species on the answer alone. The reply narrows or kills a candidate; it doesn't promote one. "Tiny" earns a genus, not a species name.
- "Not sure" is a valid answer and never costs the user anything. Ship the widest level the evidence does support — genus if the genus held, family + shortlist if the unanswered question was the genus question. Never push someone into a species they didn't actually see.
- No user to ask (batch, automated, no reply)? Default to genus-only. Silence is not confirmation.
Phase 2 — Location
On the resolved name: range + type locality (from the register / the description paper), depth band (m), habitat/substrate/host, and notable verified sightings.
- Occurrence: OBIS is marine-only — for freshwater use GBIF and iNaturalist (research-grade only).
- Set the 🇹🇭 Thailand status badge from ACTUAL records:
Recorded(green — confirmed Thai observation, cite it) /Likely(grey — range & habitat fit, adjacent-country records, none confirmed in Thai waters) /No record(dashed — not yet recorded; a solid Thai photo would be a notable new record). Never markRecordedwithout a real Thai observation — an honestNo recordis the whole point of the badge. - Thailand is the default home water because that's who this was built for. If the user asks for another country, swap the badge to theirs and apply the identical rule.
Phase 3 — Detail
On the resolved name (or genus + shortlist): the 3–5 diagnostic ID features in the order a diver checks them, max size, diet/host (which is where to point the torch for specialist feeders), behavior/ecology, a spot-difficulty rating (1–5, how hard it is to actually find underwater), and the lookalike list with the single feature that separates each. If two species can't be split from a photo (needs radula / dissection), say so plainly.
Phase 4 — Images
Two branches:
- The user attached their own photo → that is the card photo. Use their local file
path, credit it
© <user> · own photo · <site, date>(ask only if the credit line matters to them). Skip the CC hunt — no point downloading a stranger's slug when the diver has their own. Optionally still fetch a reference shot if their photo is poor or the ID is genus-only, and label it clearly as a reference, not their animal. - No user photo → search on the accepted scientific name (not common name). Use a
creditable, license-clean source — prefer Creative Commons (iNaturalist open-data,
Wikimedia Commons) or the register/description-paper image; never a random copyrighted
Google result. Download the chosen photo to a local file (don't hotlink — the card
must work offline) and record the credit line
© Photographer · LICENCE · Source.
Prefer in-situ shots of the living animal. If confidence is genus-only or lookalikes exist, also grab the top confusion species, clearly labelled. Never present a lookalike as the target. If no license-clean image exists, ship the card with no photo and say so — an empty frame beats a stolen one.
Routing: is it a nudibranch?
If the organism is (or might be) a sea slug / nudibranch, load references/nudibranch.md before Phase 1. Nudibranch ID has its own trap — thousands of near-identical species, many undescribed "sp." animals, IDs hinging on rhinophore/gill/papillae/cerata detail plus diet — and its own authoritative sources that beat a generic search.
Everything else (fish, coral, crustacean, echinoderm, freshwater) uses the general sources in references/sources.md.
Data sources — don't reinvent
Full per-taxon source list and query order: references/sources.md. Short version: WoRMS is the accepted-name backbone for marine life; FishBase for fish (marine and freshwater); Eschmeyer's Catalog of Fishes for contested fish names; MolluscaBase + the sea-slug trio for nudibranchs; GBIF for freshwater and everything else; OBIS (marine) / GBIF / iNaturalist for "where actually seen." Gather from these; never fabricate a range or a record. If sources disagree, surface the conflict rather than picking silently.
Default output — a shareable species card
The deliverable is a self-contained species card styled like a printed dive field guide — image embedded, so it works offline and survives being forwarded around. Build it:
-
Fill the
{{PLACEHOLDERS}}in assets/species-card.html (documented at the top of that file) with the resolved data from Phases 1–3. The "Where to find" chips are labels, not a fixed menu — swap them to match the Phase-1WATERand the Phase-2HABITAT(marine: Sponge/Muck/Reef/Drop-off/Seagrass · freshwater: River/Stream/Lake/Paddy/Blackwater · brackish: Mangrove/Estuary/Tidal creek). Leaving marine chips on a freshwater card is a bug. -
Put the Phase-4 photo in
{{PHOTO_URL}}as a local file path and set{{PHOTO_CREDIT}}— the user's own photo, or a license-clean one (CC / Wikimedia / register), never a copyrighted one. The build step embeds it as base64 so nothing is hotlinked. -
Run
python assets/build_card.py <filled-card.html> <photo.jpg> <out.png>— it embeds the image and renders with headless Chromium (preserving grid + web fonts). The output format follows the extension:.png/.jpg→ the default. A retina card image — what people actually send to their dive buddies on LINE/WhatsApp and read on a phone..pdf→ one card on a single A4 page, for printing a physical field-guide card.
Needs
pip install playwright && playwright install chromium(see assets/requirements.txt).
Fields carried: accepted name + authority + confidence tag, common/local name (optional),
taxon tag + 🇹🇭 Thailand status badge (Recorded / Likely / No record, from real records
only), embedded photo + credit, Size · Depth · Spot-difficulty pips · habitat chips,
Look for (diagnostic features in check-order), Field notes (<mark> key terms),
Lookalikes, and a Sources footer. Only include a field the user asked for or that
the register supports — don't add unrequested sections.
When the ID is only genus-level, say so in the tag and let Lookalikes carry the shortlist — an honest genus beats a wrong species.
Fallbacks. No Chromium / no Python? The filled HTML renders on screen — screenshot it, or print to PDF from any browser; the card is designed for both. No HTML wanted? The same fields collapse to a plain-text card in the order above. The data is the deliverable; the image is a convenience.
What ships with it: 10 files
118.6 KB alongside SKILL.md, 1 of them executable
agents/
- divedex-detail.md2.2 KB
- divedex-images.md2.1 KB
- divedex-location.md2.0 KB
- divedex-taxonomy.md5.2 KB
assets/
- build_card.pyruns5.0 KB
- requirements.txt556 B
- species-card.html12.6 KB
- trapania_scurra_picton_ccby.jpg80.5 KB
references/
- nudibranch.md3.5 KB
- sources.md5.0 KB