- Posted on
- • Artificial Intelligence
Artificial Intelligence Ollama Projects
- Author
-
-
- User
- linuxbash
- Posts by this author
- Posts by this author
-
4 Practical Ollama Projects You Can Build with Pure Bash on Linux
If you’ve ever wished you could use powerful AI models directly from your terminal—without sending your data to the cloud—this is your moment. Ollama makes it easy to run large language models (LLMs) locally, and with a few Bash scripts you can automate real work: generate commit messages, summarize logs, or query your docs with a tiny RAG pipeline.
This post shows why running AI locally is worth your time, then walks you through four hands-on Ollama projects you can build today—entirely from Bash.
Why Ollama on Linux?
Privacy by default: Your prompts and data never leave your machine.
Cost control: No per-token API bills. Run as much as you want on your hardware.
Low latency: Local inference is fast for most 7B/8B models, and even faster with a GPU.
Unix-native workflow: Pipe, filter, and compose with standard tools (bash, jq, ripgrep, systemd, cron).
Prerequisites
We’ll install a few common CLI tools. Choose the commands for your distro.
- Debian/Ubuntu (apt):
sudo apt update
sudo apt install -y curl jq git ripgrep
- Fedora/RHEL/CentOS (dnf):
sudo dnf install -y curl jq git ripgrep
- openSUSE (zypper):
sudo zypper refresh
sudo zypper --non-interactive install curl jq git ripgrep
Install Ollama
The recommended Linux install is a one-liner script that sets up the ollama binary and a systemd service.
curl -fsSL https://ollama.com/install.sh | sh
Start and enable the service (system-wide):
sudo systemctl enable --now ollama
sudo systemctl status ollama
If your environment prefers a user service:
systemctl --user enable --now ollama
systemctl --user status ollama
Verify:
ollama --version
ollama list
Optional: run via Docker instead of systemd:
docker run -d --name ollama -p 11434:11434 -v ollama:/root/.ollama ollama/ollama
Pull a few models we’ll use:
ollama pull llama3
ollama pull codellama
ollama pull nomic-embed-text
Notes:
llama3is a strong general-purpose instruction model.codellamaworks well for code-oriented prompts.nomic-embed-textgenerates embeddings for similarity search (for our mini-RAG).
Project 1: A one-liner terminal assistant
Use a local LLM like a shell tool. Great for quick explanations or throwaway drafts.
- Interactive:
ollama run llama3
- One-off output you can pipe or capture:
ollama generate -m llama3 -p "Explain the difference between hard links and symbolic links in Linux. Keep it under 120 words."
- With a lightweight “system prompt”:
SYS="You are a concise Linux assistant. Prefer examples and POSIX tools."
Q="Show a one-liner to find the 10 largest files under /var, excluding /var/log."
ollama generate -m llama3 -p "$SYS"$'\n\n'"Question: $Q"
Actionable tip: For automation, always prefer ollama generate (non-interactive) over ollama run (REPL).
Project 2: AI-assisted Git commit messages (conventional commits)
Turn your staged diff into a well-structured commit message.
Create a script git-commit-ai somewhere on your PATH:
#!/usr/bin/env bash
set -euo pipefail
MODEL="${MODEL:-llama3}"
# Make sure there are staged changes.
if ! git diff --cached --quiet; then
:
else
echo "No staged changes. Stage some files first (e.g., `git add -p`)."
exit 1
fi
DIFF="$(git diff --cached)"
PROMPT="$(cat <<'EOF'
You are an expert at writing conventional commit messages.
Rules:
- Use a present-tense, imperative subject line (<= 72 chars).
- Use a conventional type like: feat, fix, docs, style, refactor, perf, test, chore.
- Provide a detailed body with bullet points when useful.
- Mention breaking changes under "BREAKING CHANGE:" if applicable.
- Infer scope (e.g., cli, api, docs) when obvious.
Generate only the commit message.
EOF
)"
MSG="$(ollama generate -m "$MODEL" -p "$PROMPT"$'\n\n'"Diff:\n$DIFF")"
# Let the user review in the standard editor:
printf '%s\n' "$MSG" > .git/COMMIT_EDITMSG
git commit -e -F .git/COMMIT_EDITMSG
Make it executable:
chmod +x git-commit-ai
Use it:
git add -p
git-commit-ai
Tip: For code-heavy repos, try MODEL=codellama git-commit-ai.
Project 3: Mini RAG in pure Bash + jq (Ask your local docs)
This simple retrieval-augmented generation (RAG) setup indexes your .md and .txt files, finds the most relevant chunks using embeddings, and feeds them to a model for grounded answers.
We’ll create two scripts: one to build an index, and one to ask questions.
1) Index your docs into index.jsonl:
#!/usr/bin/env bash
# index.sh: build a tiny embedding index from docs/*.md, *.txt
set -euo pipefail
DOC_DIR="${1:-docs}"
MODEL_EMB="${MODEL_EMB:-nomic-embed-text}"
INDEX="${2:-index.jsonl}"
[ -d "$DOC_DIR" ] || { echo "No $DOC_DIR directory"; exit 1; }
: > "$INDEX"
# Function: JSON-escape stdin to a string
json_escape() { jq -Rs '.'; }
# Chunking: ~1500 characters per chunk (rough but effective)
chunk_file() {
local file="$1"
awk -v max=1500 -v file="$file" '
BEGIN { buf=""; }
{
if (length(buf) + length($0) + 1 > max) {
print buf;
buf="";
}
buf = (buf=="" ? $0 : buf ORS $0);
}
END {
if (length(buf)>0) print buf;
}
' "$file"
}
embed() {
local text="$1"
curl -sS http://localhost:11434/api/embeddings \
-d "{\"model\":\"$MODEL_EMB\",\"prompt\":$text}" \
| jq -c '.embedding'
}
id=0
shopt -s nullglob
for f in "$DOC_DIR"/*.md "$DOC_DIR"/*.txt; do
while IFS= read -r chunk; do
esc="$(printf '%s' "$chunk" | json_escape)"
emb="$(embed "$esc")"
printf '{"id":%s,"source":%s,"text":%s,"embedding":%s}\n' \
"$id" "$(printf '%s' "$f" | jq -R '.')" "$esc" "$emb" >> "$INDEX"
id=$((id+1))
done < <(chunk_file "$f")
done
echo "Indexed $id chunks into $INDEX"
2) Ask a question using the index:
#!/usr/bin/env bash
# ask.sh: query the index with a question; returns grounded answer
set -euo pipefail
INDEX="${1:-index.jsonl}"
QUESTION="${2:-}"
MODEL_GEN="${MODEL_GEN:-llama3}"
MODEL_EMB="${MODEL_EMB:-nomic-embed-text}"
[ -s "$INDEX" ] || { echo "Missing or empty $INDEX. Run ./index.sh first."; exit 1; }
[ -n "$QUESTION" ] || { echo "Usage: ./ask.sh index.jsonl 'Your question'"; exit 1; }
# 1) Embed the question
QEMB="$(curl -sS http://localhost:11434/api/embeddings \
-d "{\"model\":\"$MODEL_EMB\",\"prompt\":$(printf '%s' "$QUESTION" | jq -Rs '.')}" \
| jq -c '.embedding')"
# 2) Rank chunks by cosine similarity (jq 1.6+)
TOPK_JSON="$(jq -s --argjson q "$QEMB" '
def dot(a;b): reduce range(0; a|length) as $i (0; . + (a[$i]*b[$i]));
def norm(a): (reduce a[] as $x (0; . + ($x*$x))) | sqrt;
def cosine(a;b): (dot(a;b)) / ((norm(a) * norm(b)) + 1e-9);
map(. + {score: cosine(.embedding; $q)}) | sort_by(-.score) | .[:3]
' "$INDEX")"
# 3) Build context string from the top chunks
CONTEXT="$(printf '%s' "$TOPK_JSON" | jq -r '.[] | "From: \(.source)\n---\n\(.text)\n"' )"
# 4) Ask the generator model with the retrieved context
PROMPT="$(cat <<EOF
You are a precise assistant. Use ONLY the provided context to answer.
If the answer is not in the context, say you don't know.
Context:
$CONTEXT
Question: $QUESTION
Answer:
EOF
)"
ollama generate -m "$MODEL_GEN" -p "$PROMPT"
Usage:
mkdir -p docs
cp README.md docs/
./index.sh docs index.jsonl
./ask.sh index.jsonl "How do I run the CLI tool? Provide exact flags if present."
Notes:
Adjust chunk size or K (top 3) as needed.
For larger corpora, consider storing
index.jsonlsomewhere persistent and automatingindex.shwith cron.
Project 4: Summarize system logs (cron-friendly)
Get a clean summary of your last hour of service logs—perfect for on-call or daily reports.
One-shot summary:
SERVICE="nginx"
LOGS="$(journalctl -u "$SERVICE" --since '1 hour ago' -o short-iso | tail -n 2000)"
PROMPT="Summarize the following $SERVICE logs from the last hour. Identify errors, recurring issues, and suggested next steps. Be concise."
ollama generate -m llama3 -p "$PROMPT"$'\n\n'"Logs:\n$LOGS"
Automate with cron to send a summary to a file every hour:
crontab -e
Add:
0 * * * * SERVICE=nginx /bin/bash -lc 'LOGS="$(journalctl -u "$SERVICE" --since "1 hour ago" -o short-iso | tail -n 2000)"; PROMPT="Summarize the following $SERVICE logs from the last hour. Identify errors, recurring issues, and suggested next steps."; ollama generate -m llama3 -p "$PROMPT"$'\n\n'"Logs:\n$LOGS" > "$HOME/${SERVICE}_summary_$(date +\%Y-\%m-\%d_\%H00).txt"'
Tip: Pipe very noisy logs through grep -v or sed to remove control characters and keep prompts under a few tens of thousands of characters.
Troubleshooting and tips
GPU acceleration: If you have a supported GPU and drivers, Ollama will try to use it automatically; check
ollama show llama3for details andnvidia-smifor load.Service health:
sudo systemctl status ollama(orsystemctl --user status ollama) to verify it’s running on port 11434.Model sizes: Prefer 7B/8B models for laptops; larger models need more RAM/VRAM.
Light dependencies recap:
- Debian/Ubuntu:
sudo apt install -y curl jq git ripgrep - Fedora/RHEL/CentOS:
sudo dnf install -y curl jq git ripgrep - openSUSE:
sudo zypper --non-interactive install curl jq git ripgrep
- Debian/Ubuntu:
Conclusion and next steps
You’ve just built four useful, privacy-preserving AI workflows entirely in Bash:
Quick terminal assistant
AI commit messages
A tiny but real RAG for your docs
Log summarization on a schedule
From here, you can:
Swap models (
ollama pull mistral,ollama pull qwen2) to see what works best.Add caching to the RAG index.
Wrap your scripts with fzf for a TUI, or expose them via a tiny HTTP server.
Call to action:
- Install Ollama and run your first one-liner today:
curl -fsSL https://ollama.com/install.sh | sh
sudo systemctl enable --now ollama
ollama pull llama3
ollama generate -m llama3 -p "What should I automate with Bash and a local LLM?"
Your terminal just got a whole lot smarter—without leaving your machine.