diff --git a/README.md b/README.md
index 539f69d..e428764 100644
--- a/README.md
+++ b/README.md
@@ -37,6 +37,33 @@ curl -fsSL vidclaw.com/install.sh | bash
Installs Node.js, git, Tailscale, and VidClaw in one command. Localhost only: add `--no-tailscale`.
+### macOS / non-root OpenClaw installs
+
+VidClaw auto-detects `~/.openclaw` and common Homebrew OpenClaw install paths on macOS. If your OpenClaw install lives somewhere unusual, set environment variables before setup/start:
+
+```bash
+export OPENCLAW_DIR="$HOME/.openclaw"
+export OPENCLAW_BUNDLED_SKILLS_DIR="/opt/homebrew/lib/node_modules/openclaw/skills"
+./setup.sh
+```
+
+### Tailscale or custom bind host
+
+Recommended: keep VidClaw bound to localhost and publish it over Tailscale Serve:
+
+```bash
+./setup.sh --tailscale
+```
+
+If you explicitly want the managed service to bind to another interface instead, set `HOST` before running `./setup.sh`:
+
+```bash
+export HOST="100.70.53.60"
+./setup.sh
+```
+
+`./setup.sh` writes the launchd/systemd service definition. `./start.sh` and `./status.sh` do **not** rewrite that service config, so changing `HOST` or `OPENCLAW_*` variables later only takes effect after running `./setup.sh` again.
+
## Update
```bash
diff --git a/scripts/lib/service.sh b/scripts/lib/service.sh
index f9f8937..e2b0cab 100644
--- a/scripts/lib/service.sh
+++ b/scripts/lib/service.sh
@@ -95,7 +95,52 @@ systemd_escape_exec_arg() {
}
systemd_default_path() {
- printf '%s\n' '/usr/local/bin:/usr/bin:/bin'
+ printf '%s\n' '/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin'
+}
+
+service_env_var_names() {
+ printf '%s\n' \
+ NODE_ENV \
+ PORT \
+ HOST \
+ PATH \
+ OPENCLAW_DIR \
+ OPENCLAW_BUNDLED_SKILLS_DIR
+}
+
+service_env_var_value() {
+ case "$1" in
+ NODE_ENV) printf '%s\n' 'production' ;;
+ PORT) printf '%s\n' "${VIDCLAW_PORT}" ;;
+ HOST) printf '%s\n' "${HOST:-127.0.0.1}" ;;
+ PATH) printf '%s\n' '/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin' ;;
+ OPENCLAW_DIR) printf '%s\n' "${OPENCLAW_DIR:-${HOME}/.openclaw}" ;;
+ OPENCLAW_BUNDLED_SKILLS_DIR)
+ if [[ -n "${OPENCLAW_BUNDLED_SKILLS_DIR:-}" ]]; then
+ printf '%s\n' "${OPENCLAW_BUNDLED_SKILLS_DIR}"
+ fi
+ ;;
+ esac
+}
+
+service_environment_lines() {
+ local format="$1"
+ local key value
+ while IFS= read -r key; do
+ [[ -n "${key}" ]] || continue
+ value="$(service_env_var_value "${key}")"
+ [[ -n "${value}" ]] || continue
+ case "${format}" in
+ systemd)
+ printf 'Environment=%s=%s\n' "${key}" "${value}"
+ ;;
+ launchd)
+ printf ' %s\n %s\n' "${key}" "${value}"
+ ;;
+ *)
+ die "Unsupported service environment format: ${format}" ;;
+ esac
+ done < <(service_env_var_names)
}
write_systemd_unit_file() {
@@ -109,9 +154,10 @@ write_systemd_unit_file() {
tailscale_line="ExecStartPre=-$(tailscale_serve_cmd)"
fi
- local run_user run_group
+ local run_user run_group env_lines
run_user="$(id -un)"
run_group="$(id -gn)"
+ env_lines="$(service_environment_lines systemd)"
cat > "${tmp_file}" <"
fi
+ env_block="$(service_environment_lines launchd)"
+
cat > "${plist_path}" <
@@ -201,12 +248,7 @@ ${program_args}
EnvironmentVariables
- NODE_ENV
- production
- PORT
- ${VIDCLAW_PORT}
- PATH
- /opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin
+${env_block}
RunAtLoad