Skip to content

Instantly share code, notes, and snippets.

@Yeshwanthyk
Last active September 25, 2025 13:12
Show Gist options
  • Select an option

  • Save Yeshwanthyk/b0917018840a7f40ae3577b1920dc48c to your computer and use it in GitHub Desktop.

Select an option

Save Yeshwanthyk/b0917018840a7f40ae3577b1920dc48c to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<'USAGE'
Usage: ai-tools.sh --tool <codex|opencode|gemini> [options] [prompt...]
Options:
-t, --tool <name> Target CLI to invoke (required).
-p, --prompt <text> Add prompt text; can be provided multiple times.
-f, --file <path(s)> Inline file contents; repeatable or comma-separated list.
--model <name> Override default model (currently opencode only).
-h, --help Show this message.
If stdin is provided, it is appended to the prompt as an additional block.
Example:
ai-agent.sh -t opencode -p "Summarize" -f src/main.py
USAGE
}
error() {
echo "Error: $*" >&2
exit 1
}
trim() {
local var="$1"
var="${var#${var%%[![:space:]]*}}"
var="${var%${var##*[![:space:]]}}"
printf '%s' "$var"
}
ensure_cmd() {
if ! command -v "$1" >/dev/null 2>&1; then
error "Required command '$1' is not available in PATH."
fi
}
read_env_var() {
local key="$1"
local env_file="${ENV_FILE:-$HOME/.env}"
[[ -f "$env_file" ]] || return 1
local line value
line=$(grep -E "^(export )?${key}=" "$env_file" | tail -n 1 || true)
[[ -n "$line" ]] || return 1
value="${line#*=}"
value="${value%\r}"
value="${value%\n}"
value="${value#\"}"
value="${value%\"}"
echo "$value"
}
append_block() {
local content="$1"
[[ -z "$content" ]] && return
if [[ -n "${prompt_payload:-}" ]]; then
prompt_payload+=$'\n\n'
fi
prompt_payload+="$content"
}
prompt_parts=()
files=()
model_override=""
tool=""
while [[ $# -gt 0 ]]; do
case "$1" in
-t | --tool)
[[ $# -ge 2 ]] || error "--tool requires a value"
tool="$2"
shift 2
;;
-p | --prompt)
[[ $# -ge 2 ]] || error "--prompt requires a value"
prompt_parts+=("$2")
shift 2
;;
-f | --file)
[[ $# -ge 2 ]] || error "--file requires a path"
IFS=',' read -r -a raw_files <<<"$2"
for entry in "${raw_files[@]}"; do
trimmed=$(trim "$entry")
[[ -z "$trimmed" ]] && continue
if [[ $trimmed == ~* ]]; then
trimmed="${trimmed/#\~/$HOME}"
fi
files+=("$trimmed")
done
shift 2
;;
--model)
[[ $# -ge 2 ]] || error "--model requires a value"
model_override="$2"
shift 2
;;
-h | --help)
usage
exit 0
;;
--)
shift
while [[ $# -gt 0 ]]; do
prompt_parts+=("$1")
shift
done
;;
*)
prompt_parts+=("$1")
shift
;;
esac
done
[[ -n "$tool" ]] || error "--tool is required"
tool=$(echo "$tool" | tr '[:upper:]' '[:lower:]')
prompt_payload=""
if [[ ${#prompt_parts[@]} -gt 0 ]]; then
append_block "$(printf '%s' "${prompt_parts[*]}")"
fi
if [[ ! -t 0 ]]; then
stdin_input=$(cat)
append_block "stdin:\n${stdin_input}"
fi
if ((${#files[@]})); then
for file in "${files[@]}"; do
[[ -r "$file" ]] || error "File '$file' not found or not readable"
file_block=$'File: '
file_block+="$file"
file_block+=$'\n```\n'
file_block+=$(<"$file")
file_block+=$'\n```'
append_block "$file_block"
done
fi
[[ -n "$prompt_payload" ]] || error "Prompt is empty; provide --prompt, positional text, stdin, or --file"
case "$tool" in
codex)
if /bin/zsh -lic 'command -v cdx >/dev/null' >/dev/null 2>&1; then
PROMPT_PAYLOAD="$prompt_payload" exec /bin/zsh -lic 'cdx exec "$PROMPT_PAYLOAD"'
fi
ensure_cmd codex
exec codex exec "$prompt_payload"
;;
opencode)
ensure_cmd opencode
model_value="${model_override:-openrouter/x-ai/grok-4-fast:free}"
exec opencode run --model "$model_value" "$prompt_payload"
;;
claude)
ensure_cmd claude
exec claude --dangerously-skip-permissions -p "$prompt_payload"
;;
gemini)
ensure_cmd gemini
model_value="${model_override:-gemini-2.5-pro}"
exec gemini --model "$model_value" -p "$prompt_payload"
;;
*)
error "Unsupported tool '$tool'."
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment