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.
翻訳待ち
リポジトリ情報はまだ収集していません。
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 ↗