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
1.3.6: claude-rc seeds Claude's first-run flags itself and gains 'ensure' (remote control on by default on ah)
4 files changed
+89−4
SKILL.md+9@@ -16,6 +16,15 @@ The registry-native, cross-agent auto-update hook. It keeps your `adom/core` app and skills current from the wiki registry (wiki.adom.inc) without git or any private repository. ++## On Adom Hydrogen, it is on by default++`claude-rc ensure` is what hydrogen-bootstrap runs on every converge: on an ah container it+turns remote control on without asking, so a fresh install reaches the Claude mobile app on+its own. It respects an explicit `claude-rc decline` or `disable`, and it stays quiet until+Claude Code is signed in (a brand-new box), retrying on the next sweep. Hydrogen Cloud keeps+the offer-based flow through the prompt hook.+ ## What it does On every Claude Code and Codex prompt (`UserPromptSubmit`), a throttled check runs
claude-rc+77−1@@ -8,6 +8,8 @@ # and on hc (no cron) doubles as the watchdog. # claude-rc check the watchdog: launch if absent, with cooldown after failures. # claude-rc enable record consent, register cron on ah, launch now.+# claude-rc ensure what hydrogen-bootstrap calls on every converge: on ah, turn it on+# by default (respects decline/disable, quiet when not ready yet). # claude-rc decline record "no thanks"; the hook never offers again. # claude-rc disable stop the server, drop cron, stop watching (re-enable any time). # claude-rc status where things stand (state, pid, name, env, last log lines).@@ -78,9 +80,55 @@ stop_server() { # Prerequisites `claude rc` needs: the CLI, a logged-in account, and the workspace # trust dialog accepted for PROJECT_DIR. A UserPromptSubmit hook fires from inside a # session so these normally already hold; the check matters for Codex callers.+# Claude Code's own first-run state lives in ~/.claude.json: hasCompletedOnboarding, a+# theme, and per-folder hasTrustDialogAccepted. Claude REWRITES that file when it signs in,+# dropping whatever seeded it, and then `claude rc` sits on the trust prompt forever. So we+# do not merely CHECK those keys, we write the missing ones ourselves (never overwriting a+# value the user already set). arav-rog 2026-09-23: a fresh install lost the flags at+# sign-in, prereqs read "missing", and remote control never came up for a whole day.+seed_claude_flags() {+ command -v python3 >/dev/null 2>&1 || return 0+ python3 - "$HOME/.claude.json" "$PROJECT_DIR" <<'PY' 2>/dev/null || true+import json, os, sys+path, proj = sys.argv[1], sys.argv[2]+try:+ d = json.load(open(path))+except Exception:+ d = {}+changed = False+for k, v in (("hasCompletedOnboarding", True), ("theme", "dark")):+ if k not in d:+ d[k] = v; changed = True+pr = d.setdefault("projects", {}).setdefault(proj, {})+if not pr.get("hasTrustDialogAccepted"):+ pr["hasTrustDialogAccepted"] = True; changed = True+if changed:+ tmp = path + ".claude-rc.tmp"+ json.dump(d, open(tmp, "w"), indent=2)+ os.replace(tmp, path)+PY+}++# Is an account signed in? `claude rc` needs one; without it the server starts and dies.+signed_in() {+ [ -s "$HOME/.claude/.credentials.json" ] && return 0+ [ -n "${ANTHROPIC_API_KEY:-}" ] && return 0+ command -v python3 >/dev/null 2>&1 || return 1+ python3 - "$HOME/.claude/settings.json" <<'PY' 2>/dev/null+import json, sys+try:+ d = json.load(open(sys.argv[1]))+except Exception:+ sys.exit(1)+sys.exit(0 if (d.get("env") or {}).get("ANTHROPIC_API_KEY") else 1)+PY+}+ prereqs_ok() { command -v claude >/dev/null 2>&1 || return 1 [ -d "$PROJECT_DIR" ] || return 1+ signed_in || return 1+ seed_claude_flags command -v python3 >/dev/null 2>&1 || return 0 python3 - "$HOME/.claude.json" "$PROJECT_DIR" <<'PY' 2>/dev/null import json, sys@@ -236,6 +284,33 @@ cmd_enable() { fi fi }+# ---- ensure: remote control is ON by default on an Adom Hydrogen container ----------+# John 2026-09-23, after two boxes ran all day without it: have the bootstrap enable this on+# an ah container by default, so a fresh install has remote control from day one without+# anyone answering a prompt. Called by every bootstrap converge: quiet, cheap, idempotent.+# It NEVER overrides a human answer (declined/disabled stay), and hc keeps the offer flow.+cmd_ensure() {+ local verbose="${1:-}"+ is_ah || { [ "$verbose" = "--verbose" ] && echo "claude-rc: not an ah container; the prompt hook still offers it."; return 0; }+ case "$(state)" in+ declined|disabled) [ "$verbose" = "--verbose" ] && echo "claude-rc: $(state) by the user; leaving it alone."; return 0 ;;+ enabled)+ if [ -n "$(running_pid)" ]; then+ [ "$verbose" = "--verbose" ] && echo "claude-rc: already running (pid $(running_pid))."+ else+ check+ fi+ return 0 ;;+ esac+ if ! prereqs_ok; then+ # Not signed in yet is the normal case on a brand-new box: stay `unasked` and try again on+ # the next converge, so remote control starts as soon as the user signs Claude Code in.+ [ "$verbose" = "--verbose" ] && echo "claude-rc: prerequisites not met yet (sign in to Claude Code); will try again next sweep."+ return 0+ fi+ cmd_enable+}+ cmd_decline() { st_set state declined; st_set declined_at "$(now)"; cron_remove; echo "claude-rc: declined. The hook will not offer again; 'claude-rc enable' turns it on later."; } cmd_disable() { st_set state disabled; cron_remove@@ -284,12 +359,13 @@ main() { hook) cmd_hook ;; check) check ;; enable) cmd_enable ;;+ ensure) cmd_ensure "${2:-}" ;; decline) cmd_decline ;; disable) cmd_disable ;; status) cmd_status ;; logs) cmd_logs "${2:-40}" ;; -h|--help|help) sed -n 2,24p "$0" ;;- *) echo "claude-rc: unknown verb '$1' (hook|check|enable|decline|disable|status|logs)" >&2; exit 2 ;;+ *) echo "claude-rc: unknown verb '$1' (hook|check|ensure|enable|decline|disable|status|logs)" >&2; exit 2 ;; esac }
package.json+1−1@@ -1,6 +1,6 @@ { "slug": "hook",- "version": "1.3.5",+ "version": "1.3.6", "type": "app", "org": "adom", "bundled": true,
page.json+2−2@@ -1,6 +1,6 @@ { "slug": "hook",- "version": "1.3.5",+ "version": "1.3.6", "type": "app", "org": "adom", "bundled": true,@@ -79,4 +79,4 @@ } ], "tag": "latest"-}+}