{"id":50876769,"url":"https://github.com/gellsmore-svg/hoglah","last_synced_at":"2026-06-15T11:00:25.230Z","repository":{"id":364412003,"uuid":"1267593278","full_name":"gellsmore-svg/hoglah","owner":"gellsmore-svg","description":"Lightweight, local-first job queue manager and Ollama wrapper for resource-constrained environments.","archived":false,"fork":false,"pushed_at":"2026-06-12T22:31:46.000Z","size":70,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-13T00:20:29.394Z","etag":null,"topics":["agentic","asyncio","background-tasks","job-queue","llm","local-first","ollama","python"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gellsmore-svg.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-12T17:24:11.000Z","updated_at":"2026-06-12T22:31:50.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/gellsmore-svg/hoglah","commit_stats":null,"previous_names":["gellsmore-svg/hoglah"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/gellsmore-svg/hoglah","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gellsmore-svg%2Fhoglah","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gellsmore-svg%2Fhoglah/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gellsmore-svg%2Fhoglah/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gellsmore-svg%2Fhoglah/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gellsmore-svg","download_url":"https://codeload.github.com/gellsmore-svg/hoglah/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gellsmore-svg%2Fhoglah/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34357285,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-15T02:00:07.085Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agentic","asyncio","background-tasks","job-queue","llm","local-first","ollama","python"],"created_at":"2026-06-15T11:00:17.390Z","updated_at":"2026-06-15T11:00:25.221Z","avatar_url":"https://github.com/gellsmore-svg.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Hoglah\n\n**Hoglah** is a lightweight, local-first job queue manager and Ollama wrapper designed for resource-constrained environments.\n\nIt lets applications submit LLM inference requests (generate or chat) asynchronously, receive a job ID immediately, monitor progress, retrieve full results, and receive completion callbacks — even when the underlying hardware can only run one (or very few) model inferences at a time.\n\nNamed after one of the daughters of Zelophehad (Numbers 26/27/36, Joshua 17), continuing the Old Testament women's names pattern used by sister projects in the domains family (Mahalath, Tirzah, etc.).\n\n## Core Value Proposition\n\n- Simple Python-native interface for internal/library use\n- Reliable queuing with durable persistence (survives restarts)\n- Smart handling of context windows and model capabilities\n- Fire-and-forget + callback patterns for workflow orchestration\n- Fully local, privacy-focused, zero-cloud dependency\n- Extensible foundation (web API / webhooks / distributed backends planned for later versions)\n\n**Target users**: Developers building multi-agent systems, background task processors, or local AI tooling that needs to safely queue and manage LLM calls.\n\n## Goals (V1)\n\n- Clean, reliable abstraction over Ollama for queuing\n- Configurable concurrency (default: 1 for low-resource setups)\n- Model discovery, context calibration, and basic resource awareness\n- Easy integration into existing Python applications\n- Persistent job state across process restarts\n- Keep V1 simple, focused, and production-ready for local use\n\n## Non-Goals (V1)\n\n- Full distributed orchestration or high-availability clustering\n- Built-in web UI (deferred to V2)\n- Advanced authentication / multi-tenancy\n- Non-Ollama backends\n- Real-time streaming UI surfaces (file + callback sufficient)\n\n## Installation\n\n### From PyPI (recommended)\n```bash\npip install hoglah\n# With the CLI\npip install \"hoglah[cli]\"\n# With the MongoDB backend (optional — adds pymongo)\npip install \"hoglah[mongo]\"\n```\nHoglah is published on PyPI: https://pypi.org/project/hoglah/\n\n### From GitHub Releases (no PyPI needed)\nEvery `vX.Y.Z` tag publishes a GitHub Release with a wheel + sdist:\n\n```bash\n# Latest wheel\npip install \"hoglah[cli] @ https://github.com/gellsmore-svg/hoglah/releases/latest/download/hoglah-0.2.2-py3-none-any.whl\"\n\n# Or a specific version\npip install \"hoglah[cli] @ https://github.com/gellsmore-svg/hoglah/releases/download/v0.2.2/hoglah-0.2.2-py3-none-any.whl\"\n```\n\n### From source (for development)\n```bash\ngit clone https://github.com/gellsmore-svg/hoglah\ncd hoglah\npython -m venv .venv\n.venv/bin/pip install -e \".[dev,cli]\"\n```\n\n### Maintainers: releasing\n\nReleases are automated. Pushing a `vX.Y.Z` tag runs `.github/workflows/release.yml`,\nwhich builds the wheel + sdist, creates the GitHub Release, and publishes to PyPI\nvia OIDC trusted publishing (no API token stored). PyPI trusted publishing is\nalready configured for this repo (publisher: `gellsmore-svg/hoglah`, workflow\n`release.yml`, no environment). So a release is just:\n\n```bash\n# bump version in pyproject.toml + update CHANGELOG, commit, then:\ngit tag vX.Y.Z \u0026\u0026 git push origin vX.Y.Z\n```\n\n## Quick Start (Planned)\n\nOnce implemented:\n\n```bash\ngit clone https://github.com/gellsmore-svg/hoglah\ncd hoglah\npython -m venv .venv \u0026\u0026 .venv/bin/pip install -e \".[dev,cli]\"\n```\n\n```python\nfrom hoglah import Hoglah\n\nh = Hoglah()  # or Hoglah(config_path=\"...\")\n\njob_id = h.submit(\n    prompt=\"Explain the significance of Hoglah in the biblical land allotment.\",\n    model=\"gemma3:1b\",\n    tags=[\"research\", \"bible\"],\n    callback=lambda result: print(\"Done:\", result.job_id, result.output[:100]),\n)\n\nprint(\"Submitted:\", job_id)\nprint(h.status(job_id))\n\nresult = h.wait(job_id, timeout=120)\nprint(result.output)\n\n# Recommended: context manager for auto cleanup of the background worker\nwith Hoglah() as h:\n    job_id = h.submit(prompt=\"...\", model=\"gemma3:1b\")\n    print(h.wait(job_id).output)\n```\n\nCLI:\n\n```bash\nhoglah submit \"Explain Hoglah\" --model gemma3:1b --wait\nhoglah list --status completed\nhoglah ps --json                 # alias for list, machine-readable\nhoglah stats --json              # queue overview (counts by status)\nhoglah info --json               # config + adapter + log_level + stats snapshot\nhoglah show gemma3:1b --json     # model details (context, template, etc.)\nhoglah clear --status completed --older-than 7 --yes  # prune old jobs\nhoglah rm \u003cjob-id\u003e --yes  # remove specific job\nhoglah wait \u003cjob-id\u003e --timeout 60 --json  # block until done, machine readable\nhoglah doctor --real  # diagnose setup and real Ollama/llama.cpp connectivity\nhoglah status \u003cjob-id\u003e --json\n```\n\n## Backends\n\nHoglah stores jobs through a pluggable `JobStore`. Two are built in; the default\nneeds no setup.\n\n### SQLite (default)\n\nA single file (`~/.hoglah/hoglah.db` by default), zero extra dependencies. Best\nfor one machine. The store uses write-ahead logging + a busy timeout so a\nsubmitter and the worker can share the file without \"database is locked\" errors.\n\n```python\nh = Hoglah()  # SQLite at ~/.hoglah/hoglah.db\nh = Hoglah(config={\"db_path\": \"/data/queue.db\"})\n```\n\n### MongoDB (optional)\n\nPoint Hoglah at a MongoDB **server** instead. Install the extra (`pymongo`):\n\n```bash\npip install \"hoglah[mongo]\"\n```\n\n```python\nh = Hoglah(config={\n    \"backend\": \"mongo\",\n    \"mongo_uri\": \"mongodb://localhost:27017\",  # default\n    \"mongo_db\": \"hoglah\",                       # default\n    \"mongo_collection\": \"jobs\",                 # default\n})\n# or via environment:\n#   HOGLAH_BACKEND=mongo HOGLAH_MONGO_URI=mongodb://host:27017\n```\n\nEverything else — `submit`, `wait`, the CLI, callbacks, recovery — works\nidentically. Use Mongo when you want:\n\n- **No single-file lock.** A server has no SQLite file-locking concern, and job\n  claiming is atomic server-side (`find_one_and_update`), so **multiple workers,\n  even on different machines**, can drain one shared queue and still run each job\n  exactly once.\n- **External visibility.** Jobs are stored as native documents (request, result\n  and tags are sub-documents, not opaque JSON blobs), so you can watch the queue\n  live from `mongosh` or Compass:\n\n  ```js\n  use hoglah\n  db.jobs.find({ status: \"queued\" }).sort({ priority: -1, created_at: 1 })\n  db.jobs.aggregate([{ $group: { _id: \"$status\", n: { $sum: 1 } } }])\n  ```\n\n## V1 Scope\n\nHoglah 0.2.1 implements the full V1 specification from `docs/requirements-v1.0.md` and `docs/project-brief.md`.\n\n**Included (V1):**\n- Submit (prompt or messages/chat), immediate UUID.\n- Status, get result (with output, usage, timings, metadata, parent, **truncated** reporting + effective_num_ctx).\n- List (status, tags, **parent_job_id** filters; rich human + --json with preview).\n- Cancel (best-effort).\n- Wait (standalone or via submit --wait).\n- rm / clear (per-job or bulk by status/age).\n- info / stats (config, adapter, queue overview).\n- Models: list + show (details, context size, template, family).\n- pull (auto on real submit, or explicit).\n- run (foreground worker).\n- In-process callbacks (direct + named registry for restart re-delivery).\n- Restart recovery (interrupted jobs + callback re-delivery).\n- Pluggable adapters (safe Stub default + real Ollama with auto-pull, model-aware context, truncation via done_reason).\n- Configurable concurrency (default 1), log_level, db, ollama host.\n- Full submit surface (temperature, top_p/k, num_ctx, format, keep_alive, metadata, parent, etc.).\n- Persistence (SQLite), context manager, --json everywhere.\n\n**Explicitly not in V1 (per non-goals):**\n- Web UI / HTTP server (V2).\n- Webhooks / callback_url.\n- Distributed / multi-node.\n- Non-Ollama backends.\n- Complex dependency graph execution (parent_job_id is for traceability only; no automatic waiting/fan-out).\n- Real-time streaming UI (polling wait + final callbacks sufficient).\n\nSee the full requirements review and V1 completeness note in `.restart.md`.\n\nYou can also run the packaged install smoke test after installing the wheel:\n```bash\npython scripts/test_packaged_install.py\n```\n\nTo validate with your working local Ollama (full real adapter paths including show, pull, context auto-detect):\n```bash\nRUN_OLLAMA_TESTS=1 python scripts/test_packaged_install.py\n# or\nHOGLAH_USE_REAL_ADAPTER=1 python scripts/test_packaged_install.py\n```\n\n**Real Ollama / llama.cpp:** Opt-in via `use_real=True` / `HOGLAH_USE_REAL_ADAPTER=1` / `--real`. The \"real\" adapter talks to Ollama (which uses llama.cpp for inference).\n\n**Real-Ollama validation status:** v0.2.2 has been validated end-to-end against a live Ollama (submit → worker → real inference, plus the gated integration test and the packaged-wheel smoke test in real mode). To reproduce on your machine:\n```bash\npython3 -m venv /tmp/hoglah-validate\n/tmp/hoglah-validate/bin/pip install \"hoglah[cli]\"            # from PyPI\nRUN_OLLAMA_TESTS=1 /tmp/hoglah-validate/bin/python scripts/test_packaged_install.py\n\n# Or the gated integration test from a source checkout\nRUN_OLLAMA_TESTS=1 python -m pytest tests/test_worker_execution.py::test_real_ollama_adapter_end_to_end -q -s\n```\n\n**WSL2 note:** if Ollama runs as the Windows binary and your code runs in WSL, the daemon is *not* reachable at `localhost` over HTTP. Set `OLLAMA_HOST=0.0.0.0` on the Windows side (`setx OLLAMA_HOST \"0.0.0.0\"`, then restart Ollama) and point the client at the WSL2 gateway IP, e.g.:\n```bash\nOLLAMA_HOST=\"http://$(ip route show default | awk '{print $3}'):11434\" \\\n  RUN_OLLAMA_TESTS=1 python scripts/test_packaged_install.py\n```\n```bash\nhoglah cancel \u003cjob-id\u003e\nhoglah models\nhoglah run --real                # foreground worker using real Ollama\n```\n\nBy default `hoglah` and `Hoglah()` use the safe stub adapter (no LLM calls). Use `--real` (CLI) or pass `adapter=OllamaAdapter(...)` (library) when you want actual inference.\n\n`hoglah --version` / `-V` and `hoglah version` are supported. Use `with Hoglah(...) as h:` for automatic cleanup.\n\nCLI now also includes `hoglah ps` (list alias) and `--json` output on list/ps/status/models. `hoglah submit` supports `--metadata` (JSON) and `--parent-job-id`. Real integration tests are gated behind `RUN_OLLAMA_TESTS=1`.\n\nSee `docs/requirements-v1.0.md` for the full initial specification.\n\n## Submit API (Initial Draft)\n\n```python\njob_id = hoglah.submit(\n    prompt: str | None = None,                    # or messages for chat\n    messages: list[dict] | None = None,           # OpenAI-style chat history\n    model: str,                                   # e.g. \"gemma:7b\", \"mistral\"\n    system_prompt: str | None = None,\n    num_ctx: int | None = None,                   # Context window size\n    options: dict | None = None,                  # Passthrough for llama.cpp params\n    callback: Callable[[JobResult], None] | None = None,  # Python callable\n    callback_url: str | None = None,              # V2: HTTP webhook\n    tags: list[str] | None = None,\n    priority: int = 0,                            # Higher = earlier\n    timeout_seconds: int | None = None,\n    max_retries: int = 2,\n    metadata: dict | None = None,                 # User-defined data\n    parent_job_id: str | None = None,             # For chaining/dependencies\n    temperature: float | None = None,\n    top_p: float | None = None,\n    top_k: int | None = None,\n    repeat_penalty: float | None = None,\n    seed: int | None = None,                      # Reproducibility\n    stop: list[str] | None = None,                # Stop sequences\n    num_predict: int | None = None,               # Max output tokens\n    format: str | None = None,                    # e.g. \"json\"\n    keep_alive: str | int | None = None,\n    # ... full options dict covers the rest\n)\n```\n\n## Current Status\n\n**2026-06-12 (updated)**: Core implementation complete (Chunks 1-3 + follow-on polish).\n\n- Full durable queue + background asyncio worker (concurrency=1 default)\n- Pluggable adapters: `StubAdapter` (default, safe) + `OllamaAdapter` (real, opt-in via `use_real=True` or `--real`)\n- `Hoglah(use_real=True)` convenience + `HOGLAH_USE_REAL_ADAPTER` env var\n- Submit (prompt **or** messages/chat), rich generation params, status, get, list, cancel, wait, named+direct callbacks\n- Restart recovery (interrupted jobs + callback re-delivery)\n- Truncation metadata always surfaced (never fails the job)\n- CLI: `list`, `status`, `cancel`, `submit` (with --messages, --temperature, --num-ctx etc.), `run`, `models`, `version`\n- `examples/basic_usage.py` demonstrating the common patterns\n- 26 passing tests (+1 gated real-Ollama test that passes against a live server); the default suite needs no Ollama (stub adapter).\n\nSee `docs/requirements-v1.0.md`, `docs/architecture-decisions.md`, and `.restart.md` for history and how to continue.\n\nSee sister domains for style and quality references:\n- [Mahalath](https://github.com/gellsmore-svg/mahalath)\n- [Tirzah](https://github.com/gellsmore-svg/tirzah)\n\n## Architecture Sketch (Early)\n\n- Client library (`Hoglah` or similar) for submit / status / wait / list / cancel\n- SQLite-backed job store (jobs table + results / events)\n- Worker loop (thread or task) with concurrency semaphore\n- Ollama adapter (generate + chat paths, model info)\n- In-process callback dispatch after completion\n- CLI entrypoint for inspection and operations\n- Config via constructor + env + small config file\n\nFull details will evolve in `docs/architecture-decisions.md` and implementation docs.\n\n## License\n\nApache 2.0 — see [LICENSE](LICENSE).\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgellsmore-svg%2Fhoglah","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgellsmore-svg%2Fhoglah","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgellsmore-svg%2Fhoglah/lists"}