feat(ai): default to NL2SH + add -q/--quiet for non-interactive output
Make westenfelder/NL2SH the default `ai` model (most accurate in the 25-query benchmark, only model handling hard multi-stage tasks) and add a -q/--quiet/--raw flag that prints just the generated command to stdout (errors to stderr) so `ai` composes in scripts and pipelines. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -34,22 +34,35 @@ super-man ai "count lines in js files" # AI bash one-liner via local LLM (advan
|
||||
### AI mode (local LLM via ollama)
|
||||
|
||||
`ai` generates a bash one-liner from plain English using a local [ollama](https://ollama.com)
|
||||
model. The model is configurable, so you can A/B different local LLMs:
|
||||
model. The default is `westenfelder/NL2SH`, a model purpose-built for
|
||||
natural-language-to-shell — in our 25-query benchmark it was the most accurate, the
|
||||
only one that handled hard multi-stage tasks. The model is configurable, so you can
|
||||
still A/B other local LLMs:
|
||||
|
||||
```bash
|
||||
super-man ai "find python files modified last week" # default model
|
||||
super-man ai --model qwen2.5:3b "count lines in all js files" # override model
|
||||
super-man ai --compare "list the 5 largest files" # run several models side by side
|
||||
super-man ai "find python files modified last week" # default model (NL2SH)
|
||||
super-man ai -q "list the 5 largest files" # quiet: print ONLY the command
|
||||
super-man ai --model qwen2.5-coder:1.5b "count lines in js" # override model
|
||||
super-man ai --compare "list the 5 largest files" # run several models side by side
|
||||
```
|
||||
|
||||
The `-q` / `--quiet` / `--raw` flag prints only the generated command to stdout (errors
|
||||
go to stderr), so it composes in scripts and pipelines:
|
||||
|
||||
```bash
|
||||
cmd=$(super-man ai -q "compress the logs folder into a tarball")
|
||||
echo "$cmd" # tar -czf logs.tar.gz logs/
|
||||
```
|
||||
|
||||
| Env var | Purpose | Default |
|
||||
|---------|---------|---------|
|
||||
| `SUPERMAN_AI_MODEL` | Default model for `ai` | `qwen2.5-coder:1.5b` |
|
||||
| `SUPERMAN_AI_COMPARE_MODELS` | Space-separated list for `--compare` | `qwen2.5-coder:1.5b westenfelder/NL2SH` |
|
||||
| `SUPERMAN_AI_MODEL` | Default model for `ai` | `westenfelder/NL2SH` |
|
||||
| `SUPERMAN_AI_COMPARE_MODELS` | Space-separated list for `--compare` | `westenfelder/NL2SH qwen2.5-coder:1.5b` |
|
||||
|
||||
General coder models (e.g. `qwen2.5-coder`) are prompt-wrapped to emit a single bare
|
||||
command; the purpose-built `westenfelder/NL2SH` model receives the raw query. Pull
|
||||
either with `ollama pull <model>`.
|
||||
The purpose-built `westenfelder/NL2SH` model receives the raw query; general coder
|
||||
models (e.g. `qwen2.5-coder`) are prompt-wrapped to emit a single bare command. Pull
|
||||
either with `ollama pull <model>`. See the
|
||||
[benchmark write-up](tests/performance/) for the full model comparison.
|
||||
|
||||
`Esc` in the flag browser returns to the command list; `Esc` on the home screen
|
||||
exits.
|
||||
|
||||
+42
-22
@@ -41,7 +41,7 @@ show_help() {
|
||||
echo -e " ${CYAN}Natural Language Queries:${NC}"
|
||||
echo -e " ${GREEN}ask${NC} \"query\" Ask in natural language (database)"
|
||||
echo -e " ${GREEN}task${NC} \"description\" Describe what you want to do (database)"
|
||||
echo -e " ${GREEN}ai${NC} \"complex query\" AI bash one-liner via local LLM (advanced) 🤖"
|
||||
echo -e " ${GREEN}ai${NC} \"complex query\" Text-to-bash one-liner, fully local (advanced) 🤖"
|
||||
echo ""
|
||||
echo -e " ${CYAN}Browse & Explore:${NC}"
|
||||
echo -e " ${GREEN}category${NC} NAME Browse by category (files/text/network/system)"
|
||||
@@ -76,19 +76,21 @@ show_help() {
|
||||
echo -e " ${GREEN}✓${NC} jq (for natural language queries)"
|
||||
echo -e " ${GREEN}✓${NC} fzf (for interactive mode only)"
|
||||
echo ""
|
||||
echo -e "${BOLD}${YELLOW}AI MODE${NC} 🤖"
|
||||
echo -e " Generate bash one-liners from plain English via a local ollama model:"
|
||||
echo -e "${BOLD}${YELLOW}AI MODE${NC} 🤖 (text-to-bash, fully local via ollama)"
|
||||
echo -e " ${GREEN}super-man ai \"find python files modified last week\"${NC}"
|
||||
echo -e " ${GREEN}super-man ai --model qwen2.5:3b \"count lines in all js files\"${NC}"
|
||||
echo -e " ${GREEN}super-man ai --compare \"list the 5 largest files\"${NC} # A/B models"
|
||||
echo -e " ${GREEN}super-man ai -q \"count lines in all js files\"${NC} # print ONLY the command"
|
||||
echo -e " ${GREEN}super-man ai --compare \"list the 5 largest files\"${NC} # A/B models"
|
||||
echo ""
|
||||
echo -e " ${DIM}-q/--raw prints just the command — pipeable:${NC}"
|
||||
echo -e " ${GREEN}\$(super-man ai -q \"...\")${NC} or ${GREEN}super-man ai -q \"...\" | tee cmd.sh${NC}"
|
||||
echo ""
|
||||
echo -e " Default model: ${CYAN}${SUPERMAN_AI_MODEL}${NC}"
|
||||
echo " Configure via env vars:"
|
||||
echo " SUPERMAN_AI_MODEL default model (e.g. westenfelder/NL2SH)"
|
||||
echo " SUPERMAN_AI_MODEL default model (e.g. qwen2.5-coder:1.5b for speed)"
|
||||
echo " SUPERMAN_AI_COMPARE_MODELS space-separated list for --compare"
|
||||
echo ""
|
||||
echo -e "${YELLOW}Database:${NC} $DB_FILE"
|
||||
echo -e "${YELLOW}Version:${NC} 2.2.0 (250+ commands, configurable local AI)"
|
||||
echo -e "${YELLOW}Version:${NC} 2.3.0 (250+ commands, local text-to-bash AI)"
|
||||
echo ""
|
||||
}
|
||||
|
||||
@@ -319,8 +321,8 @@ mode_category() {
|
||||
# side with `--compare`. NL2SH is purpose-built for NL->shell so it receives
|
||||
# the raw query; general coder models get an instruction wrapper plus markdown
|
||||
# fence stripping so they too emit a single bare command.
|
||||
SUPERMAN_AI_MODEL="${SUPERMAN_AI_MODEL:-qwen2.5-coder:1.5b}"
|
||||
SUPERMAN_AI_COMPARE_MODELS="${SUPERMAN_AI_COMPARE_MODELS:-qwen2.5-coder:1.5b westenfelder/NL2SH}"
|
||||
SUPERMAN_AI_MODEL="${SUPERMAN_AI_MODEL:-westenfelder/NL2SH}"
|
||||
SUPERMAN_AI_COMPARE_MODELS="${SUPERMAN_AI_COMPARE_MODELS:-westenfelder/NL2SH qwen2.5-coder:1.5b}"
|
||||
|
||||
# Build a model-appropriate prompt for a query.
|
||||
ai_build_prompt() {
|
||||
@@ -374,11 +376,13 @@ ai_explain_base() {
|
||||
|
||||
mode_ai() {
|
||||
local compare=false
|
||||
local quiet=false
|
||||
local model="$SUPERMAN_AI_MODEL"
|
||||
local args=()
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--compare|-c) compare=true ;;
|
||||
--quiet|--raw|-q) quiet=true ;;
|
||||
--model|-m) shift; model="$1" ;;
|
||||
*) args+=("$1") ;;
|
||||
esac
|
||||
@@ -387,27 +391,43 @@ mode_ai() {
|
||||
local user_query="${args[*]}"
|
||||
|
||||
if [ -z "$user_query" ]; then
|
||||
echo -e "${RED}Error: No query provided${NC}"
|
||||
echo "Usage: super-man ai [--model NAME|--compare] \"your query\""
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " super-man ai \"find all python files modified in last week\""
|
||||
echo " super-man ai --model qwen2.5:3b \"count lines in all js files\""
|
||||
echo " super-man ai --compare \"list the 5 largest files\""
|
||||
echo -e "${RED}Error: No query provided${NC}" >&2
|
||||
echo "Usage: super-man ai [--model NAME] [--quiet|--compare] \"your query\"" >&2
|
||||
echo "" >&2
|
||||
echo "Examples:" >&2
|
||||
echo " super-man ai \"find all python files modified in last week\"" >&2
|
||||
echo " super-man ai -q \"count lines in all js files\" # prints only the command" >&2
|
||||
echo " super-man ai --compare \"list the 5 largest files\"" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Check if ollama is available
|
||||
if ! command -v ollama &> /dev/null; then
|
||||
echo -e "${RED}Error: Ollama is not installed${NC}"
|
||||
echo ""
|
||||
echo "Install Ollama:"
|
||||
echo " curl -fsSL https://ollama.com/install.sh | sh"
|
||||
echo ""
|
||||
echo "For now, try: super-man ask \"$user_query\""
|
||||
echo -e "${RED}Error: Ollama is not installed${NC}" >&2
|
||||
echo "" >&2
|
||||
echo "Install Ollama:" >&2
|
||||
echo " curl -fsSL https://ollama.com/install.sh | sh" >&2
|
||||
echo "" >&2
|
||||
echo "For now, try: super-man ask \"$user_query\"" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# ── Quiet/raw mode: print ONLY the generated command (pipeable, scriptable) ─
|
||||
if $quiet; then
|
||||
if ! ai_model_installed "$model"; then
|
||||
echo "Error: model '$model' not installed. Pull with: ollama pull $model" >&2
|
||||
return 1
|
||||
fi
|
||||
local out
|
||||
out=$(ai_generate "$model" "$user_query")
|
||||
if [ -z "$out" ]; then
|
||||
echo "Error: no response from $model" >&2
|
||||
return 1
|
||||
fi
|
||||
printf '%s\n' "$out"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# ── Compare mode: run every configured model side by side ──────────────────
|
||||
if $compare; then
|
||||
echo ""
|
||||
|
||||
Reference in New Issue
Block a user