X Home
Erbauliches Wörterbücher - online Lateinische Verbklassen Griechische Grammatik Griechische Verbklassen dynamisch Griechische Verbformen (breit) Griechische Verbformen (schmal) Griechischer Wortschatz Griechisch-Konverter
AI/KI: MCP-Server AI/KI: Local LLMs Toolbox CSV-Verarbeitung Scanner Toolbox Lexer Eigener Nameserver Cloud-Telefonanlage mit Asterisk Fernsteuerung von Outlook per ssh Interaktive HTML-Tabelle Bilderverwaltung im Browser CSV => Excel (formatiert) Befehlsreferenzen
Horae vulnerant ... Terminal 2.0 ...



Linux · Ollama · OpenCode · GLM-OCR · Tesseract · yt-dlp · MCP

Working with Local LLMs on the Linux Command Line

A local LLM stack turns an ordinary Linux shell into a compact environment for OCR, programming and text processing without sending every document to an online service. Ollama provides model management and a local inference API, while OpenCode can use these models as an interactive programming agent. The workflows below focus on three practical tasks: extracting text from document images, programming with local models, and summarizing large texts such as cleaned YouTube transcripts. The same environment can also be extended with remote MCP servers for structured access to external tools and databases.

Ollama OpenCode GLM-OCR Tesseract yt-dlp MCP

Overview: One Local Runtime, Several Workflows

The common component is Ollama. It stores and runs local models and exposes an HTTP API on localhost. A model can be used directly from the shell with ollama run, called programmatically through the API, or exposed to a client such as OpenCode through its OpenAI-compatible endpoint.

Linux shell Bash, pipes, files
commands / stdin
Ollama local model runtime
model inference
Local models OCR, coding, summarization

OCR

GLM-OCR receives an image and returns recognized text. Unlike classical OCR, an LLM-based OCR model can often preserve document structure more naturally, while the complete process remains local.

Programming

OpenCode adds a terminal user interface, project context, file editing and shell tools around a local Ollama model. This is more useful for software work than a plain chat prompt.

Summarization

Shell tools prepare the source material first. The cleaned text is then combined with a prompt and streamed through standard input to ollama run.

1

Install and Start Ollama and OpenCode

Minimal Linux setup for local inference and terminal-based programming.

Install Ollama

The current official Linux installer can be invoked directly from the shell:

curl -fsSL https://ollama.com/install.sh | sh

Download the models required for the workflows, for example:

ollama pull glm-ocr
ollama pull qwen3:8b
ollama pull qwen2.5-coder:7b
ollama pull qwen3.5:4b
ollama pull granite4.1:3b

Start Ollama

When Ollama is not already running as a service, start the local server:

ollama serve

In another terminal, start an interactive model session:

ollama run qwen3:8b

The local API used by the OCR script is available below http://127.0.0.1:11434/api. OpenCode uses the OpenAI-compatible endpoint http://127.0.0.1:11434/v1.

Install OpenCode

The current OpenCode installation script is:

curl -fsSL https://opencode.ai/install | bash

An alternative installation through Node.js is:

npm install -g opencode-ai

Start OpenCode

Start it inside the project directory whose files should become available to the coding agent:

cd ~/my-project
opencode

The provider configuration shown later maps OpenCode to the local Ollama endpoint and enumerates the available models.

2

OCR with GLM-OCR and Tesseract Fallback

Local OCR is especially attractive for receipts, invoices and tax documents because the original image does not have to be uploaded to an online OCR service.

There are three practical routes. A smartphone scanner can capture, deskew and crop the document close to the source. Classical Tesseract is fast and deterministic. GLM-OCR uses a vision-capable local model and can be preferable when the visual structure of the document matters. A useful workflow is therefore to capture a clean image first, attempt local GLM-OCR, and retain Tesseract as a robust fallback.

Receipt OCR data flow

receipt / invoice scan or smartphone image GLM-OCR text file tax / bookkeeping workflow

Core design of myollamaocr

The script does not pass a potentially huge Base64 image as a shell argument. It writes the encoded image to a temporary file and lets jq --rawfile read it into the JSON request. This avoids shell argument-size limits. The request explicitly caps both output size and total HTTP runtime to prevent runaway generations.

Essential excerpt · myollamaocr

MODEL="glm-ocr"
OLLAMA_URL="http://127.0.0.1:11434/api/generate"

MAX_TOKENS=4096
MAX_TIME=120

base64 -w 0 "$INPUT" > "$IMAGE64"

jq -n \
    --rawfile image "$IMAGE64" \
    --arg model "$MODEL" \
    --argjson max_tokens "$MAX_TOKENS" \
    '{
        model: $model,
        prompt: "Text Recognition:",
        images: [$image],
        stream: false,
        options: {
            num_predict: $max_tokens,
            temperature: 0.0,
            top_k: 1,
            top_p: 0.00001,
            repeat_penalty: 1.1
        }
    }' > "$REQUEST"

curl \
    --silent \
    --show-error \
    --max-time "$MAX_TIME" \
    --output "$RESPONSE" \
    --write-out '%{http_code}' \
    --header 'Content-Type: application/json' \
    --data-binary "@$REQUEST" \
    "$OLLAMA_URL"

jq -er '.response' "$RESPONSE" > "$RESULT"
mv -- "$RESULT" "$OUTPUT"

The model prompt is intentionally minimal: Text Recognition:. The image is sent to Ollama's /api/generate endpoint, generation is non-streaming, and conservative sampling settings are used because OCR should reproduce rather than invent text. The final .response field is extracted with jq and written to a text file with the same basename as the image.

Batch selection with myocrbatch

The wrapper has two deliberately simple modes. By default it delegates to myollamaocrbatch, whose intended behavior is “GLM-OCR first, Tesseract as fallback”. With -t, Ollama is bypassed completely and every JPG/PNG file is processed by Tesseract only.

Essential excerpt · myocrbatch

# Default mode: delegate to the GLM-OCR batch wrapper
if [ "$TESSERACT_ONLY" -eq 0 ]; then
    exec myollamaocrbatch
fi

# -t mode: Tesseract only
for file in "${files[@]}"; do
    target="${file%.*}_tess.txt"

    tesseract "$file" stdout -l deu --psm 4 --oem 1 \
        -c preserve_interword_spaces=1 > "$target"
done

The central Tesseract command

Receipt recognition · mytesseract

tesseract "$file" stdout -l deu --psm 4 --oem 1 \
    -c preserve_interword_spaces=1 > ${file%.*}_tess.txt

-l deu

Selects the German language data used by Tesseract.

--psm 4

Uses a page-segmentation mode suitable for text arranged in columns or varying regions, a useful baseline for receipts.

Preserve spacing

preserve_interword_spaces=1 asks Tesseract to retain inter-word spacing rather than normalize it aggressively.

Practical hierarchy: use a scanner or smartphone to obtain the cleanest possible image; use GLM-OCR when better structural interpretation is useful; retain Tesseract for speed, deterministic behavior and a dependable fallback. Online OCR remains an option, but is not necessary for this workflow.
3

Cloud Models: Ollama Cloud and OpenRouter

Local models are attractive for privacy, independence and predictable operation, but the available RAM, VRAM and CPU/GPU performance limit the model size that can be run comfortably. Cloud inference removes this hardware restriction: OpenCode still runs locally as the programming client, while the selected LLM runs on a remote provider.

Ollama Cloud

Ollama complements its local runtime with cloud-hosted models. Depending on the account and service level, cloud use can be available within a free allowance, through a subscription, or through additional usage credits. The subscription model is convenient for regular use; credits are useful when additional capacity is needed without changing the local workflow.

The important distinction is that ollama run model:cloud looks similar to running a local model, but inference takes place in the cloud. Local Ollama remains useful as the command-line/runtime integration layer.

OpenRouter

OpenRouter provides one API and one account for models from many different providers. Some models or routes can be used free of charge, while paid models consume prepaid credits according to actual usage.

The main advantage of the credit model is flexibility: there is no need to maintain a separate subscription with every model provider. A single credit balance and API key can be used to switch between inexpensive models for routine work and stronger models for difficult tasks. This is particularly convenient for experimenting with OpenCode because the client and project workflow remain unchanged when the model changes.

Local client, remote inference

project directory OpenCode Ollama Cloud / OpenRouter API cloud LLM OpenCode tools / files

Connecting Ollama Cloud to OpenCode

  1. Sign in to an Ollama account, create an API key under Settings → Keys, then start OpenCode.
  2. In OpenCode run /connect, select Ollama Cloud, and enter the Ollama Cloud API key.
  3. Before the cloud model is selected in OpenCode, pull its model information with the local Ollama command. For example:
    ollama pull gpt-oss:20b-cloud
    For a cloud model this step prepares the local Ollama-side model information; the actual model inference remains remote rather than requiring the complete model weights to run on the local GPU or CPU.
  4. Run /models in OpenCode and select the desired Ollama Cloud model.

Connecting OpenRouter to OpenCode

  1. Create an OpenRouter account, add credits if paid models are required, and create an API key.
  2. Run /connect in OpenCode and select OpenRouter.
  3. Enter the OpenRouter API key.
  4. Run /models. Many OpenRouter models are already known to OpenCode and can be selected immediately. Free variants can be used for experiments; paid variants draw from the OpenRouter credit balance.

If only selected OpenRouter models should appear in the OpenCode configuration, they can be declared explicitly in opencode.json:

{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "openrouter": {
      "models": {
        "z-ai/glm-5.2": {},
        "z-ai/glm-5.2:free": {}
      }
    }
  }
}

The exact model IDs must match the IDs exposed by OpenRouter. Authentication does not need to be stored in this JSON file when it has already been added with /connect.

ModeWhere inference runsPayment conceptMain advantage
Local Ollamalocal computerno per-request cloud costprivacy and independence
Ollama CloudOllama cloudfree allowance / subscription / creditscloud models with an Ollama-oriented workflow
OpenRouterselected remote providerfree models or usage creditsmany model providers behind one API key and credit balance
Practical combination: keep small and privacy-sensitive jobs on local Ollama models, and select a cloud model in OpenCode when a larger context, stronger coding performance or better tool calling is required. OpenRouter is especially useful when model choice should remain flexible and usage-based credits are preferable to several separate subscriptions.
4

Programming with Local Models

From plain model prompting to a project-aware terminal coding agent.

A coding model can be queried directly with Ollama, for example:

ollama run qwen2.5-coder:7b "Explain this Bash function and simplify it."

For actual software work, OpenCode provides the more useful abstraction. It can operate inside a project, inspect files, apply edits and invoke shell commands. The supplied configuration exposes several Ollama models to OpenCode through the local OpenAI-compatible API.

OpenCode · local Ollama provider excerpt

{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "ollama": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Ollama (local)",
      "options": {
        "baseURL": "http://127.0.0.1:11434/v1"
      },
      "models": {
        "qwen3:8b": { "name": "Qwen 3 8B" },
        "qwen2.5-coder:7b": { "name": "Qwen 2.5-coder 7B" },
        "qwen3.5:4b": { "name": "Qwen 3.5 4B" },
        "glm-ocr:latest": {
          "name": "GLM-OCR",
          "modalities": {
            "input": ["text", "image"],
            "output": ["text"]
          }
        },
        "granite4.1:3b": { "name": "Granite 4.1 3B" }
      }
    }
  }
}

Programming data flow

project directory OpenCode TUI Ollama provider local coding model files / shell tools
5

Summarizing Texts and YouTube Transcripts

Use shell tools for acquisition and cleanup, then let the LLM perform the semantic compression.

YouTube automatically generated subtitles are a convenient source for lectures, talks and long technical videos, but raw VTT files contain timestamps, metadata, markup, blank lines and frequently duplicated auto-caption lines. The supplied myyoutubesubs script separates acquisition from cleanup.

Essential excerpt · myyoutubesubs

# Download automatically generated subtitles
yt-dlp --write-auto-subs --skip-download "$URL"

# Keep only VTT files created by this invocation
mapfile -t VTTFILES < <(
    find . -maxdepth 1 -type f -name '*.vtt' -newer "$MARKER" -printf '%T@ %p\n' |
    sort -n |
    cut -d' ' -f2-
)

# Remove VTT metadata/timestamps/empty lines, strip HTML-like tags,
# de-duplicate consecutive identical subtitle lines, join to flowing text
# and wrap at the configured line length.
awk '
    /^WEBVTT/                   { next }
    /^Kind:/                    { next }
    /^Language:/                { next }
    /^NOTE/                     { next }
    /-->/                       { next }
    /^[[:space:]]*$/            { next }

    {
        gsub(/<[^>]*>/, "")
        sub(/^[[:space:]]+/, "")
        sub(/[[:space:]]+$/, "")

        if (length($0) && $0 != previous) {
            print
            previous = $0
        }
    }
' "$dst_vtt" |
tr '\n' ' ' |
sed 's/[[:space:]]\+/ /g; s/^ //; s/ $//' |
fold -s -w "$LINELENGTH" > "$dst_txt"

For a single video the script produces ausgabe.vtt and cleaned ausgabe.txt. For playlists it generates numbered pairs such as ausgabe_001.vtt and ausgabe_001.txt. Option -a additionally downloads the best available audio stream, while -l controls the output line width.

Transcript-to-summary workflow

YouTube URL yt-dlp VTT awk / sed / fold clean text ollama run summary file

Pass prompt and source text together with cat

A particularly shell-friendly pattern is to keep the instruction in one file and the transcript in another, concatenate both, and pass standard input to the model:

cat summary_prompt.txt ausgabe.txt |
    ollama run qwen3:8b > condensed.txt

A prompt file could contain only the instruction, for example:

Summarize the following transcript in concise English.
Preserve the essential technical arguments, commands and conclusions.
Do not invent information that is not present in the source.

--- TRANSCRIPT ---

The same principle works without a separate prompt file. A shell group can prepend the instruction and then stream the source text:

{
    printf '%s\n\n' \
      'Summarize the following text concisely while preserving technical details:'
    cat ausgabe.txt
} | ollama run qwen3:8b > condensed.txt
6

Client Configuration: Codex, OpenCode and Claude Code

Local models and MCP solve different problems: Ollama supplies local inference; MCP supplies external tools and structured data sources. The supplied configurations demonstrate how command-line clients can combine these layers.

Codex · config.toml

Codex stores MCP configuration in config.toml. The supplied example registers the remote example endpoint, obtains its Authorization header from an environment variable, and allows the two database tools without repeated approval.

[mcp_servers.example]
url = "https://www.drbreinlinger.de/mcp/example"

[mcp_servers.example.env_http_headers]
Authorization = "example_MCP_AUTHORIZATION"

[mcp_servers.example.tools.get_database_semantics]
approval_mode = "approve"

[mcp_servers.example.tools.query_sql]
approval_mode = "approve"

The value example_MCP_AUTHORIZATION is the name of the environment variable whose value becomes the HTTP Authorization header.

OpenCode · opencode.json

The supplied OpenCode configuration combines two roles in one file: a local Ollama provider and a remote MCP server. The local provider points to port 11434; the MCP server points to the HTTPS endpoint.

{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "ollama": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Ollama (local)",
      "options": {
        "baseURL": "http://127.0.0.1:11434/v1"
      },
      "models": {
        "qwen3:8b": {
          "name": "Qwen 3 8B"
        },
        "qwen2.5-coder:7b": {
          "name": "Qwen 2.5-coder 7B"
        },
        "qwen3.5:4b": {
          "name": "Qwen 3.5 4B"
        },
        "glm-ocr:latest": {
          "name": "GLM-OCR",
          "modalities": {
            "input": [
              "text",
              "image"
            ],
            "output": [
              "text"
            ]
          }
        },
        "granite4.1:3b": {
          "name": "Granite 4.1 3B"
        }
      }
    }
  },
  "mcp": {
    "example": {
      "type": "remote",
      "url": "https://www.drbreinlinger.de/mcp/example",
      "oauth": false,
      "headers": {
        "Authorization": "Bearer {env:EXAMPLE_MCP_TOKEN}"
      },
      "enabled": true
    },
  "model": "granite4.1:3b"
}

The token is referenced as {env:EXAMPLE_MCP_TOKEN}, so the secret remains outside the configuration.

Claude Code · .mcp.json

Claude Code uses a project-scoped .mcp.json. The supplied file registers the same remote HTTP MCP endpoint and obtains the Bearer token from EXAMPLE_MCP_TOKEN.

{
  "mcpServers": {
    "example": {
      "type": "http",
      "url": "https://www.drbreinlinger.de/mcp/example",
      "headers": {
        "Authorization": "Bearer ${EXAMPLE_MCP_TOKEN}"
      }
    }
  }
}

Environment variables for credentials

export EXAMPLE_MCP_TOKEN='...'
export example_MCP_AUTHORIZATION='Bearer ...'

The two configuration formats expect slightly different values: the OpenCode and Claude examples construct the Bearer prefix inside the configuration, whereas the supplied Codex TOML maps the environment variable directly to the complete Authorization header.

Combined local-LLM / MCP architecture

OpenCode / Codex / Claude Code model inference local or hosted LLM+ MCP tools remote databases / services

Direct Comparison of the Main Workflows

Task Primary tool Input Output Why local?
Document OCR GLM-OCR via Ollama JPG / PNG TXT privacy + structural interpretation
OCR fallback Tesseract JPG / PNG TXT fast + deterministic + offline
Programming OpenCode + Ollama project files + prompt analysis / edits / commands project data remains local
Transcript cleanup yt-dlp + awk/sed/fold YouTube URL / VTT clean TXT minimal reproducible shell pipeline
Summarization ollama run <model> prompt + clean text via stdin condensed TXT large source text need not be uploaded
Final workflow: Linux shell tools remain responsible for deterministic preparation — scanning, downloading, renaming, filtering, de-duplication and piping. Local LLMs are inserted where semantic interpretation adds value: structure-aware OCR, programming assistance and summarization. This keeps the overall solution transparent, scriptable and easy to automate with ordinary command-line tools.

Official References

  • Ollama Linux installation and API documentation: docs.ollama.com
  • OpenCode installation, models, providers, Ollama Cloud, OpenRouter, configuration and MCP documentation: opencode.ai/docs
  • Ollama Cloud documentation and account management: ollama.com / docs.ollama.com
  • OpenRouter API, models and credits: openrouter.ai
  • Codex MCP configuration documentation: developers.openai.com/codex/mcp
  • Claude Code MCP documentation: docs.anthropic.com/en/docs/claude-code/mcp

Legal notice