Files
luci-app-openclaw/docs/superpowers/plans/2026-03-18-custom-install-root.md
lingyuzeng 68f24e6658 feat(storage): support configurable install root
Add a LuCI install-root input, persist the selected path in UCI,
and route install, status, backup, uninstall, and runtime scripts
through the configured storage root for new installs.

Reference: custom install root flow
2026-03-18 13:48:07 +08:00

5.3 KiB

Custom Install Root Implementation Plan

For agentic workers: REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Let new OpenClaw installs choose a LuCI-specified storage root and keep all runtime files under that configured root.

Architecture: Add a persisted UCI install-root setting, a shared shell path helper, and a small Lua path helper so UI checks and runtime scripts all derive the same directories. Keep /opt as the default and preserve the existing /openclaw/{node,global,data} subtree under whichever root the user selects.

Tech Stack: LuCI Lua, POSIX shell, Node.js runtime scripts, OpenWrt UCI


Task 1: Add failing path derivation tests

Files:

  • Create: tests/test_openclaw_paths.lua

  • Create: luasrc/openclaw/paths.lua

  • Step 1: Write the failing test

Create Lua assertions for:

  • default root -> /opt

  • /mnt/emmc/ -> /mnt/emmc

  • derived paths under <root>/openclaw

  • invalid relative paths fall back to /opt

  • Step 2: Run test to verify it fails

Run: lua /Users/lingyuzeng/project/luci-app-openclaw/tests/test_openclaw_paths.lua Expected: FAIL because luasrc/openclaw/paths.lua does not exist yet.

  • Step 3: Write minimal implementation

Add a pure-Lua helper exposing normalization and derived-path functions.

  • Step 4: Run test to verify it passes

Run: lua /Users/lingyuzeng/project/luci-app-openclaw/tests/test_openclaw_paths.lua Expected: PASS

Task 2: Add shared shell path helper

Files:

  • Create: root/usr/libexec/openclaw-paths.sh

  • Modify: Makefile

  • Step 1: Write the failing test

Extend the Lua test or add a shell smoke command that expects the helper to emit normalized install root and derived directories.

  • Step 2: Run test to verify it fails

Run: sh -c '. /Users/lingyuzeng/project/luci-app-openclaw/root/usr/libexec/openclaw-paths.sh; oc_load_paths' Expected: FAIL because the helper does not exist yet.

  • Step 3: Write minimal implementation

Implement helper functions for normalization, derived directories, and /opt-specific OverlayFS handling guards. Install the helper in the package Makefile.

  • Step 4: Run test to verify it passes

Run: sh -n /Users/lingyuzeng/project/luci-app-openclaw/root/usr/libexec/openclaw-paths.sh Expected: PASS

Task 3: Wire LuCI dialog and APIs

Files:

  • Modify: luasrc/model/cbi/openclaw/basic.lua

  • Modify: luasrc/controller/openclaw.lua

  • Modify: root/etc/config/openclaw

  • Step 1: Add failing coverage mindset

Use the existing Lua path test as the guardrail for normalization and manually confirm current UI/API code still hard-codes /opt.

  • Step 2: Implement API and dialog changes

Add:

  • UCI-backed default install root

  • dialog input and explanatory copy

  • check_system support for install_root

  • setup support for persisting the root and refusing live path switches

  • Step 3: Verify behavior

Run:

  • lua -e 'assert(loadfile("/Users/lingyuzeng/project/luci-app-openclaw/luasrc/controller/openclaw.lua"))'
  • lua -e 'assert(loadfile("/Users/lingyuzeng/project/luci-app-openclaw/luasrc/model/cbi/openclaw/basic.lua"))'

Expected: PASS

Task 4: Route runtime scripts through the configured root

Files:

  • Modify: root/usr/bin/openclaw-env

  • Modify: root/etc/init.d/openclaw

  • Modify: root/etc/profile.d/openclaw.sh

  • Modify: root/etc/uci-defaults/99-openclaw

  • Modify: root/usr/share/openclaw/oc-config.sh

  • Step 1: Update scripts

Source the shared shell helper, derive paths from UCI or OPENCLAW_INSTALL_ROOT, and keep the /opt workaround only for the default root.

  • Step 2: Verify syntax

Run:

  • sh -n /Users/lingyuzeng/project/luci-app-openclaw/root/usr/bin/openclaw-env
  • sh -n /Users/lingyuzeng/project/luci-app-openclaw/root/etc/init.d/openclaw
  • sh -n /Users/lingyuzeng/project/luci-app-openclaw/root/etc/profile.d/openclaw.sh
  • sh -n /Users/lingyuzeng/project/luci-app-openclaw/root/etc/uci-defaults/99-openclaw
  • sh -n /Users/lingyuzeng/project/luci-app-openclaw/root/usr/share/openclaw/oc-config.sh

Expected: PASS

Task 5: Fix remaining controller/runtime path call sites and verify

Files:

  • Modify: luasrc/controller/openclaw.lua

  • Modify: luasrc/model/cbi/openclaw/basic.lua

  • Modify: README.md

  • Step 1: Replace remaining hard-coded /opt/openclaw references used by user-facing flows

Cover status, uninstall, backup/restore, error hints, and install dialog copy.

  • Step 2: Run full verification

Run:

  • lua /Users/lingyuzeng/project/luci-app-openclaw/tests/test_openclaw_paths.lua
  • lua -e 'assert(loadfile("/Users/lingyuzeng/project/luci-app-openclaw/luasrc/controller/openclaw.lua"))'
  • lua -e 'assert(loadfile("/Users/lingyuzeng/project/luci-app-openclaw/luasrc/model/cbi/openclaw/basic.lua"))'
  • rg -n "/opt/openclaw" /Users/lingyuzeng/project/luci-app-openclaw

Expected:

  • tests and syntax checks PASS

  • remaining /opt/openclaw hits are limited to historical docs or intentional compatibility text

  • Step 3: Commit

git -C /Users/lingyuzeng/project/luci-app-openclaw add .
git -C /Users/lingyuzeng/project/luci-app-openclaw commit -m "feat: support configurable install root"