From 325a6a7c12832d8b9fb9b67567e8a1c496dc1330 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Fri, 31 Jul 2026 10:35:56 +0200 Subject: feat: initial release of llamachat 0.1.0 A native PySide6 chat client for a local llama.cpp server in router mode. Runs as a single persistent process with a Unix-socket control channel, so a Hyprland keybind toggles the window with a socket round trip rather than a process start. The control commands do not import Qt and answer in under a tenth of a second. Features: one-shot and multi-turn chat modes, runtime model discovery from /v1/models, streaming replies rendered as markdown, collapsible reasoning for models with a thinking budget, drag-and-drop file and image attachment with context-aware truncation, and SQLite history with FTS5 search. Markdown is parsed with MarkdownNoHTML so markup in a reply is displayed rather than interpreted, and links a reply produces cannot drive the interface. Includes the Hyprland Lua snippets for autostart, keybind and window rules, and a self-check suite covering everything except the GUI. Co-Authored-By: Claude Opus 5 --- llamachat.py | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100755 llamachat.py (limited to 'llamachat.py') diff --git a/llamachat.py b/llamachat.py new file mode 100755 index 0000000..55214c2 --- /dev/null +++ b/llamachat.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0-only +# +# llamachat - a small native chat client for a local llama.cpp router +# Copyright (C) 2026 Danilo M. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +"""Launcher. Symlink this into a directory on your PATH. + +PySide6 usually lives in a virtualenv rather than the system Python, so this +re-executes itself with the venv interpreter when it finds one. Set +LLAMACHAT_PYTHON to point at a specific interpreter, otherwise the venv +beside the checkout and the default location are tried in turn. +""" + +import sys +from pathlib import Path + +# Resolve through the symlink so the package is found next to the real file. +HERE = Path(__file__).resolve().parent +sys.path.insert(0, str(HERE)) + +import llamachat_venv # noqa: E402 + +# The control commands do not need Qt, so only pay for the handover when a +# command that builds a window is about to run. +_NO_QT = {"--toggle", "--show", "--hide", "--ping", "--quit", "--version", + "--help", "-h"} +if not _NO_QT & set(sys.argv[1:]): + llamachat_venv.reexec(__file__) + +from llamachat.__main__ import main # noqa: E402 + +if __name__ == "__main__": + sys.exit(main()) -- cgit v1.2.3