If you find yourself in a hole, stop digging, Will Rogers
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.
# 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
Man pages — abbreviation for manual pages — are the form of documentation that is available on almost all UNIX-like operating systems, including Arch Linux (sudo pacman -S man-db
). It is an offline encyclopedia of your system’s tools, the definitive reference for system commands, configuration files, system calls, etc., e.g., man ifconfig
While viewing a man page, you can press / to search for keywords within it.
ddgr is a command-line utility to search the web using the DuckDuckGo engine. It allows you to search DuckDuckGo directly from the terminal and view results in a clean, readable format, which is invaluable on a headless server or when you want to stay in CLI.
# 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).
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.
On the remote VM, install the necessary CLI tools: sudo pacman -S ddgr tldr man-db bat ripgrep cowsay
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
.
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).