Last active
July 13, 2025 17:10
-
-
Save zachdaniel/5be7c2a772f5bb73d1accae6ef534448 to your computer and use it in GitHub Desktop.
Revisions
-
zachdaniel revised this gist
Jul 8, 2025 . 1 changed file with 61 additions and 11 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -8,22 +8,72 @@ prompt="You are being used as a terminal assistant." # Parse the pipeline if we have the full command if [ -n "$full_cmd" ]; then # Find which plz instance we are by matching our arguments # Get the first positional argument to identify this plz instance first_arg="" for arg in "$@"; do if [[ "$arg" != -* ]]; then first_arg="$arg" break fi done if [ -n "$first_arg" ]; then # Find our position by looking for our specific argument # Split the command on plz and find which occurrence has our argument plz_count=0 our_position=0 # Count plz occurrences and find ours while IFS= read -r line; do if echo "$line" | grep -q "plz.*$first_arg"; then our_position=$((plz_count + 1)) break fi if echo "$line" | grep -q "plz"; then plz_count=$((plz_count + 1)) fi done <<< "$(echo "$full_cmd" | tr '|' '\n')" # Now extract before/after based on our position if [ "$our_position" -gt 0 ]; then # Escape the first_arg for use in regex escaped_arg=$(echo "$first_arg" | sed 's/[[\.*^$()+?{|]/\\&/g') # Use basic string manipulation to find plz boundaries # Remove newlines to make parsing easier clean_cmd=$(echo "$full_cmd" | tr '\n' ' ') if [ "$our_position" -eq 1 ]; then # First plz: find first " | plz" and split there before_plz=$(echo "$clean_cmd" | sed 's/ | plz.*//') # Find everything after first plz ends (look for next |) after_temp=$(echo "$clean_cmd" | sed 's/^[^|]*| plz[^|]*| *//') if [ "$after_temp" != "$clean_cmd" ]; then after_plz="$after_temp" else after_plz="" fi elif [ "$our_position" -eq 2 ]; then # Second plz: find everything before the last " | plz" before_plz=$(echo "$clean_cmd" | sed 's/ | plz[^|]*$//') after_plz="" else before_plz="" after_plz="" fi else before_plz="" after_plz="" fi else # Fallback to old behavior if we can't identify our argument before_plz=$(echo "$full_cmd" | sed -E 's/^(.*[|])?[[:space:]]*plz.*$/\1/' | sed 's/[[:space:]]*[|][[:space:]]*$//') after_plz="" fi if [ -n "$before_plz" ]; then prompt="$prompt @@ -242,4 +292,4 @@ This does not match the required format. Please respond again using ONLY one of # Get initial response response=$(get_claude_response "$prompt") handle_response "$response" "$prompt" -
zachdaniel revised this gist
Jul 8, 2025 . 1 changed file with 8 additions and 8 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -3,21 +3,21 @@ A rough draft of a script that allows piping into and out of claude code in such Some examples: ```bash # can give you a command ls -la | plz "give me an awk command to extract filenames" ``` ```bash # or just run them ls -la | plz "extract the filenames using awk" ``` ```bash echo '{"users": [{"name": "Alice", "age": 30}, {"name": "Bob", "age": 25}]}' | plz "extract just the names" ``` ```bash # knows that its piping into `jq .` and so must provide json format curl -s https://api.github.com/users/zachdaniel | plz "get the username and location" | jq . ``` -
zachdaniel created this gist
Jul 8, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,9 @@ # get current cmd before executing preexec() { export PLZ_CURRENT_COMMAND="$1" } # so we can provide it to plz plz() { PLZ_FULL_CMD="$PLZ_CURRENT_COMMAND" $HOME/.dotfiles/scripts/plz "$@" } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,23 @@ A rough draft of a script that allows piping into and out of claude code in such a way that it is aware of its context. Some examples: ```bash echo '{"users": [{"name": "Alice", "age": 30}, {"name": "Bob", "age": 25}]}' | plz "extract just the names" ``` ```bash # knows that its piping into `jq .` and so must provide json format curl -s https://api.github.com/users/zachdaniel | plz "get the username and location" | jq . ``` ```bash # can give you a command ls -la | plz "give me an awk command to extract filenames" ``` ```bash # or just run them ls -la | plz "extract the filenames using awk" ``` This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,245 @@ #!/usr/bin/env bash # Get the full command line full_cmd="${PLZ_FULL_CMD:-}" prompt="You are being used as a terminal assistant." # Parse the pipeline if we have the full command if [ -n "$full_cmd" ]; then # Extract everything before 'plz' in the pipeline before_plz=$(echo "$full_cmd" | sed -E 's/^(.*[|])?[[:space:]]*plz.*$/\1/' | sed 's/[[:space:]]*[|][[:space:]]*$//') # Extract everything after the current plz command in the pipeline # Look for: plz "args" | rest_of_pipeline if echo "$full_cmd" | grep -qE 'plz[[:space:]]+[^|]+\|'; then # Use a simpler approach: find plz, skip to the next |, then get everything after after_plz=$(echo "$full_cmd" | sed -E 's/^.*plz[[:space:]]+[^|]+\|[[:space:]]*(.*)$/\1/') # Check if the extraction actually worked if [ "$after_plz" = "$full_cmd" ]; then after_plz="" fi else after_plz="" fi if [ -n "$before_plz" ]; then prompt="$prompt Input is piped from: <piped_from> $before_plz </piped_from>" fi if [ -n "$after_plz" ]; then prompt="$prompt Output will be piped to: <piped_to> $after_plz </piped_to> IMPORTANT: Your output will be piped to '$after_plz'. You MUST output in a format that this command expects. For example: - If piping to 'jq', output valid JSON only - If piping to 'sed' or 'awk', output text that these commands can process - If piping to 'grep', output text with the expected patterns" fi fi piped_input="" full_piped_input="" if [ ! -t 0 ]; then full_piped_input=$(cat) # Get first 10 lines for initial prompt piped_input=$(echo "$full_piped_input" | head -n 10) line_count=$(echo "$full_piped_input" | wc -l) prompt="$prompt <piped_input_preview> $piped_input" if [ "$line_count" -gt 10 ]; then prompt="$prompt ... (showing first 10 lines of $line_count total lines)" fi prompt="$prompt </piped_input_preview>" fi prompt="$prompt RESPONSE FORMAT RULES: You MUST respond in ONE of these formats: 1. To pipe the input through a command to process/transform it: <cmd>command here</cmd> IMPORTANT: If your command needs to exit with an error, use exit code 42 (not 1) to avoid retries. 2. To provide a direct response without processing the input: <response>your response here</response> 3. To exit with an error message and non-zero exit code: <error>error message here</error> 4. To request the full input (if you need more than the preview): </get_output> DECISION GUIDE: - If the user asks to extract, filter, transform, format, process, get, find, or otherwise manipulate the piped input → use <cmd> - If the user asks you to \"give me a command\", \"show me a command\", \"what command should I use\", or wants to see/receive a command → use <response> to display the command - If you need to analyze or answer questions about the input → use <response> - When in doubt, if there is piped input and the user wants something done TO that input → use <cmd> CRITICAL: When the user says \"give me\" or \"show me\" a command, they want to SEE the command text, not run it. Use <response> to show them the command. NEVER use <cmd> when the user is asking for a command to be displayed to them. DO NOT include any text outside these tags. " user_input="" args=() found_positional=false verbose=false for arg in "$@"; do if [[ "$arg" == "--verbose" ]] || [[ "$arg" == "-v" ]]; then verbose=true args+=("$arg") elif [[ "$arg" != -* ]] && [[ "$found_positional" == false ]]; then user_input="<user_input>$arg</user_input>" found_positional=true else args+=("$arg") fi done if [ -n "$user_input" ]; then args+=("-p" "$user_input") fi # Function to get Claude's response get_claude_response() { local prompt_to_send="$1" echo "$prompt_to_send" | /Users/zachdaniel/.claude/local/claude --dangerously-skip-permissions "${args[@]}" } # Function to handle response handle_response() { local response="$1" local current_prompt="$2" local retry_count="${3:-0}" # Check for <cmd> tag (multiline support) if echo "$response" | grep -q "<cmd>"; then # Use awk parsing to avoid HTML entity encoding issues local cmd=$(echo "$response" | awk '/<cmd>/{flag=1; gsub(/^.*<cmd>/, ""); if(/<\/cmd>/) {gsub(/<\/cmd>.*$/, ""); print; exit} else print; next} /<\/cmd>/{gsub(/<\/cmd>.*$/, ""); print; flag=0; exit} flag') if [ -n "$cmd" ]; then if [ "$verbose" = true ]; then echo "→ Running: $cmd" >&2 fi # Fix common sed issues before executing # Fix sed 'i\' commands that are missing newlines cmd=$(echo "$cmd" | sed "s/sed '\\([0-9]*i\\\\\\)\\([^']*\\)'/sed '\\1\\\n\\2'/g") # Execute command and capture errors local error_output if [ -n "$full_piped_input" ]; then error_output=$(echo "$full_piped_input" | bash -c "$cmd" 2>&1) local exit_code=$? else error_output=$(bash -c "$cmd" 2>&1) local exit_code=$? fi if [ $exit_code -eq 0 ]; then echo "$error_output" return 0 elif [ $exit_code -eq 42 ]; then # Special exit code 42 - intentional error, don't retry echo -n "$error_output" >&2 exit 1 else # Command failed - ask Claude to try again (with retry limit) if [ "$retry_count" -ge 3 ]; then echo "Too many retries. Command failed with error: $error_output" >&2 exit 1 fi local retry_prompt="$current_prompt Your command failed with this error: $error_output Please provide a corrected command using <cmd>corrected_command</cmd> or a direct response using <response>answer</response>" local retry_response=$(get_claude_response "$retry_prompt") handle_response "$retry_response" "$retry_prompt" $((retry_count + 1)) return $? fi fi fi # Check for <response> tag (multiline support) if echo "$response" | grep -q "<response>"; then local clean_response=$(echo "$response" | sed -n '/<response>/,/<\/response>/p' | sed '1s/^.*<response>//' | sed '$s/<\/response>.*$//' | sed '/^[[:space:]]*$/d') if [ -n "$clean_response" ]; then echo -n "$clean_response" return 0 fi fi # Check for <error> tag (multiline support) if echo "$response" | grep -q "<error>"; then local error_message=$(echo "$response" | sed -n '/<error>/,/<\/error>/p' | sed '1s/^.*<error>//' | sed '$s/<\/error>.*$//' | sed '/^[[:space:]]*$/d') if [ -n "$error_message" ]; then echo -n "$error_message" >&2 exit 1 fi fi # Check for </get_output> tag if echo "$response" | grep -q "^</get_output>$"; then local new_prompt="$current_prompt <full_piped_input> $full_piped_input </full_piped_input> Now respond using one of the required formats: <cmd>command</cmd> or <response>answer</response>" local new_response=$(get_claude_response "$new_prompt") handle_response "$new_response" "$new_prompt" "$retry_count" return $? fi # Response doesn't match format - retry once local retry_prompt="$current_prompt Your previous response was: $response This does not match the required format. Please respond again using ONLY one of these formats: <cmd>command to pipe through</cmd> <response>direct answer</response> <error>error message</error> </get_output>" local retry_response=$(get_claude_response "$retry_prompt") # The retry will be handled by the recursive call to handle_response above # This section is now redundant since we use recursion } # Get initial response response=$(get_claude_response "$prompt") handle_response "$response" "$prompt"