Repository navigation
Description
Background
hey confirms the suggested command in a TUI prompt and then Command::new($SHELL).arg("-c").arg(command) runs it as a child process (src/main.rs:336-345). This means:
cd,export,sourcecannot affect the parent shell — currently surfaced asWarnwith"affects only this subshell"(correct, but a workaround).- The user can't trivially edit the suggestion before running it (the confirm flow is yes/no/edit-in-place, not "hand it to my shell").
A common pattern in shell_gpt, aichat, and friends is a shell function that captures the suggested command and pushes it to the readline buffer (print -z in zsh, commandline in fish, READLINE_LINE in bash). The user sees the command on their prompt, can edit it, and runs it themselves.
Constraint
hey init <shell> is taken — it generates clap_complete scripts (src/completions.rs:11-20, dispatched at src/main.rs:62-65). Whatever this feature is called must not collide.
Shell-buffer mechanics (worth getting right up front)
- zsh:
print -z -- "$cmd"pushes onto the editor buffer stack; the line appears at the next prompt with the cursor at end. Works from a regular function. Fine. - fish:
commandline -- "$cmd"replaces the current command line inline. Works from a regular function. Fine. - bash:
READLINE_LINEis only writable from a function invoked viabind -x '"\C-g": _hey_edit'(i.e. a readline keybinding callback). A function called from the prompt cannot prefill the next buffer. Any bash story here requires the user to bind a key, or we accept "bash gets a less nice UX" (e.g. just copy to clipboard / print, no buffer push).
This is the load-bearing constraint — the bash limitation shapes the whole design.
Proposed shape
Two pieces:
- A clean-stdout mode in
hey. Today--dry-runprints a decorated TUI block viaprint_command_block(src/main.rs:238-246) — not capturable. Make--dry-runemit just the bare command on stdout whenstdoutis not a TTY (we already detect this atsrc/main.rs:121). No new flag needed. - A
hey init <shell>extension OR a sibling subcommand that prints a shell function the user sources. The function callshey --dry-run "$@" | <buffer-push>.
Open question: extend hey init to also emit the helper, or add a sibling like hey shell-init <shell>? The former is one install command but mixes completions + helper; the latter is symmetric but adds a subcommand. Leaning toward extending hey init since both are "shell glue" and the snippet is small.
Sketch
zsh:
hey-edit() {
local out
out="$(command hey --dry-run "$@")" || return
print -z -- "$out"
}fish:
function hey-edit
set -l out (command hey --dry-run $argv); or return
commandline -- $out
endbash (requires keybinding, not a plain function):
_hey_edit() {
local out
out="$(command hey --dry-run "${READLINE_LINE}")" || return
READLINE_LINE="$out"
READLINE_POINT=${#READLINE_LINE}
}
bind -x '"\C-g": _hey_edit' # type prompt, hit Ctrl-GThe bash flow is genuinely different (you type the prompt onto the command line first, then hit a binding). If that's too much UX divergence, bash can fall back to clipboard.
Why not always use this?
- Today
hey ls docker containersis one keystroke. Buffer insertion adds Enter. - Users who want pure execution shouldn't be forced to install a shell function.
Buffer insertion stays opt-in alongside the existing flow.
Out of scope
- PowerShell / Windows.
- Streaming the suggestion as it generates.
- Replacing the existing
confirm()prompt.
Decision points
- Reuse
--dry-run(+ make it TTY-aware) vs. add a dedicated--printflag? - Extend
hey init <shell>to emit completions + helper, or add a separatehey shell-init <shell>? - Bash:
bind -xsnippet, clipboard fallback, or skip bash for v1?
Activity