hermes-official-plugins
☤ The official plugins for Hermes Agent, built and maintained by Nous Research: Home Assistant, Spotify, Claude Subscription DirectSDK and more, one install away from the Hermes plugin catalog.
Claude writes bash; the Bash tool runs zsh. This plugin makes zsh read those commands like bash.
PluginsGitHub @M1nu0x0Availability not checked yetOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Repository information has not been collected yet.
No updates detected yet. GitHub releases will appear here.
Makes the Bash tool's zsh read Claude's bash-style commands like bash: unmatched globs, word splitting, = words. Workaround for anthropics/claude-code#103027. KR/EN/JP README
Loading the full README.
Read the full README ↗Claude Code의 Bash 도구 셸이 zsh일 때, Claude가 bash 문법으로 쓴 명령을 zsh도 bash처럼 해석하게 해 주는 Claude Code 플러그인입니다.
macOS에서는 로그인 셸이 zsh라서 Bash 도구도 zsh로 명령을 실행합니다. 그런데 Claude는 bash 문법으로 명령을 쓰기 때문에, 매치 없는 glob, 따옴표 없는 변수, =로 시작하는 단어에서 명령이 멈추거나 조용히 다르게 동작합니다. 이 플러그인은 세션이 시작될 때 Bash 도구의 zsh에 no_nomatch, sh_word_split, no_equals 세 옵션을 켭니다.
또 Claude Code의 안전 검사는 ${(s/:/)PATH} 같은 zsh ${(flags)...} 확장을 파싱하지 못해, rm이 없는 명령도 rm 위험이 있다며 거부합니다. 이 플러그인의 PreToolUse 훅이 그보다 먼저 이런 명령을 거부하고, 모델에게 진짜 이유와 POSIX 형식으로 고쳐 쓰는 방법을 알려 줍니다.
Website · Releases · Changelog
| Claude가 쓴 명령 | zsh 기본값 | 이 플러그인 |
|---|---|---|
grep -rn TODO src --include=*.ts | (eval):1: no matches found: --include=*.ts, grep이 실행되지 않음 | grep이 *.ts 패턴을 받아 실행 |
echo =====; ls | (eval):1: ==== not found, 뒤 명령도 멈춤 | =====을 찍고 ls까지 실행 |
T="a.py b.py"; pytest $T | $T가 한 단어로 넘어가 a.py b.py라는 파일 하나를 찾음 | a.py, b.py 두 인자로 나뉨 |
print -l ${(s/:/)PATH} | rg -c / | 실행 전에 could not be checked for dangerous rm operations로 거부됨(명령에 rm은 없음) | 훅이 이유를 알려 거부하고, 모델이 POSIX sh로 고쳐 실행 |
anthropics/claude-code#103027 (Claude keeps writing bash syntax under zsh) 때문입니다.
이 이슈의 작성자는 2026년 7월 28일부터 10월 17일까지 자신의 transcript를 세어, Bash 도구 호출 61,040번 중 2,570번에서 zsh 오류가 났다고 보고했습니다. 9월 하순 이후로는 1,000번당 51번꼴로 늘었고, 그중 76%는 명령이 0으로 끝나서 오류가 출력 중간에 묻혔습니다. Claude가 zsh 탓이라고 알아챈 경우는 약 3%뿐이었습니다. 가장 많은 세 가지가 매치 없는 glob(--include=*.ts, ls libs/*/README.md)과 = 단어(echo ====)였고, 따옴표 없는 변수는 대부분 조용히 실패해서 셀 수 있었던 것보다 많을 것이라고 했습니다.
같은 문제는 앞서 #67146으로도 보고됐지만 활동이 없어 닫혔습니다. #103027이 Claude Code 안에서 고쳐지면 이 플러그인은 필요 없어지므로, 그때 레포를 보관(archive)할 예정입니다. CI가 매일 #103027의 상태를 확인합니다.
zsh 문법은 셸에 닿기 전에도 걸립니다. macOS auto 모드에서 print -l ${(s/:/)PATH} | rg -c /는 실행되지 않고 This command could not be checked for dangerous rm operations: the shell may read it differently than it was parsed.로 거부됩니다(#104925). 명령이 실행되기 전이라 zsh 오류가 아니고, setopt나 .zshenv는 zsh가 시작돼야 적용되므로 이 거부를 막지 못합니다. 같은 확장도 echo '${(s/:/)PATH}'처럼 작은따옴표 안에 있으면 실행됩니다. 외부 사용자의 분석(공식 확인은 아님)에 따르면 안전 검사는 tree-sitter-bash로 파싱하는데 이 문법에 ${(flags)...}가 없어 ERROR 노드가 되고, 그러면 rm 위험을 배제할 수 없다고 판단합니다. 근본 수정은 Claude Code가 세션 셸에 맞는 문법으로 파싱하거나, rm·rmdir이 없는 명령의 파싱 실패를 rm 위험으로 표시하지 않는 것입니다. 그렇게 고쳐지면 PreToolUse 훅과 아래의 세션 시작 안내를 뺄 예정입니다. CI가 매일 #104925의 상태도 확인합니다.
Claude Code 터미널 프롬프트에서:
/plugin install safe-zsh --marketplace M1nu0x0/claude-safe-zsh
Add marketplace?에 y를 누르고 scope는 user를 고릅니다. 셸에서는 이렇게 설치합니다.
claude plugin install safe-zsh --marketplace M1nu0x0/claude-safe-zsh
Claude Desktop에서는 프롬프트 옆 + → Plugins → Add marketplace에 M1nu0x0/claude-safe-zsh를 넣고 safe-zsh를 추가합니다.
설치한 뒤 새 세션부터 적용됩니다.
세션이 시작될 때(SessionStart: startup, resume, clear, compact) 훅이 $CLAUDE_ENV_FILE에 아래 한 줄을 씁니다.
if [ -n "${ZSH_VERSION:-}" ]; then setopt no_nomatch sh_word_split no_equals; fi
Claude Code는 CLAUDE_ENV_FILE의 내용을 Bash 도구 명령마다 앞에 붙여 같은 셸에서 실행합니다. 그래서 export뿐 아니라 setopt도 적용됩니다.
셸이 bash면 조건이 거짓이라 아무것도 하지 않고 0으로 끝납니다. [ ... ] && setopt 대신 if ... fi로 쓴 이유입니다.
셸이 zsh(CLAUDE_CODE_SHELL이 있으면 그 값, 없으면 $SHELL)이면 훅이 stdout으로 두 줄을 더 냅니다. SessionStart 훅의 stdout은 모델에게 전달됩니다.
zsh -c는 위 옵션을 물려받지 않으니 스크립트 맨 앞에 setopt no_nomatch sh_word_split no_equals;를 붙이거나, bash 문법이면 bash -c를 쓰라는 안내. 도구나 스크립트가 띄우는 자식 zsh에는 닿지 않습니다.${(s/:/)PATH}, ${(@f)...} 같은 zsh ${(flags)...} 확장은 안전 검사가 파싱하지 못해 실행 전에 rm 위험으로 거부되고 setopt로도 막을 수 없으니, printf '%s\n' "$PATH" | tr ':' '\n', while IFS= read -r line; do ...; done < file처럼 POSIX sh로 쓰라는 안내(#104925). 모델이 그래도 쓰면 아래 PreToolUse 훅이 거부합니다.모델이 두 안내를 따르지 않을 수 있습니다.
CLAUDE_ENV_FILE이 없으면 훅은 아무것도 쓰지 않고 0으로 끝납니다. resume이나 compact 때 같은 줄이 다시 쓰여도 setopt가 반복될 뿐입니다.
${(flags)...} 명령 거부(PreToolUse)${(flags)...}를 쓸 수 있으므로, Bash 도구 명령마다 PreToolUse 훅이 Claude Code의 안전 검사보다 먼저 명령을 읽습니다. 작은따옴표 안은 글자 그대로이므로 빼고, 남은 부분에 ${(가 있으면 거부합니다.rm 위험으로 거부될 것이라는 설명, POSIX sh로 고쳐 쓰는 방법(printf '%s\n' "$PATH" | tr ':' '\n', while IFS= read -r line; do ...; done < file), zsh -c·eval·스크립트로 감싸 검사를 피하지 말라는 것, heredoc 안의 글자라면 Write 도구로 파일을 쓰라는 것입니다.${(가 없으면 아무것도 출력하지 않으므로, Claude Code는 플러그인이 없을 때와 똑같이 판단합니다.zsh -c로 감싸는 자동 변환은 넣지 않았습니다. 안전 검사를 피하게 만들 수 있기 때문입니다.Claude Code 2.1.318, macOS의 claude -p --permission-mode auto에서 PreToolUse만 호출되고 PermissionRequest와 PermissionDenied는 호출되지 않았습니다. 거부 뒤 모델이 echo "$PATH" | tr ':' '\n' | rg -c /로 고쳐 다시 실행해 결과를 얻었습니다.
This is the beginning of the README. Read the rest at the original. Read the full README ↗