All notable changes to this project are documented here. The format follows Keep a Changelog, and this project adheres to Semantic Versioning.
[0.1.1] - 2026-08-22
First external review of this package — every sibling had between one and four rounds; this one shipped with none, and the round found two real defects.
Fixed
- A broken tool was reported as installed, with a version read out of its
own error message. Exit status was ignored whenever the default pattern
found any dotted number in the output — documented as deliberate, and
wrong: failure output routinely contains one. A Homebrew ffmpeg dying in
the dynamic loader reported
{:ok, "265.215.0"}, parsed fromlibx265.215.dylibin the dyld error, and satisfied>= 4.0.0. A non-zero exit is now an error,{:check_failed, status, output}. Tools that genuinely report their version with a non-zero exit —ssh -Vexits 255 — declareallow_nonzero: true. - A version command that waited on stdin hung the check forever.
System.cmd/3has no timeout, and the moduledoc itself places checks on a request path behind an expiring cache. The subprocess now runs under a Port with a ten-second default (:timeoutper tool), is killed by OS pid on expiry rather than abandoned, and is unlinked so a trapping caller never receives its EXIT as a strayhandle_info. - Output accumulation is capped at 64 KB, keeping the head. A
misconfigured executable that streams (
yesmeasured 2.1 GB in one second through a port) filled the heap for the whole timeout budget. The head is kept — the opposite end from a converter's error tail — because a version banner sits at the start of output. install: "one bare string"crashedinstall_hint/1— but only on the failure path, so it survived every machine where the tool existed. Now accepted as[default: hint].
Documented
- An "Awkward tools" section:
ssh(allow_nonzero),elixir(the OTP banner's erts version precedes "Elixir x.y.z", so the default pattern reads the wrong number —:patternfixes it), and slow-first-run tools (:timeout).
[0.1.0] - 2026-08-21
Initial release.
Added
use CliDepswith atool/2macro for declaring external command-line dependencies.check/1,check!/1,available?/1,explain/1,report/0,all_available?/0,invalidate/1.- Version requirements via
Versionrequirement strings, with extraction from real-world--versionoutput. - Per-OS install hints (
:macos,:linux,:windows,:default) surfaced in error messages. - Result caching in
:persistent_termwith a one-hour default TTL, monotonic clock, and per-tool or global invalidation. mix cli_deps.checktask that exits non-zero when anything is missing, for use as a CI or container-build gate.- Compile-time validation of version requirements, regex patterns, and duplicate tool names.