Summary
Host-adaptation fixes (the OpenClaw ~/.openclaw/bin PATH symlink, the Cursor sandbox.json egress guidance) currently live in the plugin bundle hook (selat-plugins's ensure-runner.sh). They should move into selat-cli so they propagate reliably.
Why (the propagation gap)
The two update channels have very different reach:
| Channel |
Updates how |
Reaches existing users? |
Plugin bundle (selat-plugins) |
harness plugin-manager, manual on OpenClaw (openclaw plugins update) — no auto-update |
❌ not until they manually update |
npm runner (@selat-ai/selat-cli) |
SessionStart hook tracks latest, reinstalls each session — even on a stale bundle |
✅ automatically, next session |
A fix in the hook reaches no existing OpenClaw user until they manually update; a fix in the runner reaches everyone automatically. The adaptive logic is currently on the channel that doesn't propagate.
Principle
Thin bootstrap hook (bundle) + fat self-updating runner (npm). The hook's only irreducible job is the chicken-and-egg bootstrap (install/refresh the runner before it exists) + emit the SessionStart context. Everything host-adaptive moves into the runner.
What moves into selat-cli
- OpenClaw PATH symlink — runner self-links
realpath(process.argv[1]) into known on-PATH harness bin dirs when their marker dir exists (OpenClaw: ~/.openclaw → ~/.openclaw/bin/selat). Idempotent, fail-safe.
- Cursor sandbox-egress hint — emit the
.cursor/sandbox.json allowlist guidance when a catalog fetch actually fails in search/run (truer signal than the hook's preflight probe). Guidance only — never auto-write.
Tasks
Sequencing
Ship the runner change first; slim the hook in a later plugin release. During overlap both perform the symlink — harmless (idempotent).
Guardrails (unchanged)
- Never auto-widen a security boundary: Cursor
sandbox.json stays guidance only, never auto-written. (A PATH symlink into a harness's own bin dir is benign — auto-doing it is fine.)
- Self-custody invariant unchanged: no wallet auto-create/fund, no auto-pay.
Net
A host-adaptation fix becomes one selat-cli npm release → every existing install picks it up next session, across all harnesses, with zero bundle update.
Design doc: selat-pay/selat-distribution/2026-06-30-host-adaptation-migration.md
Summary
Host-adaptation fixes (the OpenClaw
~/.openclaw/binPATH symlink, the Cursorsandbox.jsonegress guidance) currently live in the plugin bundle hook (selat-plugins'sensure-runner.sh). They should move intoselat-cliso they propagate reliably.Why (the propagation gap)
The two update channels have very different reach:
selat-plugins)openclaw plugins update) — no auto-update@selat-ai/selat-cli)latest, reinstalls each session — even on a stale bundleA fix in the hook reaches no existing OpenClaw user until they manually update; a fix in the runner reaches everyone automatically. The adaptive logic is currently on the channel that doesn't propagate.
Principle
Thin bootstrap hook (bundle) + fat self-updating runner (npm). The hook's only irreducible job is the chicken-and-egg bootstrap (install/refresh the runner before it exists) + emit the SessionStart context. Everything host-adaptive moves into the runner.
What moves into selat-cli
realpath(process.argv[1])into known on-PATH harness bin dirs when their marker dir exists (OpenClaw:~/.openclaw→~/.openclaw/bin/selat). Idempotent, fail-safe..cursor/sandbox.jsonallowlist guidance when a catalog fetch actually fails insearch/run(truer signal than the hook's preflight probe). Guidance only — never auto-write.Tasks
lib/host.mjs:ensureHarnessPath()(generalized link table) +describeEgressBlock()(sandbox.json hint string).ensureHarnessPath()at the start ofdoctor,init,search,run(cheap, idempotent).search/runcatalog-fetch failure, surfacedescribeEgressBlock()instead of bare "fetch failed".selat-cli(trusted-publishing CI) → propagates via the hook'slatesttracking.ensure-runner.sh(drop the now-duplicatedlink_into+ sandbox probe; keep bootstrap + SessionStart context). Bump plugin once.selat initcurrently falls through tocreateWallets()and fails when the wallet slot is full — detect an existing agent wallet (listAgentWalletsDetailed/pickAgentAddress) and skip creation when the lookup missed it.Sequencing
Ship the runner change first; slim the hook in a later plugin release. During overlap both perform the symlink — harmless (idempotent).
Guardrails (unchanged)
sandbox.jsonstays guidance only, never auto-written. (A PATH symlink into a harness's own bin dir is benign — auto-doing it is fine.)Net
A host-adaptation fix becomes one
selat-clinpm release → every existing install picks it up next session, across all harnesses, with zero bundle update.Design doc:
selat-pay/selat-distribution/2026-06-30-host-adaptation-migration.md