## Problem The command `curl URL | bash` isn't interactive because curl's output consumes bash's stdin, preventing user prompts from working. ## Solution Use bash process substitution instead: `bash <(curl URL)` This keeps stdin available for the script while downloading from curl. ## Changes - Added INTERACTIVE_CURL.md - Complete guide to interactive execution - Added NON_INTERACTIVE_MODE.md - Guide to automation/CI usage - Updated README.md to recommend `bash <(curl ...)` format - Documented OpenRouter URL alias pattern ## Recommended Usage Interactive (best UX): bash <(curl -fsSL https://openrouter.ai/lab/spawn/sprite/claude.sh) Non-interactive (CI/CD): SPRITE_NAME=dev-mk1 curl URL | bash ## Why Process Substitution? - Stdin available for prompts ✅ - Works like normal bash script ✅ - No /dev/tty workarounds needed ✅ - Better user experience ✅ Both methods are supported for maximum compatibility. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
5.6 KiB
Interactive Execution via curl
The Problem with Piping
When you run curl URL | bash:
- curl outputs the script to stdout
- stdout is piped to bash's stdin
- bash reads the script from stdin
- stdin is no longer available for the script to read user input
This is why /dev/tty tricks and other workarounds are needed.
The Solution: Process Substitution
Use bash process substitution instead of piping:
bash <(curl -fsSL URL)
How It Works
<(curl -fsSL URL)- Process substitution creates a temporary file descriptor- curl downloads the script and writes to this descriptor
- bash reads the script from the file descriptor
- stdin remains connected to your terminal for interactive input!
Comparison
❌ Piping (Not Interactive)
curl URL | bash
# - Script goes to bash's stdin
# - No stdin available for user input
# - Need /dev/tty workarounds
✅ Process Substitution (Fully Interactive)
bash <(curl -fsSL URL)
# - Script goes to file descriptor
# - stdin available for user input
# - Works like a normal bash script
Updated Usage Examples
Claude Code Setup (Interactive)
# Recommended - Fully interactive
bash <(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/sprite/claude.sh)
# Alternative - Non-interactive with env vars
SPRITE_NAME=dev-mk1 bash <(curl -fsSL https://raw.githubusercontent.com/.../claude.sh)
OpenClaw Setup (Interactive)
# Recommended - Fully interactive
bash <(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/sprite/openclaw.sh)
# Alternative - Non-interactive
SPRITE_NAME=dev-mk1 bash <(curl -fsSL https://raw.githubusercontent.com/.../openclaw.sh)
Why This Is Better
Process Substitution Advantages
✅ Fully interactive - stdin available for prompts
✅ No special code needed - Regular read commands work
✅ Cleaner implementation - No /dev/tty fallbacks required
✅ Works everywhere - bash/zsh on Linux/macOS
✅ Better UX - Users can see prompts and type naturally
Piping Disadvantages
❌ Not interactive by default - stdin consumed by bash
❌ Requires workarounds - Need /dev/tty, safe_read(), etc.
❌ Fragile - TTY may not be available (Docker, CI/CD)
❌ Poor UX - Needs env vars or fails with cryptic errors
Implementation Notes
Current Implementation (Supports Both)
Our scripts now support BOTH approaches:
-
Process substitution (recommended):
bash <(curl -fsSL URL) # Uses regular read commands, fully interactive -
Piping (fallback):
curl URL | bash # Fails gracefully, shows helpful error: # "Set SPRITE_NAME environment variable for non-interactive usage" -
Non-interactive (CI/CD):
SPRITE_NAME=dev-mk1 curl URL | bash # Works without prompts
Simplification Opportunity
If we only recommend process substitution, we could:
- Remove
safe_read()complexity - Remove environment variable checks
- Use simple
read -p "prompt: " vareverywhere - Simpler codebase
But we keep both because:
- Some tutorials/docs use piping pattern
- CI/CD needs non-interactive mode
- Environment variables are useful anyway
- Graceful degradation is better UX
Platform Support
✅ Supported Platforms
- bash (v3.0+) - Linux, macOS, WSL, Git Bash
- zsh - macOS, Linux
- Anywhere with
/dev/fdsupport
❌ Unsupported
- Very old shells without process substitution
sh(POSIX shell) - doesn't support<(...)- Some embedded/minimal environments
Fallback: Download the script first:
curl -fsSL URL -o script.sh
bash script.sh
rm script.sh
Examples
Test Interactive Mode
# This will prompt you for sprite name and guide through OAuth
bash <(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/sprite/claude.sh)
Expected output:
Claude Code on Sprite
Installing sprite CLI...
Enter sprite name: █
Test with Pre-Set Name
# Skips sprite name prompt, but OAuth is interactive
SPRITE_NAME=dev-mk1 bash <(curl -fsSL https://raw.githubusercontent.com/.../claude.sh)
Fully Automated
# No prompts at all
SPRITE_NAME=ci-test \
OPENROUTER_API_KEY=sk-or-v1-xxxxx \
bash <(curl -fsSL https://raw.githubusercontent.com/.../claude.sh)
Recommended Documentation Update
We should update README.md to show process substitution first:
Before (Current)
curl https://openrouter.ai/lab/spawn/sprite/claude.sh | bash
After (Recommended)
bash <(curl -fsSL https://openrouter.ai/lab/spawn/sprite/claude.sh)
This gives users the best experience by default while still supporting non-interactive usage.
Technical Details
What is Process Substitution?
In bash, <(command) is replaced with a file descriptor path like /dev/fd/63:
# This:
bash <(curl -fsSL URL)
# Becomes:
bash /dev/fd/63
# where /dev/fd/63 contains the curl output
stdin Flow
With piping:
Terminal stdin → curl (unused)
curl stdout → bash stdin (script)
bash needs input → NO STDIN AVAILABLE ❌
With process substitution:
Terminal stdin → bash stdin (available!) ✅
curl stdout → /dev/fd/63 (script)
bash reads script from /dev/fd/63
bash needs input → reads from stdin ✅
Security Considerations
Both methods have similar security profiles:
# Review before executing
curl -fsSL URL -o script.sh
cat script.sh # Review
bash script.sh
# Or review inline
curl -fsSL URL | less # Review
bash <(curl -fsSL URL) # Execute
Best practice: Always review scripts from the internet before executing them.