You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I really like the concept of this as a way to "draft" commands based on a natural language description of how it should work; however sometimes even after that you still need to iterate/tweak/fix and right now that means either issuing a new llm cmd prompt or manually copying and pasting the output to run again (which is a problem if the command involves the clipboard like mine just did). I'm not sure if there's a simple or cross-platform way to do it but it would be great if the command, once executed, populated the shell history just like if it were typed directly, so you could just up-arrow, tweak, and run again.
GPT4 suggested a few possibilities (given below) for executing a command from a script and populating the history, but the first option doesn't work in zsh, nor does it update the current session, so the up-arrow capability won't be there; and the second option doesn't appear to work from a script at all.
llm 'python execute command and populate shell history'
Executing commands from a Python script typically doesn't automatically populate the shell history of the terminal you're using like Bash or Zsh. Shell histories are usually managed internally by the shell itself, keeping track of the commands a user executes interactively within that shell session. When you're running something through Python's subprocess or other similar libraries/modules, you're not interacting directly with the shell in a way that it would normally log to its history.
However, if you have a specific requirement to add commands executed by a Python script to a shell history, you could technically do so by appending commands directly to the shell's history file or by using other workarounds. The implementation would depend on the shell you’re using. For example, Bash typically uses ~/.bash_history for storing the history.
Below are example approaches how you could potentially do this for Bash. Please use them with caution, considering security implications and ensuring they suit your use case.
Method 1: Directly Appending to Bash History File
This method directly appends the command to the ~/.bash_history file. Note that this will only update the history file and won’t be visible in the current session's history until a new session is started or the history is reloaded.
command="echo 'hello world'"# Execute the command# Include your method of executing the command here# Append to bash historywithopen(f"{os.getenv('HOME')}/.bash_history", 'a') ashistory_file:
history_file.write(f"{command}\n")
Method 2: Using the history -s Command
Another approach involves using the history -s command to add an entry to the current session's history. This, however, is trickier since you'd effectively need to execute this within the context of the shell, and it might not be directly applicable or effective from within a Python script running as a process separate from the shell.
As a more interactive workaround, you could consider having your Python script output the necessary shell commands to run (including history -s for Bash), then source a generated script from your Bash session or manually execute the commands it suggests.
General Consideration
Interacting with the shell history in this manner is uncommon and may have implications or introduce complexities in your workflows. It's crucial to consider why you need this functionality and whether there's a more straightforward approach to achieving your objectives (e.g., logging commands executed by a script to a separate file or system for audit or replication purposes).
Automatically doing this could interfere with the user's experience or expectations around the privacy and integrity of their shell history. Always ensure that your actions are secure, transparent to users, and compliant with any relevant policies or expectations.
An alternative is to use whatever mechanism shell autocomplete tools like fzf or qfc use to write to the actual shell prompt, and bypass the python script for execution entirely (also neatly solves the "editing the command" problem by delegating that to the shell as well). Some experimentation with zle suggests it has the capability to do this but cannot be used directly in a script only in "interactive" mode such as in response to a key press. I was able to implement a sort-of replacement for llm cmd that has the feature I want in zsh but it's a little clunky:
#!/usr/bin/env zsh# Pre-req: define an llm template with a system prompt as in https://simonwillison.net/2024/Mar/26/llm-cmd/# Doesn't use `llm cmd` directly because that has the "execution" built infunctionprint_cmd() {
# Get command to run by interpreting buffer contents as the prompt
cmd=$(llm -t cmd "${BUFFER}")# Replace contents of BUFFER
BUFFER=$cmd# Seek to the end of the line
zle end-of-line
}
zle -N llm_print_command print_cmd
bindkey "\C-f" llm_print_command
It's not ideal because (in addition to being zsh-specific) it requires the prompt to be entered, then the key Ctrl-f to be pressed, at which point the prompt is "erased" and replaced by the command to run. But at least the command once run is in the history and you can hit the up arrow to keep iterating/use fzf to recall it, etc.
Edit: I also found a (macOS-specific) way using AppleScript to emit keystrokes:
With llm-osascript.sh defined as:
#!/bin/sh
command_prompt="$@"
# Use the same "cmd" template as above
command=$(llm -t cmd "${command_prompt}")
script_cmd='tell application "System Events" to keystroke "'"${command//\"/\\\"}"'"'
osascript -e "${script_cmd}"
And marked executable:
chmod u+x llm-osascript.sh
After accepting the privilege escalation for your terminal:
As well as granting Accessibility permission to that terminal in response to:
36:71: execution error: System Events got an error: osascript is not allowed to send keystrokes. (1002)
You can run it directly (or alias to another command) akin to llm cmd:
I'm not sure why it prints the first few characters of the command on the first line and then jumps to the next, but it always prints the full command at the prompt as far as I can tell.
The text was updated successfully, but these errors were encountered:
I don't exactly understand how to use the first workaround; when I copy the code (except the first line) into my .zshrc and run print_cmd "Test", I get zle: widgets can only be called when ZLE is active"., and a quick search of the error does not yield anything that fixes it.
I don't exactly understand how to use the first workaround; when I copy the code (except the first line) into my .zshrc and run print_cmd "Test", I get zle: widgets can only be called when ZLE is active"., and a quick search of the error does not yield anything that fixes it.
Yes, that's kind of what I was alluding to with the comment:
it has the capability to do this but cannot be used directly in a script only in "interactive" mode such as in response to a key press
That is, you can't run the function as-is but when this is in your .zshrc (or sourced by it), you can activate the command using the bound key (Control-F in the example).
Also struggling with the command not populating the shell history. I find myself marking the command with my mouse and pasting back into the shell. Would love to avoid that.
I really like the concept of this as a way to "draft" commands based on a natural language description of how it should work; however sometimes even after that you still need to iterate/tweak/fix and right now that means either issuing a new
llm cmd
prompt or manually copying and pasting the output to run again (which is a problem if the command involves the clipboard like mine just did). I'm not sure if there's a simple or cross-platform way to do it but it would be great if the command, once executed, populated the shell history just like if it were typed directly, so you could just up-arrow, tweak, and run again.GPT4 suggested a few possibilities (given below) for executing a command from a script and populating the history, but the first option doesn't work in
zsh
, nor does it update the current session, so the up-arrow capability won't be there; and the second option doesn't appear to work from a script at all.An alternative is to use whatever mechanism shell autocomplete tools like
fzf
orqfc
use to write to the actual shell prompt, and bypass the python script for execution entirely (also neatly solves the "editing the command" problem by delegating that to the shell as well). Some experimentation withzle
suggests it has the capability to do this but cannot be used directly in a script only in "interactive" mode such as in response to a key press. I was able to implement a sort-of replacement forllm cmd
that has the feature I want in zsh but it's a little clunky:It's not ideal because (in addition to being zsh-specific) it requires the prompt to be entered, then the key Ctrl-f to be pressed, at which point the prompt is "erased" and replaced by the command to run. But at least the command once run is in the history and you can hit the up arrow to keep iterating/use
fzf
to recall it, etc.Edit: I also found a (macOS-specific) way using AppleScript to emit keystrokes:
With
llm-osascript.sh
defined as:And marked executable:
After accepting the privilege escalation for your terminal:

As well as granting Accessibility permission to that terminal in response to:
You can run it directly (or alias to another command) akin to
llm cmd
:I'm not sure why it prints the first few characters of the command on the first line and then jumps to the next, but it always prints the full command at the prompt as far as I can tell.
The text was updated successfully, but these errors were encountered: