plugins/languages/powershell/skills/windows-shell/SKILL.md
Windows cmd.exe and batch script (.bat / .cmd) compatibility subset for cases when PowerShell is unavailable or wrappers must run under legacy contexts. Covers setlocal / endlocal, enabledelayedexpansion (!var! vs %var%), %~dp0 / %~nx0 / %~f0 modifiers, errorlevel checks, FOR /F loops, doskey limits, argument quoting hazards, .bat vs .cmd differences, and decision rules for when to fall back to batch versus invoking pwsh. Use proactively when the user asks "写 batch 脚本 / cmd 脚本 / .bat / .cmd / Windows 批处理 / 调用 cmd". Also triggers on "cmd.exe", "batch", "setlocal", "errorlevel", "%~dp0", "doskey".
npx skillsauth add lazygophers/ccplugin powershell-windows-shellInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
PowerShell 是 Windows 自动化首选。仅在以下场景退回 batch:
任何复杂逻辑(数组 / 字典 / 错误处理)都不要写 batch;写
.ps1后用.cmdwrapper 启动。
.bat vs .cmd| 差异 | .bat | .cmd |
|------|--------|--------|
| 出身 | DOS 4DOS | Windows NT |
| ERRORLEVEL 在内部命令后行为 | 不更新 | 更新 |
| 兼容性 | 老系统也认 | NT 起 |
新脚本一律 .cmd。.bat 只为最大兼容性(极少需要)。
@echo off
setlocal EnableExtensions EnableDelayedExpansion
chcp 65001 >nul :: UTF-8(处理中文输出更稳)
set "SCRIPT_DIR=%~dp0" :: 脚本所在目录(带尾部 \)
set "SCRIPT_NAME=%~nx0"
@echo off:抑制命令回显(脚本第一行)。setlocal:把变量作用域限制到当前脚本(结束时自动 endlocal)。EnableDelayedExpansion:开启 !var! 实时展开,循环内必备。chcp 65001:UTF-8 代码页(Win 10 1903+ 稳定)。%0 脚本名(如调用方式中所写)
%~0 去除引号
%~f0 完整路径
%~d0 驱动器(C:)
%~p0 路径(不含驱动器)
%~dp0 驱动器 + 路径(脚本所在目录,**最常用**)
%~n0 文件名(不含扩展)
%~x0 扩展名
%~nx0 文件名 + 扩展
%~s0 短 8.3 路径
%~a0 属性
%~t0 修改时间
%~z0 大小
参数 %1 %2 ... 同理可叠加修饰符。%* 是全部参数。
set "name=alpha"
echo %name% :: 解析时展开
setlocal EnableDelayedExpansion
for %%i in (a b c) do (
set "current=%%i"
echo %current% :: ❌ 永远空(解析时一次性展开)
echo !current! :: ✅ 运行时展开
)
记住:%var% 在解析整段块时展开一次;!var! 在每次执行时展开。FOR / IF 块内总用 !。
some_command.exe
if errorlevel 1 (
echo failed
exit /b 1
)
:: 等价显式
some_command.exe
if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL%
注意:if errorlevel N 测试 >=N,不是 ==N。精确比较用 %ERRORLEVEL% equ N。
:: 遍历文件行
for /f "usebackq tokens=1,2 delims=:" %%a in ("config.txt") do (
echo key=%%a value=%%b
)
:: 捕获命令输出
for /f "usebackq delims=" %%i in (`git rev-parse HEAD`) do set "sha=%%i"
echo %sha%
| 选项 | 含义 |
|------|------|
| usebackq | 反引号执行命令 / 双引号是字符串 |
| tokens=1,2 | 取第 1、2 段 |
| delims=: | 分隔符 |
| skip=1 | 跳过开头 N 行 |
| eol=# | 行注释起始字符 |
@echo off
call :greet "world"
exit /b 0
:greet
setlocal
set "name=%~1"
echo Hello, %name%!
endlocal
exit /b 0
call :label 进函数,exit /b N 返回并设 errorlevel。
@echo off
:: 任何超过 20 行的逻辑:写 .ps1,这里只做 wrapper
where pwsh >nul 2>nul && (
pwsh -NoProfile -ExecutionPolicy Bypass -File "%~dp0script.ps1" %*
) || (
powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0script.ps1" %*
)
exit /b %ERRORLEVEL%
pwsh 是 PowerShell 7+,powershell 是 Windows PowerShell 5.1。-NoProfile 避免加载用户 profile(启动快、行为可预测)。-ExecutionPolicy Bypass 仅对当前进程,不改系统策略。batch 的引号处理极其反直觉:
set "var=hello world" :: ✅ 推荐:等号紧贴变量名,引号包整体
set var="hello world" :: ❌ var 的值真的含引号
if "%var%"=="hello" (...) :: ✅ 标准比较
:: 含空格的路径
"%~dp0bin\tool.exe" arg1 arg2 :: ✅
%~dp0bin\tool.exe arg1 arg2 :: ❌ 空格断行
doskey 定义 cmd 别名 仅当前 cmd 会话有效,且无法在 batch 内供后续行使用。别想用 doskey 写脚本。Windows 上"持久别名"的方案:
Set-Alias + $PROFILE。| 反模式 | 修正 |
|--------|------|
| 复杂逻辑用 batch | 改 .ps1 + .cmd wrapper |
| goto :EOF 当函数返回 | OK,但配合 call :label 与 exit /b 更明确 |
| 循环内忘记 EnableDelayedExpansion | 顶部加 setlocal |
| 引号 set var="x" 包含引号 | set "var=x" |
| 用 %var% 期望循环内更新 | 改 !var! |
| 忽略 errorlevel | 每个关键命令后 if errorlevel 1 exit /b 1 |
| 硬编码 C:\... | %~dp0 相对脚本 |
| 不设代码页 | 中文乱码;加 chcp 65001 |
| 需求 | batch 够? | 推荐 | |------|-----------|------| | 启动一个程序 + 设环境变量 | ✅ | batch wrapper | | 解析 JSON / 调用 REST | ❌ | PowerShell | | 错误恢复 / 复杂控制流 | ❌ | PowerShell | | 数组 / 字典 | ❌ | PowerShell | | 跨主版本兼容(XP+)启动器 | ✅ | batch | | 调用 MSI 安装 | ✅ | batch | | 文件批量处理 ≤ 5 行 | ✅ | batch / forfiles | | 调用 git / docker 流水 | △ | 倾向 PowerShell |
:: 临时回显
@echo on
:: 步进
pause :: 等用户按键
echo DEBUG: var=[%var%] :: 打印中间状态
:: 完整 trace
cmd /c "yourscript.cmd args" 2>&1 | tee trace.log
.cmd(除非真需 .bat)@echo off + setlocal EnableExtensions EnableDelayedExpansion%~dp0 相对脚本set "var=value"!var!.ps1,batch 仅 wrapperchcp 65001exit /b Ndevelopment
Go 数据库规范——GORM Model 命名 ModelXxx、表名单数、枚举 uint8 + 常量、索引 idx_ 前缀 + deleted_at leading column、禁 time.Time 统一 int64 unix、禁指针/nullable 字段、TEXT/BLOB/JSON 禁 default、AutoMigrate 禁改主键。设计 DB model、写 GORM tag、建索引、做 migration 审查时触发。
development
Go HTTP API 规范——响应始终 200 + body code 字段、路由 /api/* 全 POST 单段 <Action><Model>、中间件逐路由注册禁 Group(prefix,mw...)、handler 仅返回 (rsp,error)、认证走 header。设计 HTTP API、写路由/handler/中间件时触发。
development
Go 项目结构规范——三层架构(API → Impl → State)、全局状态模式、internal/ 私有包、cmd/ 仅 main.go、go.work 多模块、禁止 Repository 接口和 DI 容器、struct 公共字段开头全 omitempty、handler var rsp 顶声明、禁 legacy migration。设计项目骨架、新建目录、组织包、做架构评审时触发。
development
Go 命名规范——Id/Uid 字段(非 ID)、IsActive/HasMFA 布尔前缀、CreatedAt 时间字段、接收者统一用 p、包名全小写无下划线、泛型类型参数描述性命名、集合字段 xxx_list 禁 xxxs 复数、Enum 0 值 XxxNil 禁 Unknown、禁 Status 统一 State、Set/Update 语义区分。定义结构体字段、函数、变量、包、接收者名、泛型、枚举时触发。