#!/usr/bin/env bash # box-relay.sh — Lightweight Box Relay Client for Fleet Agent Containers. # # Enables fleet agents (646, pip, muse, opm) to access muse-cli level tools, # spawn subagents, send sidechat DMs, and inspect threads over the secure # exec-constrained HTTPS relay endpoint. # # Supports Bearer Token (EXEC_TOKEN or ~/.exec-token) AND SSH signature auth. # Endpoint: https://exec.muse-dev.online/exec (or Tailscale https://100.123.153.75:8444/exec) set -euo pipefail EXEC_URL="${EXEC_URL:-https://exec.muse-dev.online/exec}" AGENT="${BOX_AGENT:-${AGENT_NAME:-}}" TOKEN="${EXEC_TOKEN:-}" if [ -z "$TOKEN" ] && [ -f "$HOME/.exec-token" ]; then TOKEN="$(cat "$HOME/.exec-token" | tr -d '[:space:]')" fi # Detect agent identity if not set if [ -z "$AGENT" ]; then if [ -f "$HOME/.agent-name" ]; then AGENT="$(cat "$HOME/.agent-name" | tr -d '[:space:]')" elif echo "$HOSTNAME" | grep -qi "646"; then AGENT="646" elif echo "$HOSTNAME" | grep -qi "pip"; then AGENT="pip" elif echo "$HOSTNAME" | grep -qi "muse"; then AGENT="muse" elif echo "$HOSTNAME" | grep -qi "opm"; then AGENT="opm" elif echo "$HOSTNAME" | grep -qi "dev"; then AGENT="dev" elif echo "$HOSTNAME" | grep -qi "def"; then AGENT="def" else AGENT="646" fi fi # Helper: POST to exec endpoint call_exec() { local op="$1" local args_json="$2" if [ -n "$TOKEN" ]; then # Bearer token auth local body body=$(python3 -c "import json, sys; print(json.dumps({'op': sys.argv[1], 'args': json.loads(sys.argv[2])}))" "$op" "$args_json") local res res=$(curl -sk -sS -X POST "$EXEC_URL" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -H "User-Agent: Mozilla/5.0 (X11; Linux x86_64) Box-Relay/1.0" \ --data "$body") echo "$res" | python3 -c " import json, sys try: d = json.load(sys.stdin) if 'stdout' in d: sys.stdout.write(d['stdout']) elif 'error' in d: sys.stderr.write('Error: ' + str(d['error']) + '\n') sys.exit(1) else: print(json.dumps(d, indent=2)) except Exception as e: print(sys.stdin.read()) " else # Signature auth fallback local key="${SSH_KEY:-$HOME/.ssh/id_frontdoor}" if [ ! -f "$key" ] && [ -f "$HOME/.ssh/id_ed25519" ]; then key="$HOME/.ssh/id_ed25519" fi local ident="operator-$AGENT" if [ "$AGENT" = "super" ]; then ident="super" fi local ts ts=$(date +%s) local nonce nonce=$(python3 -c "import secrets; print(secrets.token_hex(16))") local payload payload=$(python3 -c " import json, sys op, args_json, ts, nonce = sys.argv[1:5] args = json.loads(args_json) print(json.dumps({'op': op, 'args': args, 'ts': int(ts), 'nonce': nonce})) " "$op" "$args_json" "$ts" "$nonce") local sig sig=$(printf '%s' "$payload" | ssh-keygen -Y sign -f "$key" -n exec-constrained 2>/dev/null) local body body=$(python3 -c " import json, sys ident, payload, sig = sys.argv[1:4] print(json.dumps({'identity': ident, 'payload': payload, 'signature': sig})) " "$ident" "$payload" "$sig") local res res=$(curl -sk -sS -X POST "$EXEC_URL" \ -H "Content-Type: application/json" \ -H "User-Agent: Mozilla/5.0 (X11; Linux x86_64) Box-Relay/1.0" \ --data "$body") echo "$res" | python3 -c " import json, sys try: d = json.load(sys.stdin) if 'stdout' in d: sys.stdout.write(d['stdout']) elif 'error' in d: sys.stderr.write('Error: ' + str(d['error']) + '\n') sys.exit(1) else: print(json.dumps(d, indent=2)) except Exception as e: print(sys.stdin.read()) " fi } cmd="${1:-help}" shift || true case "$cmd" in subagent) sub="${1:-help}" shift || true case "$sub" in spawn) title="subagent" wait=0 while [ $# -gt 0 ]; do case "$1" in --title) title="$2"; shift 2 ;; --wait) wait="$2"; shift 2 ;; --agent) AGENT="$2"; shift 2 ;; *) break ;; esac done prompt="${1:?usage: box subagent spawn [--title ] [--wait <seconds>] <prompt>}" args=$(python3 -c "import json, sys; print(json.dumps({'agent': sys.argv[1], 'title': sys.argv[2], 'prompt': sys.argv[3], 'wait': int(sys.argv[4])}))" "$AGENT" "$title" "$prompt" "$wait") call_exec "subagent.spawn" "$args" ;; *) echo "Usage: box subagent spawn [--title <title>] [--wait <seconds>] <prompt>" ;; esac ;; deploy) sub="${1:-help}" shift || true case "$sub" in subagent) title="subagent" wait=0 while [ $# -gt 0 ]; do case "$1" in --title) title="$2"; shift 2 ;; --wait) wait="$2"; shift 2 ;; --agent) AGENT="$2"; shift 2 ;; *) break ;; esac done prompt="${1:?usage: box deploy subagent [--title <title>] [--wait <seconds>] <prompt>}" args=$(python3 -c "import json, sys; print(json.dumps({'agent': sys.argv[1], 'title': sys.argv[2], 'prompt': sys.argv[3], 'wait': int(sys.argv[4])}))" "$AGENT" "$title" "$prompt" "$wait") call_exec "subagent.spawn" "$args" ;; pipeline) name="${1:?usage: box deploy pipeline <name>}" args=$(python3 -c "import json, sys; print(json.dumps({'name': sys.argv[1]}))" "$name") call_exec "pipeline.run" "$args" ;; *) echo "Usage: box deploy subagent|pipeline ..." ;; esac ;; dm) sub="${1:-help}" shift || true case "$sub" in send) to="" target="" from_agent="$AGENT" while [ $# -gt 0 ]; do case "$1" in --to) to="$2"; shift 2 ;; --target) target="$2"; shift 2 ;; --agent|--from) from_agent="$2"; shift 2 ;; *) break ;; esac done msg="${1:?usage: box dm send --to <agent> [--target <target>] <message>}" to="${to:-$AGENT}" target="${target:-$AGENT-pip}" args=$(python3 -c "import json, sys; print(json.dumps({'agent': sys.argv[1], 'to': sys.argv[2], 'target': sys.argv[3], 'message': sys.argv[4]}))" "$from_agent" "$to" "$target" "$msg") call_exec "dm.send" "$args" ;; read) target="${1:-main}" limit="${2:-10}" args=$(python3 -c "import json, sys; print(json.dumps({'agent': sys.argv[1], 'target': sys.argv[2], 'limit': int(sys.argv[3])}))" "$AGENT" "$target" "$limit") call_exec "dm.read" "$args" ;; log) limit="" log_agent="" while [ $# -gt 0 ]; do case "$1" in --agent) log_agent="$2"; shift 2 ;; *) if [ -z "$limit" ]; then limit="$1"; fi; shift ;; esac done limit="${limit:-20}" args=$(python3 -c "import json,sys; lim=int(sys.argv[1]); ag=sys.argv[2]; print(json.dumps({'limit':lim,**({'agent':ag} if ag else {})}))" "$limit" "$log_agent") call_exec "dm.log" "$args" ;; ack) to="" from_agent="" sidechat="" allow_main="" ref_id="" while [ $# -gt 0 ]; do case "$1" in --to) to="$2"; shift 2 ;; --sender|--from) from_agent="$2"; shift 2 ;; --sidechat) sidechat="$2"; shift 2 ;; --allow-main-chat) allow_main="1"; shift ;; *) if [ -z "$ref_id" ]; then ref_id="$1"; fi; shift ;; esac done ref_id="${ref_id:?usage: box dm ack <id> --to <agent> --sender <agent> [--sidechat <name>] [--allow-main-chat]}" from_agent="${from_agent:-$AGENT}" args=$(python3 -c " import json, sys ref, to, sender, sc, main = sys.argv[1:6] args = {'id': ref, 'to': to, 'sender': sender} if sc: args['sidechat'] = sc if main: args['allow_main_chat'] = True print(json.dumps(args)) " "$ref_id" "$to" "$from_agent" "$sidechat" "$allow_main") call_exec "dm.ack" "$args" ;; *) echo "Usage: box dm send|read|log|ack ..." ;; esac ;; notify) target_agent="${1:?usage: box notify <agent> [--sidechat <name>] [--sender <agent>] <message...>}" shift sidechat="" sender="" while [ $# -gt 0 ]; do case "$1" in --sidechat) sidechat="$2"; shift 2 ;; --sender|--from) sender="$2"; shift 2 ;; *) break ;; esac done msg="${*:?usage: box notify <agent> [--sidechat <name>] [--sender <agent>] <message...>}" args=$(python3 -c " import json, sys agent, message, sc, sender = sys.argv[1:5] args = {'agent': agent, 'message': message} if sc: args['sidechat'] = sc if sender: args['sender'] = sender print(json.dumps(args)) " "$target_agent" "$msg" "$sidechat" "$sender") call_exec "notify.send" "$args" ;; thread) sub="${1:-list}" shift || true case "$sub" in list) target_agent="${1:-$AGENT}" args=$(python3 -c "import json, sys; print(json.dumps({'agent': sys.argv[1]}))" "$target_agent") call_exec "thread.list" "$args" ;; view) target_agent="$AGENT" while [ $# -gt 0 ]; do case "$1" in --agent) target_agent="$2"; shift 2 ;; *) break ;; esac done if [ $# -ge 2 ] && echo " 646 opm pip muse dev def " | grep -q " $1 "; then target_agent="$1" shift fi thread_id="${1:?usage: box thread view [<agent>] <thread_id> [limit]}" limit="${2:-15}" args=$(python3 -c "import json, sys; print(json.dumps({'agent': sys.argv[1], 'thread': sys.argv[2], 'limit': int(sys.argv[3])}))" "$target_agent" "$thread_id" "$limit") call_exec "thread.view" "$args" ;; *) echo "Usage: box thread list|view ..." ;; esac ;; cron) sub="${1:-runs}" shift || true case "$sub" in runs|list) call_exec "cron.runs" "{}" ;; status) name="${1:-heartbeat}" args=$(python3 -c "import json, sys; print(json.dumps({'name': sys.argv[1]}))" "$name") call_exec "cron.status" "$args" ;; view) name="${1:?usage: box cron view <name>}" args=$(python3 -c "import json, sys; print(json.dumps({'name': sys.argv[1]}))" "$name") call_exec "cron.view" "$args" ;; run) name="${1:?usage: box cron run <name>}" args=$(python3 -c "import json, sys; print(json.dumps({'job': sys.argv[1]}))" "$name") call_exec "cron.run" "$args" ;; put) name="${1:?usage: box cron put <name> '<json-definition>'}" json_def="${2:?usage: box cron put <name> '<json-definition>'}" args=$(python3 -c " import json, sys try: definition = json.loads(sys.argv[2]) except Exception as e: sys.stderr.write('invalid job JSON: %s\n' % e) sys.exit(2) print(json.dumps({'name': sys.argv[1], 'definition': definition})) " "$name" "$json_def") call_exec "job.put" "$args" ;; trigger) name="${1:?usage: box cron trigger <name>}" args=$(python3 -c "import json, sys; print(json.dumps({'name': sys.argv[1]}))" "$name") call_exec "job.trigger" "$args" ;; chain) from_job="${1:?usage: box cron chain <from> <to> [--on-failure]}" shift || true on_failure="" to_job="" while [ $# -gt 0 ]; do case "$1" in --on-failure) on_failure="1"; shift ;; *) if [ -z "$to_job" ]; then to_job="$1"; fi; shift ;; esac done to_job="${to_job:?usage: box cron chain <from> <to> [--on-failure]}" args=$(python3 -c " import json, sys frm, to, onfail = sys.argv[1:4] args = {'from': frm, 'to': to} if onfail: args['on_failure'] = True print(json.dumps(args)) " "$from_job" "$to_job" "$on_failure") call_exec "job.chain" "$args" ;; next) job_id="" success="" while [ $# -gt 0 ]; do case "$1" in --success) success="1"; shift ;; --fail) success="0"; shift ;; *) if [ -z "$job_id" ]; then job_id="$1"; fi; shift ;; esac done job_id="${job_id:?usage: box cron next <job-id> [--success|--fail]}" args=$(python3 -c " import json, sys jid, success = sys.argv[1:3] args = {'job_id': jid} if success == '1': args['success'] = True elif success == '0': args['success'] = False print(json.dumps(args)) " "$job_id" "$success") call_exec "job.next" "$args" ;; timer-create) name="${1:?usage: box cron timer-create <name>}" args=$(python3 -c "import json, sys; print(json.dumps({'name': sys.argv[1]}))" "$name") call_exec "cron.timer_create" "$args" ;; timer-start) name="${1:?usage: box cron timer-start <name>}" args=$(python3 -c "import json, sys; print(json.dumps({'name': sys.argv[1]}))" "$name") call_exec "cron.timer_start" "$args" ;; *) echo "Usage: box cron runs|status|view|run|put|trigger|chain|next|timer-create|timer-start ..." ;; esac ;; timer) sub="${1:-list}" shift || true case "$sub" in create|set) name="${1:?usage: box timer create <name>}" args=$(python3 -c "import json, sys; print(json.dumps({'name': sys.argv[1]}))" "$name") call_exec "cron.timer_create" "$args" ;; start|enable) name="${1:?usage: box timer start <name>}" args=$(python3 -c "import json, sys; print(json.dumps({'name': sys.argv[1]}))" "$name") call_exec "cron.timer_start" "$args" ;; stop) name="${1:?usage: box timer stop <name>}" args=$(python3 -c "import json, sys; print(json.dumps({'name': sys.argv[1]}))" "$name") call_exec "cron.timer_stop" "$args" ;; disable) name="${1:?usage: box timer disable <name>}" args=$(python3 -c "import json, sys; print(json.dumps({'name': sys.argv[1]}))" "$name") call_exec "cron.timer_disable" "$args" ;; status|view|list) name="${1:-heartbeat}" args=$(python3 -c "import json, sys; print(json.dumps({'name': sys.argv[1]}))" "$name") call_exec "cron.status" "$args" ;; in|delay) min="${1:?usage: box timer in <minutes> <prompt>}" shift prompt="${*:?usage: box timer in <minutes> <prompt>}" args=$(python3 -c "import json, sys; print(json.dumps({'agent': sys.argv[1], 'in_m': float(sys.argv[2]), 'prompt': sys.argv[3]}))" "$AGENT" "$min" "$prompt") call_exec "followup.create" "$args" ;; *) echo "Usage: box timer create|start|stop|enable|disable|status <name> OR box timer in <minutes> <prompt>" ;; esac ;; followup) sub="${1:-create}" shift || true case "$sub" in create|set|schedule) min="${1:?usage: box followup create <minutes> <prompt>}" shift prompt="${*:?usage: box followup create <minutes> <prompt>}" args=$(python3 -c "import json, sys; print(json.dumps({'agent': sys.argv[1], 'in_m': float(sys.argv[2]), 'prompt': sys.argv[3]}))" "$AGENT" "$min" "$prompt") call_exec "followup.create" "$args" ;; *) echo "Usage: box followup create <minutes> <prompt>" ;; esac ;; swarm) sub="${1:-list}" shift || true case "$sub" in spawn) count="${1:?usage: box swarm spawn <count> <task...>}" shift task="$*" args=$(python3 -c "import json, sys; print(json.dumps({'count': int(sys.argv[1]), 'task': sys.argv[2]}))" "$count" "$task") call_exec "swarm.spawn" "$args" ;; status) sid="${1:?usage: box swarm status <swarm_id>}" args=$(python3 -c "import json, sys; print(json.dumps({'swarm_id': sys.argv[1]}))" "$sid") call_exec "swarm.status" "$args" ;; list) call_exec "swarm.list" "{}" ;; results) sid="${1:?usage: box swarm results <swarm_id>}" args=$(python3 -c "import json, sys; print(json.dumps({'swarm_id': sys.argv[1]}))" "$sid") call_exec "swarm.results" "$args" ;; *) echo "Usage: box swarm spawn|status|results|list ..." ;; esac ;; loop) sub="${1:?usage: box loop remediate|resolve ...}" shift || true case "$sub" in remediate) dry="" while [ $# -gt 0 ]; do case "$1" in --dry-run) dry="1"; shift ;; *) break ;; esac done if [ -n "$dry" ]; then args='{"dry_run": true}' else args='{}' fi call_exec "loop.remediate" "$args" ;; resolve) dm_id="${1:?usage: box loop resolve <dm_id> [note...]}" shift || true note="$*" args=$(python3 -c " import json, sys dm_id, note = sys.argv[1:3] args = {'dm_id': dm_id} if note: args['note'] = note print(json.dumps(args)) " "$dm_id" "$note") call_exec "loop.resolve" "$args" ;; *) echo "Usage: box loop remediate [--dry-run] OR box loop resolve <dm_id> [note...]" ;; esac ;; strat) sub="${1:?usage: box strat set|reset ...}" shift || true case "$sub" in set) stype="${1:?usage: box strat set <type> [options]}" shift || true subtype="" agent="" track="" priority="" timeout_s="" nudges="" escalate="" while [ $# -gt 0 ]; do case "$1" in --subtype) subtype="$2"; shift 2 ;; --agent) agent="$2"; shift 2 ;; --track) track="$2"; shift 2 ;; --priority) priority="$2"; shift 2 ;; --timeout) timeout_s="$2"; shift 2 ;; --nudges) nudges="$2"; shift 2 ;; --escalate) escalate="$2"; shift 2 ;; *) break ;; esac done args=$(python3 -c " import json, sys stype, subtype, agent, track, prio, timeout_s, nudges, esc = sys.argv[1:9] args = {'type': stype} if subtype: args['subtype'] = subtype if agent: args['agent'] = agent if track.lower() == 'true': args['track'] = True elif track.lower() == 'false': args['track'] = False elif track: sys.stderr.write('track must be true|false\n') sys.exit(2) if prio: args['priority'] = prio if timeout_s: args['timeout_s'] = int(timeout_s) if nudges: args['nudges'] = int(nudges) if esc: args['escalate'] = esc print(json.dumps(args)) " "$stype" "$subtype" "$agent" "$track" "$priority" "$timeout_s" "$nudges" "$escalate") call_exec "strat.set" "$args" ;; reset) stype="${1:?usage: box strat reset <type> [subtype] [--agent <agent>]}" shift || true subtype="" agent="" while [ $# -gt 0 ]; do case "$1" in --agent) agent="$2"; shift 2 ;; *) if [ -z "$subtype" ]; then subtype="$1"; fi; shift ;; esac done args=$(python3 -c " import json, sys stype, subtype, agent = sys.argv[1:4] args = {'type': stype} if subtype: args['subtype'] = subtype if agent: args['agent'] = agent print(json.dumps(args)) " "$stype" "$subtype" "$agent") call_exec "strat.reset" "$args" ;; *) echo "Usage: box strat set <type> [options] OR box strat reset <type> [subtype] [--agent <agent>]" ;; esac ;; vars) sub="${1:-list}" shift || true case "$sub" in list) call_exec "vars.list" "{}" ;; get) name="${1:?usage: box vars get <name>}" args=$(python3 -c "import json, sys; print(json.dumps({'name': sys.argv[1]}))" "$name") call_exec "vars.get" "$args" ;; set) name="${1:?usage: box vars set <name> <value>}" val="${2:?usage: box vars set <name> <value>}" args=$(python3 -c "import json, sys; print(json.dumps({'name': sys.argv[1], 'value': sys.argv[2]}))" "$name" "$val") call_exec "vars.set" "$args" ;; reset) name="${1:?usage: box vars reset <name>}" args=$(python3 -c "import json, sys; print(json.dumps({'name': sys.argv[1]}))" "$name") call_exec "vars.reset" "$args" ;; rollback) name="${1:?usage: box vars rollback <name> [revision]}" rev="${2:-}" args=$(python3 -c " import json, sys name, rev = sys.argv[1:3] args = {'name': name} if rev: args['revision'] = int(rev) if rev.isdigit() else rev print(json.dumps(args)) " "$name" "$rev") call_exec "vars.rollback" "$args" ;; *) echo "Usage: box vars list|get|set|reset|rollback ..." ;; esac ;; files) sub="${1:-read}" shift || true case "$sub" in read) path="${1:?usage: box files read <path> [lines=100]}" lines="${2:-100}" args=$(python3 -c "import json, sys; print(json.dumps({'path': sys.argv[1], 'lines': int(sys.argv[2])}))" "$path" "$lines") call_exec "files.read" "$args" ;; write) path="${1:?usage: box files write <path> <content>}" content="${2:?usage: box files write <path> <content>}" args=$(python3 -c "import json, sys; print(json.dumps({'path': sys.argv[1], 'content': sys.argv[2]}))" "$path" "$content") call_exec "files.write" "$args" ;; *) echo "Usage: box files read|write ..." ;; esac ;; web) sub="${1:-fetch}" shift || true case "$sub" in fetch) url="${1:?usage: box web fetch <url>}" args=$(python3 -c "import json, sys; print(json.dumps({'url': sys.argv[1]}))" "$url") call_exec "web.fetch" "$args" ;; *) echo "Usage: box web fetch <url>" ;; esac ;; service) sub="${1:-status}" shift || true case "$sub" in status) unit="${1:?usage: box service status <unit>}" args=$(python3 -c "import json, sys; print(json.dumps({'unit': sys.argv[1]}))" "$unit") call_exec "service.status" "$args" ;; restart) unit="${1:?usage: box service restart <unit>}" args=$(python3 -c "import json, sys; print(json.dumps({'unit': sys.argv[1]}))" "$unit") call_exec "service.restart" "$args" ;; *) echo "Usage: box service status|restart <unit>" ;; esac ;; git) sub="${1:-status}" shift || true case "$sub" in status) call_exec "git.status" "{}" ;; diff) stat="" path="" while [ $# -gt 0 ]; do case "$1" in --stat) stat="1"; shift ;; --path) path="$2"; shift 2 ;; *) if [ -z "$path" ]; then path="$1"; fi; shift ;; esac done args=$(python3 -c " import json, sys stat, path = sys.argv[1:3] args = {} if stat: args['stat'] = True if path: args['path'] = path print(json.dumps(args)) " "$stat" "$path") call_exec "git.diff" "$args" ;; log) limit="" path="" while [ $# -gt 0 ]; do case "$1" in --limit) limit="$2"; shift 2 ;; --path) path="$2"; shift 2 ;; *) if [ -z "$limit" ]; then limit="$1"; fi; shift ;; esac done limit="${limit:-10}" args=$(python3 -c " import json, sys limit, path = sys.argv[1:3] args = {'limit': int(limit)} if path: args['path'] = path print(json.dumps(args)) " "$limit" "$path") call_exec "git.log" "$args" ;; *) echo "Usage: box git status|diff|log ..." ;; esac ;; tests) sub="${1:-run}" shift || true case "$sub" in run) test_mod="" filt="" while [ $# -gt 0 ]; do case "$1" in --filter) filt="$2"; shift 2 ;; *) if [ -z "$test_mod" ]; then test_mod="$1"; fi; shift ;; esac done args=$(python3 -c " import json, sys mod, filt = sys.argv[1:3] args = {} if mod: args['test'] = mod if filt: args['filter'] = filt print(json.dumps(args)) " "$test_mod" "$filt") call_exec "tests.run" "$args" ;; *) echo "Usage: box tests run [tests.<module>] [--filter <pattern>]" ;; esac ;; approvals) sub="${1:-check}" shift || true case "$sub" in check) node="${1:-}" if [ -n "$node" ]; then args=$(python3 -c "import json, sys; print(json.dumps({'node': sys.argv[1]}))" "$node") else args="{}" fi call_exec "approval.check" "$args" ;; allow) node="" message="" main_chat="" while [ $# -gt 0 ]; do case "$1" in --message) message="$2"; shift 2 ;; --allow-main-chat) main_chat="1"; shift ;; *) if [ -z "$node" ]; then node="$1"; fi; shift ;; esac done node="${node:?usage: box approvals allow <node> --message <text> [--allow-main-chat]}" [ -n "$message" ] || { echo "usage: box approvals allow <node> --message <text> [--allow-main-chat]" >&2; exit 2; } args=$(python3 -c " import json, sys node, message, main = sys.argv[1:4] args = {'node': node, 'message': message} if main: args['allow_main_chat'] = True print(json.dumps(args)) " "$node" "$message" "$main_chat") call_exec "approval.allow" "$args" ;; deny) node="" message="" main_chat="" while [ $# -gt 0 ]; do case "$1" in --message) message="$2"; shift 2 ;; --allow-main-chat) main_chat="1"; shift 2 ;; *) if [ -z "$node" ]; then node="$1"; fi; shift ;; esac done node="${node:?usage: box approvals deny <node> --message <text> [--allow-main-chat]}" [ -n "$message" ] || { echo "usage: box approvals deny <node> --message <text> [--allow-main-chat]" >&2; exit 2; } args=$(python3 -c " import json, sys node, message, main = sys.argv[1:4] args = {'node': node, 'message': message} if main: args['allow_main_chat'] = True print(json.dumps(args)) " "$node" "$message" "$main_chat") call_exec "approval.deny" "$args" ;; auto) node="${1:-}" if [ -n "$node" ]; then args=$(python3 -c "import json, sys; print(json.dumps({'node': sys.argv[1]}))" "$node") else args="{}" fi call_exec "approval.auto" "$args" ;; *) echo "Usage: box approvals check|allow|deny|auto ..." ;; esac ;; md) sub="${1:-audit}" shift || true case "$sub" in audit) args=$(python3 -c " import json, sys accts = [a for a in sys.argv[1:] if a] print(json.dumps({'accounts': accts} if accts else {})) " "$@") call_exec "md.audit" "$args" ;; list) account="${1:?usage: box md list <account> [path]}" path="${2:-}" args=$(python3 -c "import json, sys; print(json.dumps({'account': sys.argv[1], 'path': sys.argv[2]}))" "$account" "$path") call_exec "md.list" "$args" ;; read) account="${1:?usage: box md read <account> <filename>}" filename="${2:?usage: box md read <account> <filename>}" args=$(python3 -c "import json, sys; print(json.dumps({'account': sys.argv[1], 'filename': sys.argv[2]}))" "$account" "$filename") call_exec "md.read" "$args" ;; diff) account="${1:?usage: box md diff <account> <filename>}" filename="${2:?usage: box md diff <account> <filename>}" args=$(python3 -c "import json, sys; print(json.dumps({'account': sys.argv[1], 'filename': sys.argv[2]}))" "$account" "$filename") call_exec "md.diff" "$args" ;; pull) account="${1:?usage: box md pull <account> <filename>}" filename="${2:?usage: box md pull <account> <filename>}" args=$(python3 -c "import json, sys; print(json.dumps({'account': sys.argv[1], 'filename': sys.argv[2]}))" "$account" "$filename") call_exec "md.pull" "$args" ;; inject-drive) account="${1:?usage: box md inject-drive <account>}" args=$(python3 -c "import json, sys; print(json.dumps({'account': sys.argv[1]}))" "$account") call_exec "md.inject_drive" "$args" ;; sync-all) call_exec "md.sync_all" "{}" ;; amend) filename="${1:?usage: box md amend <filename> (--content <text>|--file <path>) [--author <name>] [--reason <why>]}" shift || true content=""; content_src=""; author="operator"; reason="" while [ $# -gt 0 ]; do case "$1" in --content) content="$2"; content_src="arg"; shift 2 ;; --file) content="$2"; content_src="file"; shift 2 ;; --author) author="$2"; shift 2 ;; --reason) reason="$2"; shift 2 ;; *) echo "usage: box md amend <filename> (--content <text>|--file <path>) [--author <name>] [--reason <why>]" >&2; exit 2 ;; esac done [ -n "$content_src" ] || { echo "usage: box md amend <filename> (--content <text>|--file <path>) [--author <name>] [--reason <why>]" >&2; exit 2; } args=$(python3 -c " import json, sys fn, src, val, author, reason = sys.argv[1:6] content = open(val, encoding='utf-8').read() if src == 'file' else val args = {'filename': fn, 'content': content, 'author': author} if reason: args['reason'] = reason print(json.dumps(args)) " "$filename" "$content_src" "$content" "$author" "$reason") call_exec "md.amend" "$args" ;; append) filename="${1:?usage: box md append <filename> (--content <text>|--file <path>) [--author <name>] [--section <header>]}" shift || true text=""; text_src=""; author="operator"; section="" while [ $# -gt 0 ]; do case "$1" in --content) text="$2"; text_src="arg"; shift 2 ;; --file) text="$2"; text_src="file"; shift 2 ;; --author) author="$2"; shift 2 ;; --section) section="$2"; shift 2 ;; *) echo "usage: box md append <filename> (--content <text>|--file <path>) [--author <name>] [--section <header>]" >&2; exit 2 ;; esac done [ -n "$text_src" ] || { echo "usage: box md append <filename> (--content <text>|--file <path>) [--author <name>] [--section <header>]" >&2; exit 2; } args=$(python3 -c " import json, sys fn, src, val, author, section = sys.argv[1:6] text = open(val, encoding='utf-8').read() if src == 'file' else val args = {'filename': fn, 'text': text, 'author': author} if section: args['section'] = section print(json.dumps(args)) " "$filename" "$text_src" "$text" "$author" "$section") call_exec "md.append" "$args" ;; *) echo "Usage: box md audit|list|read|diff|pull|inject-drive|sync-all|amend|append ..." ;; esac ;; unread) target_agent="${1:-}" if [ -n "$target_agent" ]; then args=$(python3 -c "import json, sys; print(json.dumps({'agent': sys.argv[1]}))" "$target_agent") else args="{}" fi call_exec "fleet.unread" "$args" ;; health|fleet-status) call_exec "health.check" "{}" ;; cdp-latency) call_exec "cdp.latency" "{}" ;; chrome-errors) call_exec "chrome.errors" "{}" ;; watchdog-alerts) call_exec "watchdog.alerts" "{}" ;; relay-health) call_exec "relay.health" "{}" ;; quality|quality-check) call_exec "quality.check" "{}" ;; ping) call_exec "exec.ping" "{}" ;; ops) curl -sk -sS "${EXEC_URL%/exec}/ops" | python3 -m json.tool ;; help|--help|-h) cat <<EOF Box Relay Client — Agent CLI for autonomous coordination Usage: box subagent spawn [--title <title>] [--wait <s=0>] <prompt> box deploy subagent [--title <title>] [--wait <s=0>] <prompt> box deploy pipeline <name> box dm send --to <agent> [--target <target>] <message> box dm read [<target=main>] [<limit=10>] box dm log [<limit=20>] [--agent <agent>] box dm ack <id> --to <agent> --sender <agent> [--sidechat <name>] box notify <agent> [--sidechat <name>] [--sender <agent>] <message...> box thread list [<agent>] box thread view <thread_id> [<limit=15>] box cron runs box cron status [<name=heartbeat>] box cron view <name> box cron run <name> box cron put <name> '<json-definition>' box cron trigger <name> box cron chain <from> <to> [--on-failure] box cron next <job-id> [--success|--fail] box timer stop <name> box timer disable <name> box vars list box vars get <name> box vars set <name> <value> box vars reset <name> box vars rollback <name> [revision] box strat set <type> [--subtype S] [--agent A] [--track b] [--priority p] [--timeout N] [--nudges N] [--escalate E] box strat reset <type> [subtype] [--agent <agent>] box loop remediate [--dry-run] box loop resolve <dm_id> [note...] box files read <path> [lines=100] box files write <path> <content> box web fetch <url> box service status <unit> box service restart <unit> box git status box git diff [--stat] [--path <path>] box git log [<limit=10>] [--path <path>] box tests run [tests.<module>] [--filter <pattern>] box md audit [accounts...] box md list <account> [path] box md read <account> <filename> box md diff <account> <filename> box md pull <account> <filename> box md inject-drive <account> box md sync-all box md amend <filename> (--content <text>|--file <path>) [--author <name>] [--reason <why>] box md append <filename> (--content <text>|--file <path>) [--author <name>] [--section <header>] box approvals check [node] box approvals allow <node> --message <text> [--allow-main-chat] box approvals deny <node> --message <text> [--allow-main-chat] box approvals auto [node] box health box unread [<agent>] box ping box ops Configuration: EXEC_URL Endpoint (default: https://exec.muse-dev.online/exec) EXEC_TOKEN Bearer token (or store in ~/.exec-token) BOX_AGENT Agent identity (646, pip, muse, opm) EOF ;; *) echo "Unknown command: $cmd (run 'box help')" exit 1 ;; esac