app
hook
Public Made by Adomby adom
Registry-native cross-agent auto-update hook, plus claude-rc, the keeper for Claude Remote Control. Keeps adom/core apps and skills current from wiki.adom.inc on every Claude Code and Codex prompt, and keeps `claude rc` alive so users can open AI threads on their container from the Claude mobile app or claude.ai/code.
← Commit history
SKILL.md+5−2@@ -151,8 +151,11 @@ used. Detection is `ADOM_DESKTOP_MODE=local` plus a live crond. ## Facts worth knowing before you debug it -- `claude rc` skips its "Enable Remote Control? (y/n)" prompt when stdin is not a TTY, so- the watchdog launches it headless with `setsid nohup ... </dev/null`.+- `claude rc` skips its "Enable Remote Control? (y/n)" prompt when stdin is not a TTY, but+ it still READS stdin (it waits for a keypress to show the QR code) and exits on EOF. So the+ keeper launches it with a stdin that never closes (`sleep infinity | exec claude rc ...`),+ never with `</dev/null`: that variant connects and dies within a second, five times, and+ ends in `state=failed` (adom/hook 1.3.1 fix, found on an Adom cloud container). - Prereqs: `claude` on PATH, a logged-in subscription account, and workspace trust accepted for `~/project` (`hasTrustDialogAccepted` in `~/.claude.json`). The hook only offers when these hold, which inside a running session they already do.
claude-rc+13−2@@ -32,7 +32,11 @@ SELF="$HOME/.local/bin/claude-rc" PROJECT_DIR="${CLAUDE_RC_PROJECT_DIR:-$HOME/project}" # Anchored to the START of the cmdline so a shell whose command text merely # mentions "claude rc" (this script's own callers, a chat transcript) never matches.-PAT='^\S*/claude (rc|remote-control)( |$)'+# The path prefix is OPTIONAL: launched from PATH the cmdline is a bare `claude rc ...`,+# and the old mandatory `\S*/` never matched it, so the watchdog relaunched a server that+# was already up (five times an hour -> state=failed) and `status` said "not running"+# next to a live pid. Verified on an Adom cloud container 2026-08-30.+PAT='^(\S*/)?claude (rc|remote-control)( |$)' mkdir -p "$STATE_DIR" # ---- state file: KEY=VALUE lines -------------------------------------------@@ -60,6 +64,7 @@ running_pid() { pgrep -f "$PAT" | head -1; } # tear down its relay connection, so a bare pkill + immediate pgrep still sees it. stop_server() { pkill -f "$PAT" 2>/dev/null || return 0+ pkill -f '^bash -c sleep infinity \| exec claude rc' 2>/dev/null || true local i; for i in 1 2 3 4 5 6 7 8; do [ -z "$(running_pid)" ] && return 0; sleep 1; done pkill -9 -f "$PAT" 2>/dev/null || true; sleep 1 }@@ -107,7 +112,13 @@ launch() { cd "$PROJECT_DIR" || return 1 rotate_log echo "[$(date -Is)] claude-rc: launching (name=$(rc_name), env=$(env_name))" >> "$LOG"- setsid nohup claude rc --name "$(rc_name)" </dev/null >> "$LOG" 2>&1 &+ # STDIN MUST STAY OPEN. `claude rc` is a TUI that waits on a keypress ("space to show QR+ # code"); with </dev/null it connects, reads EOF, and exits within a second (the log shows+ # "Connected" five times, then the crash-loop guard marks it failed). A pipe that never+ # closes (sleep infinity) gives it a stdin with no data and no EOF, so it runs until killed.+ # The pipeline is wrapped in its own bash so `exec` keeps the pgrep pattern on the real+ # server process, not on the wrapper.+ setsid nohup bash -c 'sleep infinity | exec claude rc --name "$1"' _ "$(rc_name)" >> "$LOG" 2>&1 & # crash-loop guard: remember launch times, keep the last hour's worth local t; t="$(now)" local hist; hist="$(st_get launches)"
package.json+3−3@@ -1,6 +1,6 @@ { "slug": "hook",- "version": "1.3.0",+ "version": "1.3.1", "type": "app", "org": "adom", "bundled": true,@@ -56,7 +56,7 @@ "mode": "0755" } ],- "changelog": "1.3.0: add claude-rc, which keeps Claude Code Remote Control (`claude rc`) alive so a user can open new AI threads on their container from the Claude mobile app or claude.ai/code. It rides in adom/hook because it needs exactly what this package already owns: a UserPromptSubmit hook and a cron entry. Consent-first -- installing only wires the offer, and the AI asks the user once. Supervision differs by environment: a 2-minute cron watchdog on ah, and the prompt hook itself on hc, which has neither cron nor systemd. No dependency changes.",+ "changelog": "1.3.1: claude-rc keeps stdin open when launching `claude rc` (sleep infinity pipe). With </dev/null the server connected and exited within a second, five times, and the crash-loop guard marked it failed on every container. The watchdog's pgrep pattern also required a path prefix that a PATH launch never has, so it relaunched a live server and reported it as not running. Found on an Adom cloud container and an Adom Hydrogen WSL2 workspace, 2026-08-30. 1.3.0: add claude-rc, which keeps Claude Code Remote Control (`claude rc`) alive so a user can open new AI threads on their container from the Claude mobile app or claude.ai/code. It rides in adom/hook because it needs exactly what this package already owns: a UserPromptSubmit hook and a cron entry. Consent-first -- installing only wires the offer, and the AI asks the user once. Supervision differs by environment: a 2-minute cron watchdog on ah, and the prompt hook itself on hc, which has neither cron nor systemd. No dependency changes.", "discovery_pitch": "Use when adom packages are behind or an update failed, and when the user asks about Claude Remote Control -- opening AI threads on this container from their phone or claude.ai/code.", "sample_prompts": [ {@@ -72,4 +72,4 @@ "prompt": "are my adom packages current with the wiki?" } ]-}+}
page.json+14−2@@ -1,6 +1,6 @@ { "slug": "hook",- "version": "1.3.0",+ "version": "1.3.1", "type": "app", "org": "adom", "bundled": true,@@ -50,7 +50,7 @@ "name": "Kyle Bergstedt", "email": "[email protected]" },- "changelog": "1.3.0: add claude-rc, which keeps Claude Code Remote Control (`claude rc`) alive so a user can open new AI threads on their container from the Claude mobile app or claude.ai/code. It rides in adom/hook because it needs exactly what this package already owns: a UserPromptSubmit hook and a cron entry. Consent-first -- installing only wires the offer, and the AI asks the user once. Supervision differs by environment: a 2-minute cron watchdog on ah, and the prompt hook itself on hc, which has neither cron nor systemd. No dependency changes.",+ "changelog": "1.3.1: claude-rc keeps stdin open when launching `claude rc` (sleep infinity pipe). With </dev/null the server connected and exited within a second, five times, and the crash-loop guard marked it failed on every container. The watchdog's pgrep pattern also required a path prefix that a PATH launch never has, so it relaunched a live server and reported it as not running. Found on an Adom cloud container and an Adom Hydrogen WSL2 workspace, 2026-08-30. 1.3.0: add claude-rc, which keeps Claude Code Remote Control (`claude rc`) alive so a user can open new AI threads on their container from the Claude mobile app or claude.ai/code. It rides in adom/hook because it needs exactly what this package already owns: a UserPromptSubmit hook and a cron entry. Consent-first -- installing only wires the offer, and the AI asks the user once. Supervision differs by environment: a 2-minute cron watchdog on ah, and the prompt hook itself on hc, which has neither cron nor systemd. No dependency changes.", "discovery_pitch": "Use when adom packages are behind or an update failed, and when the user asks about Claude Remote Control -- opening AI threads on this container from their phone or claude.ai/code.", "sample_prompts": [ {@@ -65,5 +65,17 @@ "label": "Am I up to date?", "prompt": "are my adom packages current with the wiki?" }+ ],+ "managed_files": [+ {+ "src": "check-updates.sh",+ "dest": "~/.adom/hooks/adom-core-update.sh",+ "mode": "0755"+ },+ {+ "src": "claude-rc",+ "dest": "~/.local/bin/claude-rc",+ "mode": "0755"+ } ] }