Shell Non-Interactive Strategy (Global)
Context: OpenCode's shell environment is strictly non-interactive. It lacks a TTY/PTY, meaning any command that waits for user input, confirmation, or launches a UI (editor/pager) will hang indefinitely and timeout.
Goal: Achieve parity with Claude Code's shell capabilities through internalized knowledge of non-interactive flags and environment variables.
Cognitive & Behavioral Standards
To match the high-agency, autonomous capabilities of advanced models (like Claude Sonnet), this strategy enforces strict cognitive patterns. These are not just shell tips; they are behavioral requirements for success in this environment.
Goal: Eliminate "human-in-the-loop" dependency during task execution.
Key Behaviors:
Process Continuity (Turn-Taking):
-
Rule: Never stop after a tool output to "wait for instructions" unless the task is complete.
-
Why: The environment is non-interactive. You must drive the workflow.
-
Mechanism: Commands expecting input MUST use timeouts or explicit "yes" pipes.
Explicit Action Framing (Positive Constraints):
-
Rule: Follow "GOOD" (positive) instructions, ignore "BAD" (negative) assumptions.
-
Why: Models follow explicit directives ("Use -y") better than prohibitions ("Don't prompt").
-
Mechanism: Always preemptively supply non-interactive flags.
Environment Rigor (Context Awareness):
-
Rule: Assume a headless CI environment where any prompt = failure.
-
Why: There is no TTY. "Asking the user" via a shell prompt causes a hang.
-
Mechanism: Strictly avoid editors, pagers, and interactive modes.
Core Mandates
-
Assume CI=true : Act as if running in a headless CI/CD pipeline.
-
No Editors/Pagers: vim , nano , less , more , man are BANNED.
-
Force & Yes: Always preemptively supply "yes" or "force" flags.
-
Use Tools: Prefer Read /Write /Edit tools over shell manipulation (sed , echo , cat ).
-
No Interactive Modes: Never use -i or -p flags that require user input.
Environment Variables (Auto-Set)
These environment variables help prevent interactive prompts:
Variable Value Purpose
CI
true
General CI detection
DEBIAN_FRONTEND
noninteractive
Apt/dpkg prompts
GIT_TERMINAL_PROMPT
0
Git auth prompts
GIT_EDITOR
true
Block git editor
GIT_PAGER
cat
Disable git pager
PAGER
cat
Disable system pager
GCM_INTERACTIVE
never
Git credential manager
HOMEBREW_NO_AUTO_UPDATE
1
Homebrew updates
npm_config_yes
true
NPM prompts
PIP_NO_INPUT
1
Pip prompts
YARN_ENABLE_IMMUTABLE_INSTALLS
false
Yarn lockfile
Command Reference
Package Managers
Tool Interactive (BAD) Non-Interactive (GOOD)
NPM npm init
npm init -y
NPM npm install
npm install --yes
Yarn yarn install
yarn install --non-interactive
PNPM pnpm install
pnpm install --reporter=silent
Bun bun init
bun init -y
APT apt-get install pkg
apt-get install -y pkg
APT apt-get upgrade
apt-get upgrade -y
PIP pip install pkg
pip install --no-input pkg
Homebrew brew install pkg
HOMEBREW_NO_AUTO_UPDATE=1 brew install pkg
Git Operations
Action Interactive (BAD) Non-Interactive (GOOD)
Commit git commit
git commit -m "msg"
Merge git merge branch
git merge --no-edit branch
Pull git pull
git pull --no-edit
Rebase git rebase -i
git rebase (non-interactive)
Add git add -p
git add . or git add <file>
Stash git stash pop (conflicts) git stash pop or handle manually
Log git log (pager) git log --no-pager or git log -n 10
Diff git diff (pager) git diff --no-pager or git --no-pager diff
System & Files
Tool Interactive (BAD) Non-Interactive (GOOD)
RM rm file (prompts) rm -f file
RM rm -i file
rm -f file
CP cp -i a b
cp -f a b
MV mv -i a b
mv -f a b
Unzip unzip file.zip
unzip -o file.zip
Tar tar xf file.tar
tar xf file.tar (usually safe)
SSH ssh host
ssh -o BatchMode=yes -o StrictHostKeyChecking=no host
SCP scp file host:
scp -o BatchMode=yes file host:
Curl curl url
curl -fsSL url
Wget wget url
wget -q url
Docker
Action Interactive (BAD) Non-Interactive (GOOD)
Run docker run -it image
docker run image
Exec docker exec -it container bash
docker exec container cmd
Build docker build .
docker build --progress=plain .
Compose docker-compose up
docker-compose up -d
Python/Node REPLs
Tool Interactive (BAD) Non-Interactive (GOOD)
Python python
python -c "code" or python script.py
Node node
node -e "code" or node script.js
IPython ipython
Never use - always python -c
Banned Commands (Will Always Hang)
These commands will hang indefinitely - never use them:
-
Editors: vim , vi , nano , emacs , pico , ed
-
Pagers: less , more , most , pg
-
Manual pages: man
-
Interactive git: git add -p , git rebase -i , git commit (without -m)
-
REPLs: python , node , irb , ghci (without script/command)
-
Interactive shells: bash -i , zsh -i
Handling Prompts
When a command doesn't have a non-interactive flag:
The "Yes" Pipe
yes | ./install_script.sh
Heredoc Input
./configure.sh <<EOF option1 option2 EOF
Echo Pipe
echo "password" | sudo -S command
Timeout Wrapper (last resort)
timeout 30 ./potentially_hanging_script.sh || echo "Timed out"
Alternatively, use a subshell to start the hanging command and kill it after completion (e.g., for starting a dev server).
Best Practices
-
Always test commands mentally for interactive prompts before running
-
Check man pages (via web search) for -y , --yes , --non-interactive , -f , --force flags
-
Use --help to discover non-interactive options: cmd --help | grep -i "non-interactive|force|yes"
-
Prefer OpenCode tools over shell commands for file operations
-
Set timeout for any command that might unexpectedly prompt
Advanced Instruction Patterns (Cognitive Optimization)
The Problem: Implicit Constraints
Large Language Models (LLMs) often struggle with:
-
Negative constraints: Inverting or ignoring "don't do X" instructions.
-
Turn termination: Stopping after tool execution instead of auto-continuing.
-
Context weighting: Failing to prioritize authoritative instructions over general knowledge.
Strategy 1: Explicit Action Framing (BAD vs GOOD)
This plugin uses the BAD vs GOOD pattern to enforce positive constraints. Instead of saying "Don't use interactive flags", we provide a concrete "Good" alternative.
Why it works:
-
"BAD: npm init" → Model identifies the failure pattern.
-
"GOOD: npm init -y" → Model receives a specific, executable instruction.
-
Result: Reduces hallucination of interactive commands by providing a verified substitute.
Strategy 2: Process Continuity
In non-interactive environments, the agent must drive the process forward.
The Rule: Never stop after a tool execution unless the task is complete.
Pattern:
- Execute command (e.g., git status)
- Analyze output
- Explicitly state next step: "Status is clean. Next: I will run tests."
- Execute next step immediately
Strategy 3: Context Hierarchy
When instructions conflict (e.g., generic docs vs this specific strategy), establish precedence:
-
Cite the Authority: "Per shell_strategy.md..."
-
Follow the Specifics: Rules in this file override general model training or other documentation.
Strategy 4: Applying These Patterns Beyond Shell
The cognitive strategies used here (Explicit Action Framing) apply to all coding tasks:
Instead of:
Do not use logging.getLogger() Don't create CLI code here
Use:
ALWAYS USE: config.logging_config.get_logger() USE THIS REPO FOR: API backend only
By framing instructions as "Actionable Positive Constraints", you reduce hallucination and improve compliance across all models.