@@ -0,0 +1,230 @@
+# ask - AI CLI tool
+
+A lightweight bash script for querying AI models via the OpenRouter API, optimized for direct, executable output.
+
+## Features
+
+- **Direct Output** - Returns executable commands and answers without markdown formatting
+- **Multiple Models** - Quick access to Mercury Coder, Gemini, Claude Sonnet, Kimi, and Qwen models
+- **Streaming Support** - Real-time response streaming for long outputs
+- **Provider Routing** - Automatic fallback between providers for reliability
+- **Performance Metrics** - Shows response time and tokens/second
+- **Pipe Support** - Works seamlessly with Unix pipes and stdin
+
+## Quick start
+
+```bash
+# Clone and setup
+git clone https://github.com/yourusername/ask.git
+cd ask
+chmod +x ask
+
+# Set your API key
+export OPENROUTER_API_KEY="your-api-key-here"
+
+# Test it
+./ask "What is 2+2?"
+```
+
+## Installation
+
+### Option 1: Using install.sh (recommended)
+```bash
+sudo ./install.sh
+```
+
+### Option 2: Manual installation
+```bash
+chmod +x ask
+sudo cp ask /usr/local/bin/
+```
+
+### Persistent API key setup
+
+Add to your shell profile (`~/.bashrc`, `~/.zshrc`, etc.):
+```bash
+export OPENROUTER_API_KEY="your-api-key-here"
+```
+
+## Usage
+
+### Basic usage
+
+```bash
+ask "What is 2+2?"
+ask "Write a Python hello world"
+```
+
+### Model selection
+
+```bash
+# Default model (Mercury Coder - optimized for code)
+ask "Write a Python function"
+
+# Shorthand flags for quick model switching
+ask -c "prompt" # Mercury Coder (default, best for code)
+ask -g "prompt" # Gemini 2.5 Flash (fast, general purpose)
+ask -s "prompt" # Claude Sonnet 4 (complex reasoning)
+ask -k "prompt" # Kimi K2 (long context)
+ask -q "prompt" # Qwen 235B (large model)
+
+# Custom model by full name
+ask -m "openai/gpt-4o" "Explain this concept"
+```
+
+### Provider routing
+
+Specify provider order for fallback support:
+
+```bash
+ask --provider "openai,together" "Generate code"
+```
+
+This will try OpenAI first, then fall back to Together if needed.
+
+### System prompts
+
+```bash
+# Custom system prompt
+ask --system "You are a pirate" "Tell me about sailing"
+
+# Disable system prompt for raw model behavior
+ask -r "What is 2+2?"
+```
+
+### Streaming mode
+
+Get responses as they're generated:
+
+```bash
+ask --stream "Tell me a long story"
+```
+
+### Pipe input
+
+```bash
+echo "Fix this code: print('hello world)" | ask
+cat script.py | ask "Review this code"
+```
+
+## Options
+
+| Option | Description |
+|--------|-------------|
+| `-c` | Use Mercury Coder (default) |
+| `-g` | Use Google Gemini 2.5 Flash |
+| `-s` | Use Claude Sonnet 4 |
+| `-k` | Use Moonshotai Kimi K2 |
+| `-q` | Use Qwen3 235B |
+| `-m MODEL` | Use custom model |
+| `-r` | Disable system prompt |
+| `--stream` | Enable streaming output |
+| `--system` | Set custom system prompt |
+| `--provider` | Set provider order (comma-separated) |
+| `-h, --help` | Show help message |
+
+## Common use cases
+
+### Command generation
+```bash
+# Get executable commands directly
+ask "Command to find files larger than 100MB"
+# Output: find . -type f -size +100M
+
+ask "ffmpeg command to convert mp4 to gif"
+# Output: ffmpeg -i input.mp4 -vf "fps=10,scale=320:-1:flags=lanczos" output.gif
+```
+
+### Code generation
+```bash
+# Generate code snippets
+ask "Python function to calculate factorial"
+
+# Code review
+cat script.py | ask "Find potential bugs in this code"
+```
+
+### Quick answers
+```bash
+# Calculations
+ask "What is 18% of 2450?"
+# Output: 441
+
+# Technical questions
+ask "What port does PostgreSQL use?"
+# Output: 5432
+```
+
+### Advanced usage
+```bash
+# Chain commands
+ask "List all Python files" | ask "Generate a script to check syntax of these files"
+
+# Use with other tools
+docker ps -a | ask "Which containers are using the most memory?"
+
+# Provider fallback for reliability
+ask --provider "anthropic,openai" "Complex analysis task"
+```
+
+## Requirements
+
+### Dependencies
+- `bash` - Shell interpreter
+- `curl` - HTTP requests to OpenRouter API
+- `jq` - JSON parsing for API responses
+- `bc` - Performance metrics calculation
+
+### API access
+- OpenRouter API key (get one at [openrouter.ai](https://openrouter.ai))
+- Set as environment variable: `OPENROUTER_API_KEY`
+
+## Performance
+
+The tool displays performance metrics after each query:
+- **Model** - Which AI model processed the request
+- **Provider** - The infrastructure provider that served it
+- **Response Time** - Total time in seconds
+- **Token Speed** - Generation speed in tokens/second
+
+Example output:
+```
+$ ask "What is 2+2?"
+
+4
+
+[inception/mercury-coder via Inception - 0.82s - 11.0 tok/s]
+```
+
+## Troubleshooting
+
+### API key not set
+```bash
+Error: OPENROUTER_API_KEY environment variable is not set
+# Solution: export OPENROUTER_API_KEY="your-key-here"
+```
+
+### Missing dependencies
+```bash
+# Check for required tools
+which curl jq bc
+
+# Install on macOS
+brew install jq bc
+
+# Install on Ubuntu/Debian
+sudo apt-get install jq bc
+```
+
+### No response or errors
+```bash
+# Test with verbose curl output
+curl -v https://openrouter.ai/api/v1/chat/completions \
+ -H "Authorization: Bearer $OPENROUTER_API_KEY" \
+ -H "Content-Type: application/json" \
+ -d '{"model":"google/gemini-2.5-flash","messages":[{"role":"user","content":"test"}]}'
+```
+
+## License
+
+MIT
@@ -0,0 +1,201 @@
+#!/bin/bash
+
+# ask - Simple OpenRouter API CLI tool
+# Usage: ask [OPTIONS] [PROMPT]
+
+set -euo pipefail
+
+# Check for API key
+if [ -z "${OPENROUTER_API_KEY:-}" ]; then
+ echo "Error: OPENROUTER_API_KEY environment variable is not set" >&2
+ exit 1
+fi
+
+# Model shortcuts function
+get_model() {
+ case "$1" in
+ c) echo "inception/mercury-coder:nitro" ;;
+ g) echo "google/gemini-2.5-flash:nitro" ;;
+ s) echo "anthropic/claude-sonnet-4:nitro" ;;
+ k) echo "moonshotai/kimi-k2:nitro" ;;
+ q) echo "qwen/qwen3-235b-a22b-2507:nitro" ;;
+ esac
+}
+
+# Default values
+MODEL="inception/mercury-coder"
+SYSTEM_PROMPT=""
+PROMPT=""
+STREAMING=false
+NO_SYSTEM=false
+PROVIDER_ORDER=""
+
+# Default system prompt (direct answers)
+DEFAULT_PROMPT="You are a direct answer engine. Output ONLY the requested information.
+
+For commands: Output executable syntax only. No explanations, no comments.
+For questions: Output the answer only. No context, no elaboration.
+
+Rules:
+- If asked for a command, provide ONLY the command
+- If asked a question, provide ONLY the answer
+- Never include markdown formatting or code blocks
+- Never add explanatory text before or after
+- Assume output will be piped or executed directly
+- For multi-step commands, use && or ; to chain them
+- Make commands robust and handle edge cases silently"
+
+# Function to show help
+show_help() {
+ cat << EOF
+ask - Query AI models via OpenRouter API
+
+Usage: ask [OPTIONS] [PROMPT]
+
+Options:
+ -c Use inception/mercury-coder (default)
+ -g Use google/gemini-2.5-flash
+ -s Use anthropic/claude-sonnet-4
+ -k Use moonshotai/kimi-k2
+ -q Use qwen/qwen3-235b-a22b-2507
+ -m MODEL Use custom model
+ -r Disable system prompt (raw model behavior)
+ --stream Enable streaming output
+ --system Set system prompt for the conversation
+ --provider Comma-separated list of providers for routing
+ -h, --help Show this help message
+
+Examples:
+ ask "Write a hello world in Python"
+ ask -g "Explain quantum computing"
+ ask -m openai/gpt-4o "What is 2+2?"
+ echo "Fix this code" | ask
+ ask --system "You are a pirate" "Tell me about sailing"
+
+EOF
+ exit 0
+}
+
+# Parse command line arguments
+while [ $# -gt 0 ]; do
+ case "$1" in
+ -h|--help) show_help ;;
+ -[cgskq])
+ MODEL="$(get_model "${1:1}")"
+ shift ;;
+ -m)
+ MODEL="${2:?Error: -m requires a model name}"
+ shift 2 ;;
+ -r)
+ NO_SYSTEM=true
+ shift ;;
+ --stream)
+ STREAMING=true
+ shift ;;
+ --system)
+ SYSTEM_PROMPT="${2:?Error: --system requires a prompt}"
+ shift 2 ;;
+ --provider)
+ PROVIDER_ORDER="${2:?Error: --provider requires providers}"
+ shift 2 ;;
+ *)
+ PROMPT="$*"
+ break ;;
+ esac
+done
+
+# If no prompt provided as argument, read from stdin
+if [ -z "$PROMPT" ]; then
+ if [ -t 0 ]; then
+ echo "Error: No prompt provided. Use 'ask -h' for help." >&2
+ exit 1
+ fi
+ # Read all stdin, preserving multi-line format
+ PROMPT=$(cat)
+fi
+
+# Apply default system prompt unless disabled or custom prompt provided
+if [ "$NO_SYSTEM" = false ] && [ -z "$SYSTEM_PROMPT" ]; then
+ SYSTEM_PROMPT="$DEFAULT_PROMPT"
+fi
+
+# Build messages array with proper JSON escaping
+if [ -n "$SYSTEM_PROMPT" ]; then
+ MESSAGES='[{"role":"system","content":'"$(printf '%s' "$SYSTEM_PROMPT" | jq -Rs .)"'},{"role":"user","content":'"$(printf '%s' "$PROMPT" | jq -Rs .)"'}]'
+else
+ MESSAGES='[{"role":"user","content":'"$(printf '%s' "$PROMPT" | jq -Rs .)"'}]'
+fi
+
+# Record start time
+START_TIME=$(date +%s.%N)
+
+# Build JSON payload once
+PROVIDER_JSON=""
+if [ -n "$PROVIDER_ORDER" ]; then
+ PROVIDER_JSON=',"provider":{"order":['$(echo "$PROVIDER_ORDER" | awk -F, '{for(i=1;i<=NF;i++) printf "\"%s\"%s", $i, (i<NF?",":"")}')']}'
+fi
+
+JSON_PAYLOAD='{
+ "model": "'"$MODEL"'",
+ "messages": '"$MESSAGES"',
+ "stream": '$([ "$STREAMING" = true ] && echo true || echo false)"$PROVIDER_JSON"'
+}'
+
+API_URL="https://openrouter.ai/api/v1/chat/completions"
+
+# Add newline before answer
+echo
+
+# Make API request
+if [ "$STREAMING" = true ]; then
+ # Streaming mode
+ curl -sS "$API_URL" \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer $OPENROUTER_API_KEY" \
+ -d "$JSON_PAYLOAD" 2>&1 | while IFS= read -r line; do
+ # Check for errors
+ if echo "$line" | grep -q '"error"'; then
+ echo "Error: $(echo "$line" | jq -r '.error.message // .error // "Unknown error"')" >&2
+ exit 1
+ fi
+
+ # Process SSE data lines
+ if [[ "$line" == data:* ]]; then
+ json="${line#data: }"
+ [ "$json" = "" ] || [ "$json" = "[DONE]" ] && continue
+
+ content=$(echo "$json" | jq -r '.choices[0].delta.content // ""' 2>/dev/null)
+ [ -n "$content" ] && printf '%s' "$content"
+ fi
+ done
+ echo
+
+ # Show metadata
+ ELAPSED=$(printf "%.2f" $(echo "$(date +%s.%N) - $START_TIME" | bc))
+ echo
+ echo "[$MODEL - ${ELAPSED}s]" >&2
+else
+ # Non-streaming mode
+ response=$(curl -sS "$API_URL" \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer $OPENROUTER_API_KEY" \
+ -d "$JSON_PAYLOAD" 2>&1)
+
+ # Check for errors
+ if echo "$response" | grep -q '"error"'; then
+ echo "Error: $(echo "$response" | jq -r '.error.message // .error // "Unknown error"')" >&2
+ exit 1
+ fi
+
+ # Extract and print content
+ echo "$response" | jq -r '.choices[0].message.content // "No response received"'
+
+ # Show metadata
+ ELAPSED=$(printf "%.2f" $(echo "$(date +%s.%N) - $START_TIME" | bc))
+ TOKENS=$(echo "$response" | jq -r '.usage.completion_tokens // 0')
+ PROVIDER=$(echo "$response" | jq -r '.provider // "Unknown"')
+ TPS=$(echo "scale=1; $TOKENS / $ELAPSED" | bc 2>/dev/null || echo "0.0")
+
+ echo
+ echo "[$MODEL via $PROVIDER - ${ELAPSED}s - ${TPS} tok/s]" >&2
+fi
@@ -0,0 +1,58 @@
+#!/bin/bash
+
+# install.sh - Install ask CLI tool system-wide
+
+set -euo pipefail
+
+# Colors
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+NC='\033[0m'
+
+echo "Installing 'ask' CLI tool..."
+
+# Check if script exists
+if [ ! -f "ask" ]; then
+ echo "Error: 'ask' script not found in current directory" >&2
+ exit 1
+fi
+
+# Make executable
+chmod +x ask
+
+# Install to /usr/local/bin
+echo "Installing to /usr/local/bin/ask (requires sudo)..."
+sudo cp ask /usr/local/bin/
+
+echo -e "${GREEN}✓ Installation complete!${NC}"
+echo
+
+# Get OpenRouter IPs
+echo "Resolving OpenRouter DNS..."
+IPS=$(dig +short openrouter.ai 2>/dev/null | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' || nslookup openrouter.ai 2>/dev/null | grep -A1 "Name:" | grep "Address:" | awk '{print $2}' | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$')
+
+if [ -n "$IPS" ]; then
+ echo -e "${YELLOW}OpenRouter IP addresses:${NC}"
+ echo "$IPS"
+ echo
+ echo "To improve performance, you can add these to /etc/hosts:"
+ echo "----------------------------------------"
+ for IP in $IPS; do
+ echo "$IP openrouter.ai"
+ done | head -1 # Only show first IP as hosts file needs single entry
+ echo "----------------------------------------"
+ echo
+ echo "Add with: sudo nano /etc/hosts"
+ echo "(Only add ONE IP address to avoid conflicts)"
+else
+ echo "Could not resolve OpenRouter IPs. Network may be unavailable."
+fi
+
+echo
+echo -e "${GREEN}Usage:${NC}"
+echo " ask 'What is 2+2?'"
+echo " ask -g 'Explain quantum computing'"
+echo " ask --help"
+echo
+echo "Don't forget to set your API key:"
+echo " export OPENROUTER_API_KEY='your-key-here'"