JustToThePoint English Website Version
JustToThePoint en español
Colaborate with us

Centralized CLI Knowledge & AI Queries from a Remote Server

If you find yourself in a hole, stop digging, Will Rogers

Proxmox VM Arch Linux Hyprland

In a home lab, it’s possible and, I would say, recommended to centralize documentation and knowledge tools on a headless server and query them remotely via the command line.

Centralized CLI Documentation & AI Queries on a Remote Server

 # Installation via its official script
 curl -fsSL https://ollama.com/install.sh | sh
 # After installation, Ollama runs a background service (by default on port 11434).
 # If your local machine lacks a compatible GPU, Ollama will default to CPU – it still works,
 # but heavy models will be significantly slower

 # Once Ollama is installed and running, you need to fetch an LLM model
 ollama pull qwen2.5:32b-instruct-q3_K_L
 ollama pull llama3.2
 ollama pull deepseek-r1
 # Remove a model
 ollama rm qwen:4b

# Running and Querying Models
ollama run qwen:4b
# It launches an interactive shell where you can type your queries to the LLM.
>>> What is the model Qwen?
Qwen is a large language model created by Alibaba Cloud,
and it is primarily used for natural language processing tasks such as sentiment analysis, named entity recognition, and machine
translation.

➜  ~ ollama ls
NAME                           ID              SIZE      MODIFIED
qwen2.5:32b-instruct-q3_K_L    83db34c608fc    17 GB     4 minutes ago
deepseek-r1:latest             0a8c26691023    4.7 GB    14 minutes ago
 sudo pacman -S tldr # Installation
 tldr -u
 # Update the local page cache, so it fetches the latest cheat-sheets.
 tldr ps # Use, just type: tldr 


  ps

  Information about running processes.
  More information: https://manned.org/ps.

  - List all running processes:
    ps aux

  - List all running processes including the full command string:
    ps auxww

  - Search for a process that matches a string (the brackets will prevent grep from matching itself):
    ps aux | grep [s]tring

  - List all processes of the current user in extra full format:
    ps --user $(id --user) -F

  - List all processes of the current user as a tree:
    ps --user $(id --user) f

  - Get the parent PID of a process:
    ps --format ppid= --pid pid

  - Sort processes by memory consumption:
    ps --sort size
# Installation
sudo pacman -S ddgr w3m
ddgr ddgr
# Use: Simply type ddgr 
 1.  jarun/ddgr: :duck: DuckDuckGo from the terminal - GitHub [github.com]
     ddgr is a cmdline utility to search DuckDuckGo (html version) from the terminal.While googler is extremely popular among cmdline users,
     in many forums the need of a similar utility for privacy-aware DuckDuckGo came up. DuckDuckGo Bangs are super-cool too! So here's ddgr
     for you!. Unlike the web interface, you can specify the number of search results you would like to see per page.

 2.  How to Use the Command 'ddgr' (with Examples) [commandmasters.com]
     Learn how to use ddgr, a command-line utility that allows you to interact with DuckDuckGo search engine from your terminal. See examples
     of different use cases, such as limiting results, displaying URLs, opening browser, and more.

 3.  How to add the power of DuckDuckGo to your Linux terminal [www.zdnet.com]
     How to use ddgr. Now that ddgr is installed, it's ready to be used. Here's a few examples of what you can do. [...]
# Next (n), Open (o ), Quit (q).
# If you type o 1, it will attempt to open result #1 in a browser.
# Obviously, on a remote server (SSH access), unless you have a text-based browser configured (like w3m or lynx) or X forwarding, opening in a GUI browser won't work.
# Install w3m, nvim ~/.zshrc and add export BROWSER=w3m, then source ~/.zshrc, exit, and ssh to your VM.

ddgr --noprompt -n 7 "ddgr w3m"
# The --noprompt (or --np) option tells ddgr not to enter the interactive prompt – it will just print the results and exit
# -n 7 limits its output to just 7 results.
 1.  jarun/ddgr: :duck: DuckDuckGo from the terminal - GitHub [github.com]
     ddgr is a cmdline utility to search DuckDuckGo (html version) from the terminal.While googler is extremely popular among cmdline users,
     in many forums the need of a similar utility for privacy-aware DuckDuckGo came up [...]

 2.  ddgr - PyPI [pypi.org]
     ddgr. ddgr is a cmdline utility to search DuckDuckGo (html version) from the terminal. [...]

# Site-specific search.
# It will search for the term "Ollama" but restricted to JustToThePoint.com.
ddgr -w justtothepoint.com "Ollama"

 1.  Build a free writing assistant with Python and Ollama [justtothepoint.com]
     The Ollama Python library provides the easiest way to integrate Python 3.8+ projects with Ollama. It allows users to run large language
     models (LLMs) like Llama 2, Code Llama and other models locally, meaning seamless integration with a language model locally or from your
     own server. [...]

 2.  Home Server & AI: Ollama | JustToThePoint [justtothepoint.com]
     -p 11434:11434: Maps port 11434 (Ollama's default API port) on the host to the container, enabling access to the model. In other words,
     we want the port 11434 inside the container to be accessible outside the container, too. ‐‐name ollama: Names the container "ollama" for
     easy reference. [...]

# It uses DuckDuckGo's !bing bang, which might directly fetch the bing page for Ollama.
ddgr \!b Ollama

Useful Bangs: Google (!g), Bing (!b), Wikipedia (!w), Stack Overflow (!so), YouTube (!yt), Amazon (!am), Reddit (!r), Twitter (!t), News articles (!news), and maps (!map).

Automating Combined Queries with Bash

To harness all these tools together, you can create an integrated Bash script that takes a keyword or query and retrieves information from multiple sources at once.

  1. On the remote VM, install the necessary CLI tools: sudo pacman -S ddgr tldr man-db bat ripgrep cowsay

  2. On your NixOS client, add these packages to environment.systemPackages in /etc/nixos/configuration.nix:

     {
      environment.systemPackages = with pkgs; [
        bat
        tldr
        ddgr
        ripgrep
        cowsay
      ];
     }
    

    The, run: sudo nixos-rebuild switch.

  3. Create the script on your client and make it executable: touch ~/bin/getinfo.sh && chmod +x getinfo.sh.

#!/usr/bin/env bash
# __  _  _  ___   __
#(  )( \( )(  _) /  \
# )(  )  (  ) _)( () )
#(__)(_)\_)(_)   \__/
#
# Enable strict mode for more robust error handling.
set -euo pipefail

# Configuration for remote user, host, and local search path
REMOTE_USER="nmaximo7"
REMOTE_HOST="192.168.1.40"
LOCAL_RG_PATHS=(
    "$HOME/justtothepoint/content/"
    "$HOME/dotfiles/"
    "$HOME/myNewPython/"
)
# Ollama model/command on remote host.
 OLLAMA_CMD_REMOTE="ollama run qwen2.5:32b-instruct-q3_K_L"

# Help message function to guide users on how to use the script
show_help() {
	cat << EOF # Uses cat << EOF for easier multiline text.
Usage: $(basename "$0") [QUESTION] # Uses $(basename "$0") for the script name.

This script assists in querying various resources based on the provided question.

You can ask questions related to:
1. Manual pages (man): Use the word 'man' followed by the command.
   Example: $(basename "$0") 'man ls'

2. Cheat sheets (cheat.sh): Use 'cheat.sh' followed by the command.
   Example: $(basename "$0") 'cheat.sh tar'

3. TLDR pages: Use 'tldr' followed by the command.
   Example: $(basename "$0") 'tldr git'

4. General queries: Any other question will be processed with Ollama, ddgr, and local searches.
   Example: $(basename "$0") 'How to install Python?'

Requirements:
  Local:  cowsay, ssh, rg (ripgrep), bat, curl, tldr, ddgr, and a bash-compatible shell.
  Remote: man, curl, tldr, ddgr, less, and your Ollama setup ($OLLAMA_CMD_REMOTE).

Ensure you have the necessary permissions and the remote server ($REMOTE_USER@$REMOTE_HOST) is accessible.
EOF
    exit 1
}

# Check for required local commands
check_commands() {
    local missing_cmds=0
    for cmd in cowsay ssh rg bat curl tldr ddgr; do
        if ! command -v "$cmd" &> /dev/null; then
            echo "Error: Required local command '$cmd' not found." >&2
            missing_cmds=$((missing_cmds + 1))
        fi
    done
    if [ "$missing_cmds" -gt 0 ]; then
        exit 1
    fi
}

# Function to clean the question by removing specified keywords
clean_question() {
    local input_question="$1"
    echo "$input_question" | sed -e 's/man//gi' -e 's/tldr//gi' -e 's/cheat.sh//gi' -e 's/\s\+/ /g' -e 's/^ *//' -e 's/ *$//'
}

# URL encode a string (requires python3)
# Fallback to basic sed encoding if python3 is not available
url_encode() {
    local input_string="$1"
    if command -v python3 &>/dev/null; then
        python3 -c 'import urllib.parse; print(urllib.parse.quote(input()))' <<< "$input_string"
    else
        echo "$input_string" | sed 's/ /%20/g' # Basic encoding, might not cover all cases
    fi
}

# Function to colorize output text
colorize() {
    local color="$1"
    local text="$2"
    case $color in
        red) echo -e "\033[31m$text\033[0m" ;;    # Red color
        green) echo -e "\033[32m$text\033[0m" ;;  # Green color
        yellow) echo -e "\033[33m$text\033[0m" ;; # Yellow color
        blue) echo -e "\033[34m$text\033[0m" ;;   # Blue color
        *) echo "$text" ;;                        # Default color
    esac
}

# Function to query manual pages on the remote host
query_man() {
    local term="$1"
    colorize blue "Querying remote manual pages for '$term'..."
    ssh -t "$REMOTE_USER@$REMOTE_HOST" "man '$term' | less -R"
    ssh -t "$REMOTE_USER@$REMOTE_HOST" "info '$term' | less -R"
}

# Function to query TLDR pages on the remote host
query_tldr() {
    local term="$1"
    colorize blue "Querying remote manual pages for '$term'..."
    ssh -t "$REMOTE_USER@$REMOTE_HOST" "tldr '$term' | less -R"
}

# Function to query cheat.sh on the remote host
query_cheatsh() {
    local term="$1"
    colorize green "Querying remote cheat.sh for '$term'..."
    local encoded_term
    # Encode the term for URL
    encoded_term=$(url_encode "$term")
    ssh -t "$REMOTE_USER@$REMOTE_HOST" "curl -s 'cheat.sh/$encoded_term' | less -R"
}

# Function to query Ollama on the remote host
query_ollama() {
    local term="$1"
    colorize blue "Querying remote Ollama with '$term'..."
    ssh -t "$REMOTE_USER@$REMOTE_HOST" "echo '$term' | $OLLAMA_CMD_REMOTE"
}

# Function to search local files in specified directories
query_ddgr() {
    clear
    local term="$1"
    colorize green "Searching remote ddgr for '$term'..."
    ssh -t "$REMOTE_USER@$REMOTE_HOST" "ddgr -n 3 --np '$term' | less -R"
}

# Local Search Function
search_local_files() {
    local term="$1"
    colorize blue "Searching local files for '$term'..."
    # Iterates through the LOCAL_RG_PATHS array.
    for path in "${LOCAL_RG_PATHS[@]}"; do
        # Checks if the path exists.
        if [ -d "$path" ]; then
            colorize yellow "Searching in $path:"
            # shellcheck disable=SC2086
            # The previous line in a Bash script is a directive for the ShellCheck tool, which is a static analysis tool for shell scripts.
            # We want word splitting to occurr for $term if it contains spaces for rg pattern
            # Use ripgrep to search and pipes rg output to bat for syntax highlighting and paging.
            if rg --color=always -i "$term" "$path" --context 3 | bat --language=txt --color=always --paging=always; then
                 echo # Add a newline if results were found and paged
            else
                 # Add a check for rg's exit status to print "No results found" if rg doesn't find anything
                 colorize red "No results found for '$term' in $path"
            fi
        else
            colorize red "Warning: Local search path '$path' not found."
        fi
    done
}

# --- Main Script ---

# Check for local command dependencies
check_commands

# Welcome message using cowsay
cowsay "Welcome, $(whoami)!"

# Display help if no arguments are provided
if [ $# -eq 0 ]; then
    show_help
fi

# Capture all arguments into question using "$*"
question="$*"
# cleaned_question is derived by cleaning the question. This term is then used for man, tldr, cheat.sh, ollama, ddgr, and local rg searches. This ensures consistency.
cleaned_question=$(clean_question "$question")
echo "Cleaned question: $cleaned_question"

# Check for "man" in the question and query if found
if echo "$question" | grep -qi 'man'; then
    query_man "$cleaned_question"
fi

# Check for "tldr" in the question and query if found
if echo "$question" | grep -qi 'tldr'; then
    query_tldr "$cleaned_question"
fi

# Check for "cheat.sh" in the question and query if found
if echo "$question" | grep -qi 'cheat.sh'; then
    query_cheatsh "$cleaned_question"
fi

# General local and remote queries
# These will always run, providing broader search results.
search_local_files "$cleaned_question"
query_ddgr "$cleaned_question"
query_ollama "$cleaned_question"

Other ideas: StackOverflow snippets (howdoi), Topic discovery (apropos, whatis), and Multiple search engines (surfraw).

Bitcoin donation

JustToThePoint Copyright © 2011 - 2025 Anawim. ALL RIGHTS RESERVED. Bilingual e-books, articles, and videos to help your child and your entire family succeed, develop a healthy lifestyle, and have a lot of fun. Social Issues, Join us.

This website uses cookies to improve your navigation experience.
By continuing, you are consenting to our use of cookies, in accordance with our Cookies Policy and Website Terms and Conditions of use.