shell-preference.md 2.4 KB

Shell Preference — PowerShell by default (WSL is the exception)

Companion to cli-tools.md and modern-tools.md. Those pick which tool; this picks which shell syntax to hand the user.

The rule

On this machine the user ALWAYS uses Windows PowerShell. Every command you give the user to run must be PowerShell-native — never bash — UNLESS the current work is inside WSL (a Linux shell), where bash is the default.

The user's PowerShell is Windows PowerShell 5.1: no &&/|| chaining, no export, no \ line-continuation, no unix coreutils. Generate accordingly.

Why this matters

The user flagged this emphatically after being handed bash one-liners that errored on paste (The token '&&' is not a valid statement separator in this version). Bash syntax in their terminal is pure friction every time. They use PowerShell for everything except explicit WSL/Linux work.

How to apply — bash → PowerShell

Interactive-prompt lines (e.g. keeper get asking for a master password): tell the user to run that line alone, because a multi-line paste feeds the following lines into the prompt.

The WSL exception

When the work is explicitly in WSL / a Linux shell (the user says so, the cwd is a WSL path like /home/... or /mnt/..., or the task is clearly Linux), bash is the default there — give bash commands. Default to PowerShell whenever it's the normal Windows terminal.

Scope

This governs user-facing commands — what the user pastes into their terminal. The assistant's own Bash tool runs Git Bash internally and may keep using bash for its own execution; that's invisible to the user and fine. The rule is about what you hand the user to run.

Don't give the user Give instead
export NAME=value $env:NAME = "value"
cmd1 && cmd2 two separate lines (PS 5.1 has no &&). ; runs sequentially but does not stop on failure
cmd1 \` continuation one line, or backtick ` continuation
cd /x/Roam/BlockLab cd X:\Roam\BlockLab
grep PAT file Select-String -Path file -Pattern 'PAT'
jq '.x' f.json Get-Content f.json \| ConvertFrom-Json \| % { $_.x }
cat / cut -d= -f2 Get-Content / .Split('=')[1]
$(cmd) (cmd) (or $(cmd) works too, but (cmd) is idiomatic)
VAR=x cmd (inline env) $env:VAR='x'; cmd