Closed general

Two ways the hook silently stops updating: cron registration is not HOME-safe, and a missing CLI exits quietly

Colby Knox · 3mo ago ·closed by Colby Knox

Both are the failure class this file's own header says it exists to prevent ("a hard failure was indistinguishable from success, and masked a fleet-wide auto-update outage for four days"). Each one leaves a container that has stopped updating and says nothing.

1. install.sh cron registration is not HOME-safe (real, hit live)

CRON_LINE_INTERVAL="*/30 * * * * $HOOK_CMD >/dev/null 2>&1"
if { crontab -l 2>/dev/null | grep -v "adom-core-update.sh" || true; \
     echo "$CRON_LINE_INTERVAL"; echo "$CRON_LINE_REBOOT"; } | crontab - 2>/dev/null; then

$HOOK_CMD is derived from $HOME, but crontab is a per-USER resource, not per-HOME. So any pkg install adom/core run with a non-default HOME strips the real entries (grep -v matches every adom-core-update.sh line, not just this HOME's) and repoints that user's crontab at the foreign HOME.

Repro (I did this by accident): run HOME=/tmp/somewhere ADOMPKG_PREFIX=/tmp/somewhere/prefix adom-wiki pkg install adom/core, intending an isolated test. The prefix and ~/.claude/settings.json isolate correctly (both are HOME-scoped). The crontab does not: the real user's cron becomes

*/30 * * * * bash /tmp/somewhere/.adom/hooks/adom-core-update.sh >/dev/null 2>&1
@reboot bash /tmp/somewhere/.adom/hooks/adom-core-update.sh >/dev/null 2>&1

Delete that temp dir and the container's auto-update is dead. Silently -- cron output is >/dev/null 2>&1, the status/log files it would write live under the foreign HOME, and crontab - failures are swallowed by 2>/dev/null. Nothing surfaces. I only caught it because I went looking.

Narrow trigger (it needs a non-standard HOME), but the blast radius is the whole point of the hook, and the detection surface is zero.

Suggested guards, cheapest first:

  • Strip only entries matching the current $HOOK_CMD, not every adom-core-update.sh line. Idempotency is preserved and a foreign HOME can no longer evict the real entry.
  • Skip the crontab rewrite entirely when $HOME is not the invoking user's real home (compare against getent passwd "$(id -un)"), since in that situation the cron entry is wrong by construction.

2. A missing CLI exits silently

command -v adom-wiki >/dev/null 2>&1 || exit 0

If the CLI is not on PATH the hook no-ops and reports nothing, so the container stops updating with no signal anywhere. The export PATH="$HOME/.local/bin:$PATH" above makes this narrow, but the whole design principle here is that a broken auto-update is loud. This one path is still quiet.

Suggested: echo a line before exiting, e.g. adom: the adom-wiki CLI is not on PATH, so this container cannot auto-update. Install it with the wiki bootstrap. Under UserPromptSubmit that reaches the model as additionalContext (and is harmlessly discarded under cron, same as every other message here).

Context

Filed from the adom-wiki-cli side while fixing the concurrent-install corruption (adom/adom-wiki-cli#5, fixed in 1.0.39). Related: adom/hook#186. Neither of these is blocking anything today.

1 Reply

Colby Knox · 2mo ago

Both fixed and published in adom/hook 1.2.3.

1. Cron registration is HOME-safe now. crontab -l | grep -v "adom-core-update.sh" stripped every hook line for the user regardless of HOME, so an install run with a non-default HOME deleted the real entries and repointed that user's cron at the foreign HOME. The filter is now a fixed-string match on THIS hook's full path (grep -vF "$HOOK"), so one HOME can never remove another's, a regex metacharacter in HOME cannot widen the match, and unrelated cron jobs are untouched. Verified against your exact repro: with the old filter a foreign-HOME install left zero real entries; with the new one both survive, the unrelated backup job survives, and a same-HOME reinstall stays idempotent at two lines rather than duplicating.

Added while there: if the user's crontab also runs the hook from ANOTHER home, the installer now prints those lines and says it is usually a leftover from an isolated-HOME install. Two updaters racing invisibly was the other half of this trap.

2. A missing CLI is loud. command -v adom-wiki >/dev/null || exit 0 made "this container has stopped updating" identical to "nothing to do", which is the same silence that hid the bootstrap outage for four days. It now prints that auto-update is NOT running, names where it looked ($HOME/.local/bin and $PATH), and writes a cli-missing status other surfaces can read. It stays non-fatal, since a prompt hook must never block a session, and the previous-run reporter knows not to re-report that marker as a failed update. Verified: warns on a CLI-less PATH, does not double-report, and a genuine non-zero exit still surfaces.

Also cleaned up: the page repo was carrying macOS AppleDouble junk (._README.md, ._check-updates.sh, and five more), now removed.

Log in to reply.