Skip to main content

stack-guardian

ci privacy

A health doctor for a home AI stack. It collects a snapshot of your nodes (Ollama endpoints, loaded models, NVIDIA GPUs, tailnet peers), runs small Python rules against it, remembers the last runs, and reports findings with a confidence grade: one sample is at most LIKELY, the same finding twice in a row is VERIFIED. A finding can carry a typed fix that you run on purpose, never automatically.

Status: 0.1.0, first release. Standard library only, Python 3.11+.

Install

pip install stack-guardian

This gives you three commands: stack-guardian (the CLI), stack-guardian-serve and stack-guardian-mcp.

Try it offline first: the example snapshot makes every shipped rule fire once.

curl -LO https://raw.githubusercontent.com/LuminariSoftwares/stack-guardian/main/examples/snapshot.json
curl -LO https://raw.githubusercontent.com/LuminariSoftwares/stack-guardian/main/examples/ctx.json
stack-guardian doctor --snapshot snapshot.json --ctx ctx.json

From a clone instead (for writing rules or running the tests):

git clone https://github.com/LuminariSoftwares/stack-guardian.git
cd stack-guardian
python -m venv .venv
.venv\Scripts\activate          # Windows;  macOS/Linux: source .venv/bin/activate
pip install -e .
stack-guardian doctor --snapshot examples/snapshot.json --ctx examples/ctx.json

For coding agents

  • MCP server (any MCP client): stack-guardian-mcp speaks MCP over stdio with three read-only tools, stack_health, stack_snapshot and explain. In Claude Code:

    claude mcp add stack-guardian -e STACK_GUARDIAN_NODES=/path/to/nodes.json -- stack-guardian-mcp
    

    Other clients: command stack-guardian-mcp, args ["--nodes", "/path/to/nodes.json"]. stack_health grades against the saved run history without adding to it, and reuses one snapshot for 10 s (--ttl SECONDS).

  • DSH plugin (npm install dsh-stack-guardian, source in dsh/, Node 20+): adds one line at the start of a DeepSeek Harness session when the doctor reports WARN or FAIL, and nothing otherwise. It runs stack-guardian doctor --json --quiet, so set STACK_GUARDIAN_NODES to your nodes file in the harness environment.

What it does

1. doctor - run the checks

Describe your nodes in a JSON file (see examples/nodes.json) and check them live:

stack-guardian doctor --nodes examples/nodes.json --ctx examples/ctx.json

With neither --snapshot nor --nodes, doctor reads the nodes file named by $STACK_GUARDIAN_NODES.

Options: --checks-dir DIR (your own rules, default is the shipped checks.d), --ctx FILE (rule settings such as the model each node is expected to hold), --state FILE (default $STACK_GUARDIAN_STATE or ~/.stack-guardian/state.json), --json, --quiet (print nothing when all is OK).

Exit codes: 0 all OK/INFO, 1 a WARN, 2 a FAIL, 3 usage, 4 the doctor itself crashed.

Shipped rules: node.unreachable, ollama.unreachable, model.not_loaded, vram.unattributed, gpu.unavailable, tailnet.unavailable, tailnet.peer_offline, tailnet.relayed. Each raises one finding per affected node. A rule that raises becomes a check.crashed WARN - a buggy rule never reports a broken stack.

2. doctor --fix ID - run a finding's typed fix

A rule may attach fix={"action": ..., "args": {...}} to a finding. There are exactly three actions and never a raw shell string:

action what it does needs
unload_model POST keep_alive: 0 to an Ollama /api/generate node, url, model
restart_lane runs the argv list you declared for that lane lane declared in --config
set_env writes NAME=value to <state folder>/env and sets it for the process name, value
stack-guardian doctor --checks-dir examples/checks.d --snapshot examples/snapshot.json --fix ollama.stuck --config examples/lanes.json

That is a dry run: it prints the plan and changes nothing. Add --apply to perform it. An applied fix first saves the snapshot under <state folder>/snapshots/, then runs, then appends one JSON line to <state folder>/fixes.jsonl (--audit FILE to move it). A set_env value is never written to the audit, only its length. ID is the finding code, or code@node when several nodes raise the same code. With --fix, the exit code is the fix's: 0 plan or success, 1 refused or failed, 3 usage.

3. Other commands

  • stack-guardian snapshot --nodes FILE prints the raw snapshot the rules read.
  • stack-guardian-serve --nodes FILE [--port 8788] serves a fresh snapshot at GET /snapshot (read-only, loopback unless you pass --host H --allow-remote), so one machine can ask another for its health. no auth: bind to localhost or a tailnet IP only.
  • stack-guardian-mcp --nodes FILE [--ctx FILE] [--state FILE] [--ttl SECONDS]: see For coding agents.

Writing a rule

from stack_guardian import finding as F

def ollama_up(snapshot, ctx):
    if not snapshot["nodes"]["gpu-box"].get("reachable"):
        return F.make_finding("ollama.unreachable", "missing", "FAIL", "gpu-box", "Ollama does not answer")
    return None

CHECKS = [("ollama.up", ollama_up)]

Drop the file in a folder and point --checks-dir at it. A full example with a fix is in examples/checks.d/20_ollama_fix.py. A rule may also return a list of findings, one per node.

Examples

file what it is
examples/nodes.json three nodes: a local one with GPUs, two remote ones over the tailnet
examples/ctx.json rule settings: which model gpu-box-2 should hold
examples/snapshot.json an offline snapshot on which every shipped rule fires once, for trying doctor and --fix
examples/lanes.json the lanes restart_lane is allowed to run
examples/checks.d/20_ollama_fix.py a custom rule whose finding carries a fix

Test

pip install pytest
python -m pytest -q

CI runs this on Ubuntu, Windows and macOS with Python 3.11, plus a privacy scan of every tracked file.

License

MIT

Metadata

Release files for stack-guardian 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for stack-guardian 0.1.0
File Size Uploaded
stack_guardian-0.1.0.tar.gz 50.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for stack-guardian 0.1.0
File Interpreter ABI Platform
stack_guardian-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 99.0 kB

Release files / stack_guardian-0.1.0.tar.gz

Download URL stack_guardian-0.1.0.tar.gz
Size 50.7 kB
Tags Source
SHA-256 checksum
How to use checksums
668f0e0f761a5cdeddcbff62214364e10d294bc98580241dc8725d58d906ced0
BLAKE2b-256 checksum
How to use checksums
5779b629d1f9e15c1ca2d16e287fe5bc92d17ae69a86d67b986e9de70e5836b2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.9

Release files / stack_guardian-0.1.0-py3-none-any.whl

Download URL stack_guardian-0.1.0-py3-none-any.whl
Size 48.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ef4c37ab5a81dfde57c8f42cca2750cbf13be0b0d3f80d006d89e815848e7107
BLAKE2b-256 checksum
How to use checksums
58a2f6a7d7ca3738e9441216e4006d9ca09a51f7144fb93653903242f2da7045
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.9

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page