Skip to content

Instantly share code, notes, and snippets.

@0x4007
Last active June 26, 2025 06:29
Show Gist options
  • Save 0x4007/35ef0327725d28f303cbf2bacd234766 to your computer and use it in GitHub Desktop.
Save 0x4007/35ef0327725d28f303cbf2bacd234766 to your computer and use it in GitHub Desktop.
Perplexity search `?` and Claude `??` for terminal intelligence. Also `git init` will automatically create a new GitHub repository.
#!/bin/bash/env bash
# Function to query Perplexity API with session-based conversation history
perplexity_chat() {
# Check if API key is set
if [ -z "$PERPLEXITY_API_KEY" ]; then
echo "Error: PERPLEXITY_API_KEY environment variable is not set"
return 1
fi
# Check if input is provided
if [ $# -eq 0 ]; then
echo "Usage: perplexity_chat <your question>"
return 1
fi
# Combine all arguments into a single prompt
local prompt="$*"
# Create session directory if it doesn't exist
local session_dir="$HOME/.perplexity_sessions"
mkdir -p "$session_dir"
# Generate unique session ID with fallback options
local session_id
if [ -n "$TERM_SESSION_ID" ]; then
# Use terminal session ID (best for VSCode and modern terminals)
session_id=$(echo "$TERM_SESSION_ID" | tr ':' '_')
elif [ -n "$BASHPID" ]; then
# Fallback to bash process ID
session_id="$BASHPID"
else
# Final fallback to current shell PID
session_id="$$"
fi
local session_file="$session_dir/session_${session_id}.json"
# Initialize session file if it doesn't exist
if [ ! -f "$session_file" ]; then
echo '{"messages": []}' > "$session_file"
fi
# Load existing conversation history
local existing_messages
existing_messages=$(cat "$session_file" | jq -r '.messages')
# Build messages array with system message, history, and current user message
local timestamp
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
local messages_array
messages_array=$(jq -n \
--argjson existing "$existing_messages" \
--arg content "$prompt" \
--arg timestamp "$timestamp" \
'[
{ "role": "system", "content": "Be precise and concise." }
] + $existing + [
{ "role": "user", "content": $content, "timestamp": $timestamp }
]')
local json_request
json_request=$(jq -n \
--argjson messages "$messages_array" \
'{
"model": "sonar",
"messages": $messages,
"max_tokens": 1024,
"temperature": 0.7,
"top_p": 0.9,
"stream": false
}')
echo "Sending request to Perplexity API..."
local json_response
json_response=$(curl --silent \
--request POST \
--url https://api.perplexity.ai/chat/completions \
--header 'accept: application/json' \
--header "authorization: Bearer $PERPLEXITY_API_KEY" \
--header 'content-type: application/json' \
--data "$json_request")
# Check if the response contains an error
if echo "$json_response" | jq -e '.error' >/dev/null; then
echo "API Error:"
echo "$json_response" | jq '.error'
return 1
fi
# Check if the response is valid JSON with the expected structure
if ! echo "$json_response" | jq -e '.choices[0].message.content' >/dev/null; then
echo "Invalid API response structure:"
echo "$json_response"
return 1
fi
# Print the full response in debug mode
if [ "$PERPLEXITY_DEBUG" = "true" ]; then
echo "Full API response:"
echo "$json_response" | jq '.'
echo ""
fi
# Extract and print the answer
local answer
answer=$(echo "$json_response" | jq -r '.choices[0].message.content')
# Print answer in bright white
echo -e "\033[97m$answer\033[0m"
echo ""
# Extract and print citations as footnotes, if any
local citations_count
citations_count=$(echo "$json_response" | jq '.citations | length')
if [ "$citations_count" -gt 0 ]; then
echo "References:"
echo "$json_response" | jq -r '.citations[]' | nl -w1 -s'. '
echo ""
fi
# Save the conversation to session file
local response_timestamp
response_timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
# Add both user message and assistant response to session history
local updated_messages
updated_messages=$(cat "$session_file" | jq \
--arg user_content "$prompt" \
--arg user_timestamp "$timestamp" \
--arg assistant_content "$answer" \
--arg assistant_timestamp "$response_timestamp" \
'.messages += [
{ "role": "user", "content": $user_content, "timestamp": $user_timestamp },
{ "role": "assistant", "content": $assistant_content, "timestamp": $assistant_timestamp }
]')
echo "$updated_messages" > "$session_file"
}
# --- Automatic GitHub Repo Creation on 'git init' ---
git() {
# Store the original arguments
local args=("$@")
# Check if the first argument is 'init'
if [[ "${args[0]}" == "init" ]]; then
echo "--- Intercepting 'git init'..." >&2
local target_dir_arg=""
# Attempt to find a directory argument for 'git init'
# This is a simplified check; 'git init' itself has more complex parsing.
# We assume if there's a non-option argument after 'init', it's the directory.
if [[ ${#args[@]} -gt 1 ]]; then
for ((i=1; i<${#args[@]}; i++)); do
if [[ ! "${args[$i]}" =~ ^- ]]; then
# Found a potential directory argument
# Take the last non-option argument as the directory
target_dir_arg="${args[$i]}"
fi
done
fi
# Execute the original git init command
command git "${args[@]}"
local init_status=$?
# Proceed only if 'git init' was successful
if [[ $init_status -eq 0 ]]; then
echo "--- 'git init' successful." >&2
# Determine the repository name and source path
local repo_name
local source_path
local current_dir_abs
current_dir_abs=$(pwd -P) # Get the physical current working directory
if [[ -n "$target_dir_arg" ]]; then
# If a directory was specified for git init (e.g., git init my-project)
# Ensure target_dir_arg is treated as relative to the current_dir_abs if it's not absolute
if [[ "$target_dir_arg" == /* ]]; then # Absolute path
source_path="$target_dir_arg"
else # Relative path
source_path="$current_dir_abs/$target_dir_arg"
fi
repo_name=$(basename "$target_dir_arg")
else
# If 'git init' was run in the current directory (git init)
source_path="$current_dir_abs"
repo_name=$(basename "$current_dir_abs")
fi
# Normalize source_path to be an absolute path to avoid ambiguity for 'gh'
# Although 'gh' with --source=. usually works fine from within the repo dir.
# For 'gh repo create --source <path>', an absolute path is safer if not cd'ing.
# However, 'gh repo create --source=.' is often run from within the new repo dir.
# If 'git init newdir' was run, we should conceptually operate 'within' newdir
# or explicitly tell gh where 'newdir' is.
# The `gh repo create --source` path should be the directory containing the .git folder.
# The `repo_name` is just the name for GitHub.
echo "--- Repo name will be: $repo_name" >&2
echo "--- Source path for GitHub repo: $source_path" >&2
# Determine GitHub target (organization detection for ~/repos/)
local github_target="$repo_name" # Default to personal repo
# Check if we're inside ~/repos/
if [[ "$source_path" == "$HOME/repos/"* ]]; then
# Extract the relative path from ~/repos/
local relative_path="${source_path#$HOME/repos/}"
# Get the first directory component (organization name)
local org_name="${relative_path%%/*}"
# If there's actually an org directory (not directly in ~/repos/)
if [[ -n "$org_name" && "$org_name" != "$relative_path" ]]; then
github_target="$org_name/$repo_name"
echo "--- Detected organization: $org_name" >&2
else
echo "--- In ~/repos/ root, defaulting to personal account" >&2
fi
fi
# Check if gh is available and logged in
if command -v gh >/dev/null && gh auth status >/dev/null 2>&1; then
echo "--- Attempting to create private GitHub repo '$github_target' and set remote 'origin'..." >&2
# Create the GitHub repo.
# --source="$source_path" tells gh where the local repository files are.
# --remote=origin tells gh to set the local 'origin' remote to the new repo.
# 'gh' will typically run 'git -C <source_path> remote add origin <url>'
if gh repo create "$github_target" --private --source="$source_path" --remote=origin; then
echo "--- Successfully created private GitHub repo '$github_target' and configured remote 'origin'." >&2
echo "--- Your local repository is initialized and connected to GitHub." >&2
echo "--- You can now add, commit, and then push your changes (e.g., git add . && git commit -m 'Initial commit' && git push -u origin main)." >&2
else
# gh repo create can fail for various reasons:
# 1. Repo with the same name already exists on GitHub.
# 2. Permissions issues with 'gh' or GitHub.
# 3. Network issues.
# 4. '--source' path doesn't exist or isn't a git repo (shouldn't happen if 'git init' succeeded).
echo "--- NOTICE: Failed to automatically create GitHub repo '$github_target' or set remote." >&2
echo "--- This could be because:" >&2
echo " 1. The repository '$github_target' already exists on your GitHub account." >&2
echo " 2. 'gh' encountered an error (e.g., authentication, permissions, network)." >&2
echo " 3. The local remote 'origin' might already exist and point elsewhere, and 'gh' chose not to overwrite it (check 'gh' output)." >&2
echo "--- Please review any messages from 'gh' above." >&2
echo "--- Your local repository was initialized. You may need to create the repo on GitHub and/or set the remote 'origin' manually." >&2
# Example manual commands:
# git remote add origin [email protected]:YOUR_USERNAME/$repo_name.git
# gh repo create YOUR_USERNAME/$repo_name --private (if it doesn't exist yet)
fi
else
echo "--- 'gh' command not found or user not logged in. Cannot automatically create GitHub repo." >&2
echo "--- Your local repository was initialized. Please create the repo on GitHub and add the remote manually." >&2
echo "--- Example: git remote add origin [email protected]:YOUR_USERNAME/$repo_name.git" >&2
fi
# 'git init' itself was successful, so return 0 for the git command part.
# The GitHub automation is an enhancement.
return 0
else
echo "--- 'git init' command failed with status $init_status." >&2
return $init_status # Return the error status from 'git init'
fi
else
# Not a 'git init' command, just execute the original git command
command git "$@"
fi
}
# --- End Automatic GitHub Repo Creation ---
alias ?='perplexity_chat'
alias ??='plz'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment