The Command Line
Tidemark ships one command, tidemark, and on a machine set up as From a Fresh Clone describes, every operation a reader reproduces runs through one of its subcommands. This page names each subcommand, says what it does, and sets out what each of its options accepts.
Running a Subcommand
A subcommand a reader types runs through .mise/bin/tidemark, a script mise puts on the path. The script passes it to uv run --exact --locked, so the environment is built from uv.lock before anything runs:
bash
tidemark catalogEach subcommand that reaches a service, rebuilds a table the package ships, or clears what a fetch wrote also runs through a task, which The Tasks names. The other pages name that task, because a task runs the command from the repository root whatever directory you are standing in.
--help and --version describe the interface without running any of it.
| Invocation | What It Reports |
|---|---|
tidemark --help | Every subcommand, one line each |
tidemark catalog --help | One subcommand alone, with each option it takes |
tidemark --version | The installed version |
In the panel below, a reader completes each subcommand as a sentence, and where a blank takes a gauge, each row names it as the station catalog does, from the NERACOOS ERDDAP12 and NOAA CO-OPS3.
each step’s kept result against a run computing it again, leaving the cache as it stands.
the station catalog against the services that publish the gauge metadata, writing nothing.
Print the footnote citing .
Empty data/ of everything but the stakeholder’s files and the record of each run.
Print how many times GitHub has served the AVISO tar each release carries.
the pass the heights page draws against the samples the fetch kept, writing nothing.
Fetch OpenStreetMap coastline osmdata derives, cut to the box around every gauge, replacing the cut held.
Fetch of again.
Fetch the GEOID18 grid NGS publishes, as PROJ’s CDN serves it, into data/geoid/.
Fetch GNSS station velocities the Nevada Geodetic Laboratory publishes, replacing the table held.
Fetch every SWOT pass at within reach of a gauge, sending requests at once.
AVISO+, writing nothing.
NASA Earthdata.
USGS, writing nothing.
Pack each source’s files under data/ into the tar a release carries for it.
Play in the browser, building it.
Compute , comparing each gauge with the SWOT samples within meters of it, both converted to .
the pass schedule against the passes the fetch kept, writing nothing.
bash
tidemark login earthdatatask
mise run data:login:earthdataEvery Subcommand
Each section below is written from the subcommand's own docstring, whose summary and options cyclopts, the library the command is built on, also prints as its --help, so a reworded option or example reaches this page through mise run docs:render. A page of its own describes in full what each of these subcommands reads and writes:
tidemark catalogin Inside the Station Catalogtidemark fetch gaugesin The Gauge Seriestidemark fetch swotin The Satellite Passestidemark login aviso,tidemark login earthdata, andtidemark login usgsin From a Fresh Clonetidemark runin The Analysis Graphtidemark schedulein The Pass Schedule
tidemark cache
Lists the file under .cache/hamilton/ holding each step's kept result, beside computed where the most recent run computed it and kept where that run left it as kept.
console
tidemark cache [OPTIONS]| Option | Accepts | Left Out | Meaning |
|---|---|---|---|
--check | No value | Off | Computes every kept step again with no result read back, prints one line for each step whose result differs from the one kept under the same key, and exits 1 where any does |
--verbose | No value | Off | Print the log lines the analysis steps write to standard error |
Name the file holding each step's kept result, beside whether the most recent run computed it:
bash
tidemark cacheCompute every kept step again and compare each result with the one the cache keeps:
bash
tidemark cache --checktidemark catalog
Rebuilds the station catalog from the NERACOOS ERDDAP, the NOAA CO-OPS metadata API, and the USGS Water Data API.
A NOAA station whose datum table lists no NAVD 88 takes its NAVD 88 offset from its CO-OPS bench mark sheet, NGS's Data Explorer, and NOAA's VDatum, and a USGS gauge whose gage datum no survey set takes the altitude USGS records for it.
A rebuild and a check both refuse a shipped table that fails the schema the package declares, printing the fault and exiting 1.
A rebuild prints a notice line for each thing it could not read or settle, naming the gauge, or the column the table lost, beside the reason, such as a datum other than NAVD 88, or a gauge left out of the table because its dataset id opens on a prefix no vendor is declared under. It closes on the folder it wrote beside the time the command took, over a ledger naming the table, how many stations it holds, and how many each service supplied.
A rebuild records each service's answers under data/gauges/catalog/ and writes the answers it recorded and the release they ship in to parts.json beside the schedule's and the example pass's. It stops first where that release is already published, naming the mise run bump moving past it, as tidemark schedule does.
console
tidemark catalog [OPTIONS]| Option | Accepts | Left Out | Meaning |
|---|---|---|---|
--check | No value | Off | Rebuilds the table from the answers parts.json records without writing anything, seeding any it lacks from the release parts.json names, asking no service and carrying each low-cost gauge's sensor type from the shipped table. It prints every station that rebuild adds, drops, or changes, with each gauge it left out of the table among the added, and exits 1 where anything differs or an answer is missing |
Rebuild the table the package ships from the services that publish the gauge metadata:
bash
mise run data:catalogRebuild it from the answers the last rebuild recorded, writing nothing:
bash
mise run data:catalog -- --checktidemark cite
Prints the footnote definition citing each study or data product named by its key in docs/references.bib, in the form .github/CONTRIBUTING.md → Citing a Study sets out for its kind. Each definition sits on one line with a blank line between two of them, ready to paste beneath the text that cites it.
Prints a failure line for each key no entry in the file holds, and exits 1 without printing any definition, as it does when neither a key nor --check is given.
console
tidemark cite [OPTIONS] [ARGS...]| Option | Accepts | Left Out | Meaning |
|---|---|---|---|
KEYS | Text, any number of times | Optional | The key of each entry to cite, such as lichtman2025, or to check under --check |
--check | No value | Off | Asks the DOI resolver for the citation of each entry carrying a DOI, every one or those named, prints each field an entry reads differently and each DOI the resolver refuses, and exits 1 where anything differs |
Print the definition of each of two studies for a pull request or an issue, since a page takes its own from mise run docs:render:
bash
mise run docs:cite -- lichtman2025 hay2025Hold every entry carrying a DOI to the citation the DOI resolver answers:
bash
mise run docs:cite -- --checktidemark clean
Removes every entry under data/ except data/provided/, which holds the stakeholder's files, data/runs/, which holds the record of each run, and .gitkeep, which keeps the directory in git.
console
tidemark cleanIt takes no options.
Empty data/ of everything but the files the stakeholder shared by hand and the record of each run, which the task asks to confirm first:
bash
mise run data:cleantidemark downloads
Prints how many times GitHub has served the tar of AVISO's Level 3 Unsmoothed product each published release carries, one row per release, newest first, through gh, writing nothing. A tar a release carries in pieces counts as its most served piece, and a release carrying no such tar prints no row.
console
tidemark downloadsIt takes no options.
Print the record of each release's Level 3 tar:
bash
mise run data:downloadstidemark excerpt
Copies the samples within 10 km of the Bar Harbor gauge on pass 520 of cycle 11, the Level 2 Unsmoothed pass the methods page draws, out of the samples table into the package, once it has brought the table up to date with the passes tidemark fetch swot kept, on every processor core at once.
A copy closes on the folder it wrote beside the time the command took, over a ledger naming the file and how many samples it holds. Where the fetch kept no sample of that pass, it prints a failure line saying so and exits 1 without writing anything.
A copy also records in the parts.json beside the tables the part of the pass it copied and the Expert part its samples take their corrections from, each by name beside its SHA-256 and the manifest.json of the directory holding it, and the version of the package as the release whose tars carry those parts.
Where the repository has already published the release of that version, a copy prints a failure line naming that release and the one the next open milestone ships, beside the mise run bump moving the package to it, and exits 1 before copying anything, since the tars of a published release carry no part read after it. Where gh cannot list the milestones or none open ships a later release, the line names the next open milestone in place of its release. Where gh cannot list the releases, it prints a notice saying so and goes on.
console
tidemark excerpt [OPTIONS]| Option | Accepts | Left Out | Meaning |
|---|---|---|---|
--check | No value | Off | Copies the pass without writing it, prints a line where the copy differs from the one the package ships, and exits 1 where it does. Where the store lacks a part parts.json records for the pass or holds it under another SHA-256, it prints a failure line naming each such part and exits 1 before copying anything. Where the release parts.json records for the pass has published and the record its tag holds names other parts, it prints a failure line naming that release and exits 1 before copying anything, so the check mise run gha:attach runs fails before the release rolls rather than after it |
--verbose | No value | Off | Print the log lines the analysis steps write to standard error |
Copy the pass once a fetch of the Level 2 Unsmoothed file has kept it:
bash
mise run data:excerptCompare a copy with the one the package ships without writing anything:
bash
mise run data:excerpt -- --checktidemark fetch coast
Fetches the OpenStreetMap coastline osmdata derives into data/coast/, cut to the box around every gauge, which each SWOT sample's distance to the coast is measured from.
The box holds every point within twice the reach a SWOT fetch keeps samples within, so the nearest point of the coastline to any sample it keeps lies inside it.
osmdata rebuilds the coastline every day, so a fetch keeps the cut data/coast/ holds and records the day of the OpenStreetMap data it was derived from, downloading the newest only under --refresh. A refresh keeps the cut when osmdata's data has not changed since. Where the directory holds no cut and --refresh is not set, it first seeds the cut from the newest release the repository has published that carries it, as tidemark fetch geoid seeds the grid, and downloads it only where the seed takes none. The download, which osmdata's mirror at www.osmdata.org serves, is the whole world's coastline, about a gigabyte, of which nothing but the cut is kept.
Closes on Fetched or Kept beside the folder holding the cut, over a ledger naming the cut's file, its points, and the day of the data it was derived from, and exits 1 when osmdata's mirror refuses the request.
console
tidemark fetch coast [OPTIONS]| Option | Accepts | Left Out | Meaning |
|---|---|---|---|
--refresh | No value | Off | Download the newest coastline again, replacing the cut held, or keep the cut when osmdata's data has not changed since |
Fetch the coastline where none is held:
bash
mise run data:fetch:coastPass --refresh after -- to replace the cut with osmdata's newest:
bash
mise run data:fetch:coast -- --refreshtidemark fetch gauges
Fetches each gauge's water level series into data/gauges/, from its first reading to now, every NOAA station's from NOAA's CO-OPS Data API, every USGS gauge's from the USGS Water Data API, and every other gauge's from the NERACOOS ERDDAP, every gauge at once.
For a gauge fetched from the ERDDAP already holding part of its series, it compares the ERDDAP's tally of each month, and then of each day from the first month that differs on, with the readings it holds, fetches only the days that differ, and joins the files those fetches leave into one once they span 30 days or number 30. Under --refresh, it compares the same tallies and then fetches the whole series again.
Except under --refresh, it first reads through gh, with whichever login gh holds, the newest release the repository has published that carries the tar of the NOAA stations, and where a NOAA station holds no month, records another request, or is one NOAA still operates whose newest reading falls before the release was published, downloads that tar, checks it against the SHA-256 digest GitHub lists for it, and moves each month a station lacks into place. It prints a line naming how many months it seeded and the release they came from, beside how long ago it was published, or a notice naming why it seeded none, as where gh holds no login reading the private repository or the release carries no such tar, and goes on to fetch. It seeds each USGS gauge holding no range or recording another request the same way, from the tar of the USGS gauges, once it has read the gauge's monitoring location.
Where a NOAA station still holds no month, records another request, or is still operated with its newest reading more than a week old, or under --refresh, it then prints a notice naming how many months it fetches from NOAA and about how long they take. Each NOAA station is fetched a calendar month at a time, every month of every station at once, asking for each month the inventory lists that the station lacks, that falls past its newest reading, that NOAA has verified or revised since it was fetched, or, at a station NOAA still operates, that is still preliminary, and keeping each station's months oldest first, whatever order they land in. A request any service refuses as too many, as busy, or by dropping the connection, the CO-OPS throttle's 403 among them but not a USGS 429, is sent again once its host reopens, every request to that host held back while it is closed and fewer taken at once after each refusal. A terminal shows a bar counting the gauges fetched beside one counting the NOAA months while any is fetched. A NOAA station's months hold its elevation above its station datum as stnd_meters, which the series reads on NAVD 88, at Bar Harbor through the NAVD 88 offset the station catalog measures from mean lower low water, beside sigma_meters, the four coops_ flags, and verified, which a USGS gauge also fills and every other gauge leaves empty.
Each USGS gauge's series is read from its monitoring location's gage height, parameter 00065, in windows of at most 1,100 days across its whole record on the first fetch, every window at once, and on a rerun as every reading USGS modified since the newest modification the gauge holds, which covers the readings published since and every one USGS revised. Each reading keeps its gage height in feet as gage_feet beside its elevation above NAVD 88, the gage height plus the altitude of the gage datum the monitoring location records, and carries its approval as verified and its qualifier codes as usgs_qualifiers. A notice names each USGS gauge whose gage datum no survey set before anything is fetched. Each request to the API carries the key API_USGS_PAT holds or tidemark login usgs saved, which raises its hourly limit on requests, and goes without one where neither holds a key.
Each NOAA month a station held that NOAA has verified since or whose verified monthly mean changed, each run of days a gauge held whose tally on the ERDDAP changed, and each run of days a USGS gauge held in which USGS modified a reading since, the last two leaving out the day of the newest reading, is recorded in the revisions.json beside the gauge's manifest.json once the fetch replaces it, beside the instant of the fetch and what showed the revision.
Under --release, it seeds each month every NOAA station lacks from the tar of the NOAA stations that release carries and fetches nothing, printing the seed's line, and exits 1 where the release carries no such tar, or after one failure line naming the release where gh cannot read it, as under a login that cannot, or the name matches no release the repository published. The gauges the NERACOOS ERDDAP serves and the USGS gauges stay out of that seed, since the request each is fetched with is read from its service.
Prints a ledger row for each gauge as its series lands, every gauge fetched from the ERDDAP ahead of every USGS gauge and every USGS gauge ahead of every NOAA station, each in the order the gauges were named or the catalog lists them, naming how many readings it fetched, how many months or ranges it fetched new and replaced as revised, and the days of the first and the newest reading its series holds, and closes on the totals beside the time the command took. Prints a failure line for each gauge the server refused or answered with something other than the Parquet file or the CSV table asked for, including a USGS gauge past the API's hourly limit on requests, one whose key the API rejects, or one whose gage datum sits on a datum other than NAVD 88 or on none, then exits 1 once every other gauge is fetched. Prints a failure line for each name the station catalog does not list, over a line listing the gauges it does, and exits 1 without fetching anything.
console
tidemark fetch gauges [OPTIONS] [ARGS...]| Option | Accepts | Left Out | Meaning |
|---|---|---|---|
GAUGES | Text, any number of times | Optional | The catalog keys of the gauges to fetch, or none for every gauge the station catalog lists |
--refresh | No value | Off | Fetch each gauge's whole series again, replacing every range it holds |
--release | Text | Optional | The release to seed from, by its tag, such as 1.1.0, or by a day written as 2026-10-29 for the newest release the repository published by the end of that day in UTC, which seeds what the store lacks from the tars this fetch reads and fetches nothing from any source |
Fetch what each gauge's series lacks, from its first reading to now:
bash
mise run data:fetch:gaugesName gauges after -- to fetch those alone:
bash
mise run data:fetch:gauges -- Hohonu_tide_Bath_ME NWLON_8418150Fetch each gauge's whole series again, replacing every range it holds:
bash
mise run data:fetch:gauges -- --refreshSeed the NOAA stations from release 1.1.0 alone, fetching nothing:
bash
mise run data:fetch:gauges -- --release 1.1.0tidemark fetch geoid
Fetches the GEOID18 grid PROJ's CDN serves into data/geoid/, the geoid height NGS publishes for turning a height on the NAD83(2011) ellipsoid into one on NAVD 88.
Where data/geoid/ does not hold the grid yet and --refresh is not set, it first seeds the grid from the newest release the repository has published that carries it, read through gh as tidemark fetch gauges reads one, checked against the SHA-256 digest GitHub lists for its tar, and printing a line naming the release or a notice naming why it seeded nothing. It downloads the grid where the directory still lacks it, or under --refresh in any case, and keeps it only once its SHA-256 digest matches the one PROJ's catalog records.
Closes on Fetched or Kept beside the folder holding the grid, over a ledger naming the grid's file and its size, and exits 1 when PROJ's CDN refuses the request or answers with bytes whose digest differs.
console
tidemark fetch geoid [OPTIONS]| Option | Accepts | Left Out | Meaning |
|---|---|---|---|
--refresh | No value | Off | Download the grid again, replacing the one held |
Fetch the GEOID18 grid:
bash
mise run data:fetch:geoidPass --refresh after -- to download it again from PROJ's CDN:
bash
mise run data:fetch:geoid -- --refreshtidemark fetch gnss
Fetches the Nevada Geodetic Laboratory's table of MIDAS velocities in the IGS20 frame into data/gnss/, the vertical rate of each GNSS station a gauge reads its land motion from.
NGL rewrites the table every week, so a fetch keeps the table data/gnss/ holds and records the day NGL wrote it, downloading the newest only under --refresh. Where the directory holds no table and --refresh is not set, it first seeds the table from the newest release the repository has published that carries it, as tidemark fetch geoid seeds the grid, and downloads it only where the seed takes none.
Closes on Fetched or Kept beside the folder holding the table, over a ledger naming the table's file, its stations, and the day NGL wrote it, and exits 1 when NGL's server refuses the request.
console
tidemark fetch gnss [OPTIONS]| Option | Accepts | Left Out | Meaning |
|---|---|---|---|
--refresh | No value | Off | Download the newest table again, replacing the one held |
Fetch NGL's table where none is held:
bash
mise run data:fetch:gnssPass --refresh after -- to replace the table with NGL's newest:
bash
mise run data:fetch:gnss -- --refreshtidemark fetch swot
Fetches every SWOT pass within reach of a gauge in the station catalog at each level named, keeping the part of each pass within reach, and brings the samples table up to date with every part each file holds.
For l2, it lists every pass of the collection the settings name through NASA Earthdata, from the first the collection holds to the newest, requests each pass data/swot/ does not hold yet from PO.DAAC's OPeNDAP service, asking for the lines and the pixels within reach of a gauge of each variable its table reads, and downloads whole from PO.DAAC's archive and cuts each pass the service does not serve. It fetches the file the settings name, the Expert file by default, within reach_m of a gauge, beside the Unsmoothed file within unsmoothed_reach_m, whose samples take the terms of each correction from the Expert sample nearest them, or the one file --variant names alone. Every request goes through the login tidemark login earthdata saved, or through that command's prompt where none is saved.
Where the directory of a Level 2 file lacks a pass that began before the newest release the repository has published that carries the tar of that file's passes, read through gh, it first downloads that tar, or each of its pieces, checks each against the SHA-256 digest GitHub lists for it, and moves each part it holds of a pass the directory lacks into place, printing a line naming how many passes it seeded and the release they came from, beside how long ago it was published, or a notice naming why it seeded none. It seeds only a directory holding nothing yet or recording the same fetch, so the seed empties nothing before the answer below, and under --refresh it seeds nothing and requests every pass again.
For l3, it lists every pass of AVISO's Level 3 Unsmoothed product on a track whose swath covers a gauge from AVISO's THREDDS catalog, taking the reprocessed file of a pass wherever one sits beside its forward file, seeds the passes its directory lacks from the release's tar of them the same way, which needs no AVISO+ login, and requests the lines and the pixels of each pass still missing within reach through the server's DAP2 service, with the login tidemark login aviso saved, which only this level needs. Each part keeps the temporality its file carries, and a pass whose part reads forward is requested again once the catalog lists it under reproc.
Each pass kept in place of a part its source revised, a Level 2 file of another CRID or product counter or a Level 3 file the catalog lists under reproc where the part reads forward, is recorded in the revisions.json beside the file's manifest.json, beside the instant of the fetch and what showed the revision.
It lists every file before it requests any pass, and where the passes still missing come to a gigabyte or more, it prints a notice naming each file's passes, their size, and the time they take, then asks at the terminal whether to fetch them, which --yes answers ahead of time, and empties no directory before the answer. It then requests the passes every file lacks at once, under one bar counting them all, and brings the samples table up to date once they land. A fetch of every file from nothing downloads about 9 GB, most of it the Level 3 passes. It refuses outright where a file provider such as iCloud Drive syncs data/, which would upload every pass, and stops before listing any pass where data/coast/ holds no coastline, which the samples table measures every sample's distance to the coast from, on an error naming the task that fetches it, which data:fetch:swot runs first.
Closes each file it fetched on the folder it fetched into beside the time the command has taken, over a ledger counting the passes it listed, fetched new, replaced as revised, fetched again where any were, kept, and found empty, and the samples the table holds of the file. The fetch then closes on the page that explains the passes and, for l2, the task that rebuilds the pass schedule from them, and prints a failure line and exits 1 when:
- A file provider syncs
data/ - Earthdata lists no Level 2 pass on the box around every gauge's reach, or AVISO's catalog no Level 3 pass on a covering track, or AVISO's catalog does not answer
- The fetch comes to a gigabyte or more,
--yesis not set, and no terminal is attached to ask at or nothing answers the prompt - A Level 2 pass has to be fetched, no login is saved, and no terminal is attached to type one at, or Earthdata rejects the login
- A Level 3 pass has to be fetched and no AVISO+ login is saved
- A pass fails to fetch, after the table takes the samples of the rest
An answer of no at the prompt fetches nothing and exits 0.
Under --release, it lists nothing and fetches nothing, seeding every part each file's tar in that release holds of a pass the store lacks, printing each seed's line, and then prints a failure line and exits 1 for each part parts.json records that the store still lacks or holds under another SHA-256. A tar recording another manifest, as an earlier release's does, takes the whole directory under that manifest, at the path this code reads, and no part is checked. Where gh cannot read the release, as under a login that cannot, or the name matches no release the repository published, it prints one failure line naming it and exits 1 before reading any part.
console
tidemark fetch swot [OPTIONS] [ARGS...]| Option | Accepts | Left Out | Meaning |
|---|---|---|---|
LEVELS | One of l2, l3, any number of times | Optional | The levels to fetch, l2 for PO.DAAC's Level 2 product and l3 for AVISO's Level 3 Unsmoothed product, or none for l2 alone |
--refresh | No value | Off | Seed from no release and request every pass again, replacing every part held |
--release | Text | Optional | The release to seed from, by its tag, such as 1.1.0, or by a day written as 2026-10-29 for the newest release the repository published by the end of that day in UTC, which seeds what the store lacks from the tars this fetch reads and fetches nothing from any source |
--threads | A whole number | Optional | The most requests of each file to PO.DAAC's OPeNDAP service or AVISO's DAP2 service in flight at once, which is one for each pass the file lacks where none is given |
--variant | One of basic, expert, unsmoothed, windwave | Optional | The one Level 2 file to fetch, or none for the file the settings name beside the Unsmoothed file, whose samples take their corrections from the Expert parts beside them |
--yes | No value | Off | Fetch without asking first, however large the fetch, which a fetch run without a terminal needs once it comes to a gigabyte |
Fetch every Level 2 pass within reach of a gauge and keep their samples:
bash
mise run data:fetch:swotFetch AVISO's Level 3 passes alone, or both levels:
bash
mise run data:fetch:swot l3
mise run data:fetch:swot l2 l3Pass --threads to cap how many requests are in flight at once, such as to measure a service at one count:
bash
mise run data:fetch:swot --threads 64Pass --variant to fetch one Level 2 file alone, such as the Expert file the analysis reads:
bash
mise run data:fetch:swot --variant expertPass --yes to fetch without being asked, as an unattended run does:
bash
mise run data:fetch:swot l2 l3 --yesPass --refresh to request every pass of both levels again:
bash
mise run data:fetch:swot l2 l3 --refreshSeed both Level 2 files from release 1.1.0 alone, fetching nothing:
bash
mise run data:fetch:swot --release 1.1.0tidemark login aviso
Logs in to AVISO+, or confirms that the saved login opens a SWOT Level 3 file.
Prompts for an AVISO+ username and password, offering the username the tds-odatis.aviso.altimetry.fr entry in ~/.netrc already holds, and asks AVISO's THREDDS server for one Level 3 file with them before writing that entry, leaving every other entry in the file as it was.
Prints the account it logged in as, and exits 1 when:
- AVISO rejects the login
- AVISO answers the request for the file with another client error, as an account missing the SWOT products under My products may meet
- The password typed holds a space or a backslash, which the entry, written unquoted, cannot carry, so the command puts
~/.netrcback as it was and says to change the password ~/.netrcholds a line the standard library cannot read- Nothing answers the prompt
- AVISO cannot be reached at all, or answers with a server error, which usually means maintenance rather than an account problem, so the command points at AVISO's site
console
tidemark login aviso [OPTIONS]| Option | Accepts | Left Out | Meaning |
|---|---|---|---|
--check | No value | Off | Reads the tds-odatis.aviso.altimetry.fr entry without prompting and without writing ~/.netrc, asks for the same file with it, and exits 1 when AVISO rejects the one saved or answers with another error, or when AVISO cannot be reached at all or answers with a server error. A clone with no entry saved passes, since the login is optional, as only a Level 3 pass the newest release carrying them lacks needs it. The aviso check in mise doctor project runs this mode |
Save an AVISO+ username and password to ~/.netrc once, so every later request for a Level 3 file authenticates without a prompt:
bash
mise run data:login:avisoConfirm that the saved login opens a Level 3 file, without prompting and without writing anything:
bash
tidemark login aviso --checktidemark login earthdata
Logs in to NASA Earthdata, or names the source that already supplies a login.
Reads these sources in order:
- The
EARTHDATA_TOKENvariable - The
EARTHDATA_USERNAMEandEARTHDATA_PASSWORDpair - The
urs.earthdata.nasa.goventry in~/.netrc
Prompts for a username and password when none of those is set, and when Earthdata rejects the ~/.netrc entry, which the typed login then replaces. Checks what is typed against Earthdata before writing that entry itself, leaving every other entry in the file as it was.
Prints the account it logged in as beside the day its token expires and how many days remain, and exits 1 when:
- Earthdata rejects the variable pair, since every fetch reads those variables first and would never reach a login the prompt saved to
~/.netrc - Earthdata rejects the login typed at the prompt
- The password typed holds a space or a backslash, which the entry, written unquoted, cannot carry, so the command puts
~/.netrcback as it was and says to setEARTHDATA_TOKENor to change the password ~/.netrcholds a line the standard library cannot read- The token has expired, does not decode, or carries no readable expiry
- Nothing answers the prompt
- Earthdata cannot be reached at all, so the command points at its status page
console
tidemark login earthdata [OPTIONS]| Option | Accepts | Left Out | Meaning |
|---|---|---|---|
--check | No value | Off | Reads the same sources without prompting and without writing ~/.netrc, names the one that supplies the login, and exits 1 when none of them does, when Earthdata rejects the one it found, when the token from EARTHDATA_TOKEN has expired, does not decode, or carries no readable expiry, or when Earthdata cannot be reached at all. The earthdata check in mise doctor project runs this mode |
Save a NASA Earthdata username and password to ~/.netrc once, so every later fetch authenticates without a prompt:
bash
mise run data:login:earthdataAsk which source already supplies the login, without prompting and without writing anything:
bash
tidemark login earthdata --checktidemark login usgs
Logs in to USGS with a Water Data API key, which raises the API's hourly limit on requests, or names the source that already supplies one.
Reads these sources in order:
- The
API_USGS_PATvariable, which USGS's own Python and R clients read - The
api.waterdata.usgs.goventry in~/.netrc
Prompts for the key without showing it when neither holds one, and when the API rejects the ~/.netrc entry, which the typed key then replaces. Asks the API for one monitoring location with the key before writing that entry, leaving every other entry in the file as it was.
Prints the source the key came from, and exits 1 when:
- The API rejects the key in
API_USGS_PAT, since every fetch reads that variable first and would never reach a key the prompt saved - The API rejects the key typed at the prompt
- The key typed holds a space or a backslash, which the entry, written unquoted, cannot carry, so the command puts
~/.netrcback as it was and says to setAPI_USGS_PATinstead ~/.netrcholds a line the standard library cannot read- Nothing answers the prompt
- The API cannot be reached at all, or answers with another error
console
tidemark login usgs [OPTIONS]| Option | Accepts | Left Out | Meaning |
|---|---|---|---|
--check | No value | Off | Reads the same sources without prompting and without writing ~/.netrc, names the one that supplies the key, and exits 1 when the API rejects it, answers with another error, or cannot be reached. A clone with no key passes, since every request goes without one under a lower hourly limit |
Save a USGS Water Data API key to ~/.netrc once, so every later request to the API sends it:
bash
mise run data:login:usgsAsk which source already supplies the key, without prompting and without writing anything:
bash
tidemark login usgs --checktidemark pack
Packs the files each source's fetch keeps under data/ into the Zstandard tars a release carries, one for each source and one for each SWOT file, in data/packs/, each file under its path below data/, in the order of those paths and with no time, owner, or group of its own:
catalog.tar.zst, the answers the NERACOOS ERDDAP, NOAA, and the USGS gave the last rebuild of the station catalog, beside their manifest and their index, from whichtidemark catalog --checkrebuilds itcoast.tar.zst, the cut of the OpenStreetMap coastline beside its manifestcoops.tar.zst, every NOAA station's manifest, months, and recorded monthly meanserddap.tar.zst, every gauge's manifest and ranges the NERACOOS ERDDAP servesusgs.tar.zst, every USGS gauge's manifest and rangesgeoid.tar.zst, the GEOID18 grid beside its manifestgnss.tar.zst, NGL's table of MIDAS velocities beside its manifestswot-expert.tar.zstandswot-unsmoothed.tar.zst, one for each file of PO.DAAC's Level 2 product the SWOT fetch keeps, andswot-l3-unsmoothed.tar.zstfor AVISO's Level 3 Unsmoothed file, each holding that file's manifest and every pass's part, from which a fetch reads their samples again
The directory of each gauge and of each SWOT file travels with the revisions.json its fetches wrote, wherever they replaced a range or a pass once its source revised it.
Ahead of packing, it adds to each Level 3 part what the pipeline works out from the pass, which makes the part a Value-Added Product rather than a copy of AVISO's file, leaving every variable the fetch kept as it stood:
correction, the sum ofmss,ocean_tide,dac, andinternal_tideheight,ssha_unfilteredpluscorrection, ahead of taking out the load tide the Level 2 Expert file suppliesgauge_distance, each sample's distance to the nearest gaugecoastline_distance, each sample's distance to the OpenStreetMap coastline, for each sample within reach of a gauge
Each tar opens on CREDITS.md, the notice of every source and license licenses.toml names it under, which no seed moves into data/, and NOTICE.md beside the tars holds the notice of every source whose terms are established and of every license. A tar reaching the 2 GiB GitHub allows a release file is written across numbered pieces, swot-unsmoothed.tar.zst.1 and on, each under that size.
Beside each tar it writes the record of what the tar was packed from, such as coops.json, meaning the fingerprint of each record whose files it holds, the text of its credits, the digest of the code writing it, and the version of zstd. A tar whose record reads the same on the next pack and whose files are whole is kept as it stands, and every other tar is written again.
Where the catalog's answers, any gauge, the grid, the table, or a SWOT file holds no file under data/ beyond its manifest.json and revisions.json, it prints a failure line for each, naming its directory and the fetch that fills it, and exits 1 writing no tar. A tar falling under no source in licenses.toml, or holding a source whose terms it does not list, prints a failure line and exits 1 the same way. Otherwise it keeps each tar whose record reads the same beside that record, removes every other file in data/packs/, such as a piece past a count that shrank, then draws a bar with no count while each other tar is written, and closes on the folder it packed into beside the time the command took, over a ledger naming each tar, how many files it holds, and its size in bytes, beside how many pieces it takes where it takes more than one and kept where it kept the tar. Should the Level 3 tar, read back, hold a part lacking what the pipeline adds, it prints a failure line for each and exits 1.
Under --release, it packs nothing under data/packs/, and instead writes the Level 3 tar that release carries into .cache/repacked/<tag>/ as a tar of parts holding those additions, measured from the coastline data/coast/ holds, keeping that tar's manifest and every variable, so the tag's own code reads the new tar's parts as it read the old tar's.
console
tidemark pack [OPTIONS]| Option | Accepts | Left Out | Meaning |
|---|---|---|---|
--release | Text | Optional | The release whose Level 3 tar to write again, by its tag or by a day written as 2026-10-29 |
Pack every source's files into data/packs/:
bash
mise run data:packWrite the Level 3 tar release 1.1.0 carries as a modified product:
bash
mise run data:pack -- --release 1.1.0tidemark present
Builds a talk with the site's own toolchain, Vite under the package's configuration with the site's Tailwind sheets, into .cache/presentations/ where no build stands or a file the last build read has changed since, then serves the build on 127.0.0.1 and opens it in the browser until the command is stopped. The arrow keys, a click, or the space bar step through each slide's beats, F fills the screen, D turns the dark scheme off and on, and --slide 7.2 opens the talk at the second beat of its seventh slide, as #7.2 after the address does.
Closes on Built or Kept beside the build's folder, over a ledger naming how many files the build read. Exits 1 where the package holds no such talk, where the site's packages are not installed, where the build fails, printing Vite's output above the failure line, or where --slide names a slide or a beat the talk does not hold.
console
tidemark present [OPTIONS] NAME| Option | Accepts | Left Out | Meaning |
|---|---|---|---|
NAME | Text | Required | The talk to play, by its folder under docs/classroom/presentations/ |
--rebuild | No value | Off | Build the talk even where its build is current |
--slide | Text | Optional | The place to open the talk at, as <slide>.<beat> counted from one, or a slide alone at its first beat |
Play the 1.0 talk, building it first where it is out of date:
bash
mise run site:present -- 1.0Build the talk again before playing it:
bash
tidemark present 1.0 --rebuildOpen the talk at the second beat of its seventh slide:
bash
tidemark present 1.0 --slide 7.2tidemark run
Computes every analysis step, or only the steps named on the command line, and records the settings and the revision of the code that computed them under data/runs/, which mise run data:browse opens. A step is read back from the cache wherever its code, the data it reads, and the settings read as they did when a run computed it.
Closes on the run's directory beside the time the command took, over a ledger counting the steps it computed, the steps it read back, and the tables it saved into the run's directory.
Prints a failure line for each name the graph declares no step for, over a line listing the steps it does declare, and exits 1 without computing or recording anything.
console
tidemark run [OPTIONS] [ARGS...]| Option | Accepts | Left Out | Meaning |
|---|---|---|---|
STEPS | Text, any number of times | Optional | The names of the steps to compute, or none for every step |
--collection-short-name | Text | Default SWOT_L2_LR_SSH_D | The Earthdata name of the SWOT data collection every pass is taken from. The default names PO.DAAC's SWOT Level 2 KaRIn Low Rate Sea Surface Height Data Product, Version D, which holds all four files the mission writes for each pass and lists passes that the collection of each file alone leaves out |
--collection-variant | One of basic, expert, unsmoothed, windwave | Default expert | The file of the four the collection holds that a Level 2 fetch reads for every pass ahead of the Unsmoothed file, or the Unsmoothed file alone where this setting names it, and from whose parts the tracks step reads each nadir track. The default is the Expert file, which carries every variable of the Basic and WindWave files beside the terms of each correction applied to it |
--collection-version | Text | Default D | The version of the collection that Earthdata publishes, which the granule search sends beside the collection's name. PO.DAAC ends each Version D collection's short name with the same letter this setting carries |
--gnss-radius-m | A whole number | Default 25000 | The distance in meters from a gauge within which its land motion is read from the GNSS station whose vertical rate NGL measures with the smallest uncertainty, 25,000 meters by default, among the stations whose series spans gnss_span_years. A gauge with no such station inside the distance reads the nearest one beyond it. NGL's long-running stations along the Maine coast agree on one vertical rate within their uncertainties, so the most certain station near a gauge stands for the land beneath it as well as the nearest does |
--gnss-span-years | A number | Default 3.0 | The fewest years a GNSS station's series spans for its vertical rate to be read, 3 by default, the shortest span over which the MIDAS estimator NGL computes each rate with tolerates one step in the series, such as an antenna change leaves, as Blewitt et al. 2016, doi:10.1002/2015JB012552, derive, whereas a step in a shorter series can bias the rate without bound, a figure derived for a series without gaps. MIDAS pairs readings a year apart wherever the series allows, so a signal repeating each year leaves the rate unbiased |
--height | One of ssh-karin, ssh-karin-2 | Default ssh-karin-2 | The sea surface height a selection reads from a Level 2 file, by default ssh_karin_2, whose weather model leaves no void where the radiometer reads land, the height Hay and colleagues read beside the coast |
--min-coast-distance-m | A whole number | Default 0 | A distance in meters out to sea from the OpenStreetMap coastline that a usable sample keeps, zero by default, which keeps every sample and leaves to the Level 3 editing and the surface map the samples nearest the coast |
--min-samples | A whole number | Default 5 | The fewest usable samples a level keeps of one pass at one gauge for that pass to give a height, by default 5 and at least 2, since one sample has no spread, which scipy.stats.bootstrap refuses, and two or three give an unstable one. A pass whose Level 3 samples fall short takes its Level 2 samples, and one whose Level 2 samples fall short as well gives no height |
--quality-flag | One of bad, degraded, good, suspect | Default good | A quality band of a SWOT sample's height, good by default, which the mission's user handbook, JPL D-109532, names as the band a reader would normally use |
--radius-m | A whole number | Default 5000 | A search radius in meters around a gauge, 5,000 meters by default |
--reach-m | A whole number | Default 50000 | The distance in meters from a gauge within which a fetch keeps the SWOT samples of a file on the 2 km grid, bounding radius_m. The default of 50,000 meters is the radius Vega-Gimenez and colleagues kept after testing radii out to 100 km, since the smallest differences from the gauges fell between 40 and 60 km |
--reduction | One of clipped, median | Default median | How the samples of one pass at one gauge reduce to one height, by default their median, which the closest comparisons with gauges take |
--reference | One of ellipsoid, navd88 | Default navd88 | A height reference, NAVD 88 by default, the datum every gauge series reads on, Bar Harbor's through the offset the station catalog measures from mean lower low water |
--resamples | A whole number | Default 1000 | The resamples the bootstrap draws of each pass's samples, 1,000 by default and at least 2, since the standard error of one resample is undefined |
--seed | A whole number | Default 0 | The seed the bootstrap's random draws start from, so a run draws the same resamples every time |
--surfaces | One of aquatic-vegetation, continental-ice-snow, continental-water, floating-ice, land, open-ocean, salted-basin | Default [continental-water, open-ocean] | The surface types a selection keeps a Level 2 sample over, by default open ocean and continental water |
--uncertainty | One of analytic, bootstrap, swot | Default bootstrap | The uncertainty the heights table names as each pass's own, by default the bootstrap's, which reads any reduction the same way |
--unsmoothed-reach-m | A whole number | Default 50000 | The distance in meters from a gauge within which a fetch keeps the SWOT samples of a file on the 250 meter grid, meaning PO.DAAC's Level 2 Unsmoothed file and AVISO's Level 3 Unsmoothed product, bounding radius_m as well. The default of 50,000 meters is the radius Vega-Gimenez and colleagues took their median within for this product as for the 2 km one, counting a pass only where it held valid data within 10 km |
--verbose | No value | Off | Print the log lines the analysis steps write to standard error |
Compute every step the analysis graph declares:
bash
tidemark runName a step to compute that step and whatever it reads:
bash
tidemark run lookstidemark schedule
Rebuilds the pass schedule the package ships from the passes tidemark fetch swot kept, meaning how many passes cover each gauge, when each cycle began, where each gauge sits across every pass that runs within 60 km of it, the ground track of each of those passes, and every look due at each gauge.
A table is read back from the analysis graph's cache wherever its code, the data it reads, and the settings read as they did when a run computed it. A rebuild closes on the folder it wrote beside the time the command took, over a ledger naming each table's file, how many rows it holds, what one row is, and a note read from the table, beneath which it counts the steps it computed and the steps it read back. Where the fetch has kept no pass, it prints a failure line saying so and exits 1 without writing anything.
A rebuild also writes parts.json beside the tables, recording each part it read the nadir tracks of by name beside its SHA-256 and the manifest.json of the directory holding them, and the version of the package as the release whose tars carry those parts.
Where the repository has already published the release of that version, a rebuild prints a failure line naming that release and the one the next open milestone ships, beside the mise run bump moving the package to it, and exits 1 before computing anything, since the tars of a published release carry no part read after it. Where gh cannot list the milestones or none open ships a later release, the line names the next open milestone in place of its release. Where gh cannot list the releases, it prints a notice saying so and goes on.
console
tidemark schedule [OPTIONS]| Option | Accepts | Left Out | Meaning |
|---|---|---|---|
--check | No value | Off | Computes the schedule from exactly the parts parts.json records without writing it, prints one line for each table the rebuild reads differently from the one the package ships, and exits 1 where anything differs. Where the store lacks a recorded part or holds it under another SHA-256, it prints a failure line naming each such part and exits 1 before computing anything. Where the release parts.json records for the schedule has published and the record its tag holds names other parts, it prints a failure line naming that release and exits 1 before computing anything, so the check mise run gha:attach runs fails before the release rolls rather than after it |
--verbose | No value | Off | Print the log lines the analysis steps write to standard error |
Rebuild the schedule once a fetch has added passes:
bash
mise run data:scheduleCompute the same tables without writing anything:
bash
mise run data:schedule -- --checkThe coastline this page reads is a derivative database under the Open Database License, and tidemark fetch coast makes a free copy of the cut.
1Gulf of Maine Research Institute & Brown University 2026. "NERACOOS ERDDAP." Northeastern Regional Association of Coastal Ocean Observing Systems. https://data.neracoos.org/
erddap/ .↩︎2United States Geological Survey 1994. "USGS Water Data for the Nation." https://doi.org/
10.5066/ .↩︎F7P55KJN 3NOAA CO-OPS 2026. "CO-OPS Data Retrieval API and Metadata API." https://tidesandcurrents.noaa.gov/
web_services_info.html .↩︎