Skip to content

Releases

v2.4.3

Choose a tag to compare

@furey furey released this 09 Nov 03:43
Immutable release. Only release title and notes can be modified.
  • The README icon is half the size, 64 pixels wide, so the header fits a phone screen.
  • scripts/render-logo-gif.mjs has a --size option for the GIF's width in pixels (256 by default).

What changes for existing installs: nothing. The CLI and the Docker image work as in 2.4.2.

v2.4.2

Choose a tag to compare

@furey furey released this 08 Nov 13:20
Immutable release. Only release title and notes can be modified.
  • The README has a new header: an animated 8-bit fetchtv icon, a short description, and badges.
  • scripts/render-logo-gif.mjs renders the icon from the Fetch My Recordings mark.

What changes for existing installs: nothing. The CLI and the Docker image work as in 2.4.1.

v2.4.1

Choose a tag to compare

@furey furey released this 05 Nov 04:58

Docs only. The VPN note now says a VPN can block discovery even with local network access allowed, and to give the box's IP address with --ip instead.

Also moves the CI and publish workflows to actions that run on Node 24.

v2.4.0

Choose a tag to compare

@furey furey released this 05 Nov 01:08

Some Fetch boxes list a finished recording with size -1, so fetchtv treated it as still recording and never saved it.

  • For each recording listed with no size, fetchtv now asks the box for the file length twice, 3 seconds apart. A steady length means the recording is finished, and it saves as normal.
  • New growing: true when fetchtv is sure a recording is in progress: the box gives its live-recording size, or the length grew between the two checks.
  • New unavailable: true when the box lists a recording but answers 404 or 410 for its file (for example, a recording deleted on the box).
  • fetchtv save gives such a recording the new status unavailable with a one-line message. It does not count as a failure, so the exit code stays 0.
  • --json output now always includes growing and unavailable.
  • The README has a note on VPNs: a VPN that sends all traffic through its tunnel can block discovery; allow local network access or pass --ip.

What changes for existing users: recordings that used to stay "still recording" forever may now save. A deleted-on-box recording reports unavailable instead of still_recording.

v2.3.2

Choose a tag to compare

@furey furey released this 04 Nov 13:59

Docs only. The README and Docker Hub description now give Fetch's new levy dates: opt in by 30 November 2026; Fetch suspends Gen 3 boxes that have not opted in from 1 December 2026.

v2.3.1

Choose a tag to compare

@furey furey released this 04 Nov 13:17

Security

  • npm audit now reports no advisories.
  • Dropped the node-ssdp dependency. fetchtv now sends its own box search on the network, so the ip advisory (GHSA-2p57-rm9w-gvfp) is gone. The search finds the same boxes as before.
  • Upgraded fast-xml-parser to 5.11.2 (GHSA-gh4j-gqv2-49f6). Titles, descriptions, and download links read exactly as before, including characters such as apostrophes and ampersands.
  • Upgraded follow-redirects to 1.16.2 (GHSA-mrwp-f3q8-3g9p).

API

  • discoverFetchServers returns an empty list when the computer has no IPv4 network, as documented.

Upgrading

Nothing changes for saved recordings or file names. Use npx fetchtv@latest to get this version.

v2.3.0

Choose a tag to compare

@furey furey released this 03 Nov 04:20

What's new

  • --box-wait <minutes> lets a save wait for a box that stops answering, for example after standby or a restart. While it waits, fetchtv starts no new recordings and checks the box at 5, 10, and 20 seconds, then every 30 seconds. When the box answers, each recording carries on from its .part file, and the wait does not use up its retries. If the box does not answer in time, the remaining recordings fail with box-unreachable. The default is 0, which keeps the old behaviour.
  • Saving again no longer copies a recording a second time when its file name changed (for example after switching on Plex names). A half-saved recording carries on under its new name.
  • A save that stalls because the box went quiet now tries again after 60 seconds, and Stop works at once.
  • A show the box says no longer exists is skipped at once, instead of being retried for about 10 seconds.

Upgrading

  • A download now gives up on connecting after 10 seconds, even with --box-wait at 0. Before, a box that did not answer could hold a connection attempt for as long as the operating system allowed. The retries stay the same.

API

  • saveRecordings takes boxWaitMs (default 0), connectTimeout (default 10000), onBoxState({ state }) with lost, back, or gave-up, and onRetry({ id, attempt, of }). If onBoxState or onRetry throws, the save carries on.
  • downloadFile takes connectTimeout (default 10000).
  • New exports: BOX_STATE and BOX_UNREACHABLE ('box-unreachable').
  • planSaves and copyAgain are new in this release.

v2.2.8

Choose a tag to compare

@furey furey released this 02 Nov 11:59

What's new

  • The README warns that renaming a .ts file to .mp4 does not convert it.

Upgrading

Docs only. No code changes.

v2.2.7

Choose a tag to compare

@furey furey released this 02 Nov 09:27

Fixes

  • When the box lists its shows but does not answer for any of them, fetchtv now says the box did not send its recordings (restart the box and try again). Before, it said "No Recordings found", which read as an empty box. If only some shows fail, it still lists the ones that loaded.

For programs that use fetchtv

  • onOutcome has one new outcome value, items-browse-failed, also in LISTING_OUTCOME. The return value is unchanged.

Upgrading

Run npx fetchtv@latest, or docker pull furey/fetchtv:latest. Nothing else changes.

v2.2.6

Choose a tag to compare

@furey furey released this 02 Nov 08:40

Fixes

  • When fetchtv cannot list recordings, it now says why, instead of one line for every case:
    • The box does not offer a ContentDirectory service, or did not answer the request for its folders, or did not answer the request for its Recordings folder: restart the box and try again. This does not mean the box has no recordings.
    • The box lists no Recordings folder: a Fetch box that has lost its Fetch service (account cancelled or suspended, or no internet) shows its setup screen on the TV and lists no recordings until that is fixed.
    • The Recordings folder is empty: the box answered and has no recordings.
  • A filter that matches nothing (--show, --exclude, --title) no longer prints the cancelled-account hint.

For programs that use fetchtv

  • getFetchRecordings takes an optional onOutcome callback. It is called once with { outcome, error?, folders? }. outcome is one of ok, empty, no-content-directory, browse-failed, no-recordings-folder, or recordings-browse-failed. The exported LISTING_OUTCOME object holds these values. The return value is unchanged.

Upgrading

Run npx fetchtv@latest, or docker pull furey/fetchtv:latest. Nothing else changes.