Local agent harness: central skill library, Obsidian + SQLite FTS5 memory, background curator — served over MCP.
Project description
OyHub
A local, always-on agent harness that fixes skill sprawl and context exhaustion.
Engineers using AI assistants hit two walls: skills scattered across projects with nothing organized in one place, and context windows that fill up and forget everything between sessions. OyHub is an MCP server you install once on your machine — Claude Desktop, Claude Code, and Cursor connect to it and gain:
- One central skill library with per-project activation. Skills live in
~/.oyhub/skills(agentskills.io-compatibleSKILL.mdformat). Activate a project and only its relevant skills appear — your Kubernetes skills stay out of your React sessions. - Persistent memory that survives any context window. Curated facts go to your Obsidian vault as plain markdown (human-readable, editable, graph-linked). Full conversation history goes to SQLite + FTS5 — full-text searchable recall at zero LLM cost. Instead of context running out, the assistant retrieves the five messages that matter.
- Loop engineering in the background. A curator loop runs on idle: archives stale skills (never deletes — archive is recoverable), dedupes memory entries, pins protect anything you care about, and every action is logged to a
Curator Log.mdnote in your vault so the loop's work stays visible. - Injection-scanned writes. Memory and skills persist into every future session's context, so anything flowing into them is scanned at write time — instruction-override phrasing and credential-exfil link shapes are refused with a reason. Legitimate engineering content (curl commands, env var names) passes.
- Safe under concurrent clients. Multiple assistants can run OyHub against the same state simultaneously: SQLite runs in WAL mode with busy timeouts, and all shared JSON/markdown writes go through file-locked atomic read-modify-write.
- Web dashboard + REST API.
oyhub dashboardserves a local FastAPI app: skill usage stats, memory browser, full-text session search, curator log — plus a JSON API for scripting against your hub. - Observability built in. Every tool call is recorded (tool, latency, status) in the shared SQLite DB; the dashboard exposes a Prometheus
/metricsendpoint, anddocker compose --profile observability upstarts a provisioned Grafana with a ready-made OyHub dashboard (call rates, latencies, error rates). - CI/CD + Docker from day one. GitHub Actions runs lint + tests on a 6-way OS/Python matrix, builds the Docker image, cuts a GitHub release on every version tag, and publishes to PyPI via trusted publishing.
Zero runtime dependencies — Python stdlib only. No API key: the connected assistant is the intelligence; OyHub is the harness.
Install
git clone https://github.com/Asanovichoff/oyhub && cd oyhub
python3 -m oyhub doctor # health check
Set where memory lives (your existing Obsidian vault):
export OYHUB_VAULT=~/Documents/MyVault
Connect Claude Desktop
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"oyhub": {
"command": "python3",
"args": ["-m", "oyhub"],
"env": {
"PYTHONPATH": "/path/to/oyhub",
"OYHUB_VAULT": "/Users/you/Documents/MyVault"
}
}
}
}
Note: Claude Desktop ignores a
cwdfield —PYTHONPATHis what makespython3 -m oyhubimportable. Alternatively,pip3 install -e /path/to/oyhubonce, then use"command": "oyhub"with noargsorPYTHONPATH.
Connect Claude Code
claude mcp add oyhub --env PYTHONPATH=/path/to/oyhub --env OYHUB_VAULT=~/Documents/MyVault -- python3 -m oyhub
Or after pip3 install -e /path/to/oyhub: claude mcp add oyhub -- oyhub
Docker
docker compose run --rm oyhub # stdio MCP server
docker compose run --rm --entrypoint python oyhub -m oyhub doctor
Dashboard & observability
pip install "oyhub[dashboard]"
oyhub dashboard # web UI + API at http://127.0.0.1:8400
Full observability stack (dashboard + Prometheus + Grafana, pre-provisioned):
docker compose --profile observability up
# dashboard http://localhost:8400 · prometheus http://localhost:9090 · grafana http://localhost:3000
The core MCP server stays dependency-free — FastAPI/uvicorn are an optional extra used only by the dashboard process.
The tools it exposes
| Tool | What it does |
|---|---|
project_activate |
Scope skills + memory to a project (creates profile if new) |
skill_add / skill_view / skill_list / skill_search |
Central library; list shows the compact index (60-char descriptions), bodies load on demand |
memory_add / memory_snapshot |
Curated memory in your Obsidian vault, project-scoped or global |
session_log / session_search / session_recent |
FTS5-indexed history: log important turns, search them later with context windows |
curator_run / curator_pin |
Run maintenance now; pin skills the curator must never touch |
A typical day
- Start a session: Claude calls
project_activate("webapp")andmemory_snapshot— it now knows your conventions and this project's facts, without you repeating them. - Work normally. When something worth keeping comes up, Claude calls
memory_add("staging DB is read-only") orskill_add(a deploy procedure it just worked out). - Next week, in a fresh session: "how did we fix that CORS issue?" →
session_search("CORS")returns the exact exchange. Nothing was lost when the old context window died. - Meanwhile the curator has deduped memory and archived skills untouched for 90 days — check
Curator Log.mdin Obsidian to see what it did.
Architecture
Claude / Cursor ──MCP (stdio JSON-RPC)──► oyhub/server.py
│
┌─────────────────────────┼─────────────────────┐
▼ ▼ ▼
skills.py memory.py curator.py
central library + index Obsidian vault (curated) idle-triggered loop:
per-project activation SQLite FTS5 (raw recall) archive stale, dedupe,
usage tracking frozen-snapshot reads log actions to vault
Design lineage: the frozen-snapshot memory, 60-char skill index, archive-never-delete curator, and idle-triggered maintenance are patterns from Hermes Agent (Nous Research, MIT), adapted for a keyless MCP harness.
Development
pip install -e ".[dev]"
ruff check oyhub tests && pytest tests/ -q # what CI runs
25 tests, all offline — including concurrency tests (parallel writers, no lost updates), injection-guard tests, and dashboard API tests. CI matrix: Ubuntu + macOS × Python 3.10–3.12, plus a Docker build + smoke test. Tag v* to cut a GitHub release and publish to PyPI (trusted publishing — configure once under PyPI → Publishing).
Roadmap
- LLM-assisted curation (summarize/consolidate memory notes, improve skill descriptions)
- Skill import from agentskills.io and Claude skill bundles
- Session auto-logging middleware
- Vector search as an optional complement to FTS5
MIT license.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file oyhub-0.3.0.tar.gz.
File metadata
- Download URL: oyhub-0.3.0.tar.gz
- Upload date:
- Size: 28.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ddc3cbe3743cc4920a47d41300e6de0f56798705b4fa4e85f900826950943a2a
|
|
| MD5 |
bac77338d8c69e497b9184a297161f36
|
|
| BLAKE2b-256 |
c15ea2fd0f234585ddc6ee7e74aa834602c74c59e2f13bc1258b33bfa6e089b2
|
Provenance
The following attestation bundles were made for oyhub-0.3.0.tar.gz:
Publisher:
ci.yml on Asanovichoff/oyhub
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
oyhub-0.3.0.tar.gz -
Subject digest:
ddc3cbe3743cc4920a47d41300e6de0f56798705b4fa4e85f900826950943a2a - Sigstore transparency entry: 2169747402
- Sigstore integration time:
-
Permalink:
Asanovichoff/oyhub@145bfeb97cb6b134389eb470ee4fe57b2e7d38c3 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/Asanovichoff
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@145bfeb97cb6b134389eb470ee4fe57b2e7d38c3 -
Trigger Event:
push
-
Statement type:
File details
Details for the file oyhub-0.3.0-py3-none-any.whl.
File metadata
- Download URL: oyhub-0.3.0-py3-none-any.whl
- Upload date:
- Size: 25.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5295b1b0a3159439bd005b7f199a85107d7db2ffac37c44c658f16da9fac2293
|
|
| MD5 |
947df46ff2daafdcb1c0c51378babb67
|
|
| BLAKE2b-256 |
7d5fa50971a5c1dd3f7308750fa71145b5b8cf5c903ef58abeec79f758fe7fb3
|
Provenance
The following attestation bundles were made for oyhub-0.3.0-py3-none-any.whl:
Publisher:
ci.yml on Asanovichoff/oyhub
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
oyhub-0.3.0-py3-none-any.whl -
Subject digest:
5295b1b0a3159439bd005b7f199a85107d7db2ffac37c44c658f16da9fac2293 - Sigstore transparency entry: 2169747546
- Sigstore integration time:
-
Permalink:
Asanovichoff/oyhub@145bfeb97cb6b134389eb470ee4fe57b2e7d38c3 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/Asanovichoff
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@145bfeb97cb6b134389eb470ee4fe57b2e7d38c3 -
Trigger Event:
push
-
Statement type: