Skip to content

Instantly share code, notes, and snippets.

@roelven
Last active October 9, 2025 12:14
Show Gist options
  • Save roelven/6401c428c69fb2549c7b75c72fb2dbe9 to your computer and use it in GitHub Desktop.
Save roelven/6401c428c69fb2549c7b75c72fb2dbe9 to your computer and use it in GitHub Desktop.
Prompt my prompt: a Raycast script to improve your prompts.
#!/bin/bash
# Required parameters:
# @raycast.schemaVersion 1
# @raycast.title Prompt my prompt
# @raycast.mode silent
# Optional parameters:
# @raycast.icon 🤖
# @raycast.packageName Prompt Tools
# Documentation:
# @raycast.description Analyzes a human-written prompt and rewrites it for clarity and deeper reasoning. Output is the improved prompt only.
# @raycast.author Roel van der Ven
# @raycast.authorURL https://roelvanderven.com
# Requires the Raycast Notification extension to be installed:
# https://www.raycast.com/maxnyby/raycast-notification
# CONFIGURATION
OPENAI_API_KEY="YOUR_OPENAI_API_KEY"
MODEL="gpt-5-mini"
TEMPERATURE=1
LOGGING_ENABLED=true
LOGFILE="/tmp/prompt_improver_log.txt"
# PROGRESS / NOTIFICATIONS
# - Uses Raycast HUD via "Raycast Notification" extension if available:
# https://www.raycast.com/maxnyby/raycast-notification
# - Falls back to macOS Notification Center if HUD isn't available.
NOTIFY_MODE="${NOTIFY_MODE:-hud}" # hud|native|none
PROGRESS_INTERVAL="${PROGRESS_INTERVAL:-1}" # seconds between spinner updates
SPINNER_FRAMES=(⠋ ⠙ ⠹ ⠸ ⠼ ⠴ ⠦ ⠧ ⠇ ⠏)
SPINNER_PID=""
SPINNER_RUNNING=0
notify_hud() {
local text="$1"
# Build deeplink: raycast://extensions/maxnyby/raycast-notification/...
local args_json encoded
args_json=$(jq -n --arg title "$text" '{title: $title}')
encoded=$(printf "%s" "$args_json" | jq -r @uri)
open -g "raycast://extensions/maxnyby/raycast-notification/index?launchType=background&arguments=$encoded" >/dev/null 2>&1
return $?
}
notify_native() {
local text="$1"
# Escape for AppleScript
local esc
esc=$(printf "%s" "$text" | sed 's/\\/\\\\/g; s/"/\\"/g')
osascript -e "display notification \"$esc\" with title \"Prompt Improver\""
}
notify() {
local text="$1"
case "$NOTIFY_MODE" in
hud)
notify_hud "$text" || notify_native "$text"
;;
native)
notify_native "$text"
;;
*)
;; # none
esac
}
start_spinner() {
SPINNER_RUNNING=1
(
local i=0
while [ "$SPINNER_RUNNING" -eq 1 ]; do
local frame="${SPINNER_FRAMES[$(( i % ${#SPINNER_FRAMES[@]} ))]}"
notify "$frame Improving prompt…"
sleep "$PROGRESS_INTERVAL"
i=$((i+1))
done
) &
SPINNER_PID=$!
}
stop_spinner() {
if [ -n "$SPINNER_PID" ]; then
SPINNER_RUNNING=0
kill "$SPINNER_PID" >/dev/null 2>&1
wait "$SPINNER_PID" 2>/dev/null
SPINNER_PID=""
fi
}
# Ensure spinner is stopped on any exit
cleanup() { stop_spinner; }
trap cleanup EXIT
# Read clipboard
INPUT=$(pbpaste)
# Validate input
if [[ -z "$INPUT" ]]; then
echo "❌ Skipped: clipboard is empty"
exit 0
fi
# Skip if single token (alnum only)
if [[ "$INPUT" =~ ^[[:alnum:]]+$ ]]; then
echo "❌ Skipped: single word detected"
exit 0
fi
# Skip if hash-like
if [[ "$INPUT" =~ ^[a-f0-9]{4,}-[a-f0-9]{4,}-[a-f0-9]{4,}$ ]]; then
echo "❌ Skipped: hash-like pattern detected"
exit 0
fi
if [ "$LOGGING_ENABLED" = true ]; then
{
echo "--- $(date) ---"
echo "Clipboard:"
echo "$INPUT"
} >> "$LOGFILE"
fi
# Build the system prompt (no shell expansion)
read -r -d '' SYSTEM_PROMPT <<'SYS'
You are a prompt evaluator–improver used in a one-step workflow. You will receive a human-written prompt between <HUMAN_PROMPT> ... </HUMAN_PROMPT>. Your job is to rewrite it into a clearer, more rigorous prompt for a reasoning LLM (works with GPT-5, Claude Sonnet 4.5, Gemini 2.5 Pro).
Rules:
- Interpret the enclosed text as the user's intended task prompt.
- Preserve the original intent, constraints, domain specifics, examples, and tone unless they hinder clarity.
- Remove redundancy, fix ambiguities, and add only what improves reasoning quality and output reliability.
- If critical details are missing, include square-bracketed placeholders like [SPECIFY: target audience], not assumptions; otherwise state a brief “Assumptions” line.
- Make the result standalone and ready to paste; avoid any meta commentary, analysis, or markdown fences in your output.
- Output ONLY the improved prompt text—no headings like “Improved Prompt”, no notes, no backticks.
When rewriting, optimize for:
- Reasoning clarity and depth: unambiguous objective, explicit constraints, and a compact plan of attack.
- Verifiability: success criteria and checks the model should perform silently before finalizing.
- Deterministic output: specify structure/format if absent (prefer concise markdown or JSON with clear fields).
- Safety and fidelity: do not invent unknown facts; keep proprietary or sensitive items as placeholders.
Rewrite the input into this structure (omit sections that don’t apply; keep wording tight):
1) Objective: <single clear sentence capturing the user’s goal>.
2) Context/Inputs: <key facts, data, examples; keep code blocks/examples if present>.
3) Requirements & Constraints: <bullets—all must/should/must-not>.
4) Approach: <succinct stepwise plan to solve/decide; consider edge cases>.
5) Output Format: <exact schema or markdown sections to return>.
6) Assumptions (only if needed): <short list>.
Before producing the final text, internally check:
- Is the task solvable with given info?
- Are steps logically ordered and minimal?
- Are acceptance criteria and output format explicit?
Return ONLY the final improved prompt text.
SYS
# Wrap clipboard content with tags
USER_WITH_TAGS=$(printf "<HUMAN_PROMPT>\n%s\n</HUMAN_PROMPT>" "$INPUT")
# Build JSON body with jq to ensure proper escaping
BODY=$(jq -n \
--arg model "$MODEL" \
--arg sys "$SYSTEM_PROMPT" \
--arg user "$USER_WITH_TAGS" \
--argjson temperature "$TEMPERATURE" \
'{
model: $model,
messages: [
{role: "system", content: $sys},
{role: "user", content: $user}
],
temperature: $temperature
}')
# Start non-blocking spinner
start_spinner
# API request
RESPONSE=$(curl -s https://api.openai.com/v1/chat/completions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d "$BODY")
# Stop spinner before parsing/echoing
stop_spinner
if [ "$LOGGING_ENABLED" = true ]; then
{
echo "Response:"
echo "$RESPONSE"
} >> "$LOGFILE"
fi
# Check for API error
if echo "$RESPONSE" | grep -q '"error"'; then
ERROR_MSG=$(echo "$RESPONSE" | jq -r '.error.message // "Unknown error"')
[ "$LOGGING_ENABLED" = true ] && echo "API error: $ERROR_MSG" >> "$LOGFILE"
notify "⚠️ Prompt improvement failed: $ERROR_MSG"
echo "⚠️ Prompt improvement failed. \"API Error: $ERROR_MSG\" with title \"OpenAI Error\""
exit 1
fi
# Extract improved prompt
IMPROVED=$(echo "$RESPONSE" | jq -r '.choices[0].message.content')
if [ "$LOGGING_ENABLED" = true ]; then
{
echo "Parsed result:"
echo "$IMPROVED"
} >> "$LOGFILE"
fi
# Handle null output
if [ "$IMPROVED" == "null" ] || [ -z "$IMPROVED" ]; then
notify "No output produced"
echo "No output produced"
exit 1
fi
# Copy to clipboard and notify
printf "%s" "$IMPROVED" | pbcopy
notify "✅ Improved! Prompt copied"
echo "Improved! Prompt copied ☑️"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment