Releases: subinium/hey-cli
Releases · subinium/hey-cli
v0.6.0
Security
- Risk gate: three dead branches fixed.
curl ... | sh/wget ... | bash(and... | sudo bash) were not warned because the segment-level check looked for|inside a segment whose|had already been consumed bysplit_segments. The detection moved to the whole-command level, mirroringcontains_decoded_shell, and strips plumbing on the consumer side sosudo bashis also caught. Rscript -e '...'now warns. The interpreter match arm matched"Rscript", butnormalize_for_risklowercases the input — the arm was unreachable.tee file < /dev/nullnow blocks.teeopens its arg files withO_TRUNC, so reading EOF from/dev/nulltruncates them. The previous segment-level check was unreachable for the same reason ascurl|sh. Detection moved to the whole-command level.- 6 new unit tests for the regressions above.
UX
- Preset rewrite preview. When
apply_presetsswaps the binary the model returned for a different one (cat → bat,cat → jq,ls → eza,tree → eza,diff → delta), a single dim line under the command shows what changed. Pure flag additions (grep --color,tree -C) stay silent. Helps users distinguish local rewrites from model output. Use--rawto disable.
Release
- SHA-256 checksums published.
taiki-e/upload-rust-binary-actionnow emits a<archive>.sha256file alongside each release archive. Verifiable withshasum -a 256 -c hey-aarch64-apple-darwin.tar.gz.sha256. Useful for the upcoming Homebrew tap and any curl-based installer.
v0.5.0
Fixed
- Shell command line no longer erased —
print_thinkingcounted theart[0]/ fallbackthinking…row as an extra line advance even though it had no trailing\n.clear_thinkingthen walked one line too far up, and the final\r\x1b[Jwiped the user's original$ hey …prompt line from the terminal. The off-by-one is fixed, so the shell command that invokedheystays visible in scrollback. - Thinking block spacing matches the result view — added a blank row between the backend label and the mascot so the thinking layout has the same vertical rhythm as
print_command_block's output. Previously the label and mascot touched during thinking, then a gap appeared once the result rendered.
v0.4.0
Security audit + UX pass. Breaking in a few narrow places but safer everywhere.
Security
- Risk gate rewritten with segment-aware parsing so command substitutions (
$(rm ...),<(rm ...),>(rm ...), backticks) and process substitution now classify correctly instead of silently bypassing as Safe. - Whitespace obfuscation blocked —
rmhidden by tabs,$IFS,${IFS}is caught. - Interpreter guard —
python -c,perl -e,node -e,ruby -e,awk 'BEGIN{...'surface Warn so obfuscated destructive calls don't land as Safe. - Decoded shell pipes blocked —
base64 -d | sh,xxd -r | bash,openssl enc -d | shnow Block. - More destructive primitives blocked —
truncate,: > file,true > file,cp /dev/null target,git reset --hard,git clean -fd,git push --force. rmfalse-positive fixed — v0.3 blocked anything containing the tokenrm(includinggrep rm logfile). v0.4 only blocks whenrmis a command-position first token of a segment.- Content filter expanded — fine-grained GitHub PATs (
ghu_,ghs_,ghr_,github_pat_), Stripe, SendGrid, HuggingFace, JWT, Google service-account JSON, Azure storage, and any URL with embedded credentials (scheme://user:pass@host). - Codex tempfile hardened — replaced predictable
/tmp/ait-codex-<pid>.txtwithtempfile::NamedTempFile(O_EXCL, mode 0600, auto-cleanup on Drop). Closes a symlink/TOCTOU vector. - Codex prompt via stdin — was visible in
ps//proc/<pid>/cmdline; now piped via stdin. - HTTP response size cap (1 MiB) — OpenRouter and direct Anthropic API responses are Content-Length-checked and capped during read.
- ANSI escape sanitization — model output and backend error text is stripped of ESC sequences (CSI / OSC) before display, closing OSC-52 clipboard-injection.
hey doctorno longer leaks key body — shows only the public prefix (sk-or-v1-****).- 19 unit tests added for the risk gate.
UX
hey doctor— new diagnostic subcommand. Shows detected backends, preset tools, shell/TTY state, env-var config, and the active auto chain.hey init <shell>— emits a shell completion script (bash / zsh / fish / powershell / elvish).- Stdin prompt support —
echo "list docker containers" | hey --yes. Requires--yesor--dry-runsince confirm can't read. - EOF = abort — pressing Ctrl-D (or piping
hey foo < /dev/null) now aborts withaborted (no input)instead of silently running. - Warn requires explicit
y— forRisk::Warncommands the default is capitalN; blank Enter aborts. - Stdout-not-TTY refusal —
hey foo | headused to hang; now errors with a suggestion to pass--yesor--dry-run. - Edit → copy & edit in shell —
eat the confirm prompt copies the command to your clipboard, reports whether the copy succeeded, and aborts. Paste in your shell for readline editing. - Richer help text and error messages —
--helpdocuments subcommand-style backend selection;OPENROUTER_API_KEY not setpoints atopenrouter.ai/keys; Claudenot authenticatedsurfacesclaude login. - Narrow-terminal-safe thinking animation — uses
\x1b[Jso wrapped lines don't leave cruft on <70-col terminals.
Breaking changes
orshorthand foropenrouterremoved — too ambiguous with the English preposition.- Backend subcommand matching is now case-sensitive lowercase —
hey Claude is fastis a prompt. Risk::Warnno longer defaults to Yes on blank Enter.- EOF on the confirm prompt aborts instead of running.
hey foo | headrefuses without--yes/--dry-run.
v0.3.0
hey v0.3.0
v0.2.3
hey v0.2.3 — ASCII art personas + du-dot fix
v0.2.2
Changed
- Claude backend fast-path — when
ANTHROPIC_API_KEYis set,hey claude ...calls the Anthropic Messages API directly via HTTP (~2s) instead of spawningclaude -p(~6s). Falls back to the subprocess when no key is present. - Code split into 12 modules —
main.rswent from 1056 lines to 224. Backend logic, risk gate, presets, sanitizer, UI, and style constants each live in their own file. - ANSI constants extracted — duplicated
\x1b[...escape codes replaced with named constants insrc/style.rs(GRAY,RESET,DIM,BOLD_WHITE, etc.). which_bin()now cached — binary lookups (eza,bat,jq,delta,claude,codex) are scanned once at startup into aOnceLock<HashMap>instead of re-scanning PATH on every call.prettify_commandinlined — thin wrapper removed; callers useapply_presets()directly.- Function-level
useimports moved to module scope.
v0.2.1
Added
- Content filter — prompts containing API keys (
sk-ant-,sk-or-,AKIA...,ghp_,gho_,glpat-,xoxb-,xoxp-), private key headers (-----BEGIN RSA PRIVATE, etc.) are blocked before being sent to any backend. Shows which pattern matched. Override with--allow-sensitive.
Improved
- System prompt compressed — ~600 tokens → ~120 tokens, saving ~480 input tokens per request. Prompt text is stable to maximize OpenRouter's automatic 5-minute cache TTL.
- max_tokens reduced — 512 → 256. Shell commands are rarely > 50 tokens; tighter cap reduces latency and cost.
- HTTP-Referer/X-Title headers — updated from old
aitbranding tohey-cli.
v0.2.0
Added
- Auto-fallback chain — when
heyruns in auto mode and the first backend fails (rate limit, auth, network), it surfaces a short inline notice and transparently retries with the next available backend. Chain isclaude → codex → openrouter, filtered by what's installed. - Codex rate-limit detection —
heynow inspects Codex stdout/stderr/output-file for rate-limit and quota markers and produces a friendly"codex is rate-limited — try 'hey claude ...' or 'hey openrouter ...' instead"instead of a raw subprocess error. - Codex auth-error detection —
"not authenticated"errors fromcodex execnow produce a clear"run 'codex login' first"message.
Fixed
hey:error prefix (was still showing the oldait:project name)- Codex backend swallowing stdout — useful diagnostic info is now aggregated from stdout, stderr, and the
-ooutput file before deciding what error to show.
v0.1.0
Initial release.
Added
hey <prompt>— convert natural language to a shell command and confirm before running- Three interchangeable backends: Claude Code headless, Codex CLI headless, OpenRouter HTTP API
- Auto backend selection:
claude → codex → openrouter - Subcommand-style backend override:
hey claude ...,hey codex ...,hey openrouter ... - Per-backend personas with icons and voices (
✱ claude,☁ codex,◆ openrouter) - Risk gate that blocks destructive commands (
rm,dd,mkfs,find -delete,-exec rm, shell-wrappedrm, fork bomb,git reset --hard, etc.) and copies them to the clipboard instead - Soft warnings for
sudo,cd,mv,chmod,chown, truncating redirects,curl | sh,kill - Conservative command presets: bare
ls/tree/catget rewritten toeza/jq/batwhen available --rawflag to disable all rewrites-y/--yesauto-confirm,-n/--dry-run,-e/--explain- Fenced-code-block sanitizer so model responses with triple-backtick wrappers are parsed correctly
- Strict prose detection — bail out if the backend returns non-command text