Skip to content

Instantly share code, notes, and snippets.

@StephenFluin
Created April 8, 2026 14:40
Show Gist options
  • Select an option

  • Save StephenFluin/f48d3abb6b07f485ed765c82ba625083 to your computer and use it in GitHub Desktop.

Select an option

Save StephenFluin/f48d3abb6b07f485ed765c82ba625083 to your computer and use it in GitHub Desktop.
Want to run a command but don't know the syntax? Let AI figure it out for you.
#!/usr/bin/env bash
# ─────────────────────────────────────────────────────────────────
# ai-cmd — natural-language → shell command via Claude or Gemini
#
# Usage:
# !! strip the audio from obs.mp4
# !! list all jpg files larger than 5MB
# !! compress this-dir into a tar.gz
#
# Setup:
# 1. chmod +x ai-cmd.sh
# 2. Set ONE of these env vars (Claude is tried first):
# export ANTHROPIC_API_KEY="sk-ant-..."
# export GEMINI_API_KEY="AI..."
# 3. Add this alias to your .bashrc / .zshrc:
# alias '!!'='source /path/to/ai-cmd.sh'
#
# "source" is needed so the command runs in your current shell
# (inherits cd, env vars, etc.)
# ─────────────────────────────────────────────────────────────────
set -euo pipefail
# ── Colors ───────────────────────────────────────────────────────
BOLD='\033[1m'
DIM='\033[2m'
CYAN='\033[36m'
GREEN='\033[32m'
YELLOW='\033[33m'
RED='\033[31m'
RESET='\033[0m'
# ── Collect the prompt ───────────────────────────────────────────
PROMPT="$*"
if [[ -z "$PROMPT" ]]; then
echo -e "${RED}Usage:${RESET} !! <describe what you want to do>"
return 0 2>/dev/null || exit 0
fi
# ── Gather context ───────────────────────────────────────────────
SHELL_NAME=$(basename "$SHELL" 2>/dev/null || echo "bash")
OS_INFO=$(uname -s 2>/dev/null || echo "Unknown")
CWD=$(pwd)
DIR_LISTING=$(ls -1 2>/dev/null | head -30)
SYSTEM_PROMPT="You are a command-line assistant. The user describes a task in natural language. \
Respond with ONLY the shell command(s) to accomplish it — no explanation, no markdown fences, \
no commentary. If multiple commands are needed, separate them with && or newlines. \
Use common CLI tools (ffmpeg, tar, find, grep, sed, awk, curl, etc.). \
Context: shell=$SHELL_NAME, os=$OS_INFO, cwd=$CWD
Files in cwd:
$DIR_LISTING"
# ── API call: Claude ─────────────────────────────────────────────
call_claude() {
local response
response=$(curl -sS https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d "$(jq -n \
--arg model "claude-sonnet-4-20250514" \
--arg system "$SYSTEM_PROMPT" \
--arg prompt "$PROMPT" \
'{
model: $model,
max_tokens: 1024,
system: $system,
messages: [{role: "user", content: $prompt}]
}')")
# Check for errors
local err
err=$(echo "$response" | jq -r '.error.message // empty' 2>/dev/null)
if [[ -n "$err" ]]; then
echo "CLAUDE_ERROR: $err" >&2
return 1
fi
echo "$response" | jq -r '.content[0].text // empty' 2>/dev/null
}
# ── API call: Gemini ─────────────────────────────────────────────
call_gemini() {
local response
response=$(curl -sS \
"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=$GEMINI_API_KEY" \
-H "content-type: application/json" \
-d "$(jq -n \
--arg system "$SYSTEM_PROMPT" \
--arg prompt "$PROMPT" \
'{
system_instruction: {parts: [{text: $system}]},
contents: [{parts: [{text: $prompt}]}]
}')")
# Check for errors
local err
err=$(echo "$response" | jq -r '.error.message // empty' 2>/dev/null)
if [[ -n "$err" ]]; then
echo "GEMINI_ERROR: $err" >&2
return 1
fi
echo "$response" | jq -r '.candidates[0].content.parts[0].text // empty' 2>/dev/null
}
# ── Pick provider & call ─────────────────────────────────────────
echo -e "${DIM}Thinking...${RESET}"
COMMAND=""
PROVIDER=""
if [[ -n "${ANTHROPIC_API_KEY:-}" ]]; then
PROVIDER="Claude"
COMMAND=$(call_claude 2>/dev/null) || true
fi
if [[ -z "$COMMAND" ]] && [[ -n "${GEMINI_API_KEY:-}" ]]; then
PROVIDER="Gemini"
COMMAND=$(call_gemini 2>/dev/null) || true
fi
if [[ -z "$COMMAND" ]]; then
echo -e "${RED}Error:${RESET} No response. Check your API key."
echo " Set ANTHROPIC_API_KEY or GEMINI_API_KEY in your environment."
return 1 2>/dev/null || exit 1
fi
# Strip any markdown fences the model might have snuck in
COMMAND=$(echo "$COMMAND" | sed '/^```/d' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
# ── Present the command ──────────────────────────────────────────
echo ""
echo -e "${DIM}── ${PROVIDER} suggests ──────────────────────────${RESET}"
echo -e "${BOLD}${CYAN}${COMMAND}${RESET}"
echo -e "${DIM}────────────────────────────────────────────────${RESET}"
echo ""
# ── Interactive loop ─────────────────────────────────────────────
while true; do
echo -en " ${GREEN}[r]un${RESET} ${YELLOW}[e]dit${RESET} ${RED}[c]ancel${RESET} → "
read -r -n1 CHOICE
echo ""
case "$CHOICE" in
r|R|"")
echo ""
echo -e "${DIM}▶ Running...${RESET}"
echo ""
eval "$COMMAND"
RESULT=$?
echo ""
if [[ $RESULT -eq 0 ]]; then
echo -e "${GREEN}✔ Done (exit $RESULT)${RESET}"
else
echo -e "${RED}✘ Exited with code $RESULT${RESET}"
fi
break
;;
e|E)
# Pre-fill the command into readline for editing
echo ""
read -r -e -i "$COMMAND" -p "$(echo -e "${CYAN}Edit: ${RESET}")" COMMAND
echo ""
echo -e "${DIM}Updated command:${RESET}"
echo -e "${BOLD}${CYAN}${COMMAND}${RESET}"
echo ""
# Loop back to ask run/edit/cancel again
;;
c|C)
echo -e "${DIM}Cancelled.${RESET}"
break
;;
*)
echo -e "${DIM} Press r, e, or c${RESET}"
;;
esac
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment