* fix(install): harden stdin consumers to prevent pipe corruption in curl | bash Redirect stdin from /dev/null for non-interactive subprocesses (npm install, openclaw daemon restart, openclaw plugins update, openclaw dashboard) and from /dev/tty for interactive ones (openclaw onboard in bootstrap). Also protect the fallback paths in run_with_spinner and run_quiet_step. This prevents subprocesses from consuming the script stream when the installer is piped via curl | bash, which causes truncated function names and hangs (reported in #73814). Unlike the global pipe guard in #82918 (closed as too broad), this approach has no detection heuristics and no re-execution. Each subprocess simply gets the correct stdin for its purpose. Fixes #73814 Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca> * chore: retrigger proof evaluation Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca> * fix: redirect stdin in run_with_spinner raw-mode fallback The success-path raw-mode fallback in run_with_spinner invoked the command with inherited stdin. In a curl | bash scenario, this allowed the child process to consume bytes from the script stream, causing truncation. Add < /dev/null to match the other two fallback paths. * retrigger proof check * fix(test): update gum fallback assertion for stdin redirect * fix: redirect gum-wrapped stdin and preserve TTY for interactive commands Address ClawSweeper P1 and P2 findings: - P1: Redirect stdin from /dev/null on the normal gum spin path so child commands cannot consume the piped script stream (gum v0.17.0 passes os.Stdin to wrapped commands). - P2: Use is_non_interactive_shell to conditionally redirect stdin in fallback paths. When running interactively (bash install.sh), commands that need user input (e.g. Homebrew prompts) keep terminal stdin. When piped (curl | bash), stdin is redirected from /dev/null. - P2: Revert labeler.yml changes to keep the PR focused on installer stdin safety. Size-label best-effort handling belongs in a separate PR. Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca> * chore: retrigger proof evaluation Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca> * retrigger proof check * fix: base stdin isolation on stdin TTY check, not stdout Replace is_non_interactive_shell with needs_stdin_isolation for stdin redirection decisions. The new function checks stdin directly (! -t 0) and NO_PROMPT, without checking stdout (-t 1). This ensures that stdout redirection (e.g. install.sh > log.txt) does not suppress interactive prompts when stdin is a terminal. * test(install): add stdin isolation and NO_PROMPT coverage Three focused tests for the needs_stdin_isolation function: 1. Verify needs_stdin_isolation returns true when stdin is piped (the core curl|bash scenario). 2. Verify needs_stdin_isolation returns true when NO_PROMPT=1 is set (explicit non-interactive override). 3. Verify run_quiet_step redirects subprocess stdin to /dev/null when running in a piped context, preventing script consumption. * test(install): strengthen stdin isolation test with sentinel data Replace the weak TTY check (which passes even without the fix since the test pipe is also non-TTY) with a sentinel-based test: pipe SENTINEL_DATA on stdin and verify the child process reads nothing, proving run_quiet_step actually redirects stdin to /dev/null. * test(install): add counterproof and cat-based stdin isolation tests Add two new tests to prove the stdin isolation fix is necessary and works correctly: - counterproof: demonstrates that pipe data DOES leak to the child when stdin is not redirected through run_quiet_step, proving the /dev/null redirect is the isolation barrier - cat-based test: uses cat (reads all of stdin) instead of read -t 1 (timeout-based) for a deterministic assertion that run_quiet_step produces empty stdin * fix: gate gum spin stdin redirect on needs_stdin_isolation The gum spin command unconditionally redirected stdin from /dev/null, which also killed interactive prompts for direct installs since gum v0.17 passes os.Stdin to the wrapped command. Now only redirect stdin when needs_stdin_isolation returns true (piped install context). Adds focused tests verifying both paths: piped installs get /dev/null redirect, direct interactive installs preserve terminal stdin. * test: assert gum stdin is not /dev/null for direct interactive installs The direct gum runtime test now reads the child command's stdin-source log file and asserts stdin was NOT /dev/null, using device:inode comparison (stat -f on macOS, stat -c on Linux) for reliable detection across both platforms. * retrigger proof check * retrigger proof check with real installer evidence Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca> * fix(install): preserve interactive post-install stdin * fix(install): route piped prompts through controlling tty * fix(install): keep quiet piped steps noninteractive * fix(install): avoid hidden prompts with redirected output * fix(install): preserve visible prompt output state --------- Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca> Co-authored-by: Vincent Koc <25068+vincentkoc@users.noreply.github.com>
summary, read_when, title
| summary | read_when | title | |||
|---|---|---|---|---|---|
| Repository script entry points and compatibility notes |
|
Scripts Directory |
Scripts Directory
The scripts/ directory contains repository tooling used by local development,
CI, docs publishing, releases, Docker proof, and maintainer operations. Prefer
the package-script entry points in package.json when one exists, then read the
underlying script before running it directly.
Compatibility
Many scripts are stable paths referenced by package.json, GitHub Actions,
docs, and maintainer runbooks. Do not move, rename, or regroup scripts only to
improve taxonomy. A directory migration needs an explicit maintainer-approved
compatibility plan for package scripts, workflows, docs snippets, and any raw
script paths users may have copied.
This index is a discovery aid for the current flat layout. It does not define a new directory taxonomy.
Common Entry Points
| Area | Prefer | Notes |
|---|---|---|
| Build | pnpm build |
Runs scripts/build-all.mjs; use specific build scripts only when debugging a build stage. |
| Changed checks | pnpm changed:lanes --json, pnpm check:changed |
Lane classification lives in scripts/changed-lanes.mjs; changed-file checks live in scripts/check-changed.mjs. |
| Docs | pnpm docs:list, pnpm docs:check-mdx, pnpm docs:check-links |
Backed by scripts/docs-list.js, scripts/check-docs-mdx.mjs, and scripts/docs-link-audit.mjs. |
| Formatting docs | pnpm format:docs:check |
Uses scripts/format-docs.mjs; use write mode only when intentionally formatting docs. |
| Lint | pnpm lint, pnpm lint:core, pnpm lint:all |
Wrapper scripts keep oxlint behavior aligned with repo config. |
| Targeted tests | pnpm test <path-or-filter> or node scripts/run-vitest.mjs <path-or-filter> |
Avoid bare vitest; it can start watch mode. |
| Changed tests | pnpm test:changed |
Uses the repo's changed-test resolver instead of a broad Vitest run. |
| Docker proof | pnpm test:docker:all, pnpm test:docker:rerun, pnpm test:docker:timings |
Use the planner/rerun helpers before launching broad Docker work. |
| Live proof | pnpm test:live |
Live checks require the matching environment and credentials. |
| Release checks | pnpm release:check, pnpm release:beta, pnpm release:candidate |
Release scripts are maintainer workflows; read release docs before use. |
| GitHub reads | scripts/gh-read |
Uses a GitHub App read token when configured, leaving normal gh login for writes. |
| Commits | scripts/committer "<message>" <files...> |
Preferred scoped commit helper for OpenClaw changes. |
| Remote proof | node scripts/crabbox-wrapper.mjs ... |
Agent default for tests and heavy work; pre-warm by source trust, sync each run, reuse the lease. |
Script Families
check-*.mjs/check-*.ts: guardrails for architecture, docs, package contents, boundaries, workflows, and generated artifacts.run-*.mjs: wrappers around repo runtimes or tools, such as Node, Vitest, oxlint, tsgo, and environment setup.test-*.mjs/test-*.sh/test-*.ts: test planners, Docker lanes, live checks, and focused validation helpers.docs-*andcheck-docs-*: docs listing, link auditing, MDX checks, spellcheck, sync, and i18n glossary checks.release-*,openclaw-npm-*, andplugin-*-release-*: release preparation, package verification, and publishing helpers.docker-*,test-docker-*, andtest-live-*-docker.sh: Docker E2E planning, rerun, timing, and live/package lane helpers.gh-read*,label-*,sync-labels.ts, and PR helpers: GitHub read, labeling, and maintainer workflow support.generate-*,write-*,copy-*, andsync-*: generated docs, metadata, package surfaces, and build artifact support.lib/: shared helpers imported by script entry points.
Maintenance Rules
- Read
scripts/AGENTS.mdbefore changing scripts. - Keep package scripts, generators, generated-artifact checks, docs references, and workflow references aligned when touching a script path.
- Prefer existing wrappers instead of introducing a raw tool invocation.
- Add or update focused tests under
test/scripts/when changing script behavior.
See also Scripts for public-facing script guidance.