User Guide
Complete user manual for GGUF Loader - learn all features and capabilities
This is the complete manual for GGUF Loader 2.1.2. GGUF Loader is a privacy-first desktop app for running large language models locally from GGUF files, with zero data leaving your machine.
πͺ The Main Window
The app is divided into three areas:
- Header bar (top) β brand on the left, a live model status chip on the right.
- Sidebar (left) β Model Settings, Environment, and Launcher sections.
- Chat area (center) β the conversation, or a welcome screen when no model is loaded.
βοΈ Model Settings Sidebar
Model
- Load GGUF Model β opens a file dialog; pick any
.gguffile. - Model info β shows the loaded file name (or an error).
Processing
- CPU Only β runs on any machine using llama.cppβs CPU backend.
- GPU Accelerated β offloads layers to an NVIDIA GPU (Windows/Linux). Requires a working CUDA llama-cpp-python install.
Context Length
The modelβs context window in tokens (512β32768). Larger contexts use more RAM. Change it before loading a model.
π Environment Section
GGUF Loader ships with a built-in dependency manager for source installs:
- Python Β· .venv status β shows the interpreter and whether the app runs from a virtual environment.
- Install Missing Dependencies β appears when packages are missing; runs
pip install -r requirements.txt. - Create .venv & Restart β bootstraps a virtual environment and relaunches inside it.
- Check Again β re-scans the environment.
The packaged installers (
.exe/ Linux tarball) bundle everything, so this section is mostly relevant when running from source.
π Launcher Section
One-click buttons that open the projectβs scripts/ utilities (e.g. GPU support verification, monitor) in separate windows, plus Restart App.
π¬ Chatting
- Type in the input box; Enter sends, Shift+Enter inserts a newline.
- Send is disabled until you type something, and is disabled entirely until a model is loaded.
- Responses stream token-by-token into bubbles: your messages right (amber), AI left (charcoal).
- View β Text Size (12β22) changes bubble font size live.
- File β Clear Chat wipes the conversation (the model stays loaded).
π€ Agent Mode
Agent Mode turns the chat into a tool-using assistant that works inside a workspace folder:
- Toggle π€ Agent Mode: OFF β ON.
- Choose a workspace (combo box or π browse button). Default:
./agent_workspace. - Ask for file operations β e.g. βCreate a markdown file listing todayβs tasksβ.
The agent will:
- Analyze complex requests,
- Plan tool calls and stream status updates (π€/π‘/β/β/β),
- Execute tools against the workspace β
list_directory,read_file,write_file,edit_file,search_files, - Summarize results in natural language.
Safety: all tools are sandboxed to the workspace; paths that escape it are rejected.
π¨ Appearance
- View β Dark Mode toggles the βMidnight & Amberβ dark theme and a light theme.
- View β Text Size adjusts chat bubble text.
- The app remembers dark mode per session (dark is the default).
π§© Addons
The Addons menu lists every loaded addon (e.g. floating_chat). Selecting one opens it in a floating dialog; Refresh Addons re-scans the addons/ folder. See the Addon Development Guide.
π¬ Floating Chat
The built-in addon adds a Messenger-style floating button (always on top, draggable) that opens a chat window connected to the loaded model. It:
- Stays on top of all windows (see platform notes below)
- Remembers its position between sessions
- Shows model status (π’ Ready / π΄ offline) and streams responses
- Has Copy All / Clear controls
Platform notes: fully floating on Windows and Linux/X11. On Linux Wayland, compositors confine it to the app window β run under X11 (QT_QPA_PLATFORM=xcb) for the full effect. On macOS the button stays visible when the app loses focus but also appears in Mission Control.
π Where Files Live
- Config:
%APPDATA%\GGUFLoader(Windows) /~/.ggufloader(Linux/macOS) - Cache:
%LOCALAPPDATA%\GGUFLoader\cache(Windows) /~/.cache/ggufloader(Linux) - Logs:
%LOCALAPPDATA%\GGUFLoader\logs(Windows) /~/.ggufloader/logs(Linux) - Addons: the
addons/folder next to the app
β€οΈ Feedback
Help β Send Feedback opens the feedback dialog. Point it at your own Formspree endpoint via feedback_config.json:
{ "endpoint_url": "https://formspree.io/f/YOUR_FORM_ID" }
π Still Stuck?
See the Troubleshooting Guide.
Related Documentation
quick start guide
get up and running with gguf loader in just a few minutes
beginner 5 minutesget up and running with gguf loader 2.2.0 in just a few minutes! new to gguf loader? check out the homepage to see what makes it special.
π step 1: install gguf loader
follow the installation guide for your platform, or download directly:
- windows: ggufloader_v2.2.0_cpu.exe (cpu-only) Β· ggufloader_v2.2.0_gpu.exe (nvidia cuda)
- linux: ggufloader_v2.2.0_linux_x86_64_cpu
π₯ step 2: get a gguf model
gguf loader runs any gguf-format model. good starter models on hugging face:
- small (fast): llama-3-8b-instruct gguf (q4_0) β ~4.7 gb, runs great on cpu
- medium: mistral-7b-instruct gguf (q4_k_m) β ~4.1 gb
- larger: phi-3.5-mini-instruct gguf or any qwen/llama gguf you like
download the
.gguffile and remember where you saved it.π₯οΈ step 3: load the model
- launch gguf loader.
- in the model settings sidebar, choose processing mode β
cpu only(default, works everywhere) orgpu accelerated(nvidia cuda). - set a context length (8192 is a safe default for most models; 32768 uses more ram).
- click load gguf model and select your
.gguffile. - wait for the status to show βmodel ready!β β the header chip turns green with the model name.
π¬ step 4: chat
type a message in the input box at the bottom and press enter (shift+enter inserts a newline). responses stream in as chatgpt-style bubbles β your messages on the right (amber), the aiβs on the left.
use the view β text size menu to adjust bubble font size.
π€ step 5 (optional): try agent mode
click π€ agent mode: off in the input area to toggle it on:
- pick a workspace folder (defaults to
./agent_workspace). - ask the agent to do file work β e.g. βcreate a file called hello.py that prints βhiββ.
- the agent plans tool calls, executes them (read/write/edit/search files inside the workspace only), and reports back with live status updates.
β next steps
- user guide β everything the app can do
- addon development β extend gguf loader with addons
related documentation
installation guide
complete guide to installing gguf loader on windows, macos, and linux
beginner 5 minutesthis guide will help you install gguf loader 2.2.0 on your system. want to see what gguf loader can do first? explore the features on our homepage.
π system requirements
- os: windows 10/11, linux (x86_64), or macos
- ram: 4 gb minimum (8 gb+ recommended for larger models)
- storage: 2 gb free space for the app, plus room for model files
- gpu: optional β cpu-only works everywhere; nvidia cuda is supported on windows and linux
- python: not required for the installers (everything is bundled)
π quick installation
the prebuilt installers bundle python, pyside6, and llama.cpp β you do not need python installed.
windows
- download ggufloader_v2.2.0_cpu.exe (~69 mb) from the releases page. this is the cpu-only build that works on any pc.
- have an nvidia gpu with cuda? grab ggufloader_v2.2.0_gpu.exe (~854 mb) instead for gpu acceleration.
- double-click the downloaded file and run it. no installation wizard β the app starts immediately.
β οΈ windows smartscreen: the first launch may show βwindows protected your pcβ. click more info β run anyway. this is normal for unsigned open-source binaries.
linux (x86_64)
- download ggufloader_v2.2.0_linux_x86_64_cpu (~121 mb) from the releases page.
- make it executable and run:
chmod +x ggufloader_v2.2.0_linux_x86_64_cpu ./ggufloader_v2.2.0_linux_x86_64_cpuno installation needed β the app starts directly. everything (python, pyside6, llama.cpp) is bundled.
macos
no prebuilt installer is published yet. run from source (below) β everything works on macos.
run from source (any platform)
for development, or to run on an unsupported platform:
git clone https://github.com/ggufloader/gguf-loader.git cd gguf-loader pip install -r requirements.txt python main.pyβ verify your installation
run
ggufloader_v2.2.0_cpu.exe --version(windows) or./ggufloader_v2.2.0_linux_x86_64_cpu --version(linux) β it printsgguf loader version 2.2.0and exits.π§ next steps
- quick start guide β load your first model
- troubleshooting β if something isnβt working
related documentation
- get up and running with gguf loader 2.2.0 in just a few minutes! new to gguf loader? [check out the homepage](/) to see what makes it special. ## π step 1: install gguf loader follow the [installation guide](/docs/installation/) for your platform, or download directly: - **windows**: [ggufloader_v2.2.0_cpu.exe](https://github.com/ggufloader/gguf-loader/releases/download/v2.2.0/ggufloader_v2.2.0_cpu.exe) (cpu-only) Β· [ggufloader_v2.2.0_gpu.exe](https://github.com/ggufloader/gguf-loader/releases/download/v2.2.0/ggufloader_v2.2.0_gpu.exe) (nvidia cuda) - **linux**: [ggufloader_v2.2.0_linux_x86_64_cpu](https://github.com/ggufloader/gguf-loader/releases/download/v2.2.0/ggufloader_v2.2.0_linux_x86_64_cpu) ## π₯ step 2: get a gguf model gguf loader runs any gguf-format model. good starter models on hugging face: - **small (fast)**: [llama-3-8b-instruct gguf (q4_0)](https://huggingface.co/thebloke/llama-3-8b-instruct-gguf) β ~4.7 gb, runs great on cpu - **medium**: [mistral-7b-instruct gguf (q4_k_m)](https://huggingface.co/thebloke/mistral-7b-instruct-v0.2-gguf) β ~4.1 gb - **larger**: [phi-3.5-mini-instruct gguf](https://huggingface.co/microsoft/phi-3.5-mini-instruct-gguf) or any qwen/llama gguf you like download the `.gguf` file and remember where you saved it. ## π₯οΈ step 3: load the model 1. launch gguf loader. 2. in the **model settings** sidebar, choose **processing** mode β `cpu only` (default, works everywhere) or `gpu accelerated` (nvidia cuda). 3. set a **context length** (8192 is a safe default for most models; 32768 uses more ram). 4. click **load gguf model** and select your `.gguf` file. 5. wait for the status to show **"model ready!"** β the header chip turns green with the model name. ## π¬ step 4: chat type a message in the input box at the bottom and press **enter** (shift+enter inserts a newline). responses stream in as chatgpt-style bubbles β your messages on the right (amber), the ai's on the left. use the **view β text size** menu to adjust bubble font size. ## π€ step 5 (optional): try agent mode click **π€ agent mode: off** in the input area to toggle it on: 1. pick a **workspace folder** (defaults to `./agent_workspace`). 2. ask the agent to do file work β e.g. *"create a file called hello.py that prints 'hi'"*. 3. the agent plans tool calls, executes them (read/write/edit/search files inside the workspace only), and reports back with live status updates. ## β next steps - [user guide](/docs/user-guide/) β everything the app can do - [addon development](/docs/addon-development/) β extend gguf loader with addons
- common issues and their fixes. running the app from a terminal (`python main.py` or the installed binary) shows the console log, which is the fastest way to diagnose most problems. ## π app won't start ### windows smartscreen blocks the .exe - click **more info β run anyway**. the binaries are unsigned open-source builds; this is expected. ### "llama-cpp-python is required but not installed" - the llama.cpp runtime is missing. in the app's **environment** section click **install missing dependencies**, or from source: `pip install -r requirements.txt`. ### dll load errors on windows (`importerror: dll load failed`) - the bundled `llama_cpp/lib` wasn't found. make sure you're running the full package (not just copying a single file), and check the console log for `added windows dll directory: ...`. ## π§ model won't load ### "failed to load model" / unknown format - confirm the file is a real gguf file (`.gguf`). corrupted or partial downloads fail; re-download the file. - check the file has enough disk space and isn't on a network drive with strict permissions. ### out of memory / crashes when loading - reduce **context length** (try 4096 or 8192). - switch **processing** to `cpu only` if gpu mode crashes (vram exhaustion). - use a smaller quantized model (q4_0/q4_k_m instead of q8). ### gpu accelerated is slow or doesn't use the gpu - gpu mode requires a cuda-enabled `llama-cpp-python` build. verify with `scripts/verify_gpu_support.py` or run `scripts/install_gpu_llama.bat`/`.sh` (see the [installation guide](/docs/installation/)). - on linux, make sure the nvidia driver and cuda toolkit are installed. ## π¬ chat problems ### send button is disabled - no model is loaded. load a `.gguf` model first. ### responses are empty or garbled - some models need specific prompt formats. check the model card for a chat template; very small models also produce weak output. - lower `temperature`-style randomness isn't exposed per-chat β try a different preset or model. ### chat is slow - smaller context, cpu-only on fast threads, and a smaller quantized model all help. generation speed is dominated by model size and hardware. ## π€ agent mode issues ### "please load a model first" - agent mode needs a loaded model β load one, then toggle agent mode on. ### agent can't find files / "path escapes workspace" - the agent is **sandboxed to the workspace folder**. put files you want it to touch inside the workspace, or choose the right folder with the π button. ### agent stuck on "processing..." - generation is single-threaded; long tool chains take time. watch the status messages for progress. ## π¬ floating chat addon ### button doesn't float above other apps on linux - this is expected under **wayland** β compositors confine app windows to the app itself. run under an x11 session or with `qt_qpa_platform=xcb` for full always-on-top behavior. ### button disappears when switching apps on macos - fixed in 2.1.2 (the `tool` flag is now dropped on macos so the button stays visible). if it still happens, check the console log and confirm the addon is listed under **addons**. ### button is stuck minimized - fixed in 2.1.2 β the button now restores itself immediately if a system shortcut minimizes it. ### addon not in the addons menu - click **addons β refresh addons**, or restart the app. check the console for `failed to load addon ...`. ## πͺ window / layout problems ### window too small / layout broken - the minimum window size is 800Γ500. maximize or resize the splitter β the sidebar is collapsible via the splitter handle. ### wrong colors / theme looks off - **view β dark mode** toggles themes. if colors look broken after a theme change, restart the app. ## π environment / venv issues ### "not running from .venv" - the app detected the system python. click **create .venv & restart** in the sidebar to bootstrap an isolated environment. ### pip install fails with externally-managed-environment (linux) - on debian/ubuntu 24.04+ the system python blocks pip. use the app's **create .venv & restart**, or create a venv manually: ```bash python3 -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt ``` ## π where to find logs - **windows**: `%localappdata%\ggufloader\logs` - **linux/macos**: `~/.ggufloader/logs` include the relevant log excerpt when [opening an issue](https://github.com/ggufloader/gguf-loader/issues).
- this is the complete manual for gguf loader 2.1.2. gguf loader is a privacy-first desktop app for running large language models locally from gguf files, with zero data leaving your machine. ## πͺ the main window the app is divided into three areas: 1. **header bar** (top) β brand on the left, a live **model status chip** on the right. 2. **sidebar** (left) β model settings, environment, and launcher sections. 3. **chat area** (center) β the conversation, or a welcome screen when no model is loaded. ## βοΈ model settings sidebar ### model - **load gguf model** β opens a file dialog; pick any `.gguf` file. - **model info** β shows the loaded file name (or an error). ### processing - **cpu only** β runs on any machine using llama.cpp's cpu backend. - **gpu accelerated** β offloads layers to an nvidia gpu (windows/linux). requires a working cuda llama-cpp-python install. ### context length the model's context window in tokens (512β32768). larger contexts use more ram. change it before loading a model. ## π environment section gguf loader ships with a built-in dependency manager for source installs: - **python Β· .venv status** β shows the interpreter and whether the app runs from a virtual environment. - **install missing dependencies** β appears when packages are missing; runs `pip install -r requirements.txt`. - **create .venv & restart** β bootstraps a virtual environment and relaunches inside it. - **check again** β re-scans the environment. > the packaged installers (`.exe` / linux tarball) bundle everything, so this section is mostly relevant when running from source. ## π launcher section one-click buttons that open the project's `scripts/` utilities (e.g. gpu support verification, monitor) in separate windows, plus **restart app**. ## π¬ chatting - type in the input box; **enter** sends, **shift+enter** inserts a newline. - **send** is disabled until you type something, and is disabled entirely until a model is loaded. - responses **stream** token-by-token into bubbles: your messages right (amber), ai left (charcoal). - **view β text size** (12β22) changes bubble font size live. - **file β clear chat** wipes the conversation (the model stays loaded). ## π€ agent mode agent mode turns the chat into a tool-using assistant that works inside a **workspace folder**: 1. toggle **π€ agent mode: off β on**. 2. choose a workspace (combo box or π browse button). default: `./agent_workspace`. 3. ask for file operations β e.g. *"create a markdown file listing today's tasks"*. the agent will: - analyze complex requests, - plan tool calls and stream status updates (π€/π‘/β/β/β), - execute tools against the workspace β `list_directory`, `read_file`, `write_file`, `edit_file`, `search_files`, - summarize results in natural language. **safety**: all tools are sandboxed to the workspace; paths that escape it are rejected. ## π¨ appearance - **view β dark mode** toggles the "midnight & amber" dark theme and a light theme. - **view β text size** adjusts chat bubble text. - the app remembers dark mode per session (dark is the default). ## π§© addons the **addons** menu lists every loaded addon (e.g. **floating_chat**). selecting one opens it in a floating dialog; **refresh addons** re-scans the `addons/` folder. see the [addon development guide](/docs/addon-development/). ### π¬ floating chat the built-in addon adds a messenger-style floating button (always on top, draggable) that opens a chat window connected to the loaded model. it: - stays on top of all windows (see platform notes below) - remembers its position between sessions - shows model status (π’ ready / π΄ offline) and streams responses - has copy all / clear controls **platform notes**: fully floating on windows and linux/x11. on linux **wayland**, compositors confine it to the app window β run under x11 (`qt_qpa_platform=xcb`) for the full effect. on macos the button stays visible when the app loses focus but also appears in mission control. ## π where files live - **config**: `%appdata%\ggufloader` (windows) / `~/.ggufloader` (linux/macos) - **cache**: `%localappdata%\ggufloader\cache` (windows) / `~/.cache/ggufloader` (linux) - **logs**: `%localappdata%\ggufloader\logs` (windows) / `~/.ggufloader/logs` (linux) - **addons**: the `addons/` folder next to the app ## β€οΈ feedback **help β send feedback** opens the feedback dialog. point it at your own formspree endpoint via `feedback_config.json`: ```json { "endpoint_url": "https://formspree.io/f/your_form_id" } ``` ## π still stuck? see the [troubleshooting guide](/docs/troubleshooting/).
π related features
π― what's next?
you've completed this guide! here are some suggested next steps to continue your gguf loader journey:
πstart using gguf loader
now that you have gguf loader installed, follow our quick start guide to load your first model and start chatting.
quick start guide βπ€browse models
explore our curated collection of gguf models to find the perfect one for your needs.
browse models ββ¨π explore more features
π back to homepage
- this is the complete manual for gguf loader 2.1.2. gguf loader is a privacy-first desktop app for running large language models locally from gguf files, with zero data leaving your machine. ## πͺ the main window the app is divided into three areas: 1. **header bar** (top) β brand on the left, a live **model status chip** on the right. 2. **sidebar** (left) β model settings, environment, and launcher sections. 3. **chat area** (center) β the conversation, or a welcome screen when no model is loaded. ## βοΈ model settings sidebar ### model - **load gguf model** β opens a file dialog; pick any `.gguf` file. - **model info** β shows the loaded file name (or an error). ### processing - **cpu only** β runs on any machine using llama.cpp's cpu backend. - **gpu accelerated** β offloads layers to an nvidia gpu (windows/linux). requires a working cuda llama-cpp-python install. ### context length the model's context window in tokens (512β32768). larger contexts use more ram. change it before loading a model. ## π environment section gguf loader ships with a built-in dependency manager for source installs: - **python Β· .venv status** β shows the interpreter and whether the app runs from a virtual environment. - **install missing dependencies** β appears when packages are missing; runs `pip install -r requirements.txt`. - **create .venv & restart** β bootstraps a virtual environment and relaunches inside it. - **check again** β re-scans the environment. > the packaged installers (`.exe` / linux tarball) bundle everything, so this section is mostly relevant when running from source. ## π launcher section one-click buttons that open the project's `scripts/` utilities (e.g. gpu support verification, monitor) in separate windows, plus **restart app**. ## π¬ chatting - type in the input box; **enter** sends, **shift+enter** inserts a newline. - **send** is disabled until you type something, and is disabled entirely until a model is loaded. - responses **stream** token-by-token into bubbles: your messages right (amber), ai left (charcoal). - **view β text size** (12β22) changes bubble font size live. - **file β clear chat** wipes the conversation (the model stays loaded). ## π€ agent mode agent mode turns the chat into a tool-using assistant that works inside a **workspace folder**: 1. toggle **π€ agent mode: off β on**. 2. choose a workspace (combo box or π browse button). default: `./agent_workspace`. 3. ask for file operations β e.g. *"create a markdown file listing today's tasks"*. the agent will: - analyze complex requests, - plan tool calls and stream status updates (π€/π‘/β/β/β), - execute tools against the workspace β `list_directory`, `read_file`, `write_file`, `edit_file`, `search_files`, - summarize results in natural language. **safety**: all tools are sandboxed to the workspace; paths that escape it are rejected. ## π¨ appearance - **view β dark mode** toggles the "midnight & amber" dark theme and a light theme. - **view β text size** adjusts chat bubble text. - the app remembers dark mode per session (dark is the default). ## π§© addons the **addons** menu lists every loaded addon (e.g. **floating_chat**). selecting one opens it in a floating dialog; **refresh addons** re-scans the `addons/` folder. see the [addon development guide](/docs/addon-development/). ### π¬ floating chat the built-in addon adds a messenger-style floating button (always on top, draggable) that opens a chat window connected to the loaded model. it: - stays on top of all windows (see platform notes below) - remembers its position between sessions - shows model status (π’ ready / π΄ offline) and streams responses - has copy all / clear controls **platform notes**: fully floating on windows and linux/x11. on linux **wayland**, compositors confine it to the app window β run under x11 (`qt_qpa_platform=xcb`) for the full effect. on macos the button stays visible when the app loses focus but also appears in mission control. ## π where files live - **config**: `%appdata%\ggufloader` (windows) / `~/.ggufloader` (linux/macos) - **cache**: `%localappdata%\ggufloader\cache` (windows) / `~/.cache/ggufloader` (linux) - **logs**: `%localappdata%\ggufloader\logs` (windows) / `~/.ggufloader/logs` (linux) - **addons**: the `addons/` folder next to the app ## β€οΈ feedback **help β send feedback** opens the feedback dialog. point it at your own formspree endpoint via `feedback_config.json`: ```json { "endpoint_url": "https://formspree.io/f/your_form_id" } ``` ## π still stuck? see the [troubleshooting guide](/docs/troubleshooting/).
addon development guide
learn to create custom addons for gguf loader with examples and best practices
advanced 15 minutesgguf loaderβs addon system lets you extend the app without touching its source. addons are python packages dropped into the
addons/folder; the app discovers, loads, and manages them automatically.π¦ what an addon looks like
addons/ βββ my_addon/ βββ __init__.py # must expose register() βββ main.py # your logic (any structure you like) βββ ... # widgets, resources, etc.minimum viable addon
# addons/my_addon/__init__.py from pyside6.qtwidgets import qlabel def register(parent=none): """called by gguf loader when the addon loads.""" return qlabel("hello from my addon!")thatβs it β drop the folder in
addons/, restart (or addons β refresh addons), and your widget appears in the addons menu.π how loading works
addonmanager(addon_manager.py):scan_addons()β lists subdirectories of the addons folder that contain__init__.py.load_addon(name, path)β dynamically imports the module (importlib.util.spec_from_file_location) and requires aregisterattribute.load_all_addons()β loads every addon and records success/failure in the console log.get_addon_widget(name, parent)β callsregister(parent)and returns the widget.open_addon_dialog(name, parent)β shows the addon widget in a non-modal dialog from the addons menu.
the main window calls
get_addon_widgetfor each loaded addon at startup, soregister()runs even before the user opens the menu β this is how background addons (like the floating chat button) start automatically.π‘ talking to the app
your
register(parent)receives the parent widget. the main window exposes an addon-facing api (see the addon api reference). the robust pattern used by the built-in addon:def register(parent=none): gguf_app = none # 1. parent might already be the main window if parent and hasattr(parent, 'model') and hasattr(parent, 'model_loaded'): gguf_app = parent else: # 2. walk up the parent chain current = parent while current is not none: if hasattr(current, 'model') and hasattr(current, 'model_loaded'): gguf_app = current break current = current.parent() # 3. fall back to scanning top-level widgets if gguf_app is none: app = qapplication.instance() for widget in app.toplevelwidgets(): if hasattr(widget, 'model') and hasattr(widget, 'model_loaded'): gguf_app = widget break ...key api members:
model(callable backend),model_loaded/model_unloaded/generation_finished/generation_errorsignals,addon_manager, and_floating_chat_addon.π€ calling the model
# streaming for token in gguf_app.model(prompt, stream=true, max_tokens=512): print(token["choices"][0]["text"]) # or use the backend directly response = gguf_app.model.generate(prompt, max_tokens=512, temperature=0.7)modelisnoneuntil the user loads a model β always check, and subscribe tomodel_loadedto react.π§© widget vs. background addons
- return a widget from
register()β appears in the addons menu, opens in a dialog. - return
none(or also keep your own top-level windows) β runs in the background. the floating chat addon returns a small status widget but drives its own always-on-top windows.
π‘ best practices
- guard everything β wrap registration in
try/exceptand log failures; a broken addon must never crash the app. - clean up state β if you keep references on the main window (e.g.
gguf_app._my_addon = ...), stop them on app close (mainwindow.closeeventstops_floating_chat_addonβ follow that pattern). - use qsettings for persistence β
qsettings("ggufloader", "youraddon"). - prefer signals β let your widgets emit signals; donβt reach into other widgetsβ internals.
- qt-free logic β if you have non-ui logic (parsing, computation), put it in a module with no qt imports so itβs unit-testable.
β debugging
addon load errors print to the console with a traceback (
failed to load addon <name>: ...). run the app from a terminal to see them:python main.pyπ next steps
- addon api reference β every hook and member
- floating chat example β full walkthrough of the built-in addon
related documentation
addon api reference
complete api reference for developing gguf loader addons
advanced 20 minutescomplete reference for the hooks, signals, and objects available to gguf loader addons.
πͺ addon contract
an addon is a folder under
addons/with an__init__.pyexposing:register(parent=none) -> qwidget | nonecalled by
addonmanagerwhen the addon loads. returns an optional widget shown in the addons menu (opened in a non-modal dialog), ornonefor background-only addons.parameters β
parent: the widget the addon is being attached to (may be the main window, a dialog, or another widget).return β a widget, or
none.def register(parent=none): return qlabel("my addon") # widget addonπ₯οΈ main window api
addons receive a reference to the main window (via
parentor by scanningqapplication.instance().toplevelwidgets()). it exposes:properties
| member | type | description | |β|β|β| |
model|modelbackend \| none| the loaded model backend; callable.noneuntil a model is loaded. | |chat_generator|none| legacy hook; alwaysnone. addons should callmodelinstead. | |addon_manager|addonmanager| the addon manager instance. | |_floating_chat_addon|floatingchataddon \| none| the built-in floating chat addon (if running). |signals
| signal | signature | description | |β|β|β| |
model_loaded|signal(object)| emitted with themodelbackendafter a model loads. | |model_unloaded|signal()| emitted after the model is released. | |generation_finished|signal()| emitted when a chat generation completes. | |generation_error|signal(str)| emitted with an error message when generation fails. | |theme_changed|signal(bool)| emitted when dark mode toggles (true= dark). |gguf_app.model_loaded.connect(self._on_model_loaded) gguf_app.generation_finished.connect(self._on_finished)π§ modelbackend
gguf_app.modelis acore.llm.model_backend.modelbackend. it is callable and thread-safe (all access serialized through a lock).calling convention
# raw llama-cpp shape (addon-compatible) result = gguf_app.model(prompt, stream=false, max_tokens=512, temperature=0.7) text = result["choices"][0]["text"] # streaming for token_data in gguf_app.model(prompt, stream=true, max_tokens=512): text = token_data["choices"][0]["text"]methods & attributes
| member | description | |β|β| |
model_path| path of the loaded gguf file. | |use_gpu| whether gpu acceleration is active. | |n_ctx| context length. | |is_loaded|trueonce the runtime exists. | |load()| create the underlyingllamaruntime (raises on failure). | |unload()| release the model and free memory. | |generate(prompt, **kwargs)| complete non-streamed response string. | |generate_stream(prompt, **kwargs)| iterator of token strings. | |__call__(prompt, **kwargs)| llama-cpp-compatible callable (stream returns token-dict generator). |kwargs are passed straight to llama_cpp:
max_tokens,temperature,top_p,top_k,repeat_penalty,stop, etc.π§° agent tools (for agent-capable addons)
the agent engine (
core/agent/) exposes sandboxed tools throughtoolregistry. tools are not qt-bound and are safe to call from any thread.tool params result list_directorypath(default.){status, result: [{name, type, size}]}read_filepath,max_size,encoding{status, result: content, lines, encoding}write_filepath,content{status, path, bytes_written}edit_filepath,operation(replace/insert_line/delete_line),find,replace,line_number,content{status, operation, changes_made}search_filespattern/query,path{status, result: [paths], total_matches}every tool result includes
status("success"/"error") andtool_name. all paths are sandboxed to the workspace β escaping paths raise.from core.agent.tool_registry import create_default_registry registry = create_default_registry("./workspace") result = registry.execute("list_directory", {"path": "."})π§© addonmanager
method description scan_addons(){name: path}of addons with__init__.py.load_addon(name, path)import + validate register;true/false.load_all_addons()load all; {name: success}.get_addon_widget(name, parent)widget from register(parent).open_addon_dialog(name, parent)show addon in a non-modal dialog. get_loaded_addons()list of successfully loaded names. πΎ persistence
use qtβs
qsettingswith a scoped org/app key to avoid collisions:from pyside6.qtcore import qsettings settings = qsettings("ggufloader", "myaddon") settings.setvalue("position", point) pos = settings.value("position", qpoint(100, 100))β‘ lifecycle
register()is called at startup and on addons β refresh addons.- the main windowβs
closeeventstops the floating chat addon; follow that pattern to stop your own background objects:if hasattr(gguf_app, '_my_addon') and gguf_app._my_addon: gguf_app._my_addon.stop()
π see also
- addon development guide β tutorial
- floating chat example β full real-world addon
related documentation
- gguf loader's addon system lets you extend the app without touching its source. addons are python packages dropped into the `addons/` folder; the app discovers, loads, and manages them automatically.
## π¦ what an addon looks like
```
addons/
βββ my_addon/
βββ __init__.py # must expose register()
βββ main.py # your logic (any structure you like)
βββ ... # widgets, resources, etc.
```
### minimum viable addon
```python
# addons/my_addon/__init__.py
from pyside6.qtwidgets import qlabel
def register(parent=none):
"""called by gguf loader when the addon loads."""
return qlabel("hello from my addon!")
```
that's it β drop the folder in `addons/`, restart (or **addons β refresh addons**), and your widget appears in the **addons** menu.
## π how loading works
`addonmanager` (`addon_manager.py`):
1. `scan_addons()` β lists subdirectories of the addons folder that contain `__init__.py`.
2. `load_addon(name, path)` β dynamically imports the module (`importlib.util.spec_from_file_location`) and requires a `register` attribute.
3. `load_all_addons()` β loads every addon and records success/failure in the console log.
4. `get_addon_widget(name, parent)` β calls `register(parent)` and returns the widget.
5. `open_addon_dialog(name, parent)` β shows the addon widget in a non-modal dialog from the addons menu.
the main window calls `get_addon_widget` for each loaded addon at startup, so `register()` runs even before the user opens the menu β this is how background addons (like the floating chat button) start automatically.
## π‘ talking to the app
your `register(parent)` receives the parent widget. the **main window** exposes an addon-facing api (see the [addon api reference](/docs/addon-api/)). the robust pattern used by the built-in addon:
```python
def register(parent=none):
gguf_app = none
# 1. parent might already be the main window
if parent and hasattr(parent, 'model') and hasattr(parent, 'model_loaded'):
gguf_app = parent
else:
# 2. walk up the parent chain
current = parent
while current is not none:
if hasattr(current, 'model') and hasattr(current, 'model_loaded'):
gguf_app = current
break
current = current.parent()
# 3. fall back to scanning top-level widgets
if gguf_app is none:
app = qapplication.instance()
for widget in app.toplevelwidgets():
if hasattr(widget, 'model') and hasattr(widget, 'model_loaded'):
gguf_app = widget
break
...
```
key api members: `model` (callable backend), `model_loaded` / `model_unloaded` / `generation_finished` / `generation_error` signals, `addon_manager`, and `_floating_chat_addon`.
## π€ calling the model
```python
# streaming
for token in gguf_app.model(prompt, stream=true, max_tokens=512):
print(token["choices"][0]["text"])
# or use the backend directly
response = gguf_app.model.generate(prompt, max_tokens=512, temperature=0.7)
```
`model` is `none` until the user loads a model β always check, and subscribe to `model_loaded` to react.
## π§© widget vs. background addons
- **return a widget** from `register()` β appears in the addons menu, opens in a dialog.
- **return `none`** (or also keep your own top-level windows) β runs in the background. the floating chat addon returns a small status widget but drives its own always-on-top windows.
## π‘ best practices
1. **guard everything** β wrap registration in `try/except` and log failures; a broken addon must never crash the app.
2. **clean up state** β if you keep references on the main window (e.g. `gguf_app._my_addon = ...`), stop them on app close (`mainwindow.closeevent` stops `_floating_chat_addon` β follow that pattern).
3. **use qsettings for persistence** β `qsettings("ggufloader", "youraddon")`.
4. **prefer signals** β let your widgets emit signals; don't reach into other widgets' internals.
5. **qt-free logic** β if you have non-ui logic (parsing, computation), put it in a module with no qt imports so it's unit-testable.
## β
debugging
addon load errors print to the console with a traceback (`failed to load addon
: ...`). run the app from a terminal to see them: ```bash python main.py ``` ## π next steps - [addon api reference](/docs/addon-api/) β every hook and member - [floating chat example](/docs/floating-chat-example/) β full walkthrough of the built-in addon - this page walks through **floating_chat**, gguf loader's built-in addon β a facebook messenger-style floating button that opens a chat window connected to the loaded model. it's the best real-world reference for writing a background addon with its own windows. ``` addons/floating_chat/ βββ __init__.py # exposes register() βββ main.py # floatingchataddon (qobject) + register() βββ floating_button.py # floatingchatbutton - draggable always-on-top button βββ chat_window.py # floatingchatwindow - the chat ui βββ status_widget.py # small sidebar widget returned by register() ``` ## π§ the design the addon is a `qobject` (`floatingchataddon`) that owns two windows: - **`floatingchatbutton`** β a frameless, always-on-top tool window that can be dragged anywhere and remembers its position via `qsettings`. - **`floatingchatwindow`** β a regular top-level window (`400Γ600`) positioned next to the button, with a message list, streaming replies, and copy all / clear buttons. ## πͺ registration `__init__.py` simply re-exports `register`: ```python from .main import register __all__ = ['register'] ``` `register()` finds the main window (parent β parent chain β `toplevelwidgets()` scan), stops any previous instance, starts the addon, and returns a **status widget** for the sidebar: ```python def register(parent=none): gguf_app = _find_main_window(parent) # model + model_loaded check if gguf_app is none: return none if getattr(gguf_app, '_floating_chat_addon', none): gguf_app._floating_chat_addon.stop() addon = floatingchataddon(gguf_app) if addon.start(): gguf_app._floating_chat_addon = addon return floatingchatstatuswidget(addon) return none ``` the returned `floatingchatstatuswidget` shows up in the **addons** menu, and because `register()` runs at startup, the button appears automatically β no user action needed. ## π‘ connecting to the app `floatingchataddon.__init__` subscribes to model lifecycle signals: ```python if hasattr(self.gguf_app, 'model_loaded'): self.gguf_app.model_loaded.connect(self._on_model_loaded) if hasattr(self.gguf_app, 'generation_finished'): self.gguf_app.generation_finished.connect(self._on_generation_finished) if hasattr(self.gguf_app, 'generation_error'): self.gguf_app.generation_error.connect(self._on_generation_error) ``` `_on_model_loaded` flips the chat window's status to **π’ model: ready**; generation events update the streaming bubble / error state. ## π lifecycle: start() / stop() ```python def start(self): self._floating_button = floatingchatbutton() self._floating_button.clicked.connect(self._on_button_clicked) self._load_button_position() # qsettings restore, clamped to screen self._floating_button.show() self.addon_started.emit() return true def stop(self): self._save_button_position() # persist for next session if self._chat_window: self._chat_window.close() if self._floating_button: self._floating_button.close() self.addon_stopped.emit() ``` `stop()` is idempotent and called on app close via `mainwindow.closeevent`, so there's never a dangling button. ## π±οΈ button click β window toggle the click handler distinguishes three states (a minimized window is "visible" to qt but off-screen, so it must be restored, not hidden): ```python def _on_button_clicked(self): chat = self._chat_window if chat and chat.isvisible(): if chat.isminimized(): chat.shownormal(); chat.raise_(); chat.activatewindow() else: chat.hide() else: self._show_chat_window() ``` `_show_chat_window` creates the window lazily, positions it next to the button (flipping to the left / up when it would overflow the screen's **available geometry**, which excludes taskbars and docks), then `shownormal()` + `raise_()` + `activatewindow()`. ## πͺ window flags (the platform subtleties) ```python flags = (qt.windowtype.framelesswindowhint | qt.windowtype.windowstaysontophint | qt.windowtype.x11bypasswindowmanagerhint) # linux/x11 if sys.platform != "darwin": flags |= qt.windowtype.tool # keeps it out of the taskbar ``` - **windows/linux**: `tool` keeps the button out of the taskbar. `x11bypasswindowmanagerhint` gives true always-on-top under x11. - **macos**: the `tool` flag would turn the button into a utility window that **auto-hides when the app loses focus** β so it's deliberately dropped. trade-off: the button appears in mission control. - **wayland**: compositors don't allow floating above *other* apps' windows; the button is confined to the app window (documented, and x11 is recommended for the full experience). the chat window drops the minimize button entirely β a minimized companion window is a trap state that can't be reliably restored. ## π resiliancy touches - `changeevent` bounces the button straight back to normal if a system shortcut (e.g. win+d) minimizes *every* window including the tool: ```python if event.type() == qevent.type.windowstatechange and self.isminimized(): qtimer.singleshot(0, self.shownormal) ``` - dragging clamps to `screen.availablegeometry()` (not `(0,0)`), so the button can't slide under the macos menu bar or a windows taskbar. - saved positions are clamped the same way on restore. ## π§© what you can reuse - the **window-finding pattern** in `register()` β works for any addon. - the **qsettings position persistence** with on-screen clamping. - the **platform-conditional window flags** β copy it for any always-on-top addon window. - the **show/hide/restore toggle** logic. ## π see also - [addon development guide](/docs/addon-development/) - [addon api reference](/docs/addon-api/)
- this page documents how the gguf loader codebase is organized. the app is a pyside6 desktop application; a single `main.py` bootstraps everything, and logic is split into `core/` (pure logic), `services/` (qt threading bridges), and `ui/` + `widgets/` (presentation). ## ποΈ top-level layout ``` gguf-loader/ βββ main.py # entry point: logging, dll paths, qapplication, mainwindow βββ config.py # central configuration constants βββ resource_manager.py # resource/path discovery (dev, package, or frozen) βββ addon_manager.py # loads and manages addons βββ requirements.txt # python dependencies βββ build_exe.spec # pyinstaller spec used for windows & linux builds β βββ core/ # pure, testable logic (no qt) β βββ llm/ β β βββ model_backend.py # thread-safe llama-cpp-python wrapper β β βββ prompt_builder.py # system-prompt & conversation assembly β βββ agent/ β βββ agent_engine.py # tool-use agent loop (no qt, no llama_cpp) β βββ tool_registry.py # sandboxed workspace tools β βββ services/ # qobject bridges that run work on threads β βββ model_service.py # load/unload models on a qthread β βββ chat_service.py # streaming generation on a qthread β βββ agent_service.py # runs agentengine on a worker thread β βββ environment_service.py # venv/dependency checks & pip tasks β βββ launcher_service.py # launches scripts/ utilities β βββ ui/ # main window & panels β βββ main_window.py # composition root + addon-facing api β βββ chat_panel.py # chat display, input, agent controls β βββ sidebar_panel.py # model settings sidebar β βββ theme.py # dark/light qss token system β βββ widgets/ # reusable widgets β βββ chat_bubble.py # chatgpt-style bubble β βββ feedback_dialog.py # feedback form dialog β βββ addons/ # addon packages (each has __init__.py with register()) β βββ floating_chat/ # built-in floating chat addon β βββ scripts/ # utility & release scripts β βββ capture_screenshots.py # regenerates readme/site screenshots β βββ install_linux.sh # linux installer/uninstaller β βββ package_linux.sh # builds the linux .tar.gz release β βββ ... # gpu install/monitor helpers β βββ build_hooks/ # pyinstaller hook modules ``` ## π key design rules - **`core/` never imports qt or llama_cpp.** it receives plain callables, so it can be unit-tested in isolation. - **`services/` are the only place qt threads are created.** ui never spins up threads directly. - **`ui/` widgets are "dumb"** β they render state and emit signals; `mainwindow` owns all logic. - **`resource_manager.py`** makes paths work identically in dev, as an installed package, and in a pyinstaller bundle (`sys._meipass`). ## π§΅ threading model ``` ui thread (mainwindow) worker thread β β βββ modelservice.load() βββββββ qthread: llama_cpp loads model ββββββββ loaded(modelbackend) β βββ chatservice.generate() ββββ qthread: streams tokens ββββββββ token_received(text) β βββ agentservice.process() ββββ qthread: agentengine tool loop ββββββββ status/tool/response β ``` a fresh `qthread` + worker is created per request (the professional qt pattern β `qthread` is never subclassed). ## π entry point flow `main.py` β `setup_library_path()` (finds bundled llama.cpp libs) β `qapplication` β `mainwindow()` β builds ui, wires services, checks environment, loads addons β `app.exec()`. ## π¦ packaging - **windows**: `build_exe.bat` / `build_exe.spec` β `ggufloader_vx.y.z.exe` - **linux**: build the spec inside a linux environment, then `scripts/package_linux.sh` wraps the binary + installer + icon into a `.tar.gz` - github actions publishes both to every release automatically. see the [architecture overview](/docs/architecture/) for deeper design rationale.
π related features
π― what's next?
you've completed this guide! here are some suggested next steps to continue your gguf loader journey:
πshare your addon
built something awesome? share it with the community and get featured on our homepage.
share with community βππ€π explore more features
π back to homepage
- this page walks through **floating_chat**, gguf loader's built-in addon β a facebook messenger-style floating button that opens a chat window connected to the loaded model. it's the best real-world reference for writing a background addon with its own windows. ``` addons/floating_chat/ βββ __init__.py # exposes register() βββ main.py # floatingchataddon (qobject) + register() βββ floating_button.py # floatingchatbutton - draggable always-on-top button βββ chat_window.py # floatingchatwindow - the chat ui βββ status_widget.py # small sidebar widget returned by register() ``` ## π§ the design the addon is a `qobject` (`floatingchataddon`) that owns two windows: - **`floatingchatbutton`** β a frameless, always-on-top tool window that can be dragged anywhere and remembers its position via `qsettings`. - **`floatingchatwindow`** β a regular top-level window (`400Γ600`) positioned next to the button, with a message list, streaming replies, and copy all / clear buttons. ## πͺ registration `__init__.py` simply re-exports `register`: ```python from .main import register __all__ = ['register'] ``` `register()` finds the main window (parent β parent chain β `toplevelwidgets()` scan), stops any previous instance, starts the addon, and returns a **status widget** for the sidebar: ```python def register(parent=none): gguf_app = _find_main_window(parent) # model + model_loaded check if gguf_app is none: return none if getattr(gguf_app, '_floating_chat_addon', none): gguf_app._floating_chat_addon.stop() addon = floatingchataddon(gguf_app) if addon.start(): gguf_app._floating_chat_addon = addon return floatingchatstatuswidget(addon) return none ``` the returned `floatingchatstatuswidget` shows up in the **addons** menu, and because `register()` runs at startup, the button appears automatically β no user action needed. ## π‘ connecting to the app `floatingchataddon.__init__` subscribes to model lifecycle signals: ```python if hasattr(self.gguf_app, 'model_loaded'): self.gguf_app.model_loaded.connect(self._on_model_loaded) if hasattr(self.gguf_app, 'generation_finished'): self.gguf_app.generation_finished.connect(self._on_generation_finished) if hasattr(self.gguf_app, 'generation_error'): self.gguf_app.generation_error.connect(self._on_generation_error) ``` `_on_model_loaded` flips the chat window's status to **π’ model: ready**; generation events update the streaming bubble / error state. ## π lifecycle: start() / stop() ```python def start(self): self._floating_button = floatingchatbutton() self._floating_button.clicked.connect(self._on_button_clicked) self._load_button_position() # qsettings restore, clamped to screen self._floating_button.show() self.addon_started.emit() return true def stop(self): self._save_button_position() # persist for next session if self._chat_window: self._chat_window.close() if self._floating_button: self._floating_button.close() self.addon_stopped.emit() ``` `stop()` is idempotent and called on app close via `mainwindow.closeevent`, so there's never a dangling button. ## π±οΈ button click β window toggle the click handler distinguishes three states (a minimized window is "visible" to qt but off-screen, so it must be restored, not hidden): ```python def _on_button_clicked(self): chat = self._chat_window if chat and chat.isvisible(): if chat.isminimized(): chat.shownormal(); chat.raise_(); chat.activatewindow() else: chat.hide() else: self._show_chat_window() ``` `_show_chat_window` creates the window lazily, positions it next to the button (flipping to the left / up when it would overflow the screen's **available geometry**, which excludes taskbars and docks), then `shownormal()` + `raise_()` + `activatewindow()`. ## πͺ window flags (the platform subtleties) ```python flags = (qt.windowtype.framelesswindowhint | qt.windowtype.windowstaysontophint | qt.windowtype.x11bypasswindowmanagerhint) # linux/x11 if sys.platform != "darwin": flags |= qt.windowtype.tool # keeps it out of the taskbar ``` - **windows/linux**: `tool` keeps the button out of the taskbar. `x11bypasswindowmanagerhint` gives true always-on-top under x11. - **macos**: the `tool` flag would turn the button into a utility window that **auto-hides when the app loses focus** β so it's deliberately dropped. trade-off: the button appears in mission control. - **wayland**: compositors don't allow floating above *other* apps' windows; the button is confined to the app window (documented, and x11 is recommended for the full experience). the chat window drops the minimize button entirely β a minimized companion window is a trap state that can't be reliably restored. ## π resiliancy touches - `changeevent` bounces the button straight back to normal if a system shortcut (e.g. win+d) minimizes *every* window including the tool: ```python if event.type() == qevent.type.windowstatechange and self.isminimized(): qtimer.singleshot(0, self.shownormal) ``` - dragging clamps to `screen.availablegeometry()` (not `(0,0)`), so the button can't slide under the macos menu bar or a windows taskbar. - saved positions are clamped the same way on restore. ## π§© what you can reuse - the **window-finding pattern** in `register()` β works for any addon. - the **qsettings position persistence** with on-screen clamping. - the **platform-conditional window flags** β copy it for any always-on-top addon window. - the **show/hide/restore toggle** logic. ## π see also - [addon development guide](/docs/addon-development/) - [addon api reference](/docs/addon-api/)
- this page documents how the gguf loader codebase is organized. the app is a pyside6 desktop application; a single `main.py` bootstraps everything, and logic is split into `core/` (pure logic), `services/` (qt threading bridges), and `ui/` + `widgets/` (presentation). ## ποΈ top-level layout ``` gguf-loader/ βββ main.py # entry point: logging, dll paths, qapplication, mainwindow βββ config.py # central configuration constants βββ resource_manager.py # resource/path discovery (dev, package, or frozen) βββ addon_manager.py # loads and manages addons βββ requirements.txt # python dependencies βββ build_exe.spec # pyinstaller spec used for windows & linux builds β βββ core/ # pure, testable logic (no qt) β βββ llm/ β β βββ model_backend.py # thread-safe llama-cpp-python wrapper β β βββ prompt_builder.py # system-prompt & conversation assembly β βββ agent/ β βββ agent_engine.py # tool-use agent loop (no qt, no llama_cpp) β βββ tool_registry.py # sandboxed workspace tools β βββ services/ # qobject bridges that run work on threads β βββ model_service.py # load/unload models on a qthread β βββ chat_service.py # streaming generation on a qthread β βββ agent_service.py # runs agentengine on a worker thread β βββ environment_service.py # venv/dependency checks & pip tasks β βββ launcher_service.py # launches scripts/ utilities β βββ ui/ # main window & panels β βββ main_window.py # composition root + addon-facing api β βββ chat_panel.py # chat display, input, agent controls β βββ sidebar_panel.py # model settings sidebar β βββ theme.py # dark/light qss token system β βββ widgets/ # reusable widgets β βββ chat_bubble.py # chatgpt-style bubble β βββ feedback_dialog.py # feedback form dialog β βββ addons/ # addon packages (each has __init__.py with register()) β βββ floating_chat/ # built-in floating chat addon β βββ scripts/ # utility & release scripts β βββ capture_screenshots.py # regenerates readme/site screenshots β βββ install_linux.sh # linux installer/uninstaller β βββ package_linux.sh # builds the linux .tar.gz release β βββ ... # gpu install/monitor helpers β βββ build_hooks/ # pyinstaller hook modules ``` ## π key design rules - **`core/` never imports qt or llama_cpp.** it receives plain callables, so it can be unit-tested in isolation. - **`services/` are the only place qt threads are created.** ui never spins up threads directly. - **`ui/` widgets are "dumb"** β they render state and emit signals; `mainwindow` owns all logic. - **`resource_manager.py`** makes paths work identically in dev, as an installed package, and in a pyinstaller bundle (`sys._meipass`). ## π§΅ threading model ``` ui thread (mainwindow) worker thread β β βββ modelservice.load() βββββββ qthread: llama_cpp loads model ββββββββ loaded(modelbackend) β βββ chatservice.generate() ββββ qthread: streams tokens ββββββββ token_received(text) β βββ agentservice.process() ββββ qthread: agentengine tool loop ββββββββ status/tool/response β ``` a fresh `qthread` + worker is created per request (the professional qt pattern β `qthread` is never subclassed). ## π entry point flow `main.py` β `setup_library_path()` (finds bundled llama.cpp libs) β `qapplication` β `mainwindow()` β builds ui, wires services, checks environment, loads addons β `app.exec()`. ## π¦ packaging - **windows**: `build_exe.bat` / `build_exe.spec` β `ggufloader_vx.y.z.exe` - **linux**: build the spec inside a linux environment, then `scripts/package_linux.sh` wraps the binary + installer + icon into a `.tar.gz` - github actions publishes both to every release automatically. see the [architecture overview](/docs/architecture/) for deeper design rationale.
π related features
π― what's next?
you've completed this guide! here are some suggested next steps to continue your gguf loader journey:
πshare your addon
built something awesome? share it with the community and get featured on our homepage.
share with community βππ€π explore more features
π back to homepage
π related features
π― what's next?
you've completed this guide! here are some suggested next steps to continue your gguf loader journey:
π οΈcreate your first addon
ready to extend gguf loader? learn how to create custom addons with our development guide.
addon development βπ₯join the community
connect with other gguf loader users, share your projects, and get help.
community hub βπadvanced tutorials
take your skills to the next level with advanced how-to guides and tutorials.
how-to guides βπ explore more features
π back to homepage
installation guide
complete guide to installing gguf loader on windows, macos, and linux
beginner 5 minutesthis guide will help you install gguf loader 2.2.0 on your system. want to see what gguf loader can do first? explore the features on our homepage.
π system requirements
- os: windows 10/11, linux (x86_64), or macos
- ram: 4 gb minimum (8 gb+ recommended for larger models)
- storage: 2 gb free space for the app, plus room for model files
- gpu: optional β cpu-only works everywhere; nvidia cuda is supported on windows and linux
- python: not required for the installers (everything is bundled)
π quick installation
the prebuilt installers bundle python, pyside6, and llama.cpp β you do not need python installed.
windows
- download ggufloader_v2.2.0_cpu.exe (~69 mb) from the releases page. this is the cpu-only build that works on any pc.
- have an nvidia gpu with cuda? grab ggufloader_v2.2.0_gpu.exe (~854 mb) instead for gpu acceleration.
- double-click the downloaded file and run it. no installation wizard β the app starts immediately.
β οΈ windows smartscreen: the first launch may show βwindows protected your pcβ. click more info β run anyway. this is normal for unsigned open-source binaries.
linux (x86_64)
- download ggufloader_v2.2.0_linux_x86_64_cpu (~121 mb) from the releases page.
- make it executable and run:
chmod +x ggufloader_v2.2.0_linux_x86_64_cpu ./ggufloader_v2.2.0_linux_x86_64_cpuno installation needed β the app starts directly. everything (python, pyside6, llama.cpp) is bundled.
macos
no prebuilt installer is published yet. run from source (below) β everything works on macos.
run from source (any platform)
for development, or to run on an unsupported platform:
git clone https://github.com/ggufloader/gguf-loader.git cd gguf-loader pip install -r requirements.txt python main.pyβ verify your installation
run
ggufloader_v2.2.0_cpu.exe --version(windows) or./ggufloader_v2.2.0_linux_x86_64_cpu --version(linux) β it printsgguf loader version 2.2.0and exits.π§ next steps
- quick start guide β load your first model
- troubleshooting β if something isnβt working
related documentation
- get up and running with gguf loader 2.2.0 in just a few minutes! new to gguf loader? [check out the homepage](/) to see what makes it special. ## π step 1: install gguf loader follow the [installation guide](/docs/installation/) for your platform, or download directly: - **windows**: [ggufloader_v2.2.0_cpu.exe](https://github.com/ggufloader/gguf-loader/releases/download/v2.2.0/ggufloader_v2.2.0_cpu.exe) (cpu-only) Β· [ggufloader_v2.2.0_gpu.exe](https://github.com/ggufloader/gguf-loader/releases/download/v2.2.0/ggufloader_v2.2.0_gpu.exe) (nvidia cuda) - **linux**: [ggufloader_v2.2.0_linux_x86_64_cpu](https://github.com/ggufloader/gguf-loader/releases/download/v2.2.0/ggufloader_v2.2.0_linux_x86_64_cpu) ## π₯ step 2: get a gguf model gguf loader runs any gguf-format model. good starter models on hugging face: - **small (fast)**: [llama-3-8b-instruct gguf (q4_0)](https://huggingface.co/thebloke/llama-3-8b-instruct-gguf) β ~4.7 gb, runs great on cpu - **medium**: [mistral-7b-instruct gguf (q4_k_m)](https://huggingface.co/thebloke/mistral-7b-instruct-v0.2-gguf) β ~4.1 gb - **larger**: [phi-3.5-mini-instruct gguf](https://huggingface.co/microsoft/phi-3.5-mini-instruct-gguf) or any qwen/llama gguf you like download the `.gguf` file and remember where you saved it. ## π₯οΈ step 3: load the model 1. launch gguf loader. 2. in the **model settings** sidebar, choose **processing** mode β `cpu only` (default, works everywhere) or `gpu accelerated` (nvidia cuda). 3. set a **context length** (8192 is a safe default for most models; 32768 uses more ram). 4. click **load gguf model** and select your `.gguf` file. 5. wait for the status to show **"model ready!"** β the header chip turns green with the model name. ## π¬ step 4: chat type a message in the input box at the bottom and press **enter** (shift+enter inserts a newline). responses stream in as chatgpt-style bubbles β your messages on the right (amber), the ai's on the left. use the **view β text size** menu to adjust bubble font size. ## π€ step 5 (optional): try agent mode click **π€ agent mode: off** in the input area to toggle it on: 1. pick a **workspace folder** (defaults to `./agent_workspace`). 2. ask the agent to do file work β e.g. *"create a file called hello.py that prints 'hi'"*. 3. the agent plans tool calls, executes them (read/write/edit/search files inside the workspace only), and reports back with live status updates. ## β next steps - [user guide](/docs/user-guide/) β everything the app can do - [addon development](/docs/addon-development/) β extend gguf loader with addons
- common issues and their fixes. running the app from a terminal (`python main.py` or the installed binary) shows the console log, which is the fastest way to diagnose most problems. ## π app won't start ### windows smartscreen blocks the .exe - click **more info β run anyway**. the binaries are unsigned open-source builds; this is expected. ### "llama-cpp-python is required but not installed" - the llama.cpp runtime is missing. in the app's **environment** section click **install missing dependencies**, or from source: `pip install -r requirements.txt`. ### dll load errors on windows (`importerror: dll load failed`) - the bundled `llama_cpp/lib` wasn't found. make sure you're running the full package (not just copying a single file), and check the console log for `added windows dll directory: ...`. ## π§ model won't load ### "failed to load model" / unknown format - confirm the file is a real gguf file (`.gguf`). corrupted or partial downloads fail; re-download the file. - check the file has enough disk space and isn't on a network drive with strict permissions. ### out of memory / crashes when loading - reduce **context length** (try 4096 or 8192). - switch **processing** to `cpu only` if gpu mode crashes (vram exhaustion). - use a smaller quantized model (q4_0/q4_k_m instead of q8). ### gpu accelerated is slow or doesn't use the gpu - gpu mode requires a cuda-enabled `llama-cpp-python` build. verify with `scripts/verify_gpu_support.py` or run `scripts/install_gpu_llama.bat`/`.sh` (see the [installation guide](/docs/installation/)). - on linux, make sure the nvidia driver and cuda toolkit are installed. ## π¬ chat problems ### send button is disabled - no model is loaded. load a `.gguf` model first. ### responses are empty or garbled - some models need specific prompt formats. check the model card for a chat template; very small models also produce weak output. - lower `temperature`-style randomness isn't exposed per-chat β try a different preset or model. ### chat is slow - smaller context, cpu-only on fast threads, and a smaller quantized model all help. generation speed is dominated by model size and hardware. ## π€ agent mode issues ### "please load a model first" - agent mode needs a loaded model β load one, then toggle agent mode on. ### agent can't find files / "path escapes workspace" - the agent is **sandboxed to the workspace folder**. put files you want it to touch inside the workspace, or choose the right folder with the π button. ### agent stuck on "processing..." - generation is single-threaded; long tool chains take time. watch the status messages for progress. ## π¬ floating chat addon ### button doesn't float above other apps on linux - this is expected under **wayland** β compositors confine app windows to the app itself. run under an x11 session or with `qt_qpa_platform=xcb` for full always-on-top behavior. ### button disappears when switching apps on macos - fixed in 2.1.2 (the `tool` flag is now dropped on macos so the button stays visible). if it still happens, check the console log and confirm the addon is listed under **addons**. ### button is stuck minimized - fixed in 2.1.2 β the button now restores itself immediately if a system shortcut minimizes it. ### addon not in the addons menu - click **addons β refresh addons**, or restart the app. check the console for `failed to load addon ...`. ## πͺ window / layout problems ### window too small / layout broken - the minimum window size is 800Γ500. maximize or resize the splitter β the sidebar is collapsible via the splitter handle. ### wrong colors / theme looks off - **view β dark mode** toggles themes. if colors look broken after a theme change, restart the app. ## π environment / venv issues ### "not running from .venv" - the app detected the system python. click **create .venv & restart** in the sidebar to bootstrap an isolated environment. ### pip install fails with externally-managed-environment (linux) - on debian/ubuntu 24.04+ the system python blocks pip. use the app's **create .venv & restart**, or create a venv manually: ```bash python3 -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt ``` ## π where to find logs - **windows**: `%localappdata%\ggufloader\logs` - **linux/macos**: `~/.ggufloader/logs` include the relevant log excerpt when [opening an issue](https://github.com/ggufloader/gguf-loader/issues).
- this is the complete manual for gguf loader 2.1.2. gguf loader is a privacy-first desktop app for running large language models locally from gguf files, with zero data leaving your machine. ## πͺ the main window the app is divided into three areas: 1. **header bar** (top) β brand on the left, a live **model status chip** on the right. 2. **sidebar** (left) β model settings, environment, and launcher sections. 3. **chat area** (center) β the conversation, or a welcome screen when no model is loaded. ## βοΈ model settings sidebar ### model - **load gguf model** β opens a file dialog; pick any `.gguf` file. - **model info** β shows the loaded file name (or an error). ### processing - **cpu only** β runs on any machine using llama.cpp's cpu backend. - **gpu accelerated** β offloads layers to an nvidia gpu (windows/linux). requires a working cuda llama-cpp-python install. ### context length the model's context window in tokens (512β32768). larger contexts use more ram. change it before loading a model. ## π environment section gguf loader ships with a built-in dependency manager for source installs: - **python Β· .venv status** β shows the interpreter and whether the app runs from a virtual environment. - **install missing dependencies** β appears when packages are missing; runs `pip install -r requirements.txt`. - **create .venv & restart** β bootstraps a virtual environment and relaunches inside it. - **check again** β re-scans the environment. > the packaged installers (`.exe` / linux tarball) bundle everything, so this section is mostly relevant when running from source. ## π launcher section one-click buttons that open the project's `scripts/` utilities (e.g. gpu support verification, monitor) in separate windows, plus **restart app**. ## π¬ chatting - type in the input box; **enter** sends, **shift+enter** inserts a newline. - **send** is disabled until you type something, and is disabled entirely until a model is loaded. - responses **stream** token-by-token into bubbles: your messages right (amber), ai left (charcoal). - **view β text size** (12β22) changes bubble font size live. - **file β clear chat** wipes the conversation (the model stays loaded). ## π€ agent mode agent mode turns the chat into a tool-using assistant that works inside a **workspace folder**: 1. toggle **π€ agent mode: off β on**. 2. choose a workspace (combo box or π browse button). default: `./agent_workspace`. 3. ask for file operations β e.g. *"create a markdown file listing today's tasks"*. the agent will: - analyze complex requests, - plan tool calls and stream status updates (π€/π‘/β/β/β), - execute tools against the workspace β `list_directory`, `read_file`, `write_file`, `edit_file`, `search_files`, - summarize results in natural language. **safety**: all tools are sandboxed to the workspace; paths that escape it are rejected. ## π¨ appearance - **view β dark mode** toggles the "midnight & amber" dark theme and a light theme. - **view β text size** adjusts chat bubble text. - the app remembers dark mode per session (dark is the default). ## π§© addons the **addons** menu lists every loaded addon (e.g. **floating_chat**). selecting one opens it in a floating dialog; **refresh addons** re-scans the `addons/` folder. see the [addon development guide](/docs/addon-development/). ### π¬ floating chat the built-in addon adds a messenger-style floating button (always on top, draggable) that opens a chat window connected to the loaded model. it: - stays on top of all windows (see platform notes below) - remembers its position between sessions - shows model status (π’ ready / π΄ offline) and streams responses - has copy all / clear controls **platform notes**: fully floating on windows and linux/x11. on linux **wayland**, compositors confine it to the app window β run under x11 (`qt_qpa_platform=xcb`) for the full effect. on macos the button stays visible when the app loses focus but also appears in mission control. ## π where files live - **config**: `%appdata%\ggufloader` (windows) / `~/.ggufloader` (linux/macos) - **cache**: `%localappdata%\ggufloader\cache` (windows) / `~/.cache/ggufloader` (linux) - **logs**: `%localappdata%\ggufloader\logs` (windows) / `~/.ggufloader/logs` (linux) - **addons**: the `addons/` folder next to the app ## β€οΈ feedback **help β send feedback** opens the feedback dialog. point it at your own formspree endpoint via `feedback_config.json`: ```json { "endpoint_url": "https://formspree.io/f/your_form_id" } ``` ## π still stuck? see the [troubleshooting guide](/docs/troubleshooting/).
π related features
π― what's next?
you've completed this guide! here are some suggested next steps to continue your gguf loader journey:
πstart using gguf loader
now that you have gguf loader installed, follow our quick start guide to load your first model and start chatting.
quick start guide βπ€browse models
explore our curated collection of gguf models to find the perfect one for your needs.
browse models ββ¨π explore more features
π back to homepage
troubleshooting guide
solutions to common gguf loader issues and problems
beginner 10 minutescommon issues and their fixes. running the app from a terminal (
python main.pyor the installed binary) shows the console log, which is the fastest way to diagnose most problems.π app wonβt start
windows smartscreen blocks the .exe
- click more info β run anyway. the binaries are unsigned open-source builds; this is expected.
βllama-cpp-python is required but not installedβ
- the llama.cpp runtime is missing. in the appβs environment section click install missing dependencies, or from source:
pip install -r requirements.txt.
dll load errors on windows (
importerror: dll load failed)- the bundled
llama_cpp/libwasnβt found. make sure youβre running the full package (not just copying a single file), and check the console log foradded windows dll directory: ....
π§ model wonβt load
βfailed to load modelβ / unknown format
- confirm the file is a real gguf file (
.gguf). corrupted or partial downloads fail; re-download the file. - check the file has enough disk space and isnβt on a network drive with strict permissions.
out of memory / crashes when loading
- reduce context length (try 4096 or 8192).
- switch processing to
cpu onlyif gpu mode crashes (vram exhaustion). - use a smaller quantized model (q4_0/q4_k_m instead of q8).
gpu accelerated is slow or doesnβt use the gpu
- gpu mode requires a cuda-enabled
llama-cpp-pythonbuild. verify withscripts/verify_gpu_support.pyor runscripts/install_gpu_llama.bat/.sh(see the installation guide). - on linux, make sure the nvidia driver and cuda toolkit are installed.
π¬ chat problems
send button is disabled
- no model is loaded. load a
.ggufmodel first.
responses are empty or garbled
- some models need specific prompt formats. check the model card for a chat template; very small models also produce weak output.
- lower
temperature-style randomness isnβt exposed per-chat β try a different preset or model.
chat is slow
- smaller context, cpu-only on fast threads, and a smaller quantized model all help. generation speed is dominated by model size and hardware.
π€ agent mode issues
βplease load a model firstβ
- agent mode needs a loaded model β load one, then toggle agent mode on.
agent canβt find files / βpath escapes workspaceβ
- the agent is sandboxed to the workspace folder. put files you want it to touch inside the workspace, or choose the right folder with the π button.
agent stuck on βprocessingβ¦β
- generation is single-threaded; long tool chains take time. watch the status messages for progress.
π¬ floating chat addon
button doesnβt float above other apps on linux
- this is expected under wayland β compositors confine app windows to the app itself. run under an x11 session or with
qt_qpa_platform=xcbfor full always-on-top behavior.
button disappears when switching apps on macos
- fixed in 2.1.2 (the
toolflag is now dropped on macos so the button stays visible). if it still happens, check the console log and confirm the addon is listed under addons.
button is stuck minimized
- fixed in 2.1.2 β the button now restores itself immediately if a system shortcut minimizes it.
addon not in the addons menu
- click addons β refresh addons, or restart the app. check the console for
failed to load addon ....
πͺ window / layout problems
window too small / layout broken
- the minimum window size is 800Γ500. maximize or resize the splitter β the sidebar is collapsible via the splitter handle.
wrong colors / theme looks off
- view β dark mode toggles themes. if colors look broken after a theme change, restart the app.
π environment / venv issues
βnot running from .venvβ
- the app detected the system python. click create .venv & restart in the sidebar to bootstrap an isolated environment.
pip install fails with externally-managed-environment (linux)
- on debian/ubuntu 24.04+ the system python blocks pip. use the appβs create .venv & restart, or create a venv manually:
python3 -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt
π where to find logs
- windows:
%localappdata%\ggufloader\logs - linux/macos:
~/.ggufloader/logs
include the relevant log excerpt when opening an issue.
related documentation
installation guide
complete guide to installing gguf loader on windows, macos, and linux
beginner 5 minutesthis guide will help you install gguf loader 2.2.0 on your system. want to see what gguf loader can do first? explore the features on our homepage.
π system requirements
- os: windows 10/11, linux (x86_64), or macos
- ram: 4 gb minimum (8 gb+ recommended for larger models)
- storage: 2 gb free space for the app, plus room for model files
- gpu: optional β cpu-only works everywhere; nvidia cuda is supported on windows and linux
- python: not required for the installers (everything is bundled)
π quick installation
the prebuilt installers bundle python, pyside6, and llama.cpp β you do not need python installed.
windows
- download ggufloader_v2.2.0_cpu.exe (~69 mb) from the releases page. this is the cpu-only build that works on any pc.
- have an nvidia gpu with cuda? grab ggufloader_v2.2.0_gpu.exe (~854 mb) instead for gpu acceleration.
- double-click the downloaded file and run it. no installation wizard β the app starts immediately.
β οΈ windows smartscreen: the first launch may show βwindows protected your pcβ. click more info β run anyway. this is normal for unsigned open-source binaries.
linux (x86_64)
- download ggufloader_v2.2.0_linux_x86_64_cpu (~121 mb) from the releases page.
- make it executable and run:
chmod +x ggufloader_v2.2.0_linux_x86_64_cpu ./ggufloader_v2.2.0_linux_x86_64_cpuno installation needed β the app starts directly. everything (python, pyside6, llama.cpp) is bundled.
macos
no prebuilt installer is published yet. run from source (below) β everything works on macos.
run from source (any platform)
for development, or to run on an unsupported platform:
git clone https://github.com/ggufloader/gguf-loader.git cd gguf-loader pip install -r requirements.txt python main.pyβ verify your installation
run
ggufloader_v2.2.0_cpu.exe --version(windows) or./ggufloader_v2.2.0_linux_x86_64_cpu --version(linux) β it printsgguf loader version 2.2.0and exits.π§ next steps
- quick start guide β load your first model
- troubleshooting β if something isnβt working
related documentation
- get up and running with gguf loader 2.2.0 in just a few minutes! new to gguf loader? [check out the homepage](/) to see what makes it special. ## π step 1: install gguf loader follow the [installation guide](/docs/installation/) for your platform, or download directly: - **windows**: [ggufloader_v2.2.0_cpu.exe](https://github.com/ggufloader/gguf-loader/releases/download/v2.2.0/ggufloader_v2.2.0_cpu.exe) (cpu-only) Β· [ggufloader_v2.2.0_gpu.exe](https://github.com/ggufloader/gguf-loader/releases/download/v2.2.0/ggufloader_v2.2.0_gpu.exe) (nvidia cuda) - **linux**: [ggufloader_v2.2.0_linux_x86_64_cpu](https://github.com/ggufloader/gguf-loader/releases/download/v2.2.0/ggufloader_v2.2.0_linux_x86_64_cpu) ## π₯ step 2: get a gguf model gguf loader runs any gguf-format model. good starter models on hugging face: - **small (fast)**: [llama-3-8b-instruct gguf (q4_0)](https://huggingface.co/thebloke/llama-3-8b-instruct-gguf) β ~4.7 gb, runs great on cpu - **medium**: [mistral-7b-instruct gguf (q4_k_m)](https://huggingface.co/thebloke/mistral-7b-instruct-v0.2-gguf) β ~4.1 gb - **larger**: [phi-3.5-mini-instruct gguf](https://huggingface.co/microsoft/phi-3.5-mini-instruct-gguf) or any qwen/llama gguf you like download the `.gguf` file and remember where you saved it. ## π₯οΈ step 3: load the model 1. launch gguf loader. 2. in the **model settings** sidebar, choose **processing** mode β `cpu only` (default, works everywhere) or `gpu accelerated` (nvidia cuda). 3. set a **context length** (8192 is a safe default for most models; 32768 uses more ram). 4. click **load gguf model** and select your `.gguf` file. 5. wait for the status to show **"model ready!"** β the header chip turns green with the model name. ## π¬ step 4: chat type a message in the input box at the bottom and press **enter** (shift+enter inserts a newline). responses stream in as chatgpt-style bubbles β your messages on the right (amber), the ai's on the left. use the **view β text size** menu to adjust bubble font size. ## π€ step 5 (optional): try agent mode click **π€ agent mode: off** in the input area to toggle it on: 1. pick a **workspace folder** (defaults to `./agent_workspace`). 2. ask the agent to do file work β e.g. *"create a file called hello.py that prints 'hi'"*. 3. the agent plans tool calls, executes them (read/write/edit/search files inside the workspace only), and reports back with live status updates. ## β next steps - [user guide](/docs/user-guide/) β everything the app can do - [addon development](/docs/addon-development/) β extend gguf loader with addons
- common issues and their fixes. running the app from a terminal (`python main.py` or the installed binary) shows the console log, which is the fastest way to diagnose most problems. ## π app won't start ### windows smartscreen blocks the .exe - click **more info β run anyway**. the binaries are unsigned open-source builds; this is expected. ### "llama-cpp-python is required but not installed" - the llama.cpp runtime is missing. in the app's **environment** section click **install missing dependencies**, or from source: `pip install -r requirements.txt`. ### dll load errors on windows (`importerror: dll load failed`) - the bundled `llama_cpp/lib` wasn't found. make sure you're running the full package (not just copying a single file), and check the console log for `added windows dll directory: ...`. ## π§ model won't load ### "failed to load model" / unknown format - confirm the file is a real gguf file (`.gguf`). corrupted or partial downloads fail; re-download the file. - check the file has enough disk space and isn't on a network drive with strict permissions. ### out of memory / crashes when loading - reduce **context length** (try 4096 or 8192). - switch **processing** to `cpu only` if gpu mode crashes (vram exhaustion). - use a smaller quantized model (q4_0/q4_k_m instead of q8). ### gpu accelerated is slow or doesn't use the gpu - gpu mode requires a cuda-enabled `llama-cpp-python` build. verify with `scripts/verify_gpu_support.py` or run `scripts/install_gpu_llama.bat`/`.sh` (see the [installation guide](/docs/installation/)). - on linux, make sure the nvidia driver and cuda toolkit are installed. ## π¬ chat problems ### send button is disabled - no model is loaded. load a `.gguf` model first. ### responses are empty or garbled - some models need specific prompt formats. check the model card for a chat template; very small models also produce weak output. - lower `temperature`-style randomness isn't exposed per-chat β try a different preset or model. ### chat is slow - smaller context, cpu-only on fast threads, and a smaller quantized model all help. generation speed is dominated by model size and hardware. ## π€ agent mode issues ### "please load a model first" - agent mode needs a loaded model β load one, then toggle agent mode on. ### agent can't find files / "path escapes workspace" - the agent is **sandboxed to the workspace folder**. put files you want it to touch inside the workspace, or choose the right folder with the π button. ### agent stuck on "processing..." - generation is single-threaded; long tool chains take time. watch the status messages for progress. ## π¬ floating chat addon ### button doesn't float above other apps on linux - this is expected under **wayland** β compositors confine app windows to the app itself. run under an x11 session or with `qt_qpa_platform=xcb` for full always-on-top behavior. ### button disappears when switching apps on macos - fixed in 2.1.2 (the `tool` flag is now dropped on macos so the button stays visible). if it still happens, check the console log and confirm the addon is listed under **addons**. ### button is stuck minimized - fixed in 2.1.2 β the button now restores itself immediately if a system shortcut minimizes it. ### addon not in the addons menu - click **addons β refresh addons**, or restart the app. check the console for `failed to load addon ...`. ## πͺ window / layout problems ### window too small / layout broken - the minimum window size is 800Γ500. maximize or resize the splitter β the sidebar is collapsible via the splitter handle. ### wrong colors / theme looks off - **view β dark mode** toggles themes. if colors look broken after a theme change, restart the app. ## π environment / venv issues ### "not running from .venv" - the app detected the system python. click **create .venv & restart** in the sidebar to bootstrap an isolated environment. ### pip install fails with externally-managed-environment (linux) - on debian/ubuntu 24.04+ the system python blocks pip. use the app's **create .venv & restart**, or create a venv manually: ```bash python3 -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt ``` ## π where to find logs - **windows**: `%localappdata%\ggufloader\logs` - **linux/macos**: `~/.ggufloader/logs` include the relevant log excerpt when [opening an issue](https://github.com/ggufloader/gguf-loader/issues).
- this is the complete manual for gguf loader 2.1.2. gguf loader is a privacy-first desktop app for running large language models locally from gguf files, with zero data leaving your machine. ## πͺ the main window the app is divided into three areas: 1. **header bar** (top) β brand on the left, a live **model status chip** on the right. 2. **sidebar** (left) β model settings, environment, and launcher sections. 3. **chat area** (center) β the conversation, or a welcome screen when no model is loaded. ## βοΈ model settings sidebar ### model - **load gguf model** β opens a file dialog; pick any `.gguf` file. - **model info** β shows the loaded file name (or an error). ### processing - **cpu only** β runs on any machine using llama.cpp's cpu backend. - **gpu accelerated** β offloads layers to an nvidia gpu (windows/linux). requires a working cuda llama-cpp-python install. ### context length the model's context window in tokens (512β32768). larger contexts use more ram. change it before loading a model. ## π environment section gguf loader ships with a built-in dependency manager for source installs: - **python Β· .venv status** β shows the interpreter and whether the app runs from a virtual environment. - **install missing dependencies** β appears when packages are missing; runs `pip install -r requirements.txt`. - **create .venv & restart** β bootstraps a virtual environment and relaunches inside it. - **check again** β re-scans the environment. > the packaged installers (`.exe` / linux tarball) bundle everything, so this section is mostly relevant when running from source. ## π launcher section one-click buttons that open the project's `scripts/` utilities (e.g. gpu support verification, monitor) in separate windows, plus **restart app**. ## π¬ chatting - type in the input box; **enter** sends, **shift+enter** inserts a newline. - **send** is disabled until you type something, and is disabled entirely until a model is loaded. - responses **stream** token-by-token into bubbles: your messages right (amber), ai left (charcoal). - **view β text size** (12β22) changes bubble font size live. - **file β clear chat** wipes the conversation (the model stays loaded). ## π€ agent mode agent mode turns the chat into a tool-using assistant that works inside a **workspace folder**: 1. toggle **π€ agent mode: off β on**. 2. choose a workspace (combo box or π browse button). default: `./agent_workspace`. 3. ask for file operations β e.g. *"create a markdown file listing today's tasks"*. the agent will: - analyze complex requests, - plan tool calls and stream status updates (π€/π‘/β/β/β), - execute tools against the workspace β `list_directory`, `read_file`, `write_file`, `edit_file`, `search_files`, - summarize results in natural language. **safety**: all tools are sandboxed to the workspace; paths that escape it are rejected. ## π¨ appearance - **view β dark mode** toggles the "midnight & amber" dark theme and a light theme. - **view β text size** adjusts chat bubble text. - the app remembers dark mode per session (dark is the default). ## π§© addons the **addons** menu lists every loaded addon (e.g. **floating_chat**). selecting one opens it in a floating dialog; **refresh addons** re-scans the `addons/` folder. see the [addon development guide](/docs/addon-development/). ### π¬ floating chat the built-in addon adds a messenger-style floating button (always on top, draggable) that opens a chat window connected to the loaded model. it: - stays on top of all windows (see platform notes below) - remembers its position between sessions - shows model status (π’ ready / π΄ offline) and streams responses - has copy all / clear controls **platform notes**: fully floating on windows and linux/x11. on linux **wayland**, compositors confine it to the app window β run under x11 (`qt_qpa_platform=xcb`) for the full effect. on macos the button stays visible when the app loses focus but also appears in mission control. ## π where files live - **config**: `%appdata%\ggufloader` (windows) / `~/.ggufloader` (linux/macos) - **cache**: `%localappdata%\ggufloader\cache` (windows) / `~/.cache/ggufloader` (linux) - **logs**: `%localappdata%\ggufloader\logs` (windows) / `~/.ggufloader/logs` (linux) - **addons**: the `addons/` folder next to the app ## β€οΈ feedback **help β send feedback** opens the feedback dialog. point it at your own formspree endpoint via `feedback_config.json`: ```json { "endpoint_url": "https://formspree.io/f/your_form_id" } ``` ## π still stuck? see the [troubleshooting guide](/docs/troubleshooting/).
π related features
π― what's next?
you've completed this guide! here are some suggested next steps to continue your gguf loader journey:
πstart using gguf loader
now that you have gguf loader installed, follow our quick start guide to load your first model and start chatting.
quick start guide βπ€browse models
explore our curated collection of gguf models to find the perfect one for your needs.
browse models ββ¨π explore more features
π back to homepage
- this is the complete manual for gguf loader 2.1.2. gguf loader is a privacy-first desktop app for running large language models locally from gguf files, with zero data leaving your machine. ## πͺ the main window the app is divided into three areas: 1. **header bar** (top) β brand on the left, a live **model status chip** on the right. 2. **sidebar** (left) β model settings, environment, and launcher sections. 3. **chat area** (center) β the conversation, or a welcome screen when no model is loaded. ## βοΈ model settings sidebar ### model - **load gguf model** β opens a file dialog; pick any `.gguf` file. - **model info** β shows the loaded file name (or an error). ### processing - **cpu only** β runs on any machine using llama.cpp's cpu backend. - **gpu accelerated** β offloads layers to an nvidia gpu (windows/linux). requires a working cuda llama-cpp-python install. ### context length the model's context window in tokens (512β32768). larger contexts use more ram. change it before loading a model. ## π environment section gguf loader ships with a built-in dependency manager for source installs: - **python Β· .venv status** β shows the interpreter and whether the app runs from a virtual environment. - **install missing dependencies** β appears when packages are missing; runs `pip install -r requirements.txt`. - **create .venv & restart** β bootstraps a virtual environment and relaunches inside it. - **check again** β re-scans the environment. > the packaged installers (`.exe` / linux tarball) bundle everything, so this section is mostly relevant when running from source. ## π launcher section one-click buttons that open the project's `scripts/` utilities (e.g. gpu support verification, monitor) in separate windows, plus **restart app**. ## π¬ chatting - type in the input box; **enter** sends, **shift+enter** inserts a newline. - **send** is disabled until you type something, and is disabled entirely until a model is loaded. - responses **stream** token-by-token into bubbles: your messages right (amber), ai left (charcoal). - **view β text size** (12β22) changes bubble font size live. - **file β clear chat** wipes the conversation (the model stays loaded). ## π€ agent mode agent mode turns the chat into a tool-using assistant that works inside a **workspace folder**: 1. toggle **π€ agent mode: off β on**. 2. choose a workspace (combo box or π browse button). default: `./agent_workspace`. 3. ask for file operations β e.g. *"create a markdown file listing today's tasks"*. the agent will: - analyze complex requests, - plan tool calls and stream status updates (π€/π‘/β/β/β), - execute tools against the workspace β `list_directory`, `read_file`, `write_file`, `edit_file`, `search_files`, - summarize results in natural language. **safety**: all tools are sandboxed to the workspace; paths that escape it are rejected. ## π¨ appearance - **view β dark mode** toggles the "midnight & amber" dark theme and a light theme. - **view β text size** adjusts chat bubble text. - the app remembers dark mode per session (dark is the default). ## π§© addons the **addons** menu lists every loaded addon (e.g. **floating_chat**). selecting one opens it in a floating dialog; **refresh addons** re-scans the `addons/` folder. see the [addon development guide](/docs/addon-development/). ### π¬ floating chat the built-in addon adds a messenger-style floating button (always on top, draggable) that opens a chat window connected to the loaded model. it: - stays on top of all windows (see platform notes below) - remembers its position between sessions - shows model status (π’ ready / π΄ offline) and streams responses - has copy all / clear controls **platform notes**: fully floating on windows and linux/x11. on linux **wayland**, compositors confine it to the app window β run under x11 (`qt_qpa_platform=xcb`) for the full effect. on macos the button stays visible when the app loses focus but also appears in mission control. ## π where files live - **config**: `%appdata%\ggufloader` (windows) / `~/.ggufloader` (linux/macos) - **cache**: `%localappdata%\ggufloader\cache` (windows) / `~/.cache/ggufloader` (linux) - **logs**: `%localappdata%\ggufloader\logs` (windows) / `~/.ggufloader/logs` (linux) - **addons**: the `addons/` folder next to the app ## β€οΈ feedback **help β send feedback** opens the feedback dialog. point it at your own formspree endpoint via `feedback_config.json`: ```json { "endpoint_url": "https://formspree.io/f/your_form_id" } ``` ## π still stuck? see the [troubleshooting guide](/docs/troubleshooting/).
quick start guide
get up and running with gguf loader in just a few minutes
beginner 5 minutesget up and running with gguf loader 2.2.0 in just a few minutes! new to gguf loader? check out the homepage to see what makes it special.
π step 1: install gguf loader
follow the installation guide for your platform, or download directly:
- windows: ggufloader_v2.2.0_cpu.exe (cpu-only) Β· ggufloader_v2.2.0_gpu.exe (nvidia cuda)
- linux: ggufloader_v2.2.0_linux_x86_64_cpu
π₯ step 2: get a gguf model
gguf loader runs any gguf-format model. good starter models on hugging face:
- small (fast): llama-3-8b-instruct gguf (q4_0) β ~4.7 gb, runs great on cpu
- medium: mistral-7b-instruct gguf (q4_k_m) β ~4.1 gb
- larger: phi-3.5-mini-instruct gguf or any qwen/llama gguf you like
download the
.gguffile and remember where you saved it.π₯οΈ step 3: load the model
- launch gguf loader.
- in the model settings sidebar, choose processing mode β
cpu only(default, works everywhere) orgpu accelerated(nvidia cuda). - set a context length (8192 is a safe default for most models; 32768 uses more ram).
- click load gguf model and select your
.gguffile. - wait for the status to show βmodel ready!β β the header chip turns green with the model name.
π¬ step 4: chat
type a message in the input box at the bottom and press enter (shift+enter inserts a newline). responses stream in as chatgpt-style bubbles β your messages on the right (amber), the aiβs on the left.
use the view β text size menu to adjust bubble font size.
π€ step 5 (optional): try agent mode
click π€ agent mode: off in the input area to toggle it on:
- pick a workspace folder (defaults to
./agent_workspace). - ask the agent to do file work β e.g. βcreate a file called hello.py that prints βhiββ.
- the agent plans tool calls, executes them (read/write/edit/search files inside the workspace only), and reports back with live status updates.
β next steps
- user guide β everything the app can do
- addon development β extend gguf loader with addons
related documentation
installation guide
complete guide to installing gguf loader on windows, macos, and linux
beginner 5 minutesthis guide will help you install gguf loader 2.2.0 on your system. want to see what gguf loader can do first? explore the features on our homepage.
π system requirements
- os: windows 10/11, linux (x86_64), or macos
- ram: 4 gb minimum (8 gb+ recommended for larger models)
- storage: 2 gb free space for the app, plus room for model files
- gpu: optional β cpu-only works everywhere; nvidia cuda is supported on windows and linux
- python: not required for the installers (everything is bundled)
π quick installation
the prebuilt installers bundle python, pyside6, and llama.cpp β you do not need python installed.
windows
- download ggufloader_v2.2.0_cpu.exe (~69 mb) from the releases page. this is the cpu-only build that works on any pc.
- have an nvidia gpu with cuda? grab ggufloader_v2.2.0_gpu.exe (~854 mb) instead for gpu acceleration.
- double-click the downloaded file and run it. no installation wizard β the app starts immediately.
β οΈ windows smartscreen: the first launch may show βwindows protected your pcβ. click more info β run anyway. this is normal for unsigned open-source binaries.
linux (x86_64)
- download ggufloader_v2.2.0_linux_x86_64_cpu (~121 mb) from the releases page.
- make it executable and run:
chmod +x ggufloader_v2.2.0_linux_x86_64_cpu ./ggufloader_v2.2.0_linux_x86_64_cpuno installation needed β the app starts directly. everything (python, pyside6, llama.cpp) is bundled.
macos
no prebuilt installer is published yet. run from source (below) β everything works on macos.
run from source (any platform)
for development, or to run on an unsupported platform:
git clone https://github.com/ggufloader/gguf-loader.git cd gguf-loader pip install -r requirements.txt python main.pyβ verify your installation
run
ggufloader_v2.2.0_cpu.exe --version(windows) or./ggufloader_v2.2.0_linux_x86_64_cpu --version(linux) β it printsgguf loader version 2.2.0and exits.π§ next steps
- quick start guide β load your first model
- troubleshooting β if something isnβt working
related documentation
- get up and running with gguf loader 2.2.0 in just a few minutes! new to gguf loader? [check out the homepage](/) to see what makes it special. ## π step 1: install gguf loader follow the [installation guide](/docs/installation/) for your platform, or download directly: - **windows**: [ggufloader_v2.2.0_cpu.exe](https://github.com/ggufloader/gguf-loader/releases/download/v2.2.0/ggufloader_v2.2.0_cpu.exe) (cpu-only) Β· [ggufloader_v2.2.0_gpu.exe](https://github.com/ggufloader/gguf-loader/releases/download/v2.2.0/ggufloader_v2.2.0_gpu.exe) (nvidia cuda) - **linux**: [ggufloader_v2.2.0_linux_x86_64_cpu](https://github.com/ggufloader/gguf-loader/releases/download/v2.2.0/ggufloader_v2.2.0_linux_x86_64_cpu) ## π₯ step 2: get a gguf model gguf loader runs any gguf-format model. good starter models on hugging face: - **small (fast)**: [llama-3-8b-instruct gguf (q4_0)](https://huggingface.co/thebloke/llama-3-8b-instruct-gguf) β ~4.7 gb, runs great on cpu - **medium**: [mistral-7b-instruct gguf (q4_k_m)](https://huggingface.co/thebloke/mistral-7b-instruct-v0.2-gguf) β ~4.1 gb - **larger**: [phi-3.5-mini-instruct gguf](https://huggingface.co/microsoft/phi-3.5-mini-instruct-gguf) or any qwen/llama gguf you like download the `.gguf` file and remember where you saved it. ## π₯οΈ step 3: load the model 1. launch gguf loader. 2. in the **model settings** sidebar, choose **processing** mode β `cpu only` (default, works everywhere) or `gpu accelerated` (nvidia cuda). 3. set a **context length** (8192 is a safe default for most models; 32768 uses more ram). 4. click **load gguf model** and select your `.gguf` file. 5. wait for the status to show **"model ready!"** β the header chip turns green with the model name. ## π¬ step 4: chat type a message in the input box at the bottom and press **enter** (shift+enter inserts a newline). responses stream in as chatgpt-style bubbles β your messages on the right (amber), the ai's on the left. use the **view β text size** menu to adjust bubble font size. ## π€ step 5 (optional): try agent mode click **π€ agent mode: off** in the input area to toggle it on: 1. pick a **workspace folder** (defaults to `./agent_workspace`). 2. ask the agent to do file work β e.g. *"create a file called hello.py that prints 'hi'"*. 3. the agent plans tool calls, executes them (read/write/edit/search files inside the workspace only), and reports back with live status updates. ## β next steps - [user guide](/docs/user-guide/) β everything the app can do - [addon development](/docs/addon-development/) β extend gguf loader with addons
- common issues and their fixes. running the app from a terminal (`python main.py` or the installed binary) shows the console log, which is the fastest way to diagnose most problems. ## π app won't start ### windows smartscreen blocks the .exe - click **more info β run anyway**. the binaries are unsigned open-source builds; this is expected. ### "llama-cpp-python is required but not installed" - the llama.cpp runtime is missing. in the app's **environment** section click **install missing dependencies**, or from source: `pip install -r requirements.txt`. ### dll load errors on windows (`importerror: dll load failed`) - the bundled `llama_cpp/lib` wasn't found. make sure you're running the full package (not just copying a single file), and check the console log for `added windows dll directory: ...`. ## π§ model won't load ### "failed to load model" / unknown format - confirm the file is a real gguf file (`.gguf`). corrupted or partial downloads fail; re-download the file. - check the file has enough disk space and isn't on a network drive with strict permissions. ### out of memory / crashes when loading - reduce **context length** (try 4096 or 8192). - switch **processing** to `cpu only` if gpu mode crashes (vram exhaustion). - use a smaller quantized model (q4_0/q4_k_m instead of q8). ### gpu accelerated is slow or doesn't use the gpu - gpu mode requires a cuda-enabled `llama-cpp-python` build. verify with `scripts/verify_gpu_support.py` or run `scripts/install_gpu_llama.bat`/`.sh` (see the [installation guide](/docs/installation/)). - on linux, make sure the nvidia driver and cuda toolkit are installed. ## π¬ chat problems ### send button is disabled - no model is loaded. load a `.gguf` model first. ### responses are empty or garbled - some models need specific prompt formats. check the model card for a chat template; very small models also produce weak output. - lower `temperature`-style randomness isn't exposed per-chat β try a different preset or model. ### chat is slow - smaller context, cpu-only on fast threads, and a smaller quantized model all help. generation speed is dominated by model size and hardware. ## π€ agent mode issues ### "please load a model first" - agent mode needs a loaded model β load one, then toggle agent mode on. ### agent can't find files / "path escapes workspace" - the agent is **sandboxed to the workspace folder**. put files you want it to touch inside the workspace, or choose the right folder with the π button. ### agent stuck on "processing..." - generation is single-threaded; long tool chains take time. watch the status messages for progress. ## π¬ floating chat addon ### button doesn't float above other apps on linux - this is expected under **wayland** β compositors confine app windows to the app itself. run under an x11 session or with `qt_qpa_platform=xcb` for full always-on-top behavior. ### button disappears when switching apps on macos - fixed in 2.1.2 (the `tool` flag is now dropped on macos so the button stays visible). if it still happens, check the console log and confirm the addon is listed under **addons**. ### button is stuck minimized - fixed in 2.1.2 β the button now restores itself immediately if a system shortcut minimizes it. ### addon not in the addons menu - click **addons β refresh addons**, or restart the app. check the console for `failed to load addon ...`. ## πͺ window / layout problems ### window too small / layout broken - the minimum window size is 800Γ500. maximize or resize the splitter β the sidebar is collapsible via the splitter handle. ### wrong colors / theme looks off - **view β dark mode** toggles themes. if colors look broken after a theme change, restart the app. ## π environment / venv issues ### "not running from .venv" - the app detected the system python. click **create .venv & restart** in the sidebar to bootstrap an isolated environment. ### pip install fails with externally-managed-environment (linux) - on debian/ubuntu 24.04+ the system python blocks pip. use the app's **create .venv & restart**, or create a venv manually: ```bash python3 -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt ``` ## π where to find logs - **windows**: `%localappdata%\ggufloader\logs` - **linux/macos**: `~/.ggufloader/logs` include the relevant log excerpt when [opening an issue](https://github.com/ggufloader/gguf-loader/issues).
- this is the complete manual for gguf loader 2.1.2. gguf loader is a privacy-first desktop app for running large language models locally from gguf files, with zero data leaving your machine. ## πͺ the main window the app is divided into three areas: 1. **header bar** (top) β brand on the left, a live **model status chip** on the right. 2. **sidebar** (left) β model settings, environment, and launcher sections. 3. **chat area** (center) β the conversation, or a welcome screen when no model is loaded. ## βοΈ model settings sidebar ### model - **load gguf model** β opens a file dialog; pick any `.gguf` file. - **model info** β shows the loaded file name (or an error). ### processing - **cpu only** β runs on any machine using llama.cpp's cpu backend. - **gpu accelerated** β offloads layers to an nvidia gpu (windows/linux). requires a working cuda llama-cpp-python install. ### context length the model's context window in tokens (512β32768). larger contexts use more ram. change it before loading a model. ## π environment section gguf loader ships with a built-in dependency manager for source installs: - **python Β· .venv status** β shows the interpreter and whether the app runs from a virtual environment. - **install missing dependencies** β appears when packages are missing; runs `pip install -r requirements.txt`. - **create .venv & restart** β bootstraps a virtual environment and relaunches inside it. - **check again** β re-scans the environment. > the packaged installers (`.exe` / linux tarball) bundle everything, so this section is mostly relevant when running from source. ## π launcher section one-click buttons that open the project's `scripts/` utilities (e.g. gpu support verification, monitor) in separate windows, plus **restart app**. ## π¬ chatting - type in the input box; **enter** sends, **shift+enter** inserts a newline. - **send** is disabled until you type something, and is disabled entirely until a model is loaded. - responses **stream** token-by-token into bubbles: your messages right (amber), ai left (charcoal). - **view β text size** (12β22) changes bubble font size live. - **file β clear chat** wipes the conversation (the model stays loaded). ## π€ agent mode agent mode turns the chat into a tool-using assistant that works inside a **workspace folder**: 1. toggle **π€ agent mode: off β on**. 2. choose a workspace (combo box or π browse button). default: `./agent_workspace`. 3. ask for file operations β e.g. *"create a markdown file listing today's tasks"*. the agent will: - analyze complex requests, - plan tool calls and stream status updates (π€/π‘/β/β/β), - execute tools against the workspace β `list_directory`, `read_file`, `write_file`, `edit_file`, `search_files`, - summarize results in natural language. **safety**: all tools are sandboxed to the workspace; paths that escape it are rejected. ## π¨ appearance - **view β dark mode** toggles the "midnight & amber" dark theme and a light theme. - **view β text size** adjusts chat bubble text. - the app remembers dark mode per session (dark is the default). ## π§© addons the **addons** menu lists every loaded addon (e.g. **floating_chat**). selecting one opens it in a floating dialog; **refresh addons** re-scans the `addons/` folder. see the [addon development guide](/docs/addon-development/). ### π¬ floating chat the built-in addon adds a messenger-style floating button (always on top, draggable) that opens a chat window connected to the loaded model. it: - stays on top of all windows (see platform notes below) - remembers its position between sessions - shows model status (π’ ready / π΄ offline) and streams responses - has copy all / clear controls **platform notes**: fully floating on windows and linux/x11. on linux **wayland**, compositors confine it to the app window β run under x11 (`qt_qpa_platform=xcb`) for the full effect. on macos the button stays visible when the app loses focus but also appears in mission control. ## π where files live - **config**: `%appdata%\ggufloader` (windows) / `~/.ggufloader` (linux/macos) - **cache**: `%localappdata%\ggufloader\cache` (windows) / `~/.cache/ggufloader` (linux) - **logs**: `%localappdata%\ggufloader\logs` (windows) / `~/.ggufloader/logs` (linux) - **addons**: the `addons/` folder next to the app ## β€οΈ feedback **help β send feedback** opens the feedback dialog. point it at your own formspree endpoint via `feedback_config.json`: ```json { "endpoint_url": "https://formspree.io/f/your_form_id" } ``` ## π still stuck? see the [troubleshooting guide](/docs/troubleshooting/).
π related features
π― what's next?
you've completed this guide! here are some suggested next steps to continue your gguf loader journey:
πstart using gguf loader
now that you have gguf loader installed, follow our quick start guide to load your first model and start chatting.
quick start guide βπ€browse models
explore our curated collection of gguf models to find the perfect one for your needs.
browse models ββ¨π explore more features
π back to homepage
- this is the complete manual for gguf loader 2.1.2. gguf loader is a privacy-first desktop app for running large language models locally from gguf files, with zero data leaving your machine. ## πͺ the main window the app is divided into three areas: 1. **header bar** (top) β brand on the left, a live **model status chip** on the right. 2. **sidebar** (left) β model settings, environment, and launcher sections. 3. **chat area** (center) β the conversation, or a welcome screen when no model is loaded. ## βοΈ model settings sidebar ### model - **load gguf model** β opens a file dialog; pick any `.gguf` file. - **model info** β shows the loaded file name (or an error). ### processing - **cpu only** β runs on any machine using llama.cpp's cpu backend. - **gpu accelerated** β offloads layers to an nvidia gpu (windows/linux). requires a working cuda llama-cpp-python install. ### context length the model's context window in tokens (512β32768). larger contexts use more ram. change it before loading a model. ## π environment section gguf loader ships with a built-in dependency manager for source installs: - **python Β· .venv status** β shows the interpreter and whether the app runs from a virtual environment. - **install missing dependencies** β appears when packages are missing; runs `pip install -r requirements.txt`. - **create .venv & restart** β bootstraps a virtual environment and relaunches inside it. - **check again** β re-scans the environment. > the packaged installers (`.exe` / linux tarball) bundle everything, so this section is mostly relevant when running from source. ## π launcher section one-click buttons that open the project's `scripts/` utilities (e.g. gpu support verification, monitor) in separate windows, plus **restart app**. ## π¬ chatting - type in the input box; **enter** sends, **shift+enter** inserts a newline. - **send** is disabled until you type something, and is disabled entirely until a model is loaded. - responses **stream** token-by-token into bubbles: your messages right (amber), ai left (charcoal). - **view β text size** (12β22) changes bubble font size live. - **file β clear chat** wipes the conversation (the model stays loaded). ## π€ agent mode agent mode turns the chat into a tool-using assistant that works inside a **workspace folder**: 1. toggle **π€ agent mode: off β on**. 2. choose a workspace (combo box or π browse button). default: `./agent_workspace`. 3. ask for file operations β e.g. *"create a markdown file listing today's tasks"*. the agent will: - analyze complex requests, - plan tool calls and stream status updates (π€/π‘/β/β/β), - execute tools against the workspace β `list_directory`, `read_file`, `write_file`, `edit_file`, `search_files`, - summarize results in natural language. **safety**: all tools are sandboxed to the workspace; paths that escape it are rejected. ## π¨ appearance - **view β dark mode** toggles the "midnight & amber" dark theme and a light theme. - **view β text size** adjusts chat bubble text. - the app remembers dark mode per session (dark is the default). ## π§© addons the **addons** menu lists every loaded addon (e.g. **floating_chat**). selecting one opens it in a floating dialog; **refresh addons** re-scans the `addons/` folder. see the [addon development guide](/docs/addon-development/). ### π¬ floating chat the built-in addon adds a messenger-style floating button (always on top, draggable) that opens a chat window connected to the loaded model. it: - stays on top of all windows (see platform notes below) - remembers its position between sessions - shows model status (π’ ready / π΄ offline) and streams responses - has copy all / clear controls **platform notes**: fully floating on windows and linux/x11. on linux **wayland**, compositors confine it to the app window β run under x11 (`qt_qpa_platform=xcb`) for the full effect. on macos the button stays visible when the app loses focus but also appears in mission control. ## π where files live - **config**: `%appdata%\ggufloader` (windows) / `~/.ggufloader` (linux/macos) - **cache**: `%localappdata%\ggufloader\cache` (windows) / `~/.cache/ggufloader` (linux) - **logs**: `%localappdata%\ggufloader\logs` (windows) / `~/.ggufloader/logs` (linux) - **addons**: the `addons/` folder next to the app ## β€οΈ feedback **help β send feedback** opens the feedback dialog. point it at your own formspree endpoint via `feedback_config.json`: ```json { "endpoint_url": "https://formspree.io/f/your_form_id" } ``` ## π still stuck? see the [troubleshooting guide](/docs/troubleshooting/).
addon development guide
learn to create custom addons for gguf loader with examples and best practices
advanced 15 minutesgguf loaderβs addon system lets you extend the app without touching its source. addons are python packages dropped into the
addons/folder; the app discovers, loads, and manages them automatically.π¦ what an addon looks like
addons/ βββ my_addon/ βββ __init__.py # must expose register() βββ main.py # your logic (any structure you like) βββ ... # widgets, resources, etc.minimum viable addon
# addons/my_addon/__init__.py from pyside6.qtwidgets import qlabel def register(parent=none): """called by gguf loader when the addon loads.""" return qlabel("hello from my addon!")thatβs it β drop the folder in
addons/, restart (or addons β refresh addons), and your widget appears in the addons menu.π how loading works
addonmanager(addon_manager.py):scan_addons()β lists subdirectories of the addons folder that contain__init__.py.load_addon(name, path)β dynamically imports the module (importlib.util.spec_from_file_location) and requires aregisterattribute.load_all_addons()β loads every addon and records success/failure in the console log.get_addon_widget(name, parent)β callsregister(parent)and returns the widget.open_addon_dialog(name, parent)β shows the addon widget in a non-modal dialog from the addons menu.
the main window calls
get_addon_widgetfor each loaded addon at startup, soregister()runs even before the user opens the menu β this is how background addons (like the floating chat button) start automatically.π‘ talking to the app
your
register(parent)receives the parent widget. the main window exposes an addon-facing api (see the addon api reference). the robust pattern used by the built-in addon:def register(parent=none): gguf_app = none # 1. parent might already be the main window if parent and hasattr(parent, 'model') and hasattr(parent, 'model_loaded'): gguf_app = parent else: # 2. walk up the parent chain current = parent while current is not none: if hasattr(current, 'model') and hasattr(current, 'model_loaded'): gguf_app = current break current = current.parent() # 3. fall back to scanning top-level widgets if gguf_app is none: app = qapplication.instance() for widget in app.toplevelwidgets(): if hasattr(widget, 'model') and hasattr(widget, 'model_loaded'): gguf_app = widget break ...key api members:
model(callable backend),model_loaded/model_unloaded/generation_finished/generation_errorsignals,addon_manager, and_floating_chat_addon.π€ calling the model
# streaming for token in gguf_app.model(prompt, stream=true, max_tokens=512): print(token["choices"][0]["text"]) # or use the backend directly response = gguf_app.model.generate(prompt, max_tokens=512, temperature=0.7)modelisnoneuntil the user loads a model β always check, and subscribe tomodel_loadedto react.π§© widget vs. background addons
- return a widget from
register()β appears in the addons menu, opens in a dialog. - return
none(or also keep your own top-level windows) β runs in the background. the floating chat addon returns a small status widget but drives its own always-on-top windows.
π‘ best practices
- guard everything β wrap registration in
try/exceptand log failures; a broken addon must never crash the app. - clean up state β if you keep references on the main window (e.g.
gguf_app._my_addon = ...), stop them on app close (mainwindow.closeeventstops_floating_chat_addonβ follow that pattern). - use qsettings for persistence β
qsettings("ggufloader", "youraddon"). - prefer signals β let your widgets emit signals; donβt reach into other widgetsβ internals.
- qt-free logic β if you have non-ui logic (parsing, computation), put it in a module with no qt imports so itβs unit-testable.
β debugging
addon load errors print to the console with a traceback (
failed to load addon <name>: ...). run the app from a terminal to see them:python main.pyπ next steps
- addon api reference β every hook and member
- floating chat example β full walkthrough of the built-in addon
related documentation
addon api reference
complete api reference for developing gguf loader addons
advanced 20 minutescomplete reference for the hooks, signals, and objects available to gguf loader addons.
πͺ addon contract
an addon is a folder under
addons/with an__init__.pyexposing:register(parent=none) -> qwidget | nonecalled by
addonmanagerwhen the addon loads. returns an optional widget shown in the addons menu (opened in a non-modal dialog), ornonefor background-only addons.parameters β
parent: the widget the addon is being attached to (may be the main window, a dialog, or another widget).return β a widget, or
none.def register(parent=none): return qlabel("my addon") # widget addonπ₯οΈ main window api
addons receive a reference to the main window (via
parentor by scanningqapplication.instance().toplevelwidgets()). it exposes:properties
| member | type | description | |β|β|β| |
model|modelbackend \| none| the loaded model backend; callable.noneuntil a model is loaded. | |chat_generator|none| legacy hook; alwaysnone. addons should callmodelinstead. | |addon_manager|addonmanager| the addon manager instance. | |_floating_chat_addon|floatingchataddon \| none| the built-in floating chat addon (if running). |signals
| signal | signature | description | |β|β|β| |
model_loaded|signal(object)| emitted with themodelbackendafter a model loads. | |model_unloaded|signal()| emitted after the model is released. | |generation_finished|signal()| emitted when a chat generation completes. | |generation_error|signal(str)| emitted with an error message when generation fails. | |theme_changed|signal(bool)| emitted when dark mode toggles (true= dark). |gguf_app.model_loaded.connect(self._on_model_loaded) gguf_app.generation_finished.connect(self._on_finished)π§ modelbackend
gguf_app.modelis acore.llm.model_backend.modelbackend. it is callable and thread-safe (all access serialized through a lock).calling convention
# raw llama-cpp shape (addon-compatible) result = gguf_app.model(prompt, stream=false, max_tokens=512, temperature=0.7) text = result["choices"][0]["text"] # streaming for token_data in gguf_app.model(prompt, stream=true, max_tokens=512): text = token_data["choices"][0]["text"]methods & attributes
| member | description | |β|β| |
model_path| path of the loaded gguf file. | |use_gpu| whether gpu acceleration is active. | |n_ctx| context length. | |is_loaded|trueonce the runtime exists. | |load()| create the underlyingllamaruntime (raises on failure). | |unload()| release the model and free memory. | |generate(prompt, **kwargs)| complete non-streamed response string. | |generate_stream(prompt, **kwargs)| iterator of token strings. | |__call__(prompt, **kwargs)| llama-cpp-compatible callable (stream returns token-dict generator). |kwargs are passed straight to llama_cpp:
max_tokens,temperature,top_p,top_k,repeat_penalty,stop, etc.π§° agent tools (for agent-capable addons)
the agent engine (
core/agent/) exposes sandboxed tools throughtoolregistry. tools are not qt-bound and are safe to call from any thread.tool params result list_directorypath(default.){status, result: [{name, type, size}]}read_filepath,max_size,encoding{status, result: content, lines, encoding}write_filepath,content{status, path, bytes_written}edit_filepath,operation(replace/insert_line/delete_line),find,replace,line_number,content{status, operation, changes_made}search_filespattern/query,path{status, result: [paths], total_matches}every tool result includes
status("success"/"error") andtool_name. all paths are sandboxed to the workspace β escaping paths raise.from core.agent.tool_registry import create_default_registry registry = create_default_registry("./workspace") result = registry.execute("list_directory", {"path": "."})π§© addonmanager
method description scan_addons(){name: path}of addons with__init__.py.load_addon(name, path)import + validate register;true/false.load_all_addons()load all; {name: success}.get_addon_widget(name, parent)widget from register(parent).open_addon_dialog(name, parent)show addon in a non-modal dialog. get_loaded_addons()list of successfully loaded names. πΎ persistence
use qtβs
qsettingswith a scoped org/app key to avoid collisions:from pyside6.qtcore import qsettings settings = qsettings("ggufloader", "myaddon") settings.setvalue("position", point) pos = settings.value("position", qpoint(100, 100))β‘ lifecycle
register()is called at startup and on addons β refresh addons.- the main windowβs
closeeventstops the floating chat addon; follow that pattern to stop your own background objects:if hasattr(gguf_app, '_my_addon') and gguf_app._my_addon: gguf_app._my_addon.stop()
π see also
- addon development guide β tutorial
- floating chat example β full real-world addon
related documentation
- gguf loader's addon system lets you extend the app without touching its source. addons are python packages dropped into the `addons/` folder; the app discovers, loads, and manages them automatically.
## π¦ what an addon looks like
```
addons/
βββ my_addon/
βββ __init__.py # must expose register()
βββ main.py # your logic (any structure you like)
βββ ... # widgets, resources, etc.
```
### minimum viable addon
```python
# addons/my_addon/__init__.py
from pyside6.qtwidgets import qlabel
def register(parent=none):
"""called by gguf loader when the addon loads."""
return qlabel("hello from my addon!")
```
that's it β drop the folder in `addons/`, restart (or **addons β refresh addons**), and your widget appears in the **addons** menu.
## π how loading works
`addonmanager` (`addon_manager.py`):
1. `scan_addons()` β lists subdirectories of the addons folder that contain `__init__.py`.
2. `load_addon(name, path)` β dynamically imports the module (`importlib.util.spec_from_file_location`) and requires a `register` attribute.
3. `load_all_addons()` β loads every addon and records success/failure in the console log.
4. `get_addon_widget(name, parent)` β calls `register(parent)` and returns the widget.
5. `open_addon_dialog(name, parent)` β shows the addon widget in a non-modal dialog from the addons menu.
the main window calls `get_addon_widget` for each loaded addon at startup, so `register()` runs even before the user opens the menu β this is how background addons (like the floating chat button) start automatically.
## π‘ talking to the app
your `register(parent)` receives the parent widget. the **main window** exposes an addon-facing api (see the [addon api reference](/docs/addon-api/)). the robust pattern used by the built-in addon:
```python
def register(parent=none):
gguf_app = none
# 1. parent might already be the main window
if parent and hasattr(parent, 'model') and hasattr(parent, 'model_loaded'):
gguf_app = parent
else:
# 2. walk up the parent chain
current = parent
while current is not none:
if hasattr(current, 'model') and hasattr(current, 'model_loaded'):
gguf_app = current
break
current = current.parent()
# 3. fall back to scanning top-level widgets
if gguf_app is none:
app = qapplication.instance()
for widget in app.toplevelwidgets():
if hasattr(widget, 'model') and hasattr(widget, 'model_loaded'):
gguf_app = widget
break
...
```
key api members: `model` (callable backend), `model_loaded` / `model_unloaded` / `generation_finished` / `generation_error` signals, `addon_manager`, and `_floating_chat_addon`.
## π€ calling the model
```python
# streaming
for token in gguf_app.model(prompt, stream=true, max_tokens=512):
print(token["choices"][0]["text"])
# or use the backend directly
response = gguf_app.model.generate(prompt, max_tokens=512, temperature=0.7)
```
`model` is `none` until the user loads a model β always check, and subscribe to `model_loaded` to react.
## π§© widget vs. background addons
- **return a widget** from `register()` β appears in the addons menu, opens in a dialog.
- **return `none`** (or also keep your own top-level windows) β runs in the background. the floating chat addon returns a small status widget but drives its own always-on-top windows.
## π‘ best practices
1. **guard everything** β wrap registration in `try/except` and log failures; a broken addon must never crash the app.
2. **clean up state** β if you keep references on the main window (e.g. `gguf_app._my_addon = ...`), stop them on app close (`mainwindow.closeevent` stops `_floating_chat_addon` β follow that pattern).
3. **use qsettings for persistence** β `qsettings("ggufloader", "youraddon")`.
4. **prefer signals** β let your widgets emit signals; don't reach into other widgets' internals.
5. **qt-free logic** β if you have non-ui logic (parsing, computation), put it in a module with no qt imports so it's unit-testable.
## β
debugging
addon load errors print to the console with a traceback (`failed to load addon
: ...`). run the app from a terminal to see them: ```bash python main.py ``` ## π next steps - [addon api reference](/docs/addon-api/) β every hook and member - [floating chat example](/docs/floating-chat-example/) β full walkthrough of the built-in addon - this page walks through **floating_chat**, gguf loader's built-in addon β a facebook messenger-style floating button that opens a chat window connected to the loaded model. it's the best real-world reference for writing a background addon with its own windows. ``` addons/floating_chat/ βββ __init__.py # exposes register() βββ main.py # floatingchataddon (qobject) + register() βββ floating_button.py # floatingchatbutton - draggable always-on-top button βββ chat_window.py # floatingchatwindow - the chat ui βββ status_widget.py # small sidebar widget returned by register() ``` ## π§ the design the addon is a `qobject` (`floatingchataddon`) that owns two windows: - **`floatingchatbutton`** β a frameless, always-on-top tool window that can be dragged anywhere and remembers its position via `qsettings`. - **`floatingchatwindow`** β a regular top-level window (`400Γ600`) positioned next to the button, with a message list, streaming replies, and copy all / clear buttons. ## πͺ registration `__init__.py` simply re-exports `register`: ```python from .main import register __all__ = ['register'] ``` `register()` finds the main window (parent β parent chain β `toplevelwidgets()` scan), stops any previous instance, starts the addon, and returns a **status widget** for the sidebar: ```python def register(parent=none): gguf_app = _find_main_window(parent) # model + model_loaded check if gguf_app is none: return none if getattr(gguf_app, '_floating_chat_addon', none): gguf_app._floating_chat_addon.stop() addon = floatingchataddon(gguf_app) if addon.start(): gguf_app._floating_chat_addon = addon return floatingchatstatuswidget(addon) return none ``` the returned `floatingchatstatuswidget` shows up in the **addons** menu, and because `register()` runs at startup, the button appears automatically β no user action needed. ## π‘ connecting to the app `floatingchataddon.__init__` subscribes to model lifecycle signals: ```python if hasattr(self.gguf_app, 'model_loaded'): self.gguf_app.model_loaded.connect(self._on_model_loaded) if hasattr(self.gguf_app, 'generation_finished'): self.gguf_app.generation_finished.connect(self._on_generation_finished) if hasattr(self.gguf_app, 'generation_error'): self.gguf_app.generation_error.connect(self._on_generation_error) ``` `_on_model_loaded` flips the chat window's status to **π’ model: ready**; generation events update the streaming bubble / error state. ## π lifecycle: start() / stop() ```python def start(self): self._floating_button = floatingchatbutton() self._floating_button.clicked.connect(self._on_button_clicked) self._load_button_position() # qsettings restore, clamped to screen self._floating_button.show() self.addon_started.emit() return true def stop(self): self._save_button_position() # persist for next session if self._chat_window: self._chat_window.close() if self._floating_button: self._floating_button.close() self.addon_stopped.emit() ``` `stop()` is idempotent and called on app close via `mainwindow.closeevent`, so there's never a dangling button. ## π±οΈ button click β window toggle the click handler distinguishes three states (a minimized window is "visible" to qt but off-screen, so it must be restored, not hidden): ```python def _on_button_clicked(self): chat = self._chat_window if chat and chat.isvisible(): if chat.isminimized(): chat.shownormal(); chat.raise_(); chat.activatewindow() else: chat.hide() else: self._show_chat_window() ``` `_show_chat_window` creates the window lazily, positions it next to the button (flipping to the left / up when it would overflow the screen's **available geometry**, which excludes taskbars and docks), then `shownormal()` + `raise_()` + `activatewindow()`. ## πͺ window flags (the platform subtleties) ```python flags = (qt.windowtype.framelesswindowhint | qt.windowtype.windowstaysontophint | qt.windowtype.x11bypasswindowmanagerhint) # linux/x11 if sys.platform != "darwin": flags |= qt.windowtype.tool # keeps it out of the taskbar ``` - **windows/linux**: `tool` keeps the button out of the taskbar. `x11bypasswindowmanagerhint` gives true always-on-top under x11. - **macos**: the `tool` flag would turn the button into a utility window that **auto-hides when the app loses focus** β so it's deliberately dropped. trade-off: the button appears in mission control. - **wayland**: compositors don't allow floating above *other* apps' windows; the button is confined to the app window (documented, and x11 is recommended for the full experience). the chat window drops the minimize button entirely β a minimized companion window is a trap state that can't be reliably restored. ## π resiliancy touches - `changeevent` bounces the button straight back to normal if a system shortcut (e.g. win+d) minimizes *every* window including the tool: ```python if event.type() == qevent.type.windowstatechange and self.isminimized(): qtimer.singleshot(0, self.shownormal) ``` - dragging clamps to `screen.availablegeometry()` (not `(0,0)`), so the button can't slide under the macos menu bar or a windows taskbar. - saved positions are clamped the same way on restore. ## π§© what you can reuse - the **window-finding pattern** in `register()` β works for any addon. - the **qsettings position persistence** with on-screen clamping. - the **platform-conditional window flags** β copy it for any always-on-top addon window. - the **show/hide/restore toggle** logic. ## π see also - [addon development guide](/docs/addon-development/) - [addon api reference](/docs/addon-api/)
- this page documents how the gguf loader codebase is organized. the app is a pyside6 desktop application; a single `main.py` bootstraps everything, and logic is split into `core/` (pure logic), `services/` (qt threading bridges), and `ui/` + `widgets/` (presentation). ## ποΈ top-level layout ``` gguf-loader/ βββ main.py # entry point: logging, dll paths, qapplication, mainwindow βββ config.py # central configuration constants βββ resource_manager.py # resource/path discovery (dev, package, or frozen) βββ addon_manager.py # loads and manages addons βββ requirements.txt # python dependencies βββ build_exe.spec # pyinstaller spec used for windows & linux builds β βββ core/ # pure, testable logic (no qt) β βββ llm/ β β βββ model_backend.py # thread-safe llama-cpp-python wrapper β β βββ prompt_builder.py # system-prompt & conversation assembly β βββ agent/ β βββ agent_engine.py # tool-use agent loop (no qt, no llama_cpp) β βββ tool_registry.py # sandboxed workspace tools β βββ services/ # qobject bridges that run work on threads β βββ model_service.py # load/unload models on a qthread β βββ chat_service.py # streaming generation on a qthread β βββ agent_service.py # runs agentengine on a worker thread β βββ environment_service.py # venv/dependency checks & pip tasks β βββ launcher_service.py # launches scripts/ utilities β βββ ui/ # main window & panels β βββ main_window.py # composition root + addon-facing api β βββ chat_panel.py # chat display, input, agent controls β βββ sidebar_panel.py # model settings sidebar β βββ theme.py # dark/light qss token system β βββ widgets/ # reusable widgets β βββ chat_bubble.py # chatgpt-style bubble β βββ feedback_dialog.py # feedback form dialog β βββ addons/ # addon packages (each has __init__.py with register()) β βββ floating_chat/ # built-in floating chat addon β βββ scripts/ # utility & release scripts β βββ capture_screenshots.py # regenerates readme/site screenshots β βββ install_linux.sh # linux installer/uninstaller β βββ package_linux.sh # builds the linux .tar.gz release β βββ ... # gpu install/monitor helpers β βββ build_hooks/ # pyinstaller hook modules ``` ## π key design rules - **`core/` never imports qt or llama_cpp.** it receives plain callables, so it can be unit-tested in isolation. - **`services/` are the only place qt threads are created.** ui never spins up threads directly. - **`ui/` widgets are "dumb"** β they render state and emit signals; `mainwindow` owns all logic. - **`resource_manager.py`** makes paths work identically in dev, as an installed package, and in a pyinstaller bundle (`sys._meipass`). ## π§΅ threading model ``` ui thread (mainwindow) worker thread β β βββ modelservice.load() βββββββ qthread: llama_cpp loads model ββββββββ loaded(modelbackend) β βββ chatservice.generate() ββββ qthread: streams tokens ββββββββ token_received(text) β βββ agentservice.process() ββββ qthread: agentengine tool loop ββββββββ status/tool/response β ``` a fresh `qthread` + worker is created per request (the professional qt pattern β `qthread` is never subclassed). ## π entry point flow `main.py` β `setup_library_path()` (finds bundled llama.cpp libs) β `qapplication` β `mainwindow()` β builds ui, wires services, checks environment, loads addons β `app.exec()`. ## π¦ packaging - **windows**: `build_exe.bat` / `build_exe.spec` β `ggufloader_vx.y.z.exe` - **linux**: build the spec inside a linux environment, then `scripts/package_linux.sh` wraps the binary + installer + icon into a `.tar.gz` - github actions publishes both to every release automatically. see the [architecture overview](/docs/architecture/) for deeper design rationale.
π related features
π― what's next?
you've completed this guide! here are some suggested next steps to continue your gguf loader journey:
πshare your addon
built something awesome? share it with the community and get featured on our homepage.
share with community βππ€π explore more features
π back to homepage
- this page walks through **floating_chat**, gguf loader's built-in addon β a facebook messenger-style floating button that opens a chat window connected to the loaded model. it's the best real-world reference for writing a background addon with its own windows. ``` addons/floating_chat/ βββ __init__.py # exposes register() βββ main.py # floatingchataddon (qobject) + register() βββ floating_button.py # floatingchatbutton - draggable always-on-top button βββ chat_window.py # floatingchatwindow - the chat ui βββ status_widget.py # small sidebar widget returned by register() ``` ## π§ the design the addon is a `qobject` (`floatingchataddon`) that owns two windows: - **`floatingchatbutton`** β a frameless, always-on-top tool window that can be dragged anywhere and remembers its position via `qsettings`. - **`floatingchatwindow`** β a regular top-level window (`400Γ600`) positioned next to the button, with a message list, streaming replies, and copy all / clear buttons. ## πͺ registration `__init__.py` simply re-exports `register`: ```python from .main import register __all__ = ['register'] ``` `register()` finds the main window (parent β parent chain β `toplevelwidgets()` scan), stops any previous instance, starts the addon, and returns a **status widget** for the sidebar: ```python def register(parent=none): gguf_app = _find_main_window(parent) # model + model_loaded check if gguf_app is none: return none if getattr(gguf_app, '_floating_chat_addon', none): gguf_app._floating_chat_addon.stop() addon = floatingchataddon(gguf_app) if addon.start(): gguf_app._floating_chat_addon = addon return floatingchatstatuswidget(addon) return none ``` the returned `floatingchatstatuswidget` shows up in the **addons** menu, and because `register()` runs at startup, the button appears automatically β no user action needed. ## π‘ connecting to the app `floatingchataddon.__init__` subscribes to model lifecycle signals: ```python if hasattr(self.gguf_app, 'model_loaded'): self.gguf_app.model_loaded.connect(self._on_model_loaded) if hasattr(self.gguf_app, 'generation_finished'): self.gguf_app.generation_finished.connect(self._on_generation_finished) if hasattr(self.gguf_app, 'generation_error'): self.gguf_app.generation_error.connect(self._on_generation_error) ``` `_on_model_loaded` flips the chat window's status to **π’ model: ready**; generation events update the streaming bubble / error state. ## π lifecycle: start() / stop() ```python def start(self): self._floating_button = floatingchatbutton() self._floating_button.clicked.connect(self._on_button_clicked) self._load_button_position() # qsettings restore, clamped to screen self._floating_button.show() self.addon_started.emit() return true def stop(self): self._save_button_position() # persist for next session if self._chat_window: self._chat_window.close() if self._floating_button: self._floating_button.close() self.addon_stopped.emit() ``` `stop()` is idempotent and called on app close via `mainwindow.closeevent`, so there's never a dangling button. ## π±οΈ button click β window toggle the click handler distinguishes three states (a minimized window is "visible" to qt but off-screen, so it must be restored, not hidden): ```python def _on_button_clicked(self): chat = self._chat_window if chat and chat.isvisible(): if chat.isminimized(): chat.shownormal(); chat.raise_(); chat.activatewindow() else: chat.hide() else: self._show_chat_window() ``` `_show_chat_window` creates the window lazily, positions it next to the button (flipping to the left / up when it would overflow the screen's **available geometry**, which excludes taskbars and docks), then `shownormal()` + `raise_()` + `activatewindow()`. ## πͺ window flags (the platform subtleties) ```python flags = (qt.windowtype.framelesswindowhint | qt.windowtype.windowstaysontophint | qt.windowtype.x11bypasswindowmanagerhint) # linux/x11 if sys.platform != "darwin": flags |= qt.windowtype.tool # keeps it out of the taskbar ``` - **windows/linux**: `tool` keeps the button out of the taskbar. `x11bypasswindowmanagerhint` gives true always-on-top under x11. - **macos**: the `tool` flag would turn the button into a utility window that **auto-hides when the app loses focus** β so it's deliberately dropped. trade-off: the button appears in mission control. - **wayland**: compositors don't allow floating above *other* apps' windows; the button is confined to the app window (documented, and x11 is recommended for the full experience). the chat window drops the minimize button entirely β a minimized companion window is a trap state that can't be reliably restored. ## π resiliancy touches - `changeevent` bounces the button straight back to normal if a system shortcut (e.g. win+d) minimizes *every* window including the tool: ```python if event.type() == qevent.type.windowstatechange and self.isminimized(): qtimer.singleshot(0, self.shownormal) ``` - dragging clamps to `screen.availablegeometry()` (not `(0,0)`), so the button can't slide under the macos menu bar or a windows taskbar. - saved positions are clamped the same way on restore. ## π§© what you can reuse - the **window-finding pattern** in `register()` β works for any addon. - the **qsettings position persistence** with on-screen clamping. - the **platform-conditional window flags** β copy it for any always-on-top addon window. - the **show/hide/restore toggle** logic. ## π see also - [addon development guide](/docs/addon-development/) - [addon api reference](/docs/addon-api/)
- this page documents how the gguf loader codebase is organized. the app is a pyside6 desktop application; a single `main.py` bootstraps everything, and logic is split into `core/` (pure logic), `services/` (qt threading bridges), and `ui/` + `widgets/` (presentation). ## ποΈ top-level layout ``` gguf-loader/ βββ main.py # entry point: logging, dll paths, qapplication, mainwindow βββ config.py # central configuration constants βββ resource_manager.py # resource/path discovery (dev, package, or frozen) βββ addon_manager.py # loads and manages addons βββ requirements.txt # python dependencies βββ build_exe.spec # pyinstaller spec used for windows & linux builds β βββ core/ # pure, testable logic (no qt) β βββ llm/ β β βββ model_backend.py # thread-safe llama-cpp-python wrapper β β βββ prompt_builder.py # system-prompt & conversation assembly β βββ agent/ β βββ agent_engine.py # tool-use agent loop (no qt, no llama_cpp) β βββ tool_registry.py # sandboxed workspace tools β βββ services/ # qobject bridges that run work on threads β βββ model_service.py # load/unload models on a qthread β βββ chat_service.py # streaming generation on a qthread β βββ agent_service.py # runs agentengine on a worker thread β βββ environment_service.py # venv/dependency checks & pip tasks β βββ launcher_service.py # launches scripts/ utilities β βββ ui/ # main window & panels β βββ main_window.py # composition root + addon-facing api β βββ chat_panel.py # chat display, input, agent controls β βββ sidebar_panel.py # model settings sidebar β βββ theme.py # dark/light qss token system β βββ widgets/ # reusable widgets β βββ chat_bubble.py # chatgpt-style bubble β βββ feedback_dialog.py # feedback form dialog β βββ addons/ # addon packages (each has __init__.py with register()) β βββ floating_chat/ # built-in floating chat addon β βββ scripts/ # utility & release scripts β βββ capture_screenshots.py # regenerates readme/site screenshots β βββ install_linux.sh # linux installer/uninstaller β βββ package_linux.sh # builds the linux .tar.gz release β βββ ... # gpu install/monitor helpers β βββ build_hooks/ # pyinstaller hook modules ``` ## π key design rules - **`core/` never imports qt or llama_cpp.** it receives plain callables, so it can be unit-tested in isolation. - **`services/` are the only place qt threads are created.** ui never spins up threads directly. - **`ui/` widgets are "dumb"** β they render state and emit signals; `mainwindow` owns all logic. - **`resource_manager.py`** makes paths work identically in dev, as an installed package, and in a pyinstaller bundle (`sys._meipass`). ## π§΅ threading model ``` ui thread (mainwindow) worker thread β β βββ modelservice.load() βββββββ qthread: llama_cpp loads model ββββββββ loaded(modelbackend) β βββ chatservice.generate() ββββ qthread: streams tokens ββββββββ token_received(text) β βββ agentservice.process() ββββ qthread: agentengine tool loop ββββββββ status/tool/response β ``` a fresh `qthread` + worker is created per request (the professional qt pattern β `qthread` is never subclassed). ## π entry point flow `main.py` β `setup_library_path()` (finds bundled llama.cpp libs) β `qapplication` β `mainwindow()` β builds ui, wires services, checks environment, loads addons β `app.exec()`. ## π¦ packaging - **windows**: `build_exe.bat` / `build_exe.spec` β `ggufloader_vx.y.z.exe` - **linux**: build the spec inside a linux environment, then `scripts/package_linux.sh` wraps the binary + installer + icon into a `.tar.gz` - github actions publishes both to every release automatically. see the [architecture overview](/docs/architecture/) for deeper design rationale.
π related features
π― what's next?
you've completed this guide! here are some suggested next steps to continue your gguf loader journey:
πshare your addon
built something awesome? share it with the community and get featured on our homepage.
share with community βππ€π explore more features
π back to homepage
π related features
π― what's next?
you've completed this guide! here are some suggested next steps to continue your gguf loader journey:
π οΈcreate your first addon
ready to extend gguf loader? learn how to create custom addons with our development guide.
addon development βπ₯join the community
connect with other gguf loader users, share your projects, and get help.
community hub βπadvanced tutorials
take your skills to the next level with advanced how-to guides and tutorials.
how-to guides βπ explore more features
π back to homepage
π related features
π― what's next?
you've completed this guide! here are some suggested next steps to continue your gguf loader journey:
πexplore homepage
discover more features, download options, and community resources on our homepage.
visit homepage βπmore documentation
continue learning with our comprehensive documentation library.
all documentation βπ¬π explore more features
π back to homepage
π Related Features
π― What's Next?
You've completed this guide! Here are some suggested next steps to continue your GGUF Loader journey:
Explore Homepage
Discover more features, download options, and community resources on our homepage.
Visit Homepage βMore Documentation
Continue learning with our comprehensive documentation library.
All Documentation β