Metadata-Version: 2.4
Name: nodeiq
Version: 0.1.1
Summary: Ask plain-English questions about a Linux server, answered from its real, freshly-collected state.
License: MIT
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: openai
Requires-Dist: python-dotenv
Dynamic: license-file

# nodeIQ

Ask plain-English questions about a Linux server and get answers grounded
in that server's real, freshly-collected state — not generic advice.

nodeiq collects live data (processes, disk, services, logs, network, cron
jobs, file permissions, login/auth activity, Docker containers), routes
your question to the collectors that actually matter, and hands the
result to an LLM (OpenAI) to answer. One server, real data, one question
at a time — no fleet management, no agents that act on their own.

## Features

- **Natural-language Q&A** about a server's live state — `--ask` for a
  one-shot question, `--chat` for a REPL with short-term follow-up memory.
- **Hybrid routing** — a free keyword fast-path for the common case, a
  single bounded LLM classification call as a fallback for novel
  phrasing, broad ("full health check") questions, or genuinely
  out-of-scope ones.
- **Troubleshooting, not just reporting** — for "why is X high/failing"
  questions, nodeiq names the specific process/service responsible and
  suggests a concrete fix as advice. It never runs anything itself: every
  collector shells out with a fixed argument list, never a string built
  from a question or an answer, so there's no code path where nodeiq (or
  the LLM) could execute a command even if it tried to.
- **A free, no-LLM health sweep** — `--check` applies threshold rules
  (disk %, failed services, load, recent errors) and exits 0/1, safe to
  wire into cron or a monitoring pipeline.
- **Change tracking** — `--diff` compares live state against the last
  `--diff` snapshot and narrates what actually changed.
- **A saved report artifact** — `--report` writes a full document-style
  Markdown health check to a file, for pasting into a ticket or handoff
  doc.
- **Secret redaction** — process command lines and cron job commands are
  scanned for common secret shapes (`--password=`, `Authorization:
  Bearer`, known key prefixes) and redacted before anything is saved or
  sent to OpenAI.
- **Readable terminal output** — colored, boxed, word-wrapped answers (no
  new dependency: plain ANSI + stdlib `textwrap`), falling back to plain
  text automatically when piped, redirected, or `$NO_COLOR` is set.
- **Resilient collectors** — each collector isolates its own independent
  data sources, so one failing source (a missing `/proc` file, a hung
  `systemctl` call) doesn't blank out the rest of that collector's report.
- **An operational log** (`logs/nodeiq.log`) of what nodeiq itself did —
  questions received, routing decisions, collector outcomes, LLM calls —
  separate from the *server's* logs it reads.

## How it works

```mermaid
flowchart TD
    Q[Question] --> CLI[nodeiq/cli.py]
    CLI --> ORCH[nodeiq/orchestrator.py: route + collect]
    ORCH --> COL[nodeiq/collectors/*.py]
    COL --> REPORT[JSON report]
    REPORT --> LLM[nodeiq/llm.py + OpenAI]
    LLM --> ANSWER[Answer, colored + boxed in the terminal]
```

See `docs/architecture.md` for the fuller diagram, including the
keyword-vs-AI routing decision and the operational-logging side-channel.

## Requirements

- A Linux server. Most collectors also expect `systemd` (Ubuntu, Debian,
  RHEL, and most modern distros) — a few degrade gracefully without it
  (`permissions`, most of `cron`/`auth`), a couple simply return
  `ok: false` (`services`, `processes`, `disk`, `logs`, `network`). nodeiq
  detects the OS/architecture it's running on (`platform_info.py`) and
  announces it once per session — running it on macOS for quick dev
  testing gives clean "requires Linux" messages instead of crashes, not
  full functionality.
- Python 3.10+.
- An OpenAI API key.
- Docker, only if you want the `docker` collector to return anything —
  its absence is a normal "not applicable" case, not an error.
- No sudo required for most questions. A few checks (firewall rules, full
  log history) need it for complete data — nodeiq never escalates
  privilege itself; run the whole tool under `sudo` if you want that
  coverage (see `docs/architecture.md`).

## Quickstart

### Option A: install from PyPI

Just want to run it — [pypi.org/project/nodeiq](https://pypi.org/project/nodeiq/):

```bash
python3 -m venv venv && source venv/bin/activate
pip install nodeiq
echo "OPENAI_API_KEY=sk-..." > .env   # your real key, in the directory you'll run nodeiq from
```

### Option B: install from source

Want to read/edit the code, or run the test suite — see `docs/setup.md`
for the full walkthrough (including a local Ubuntu VM option if you don't
have a spare Linux box):

```bash
git clone <this repo> nodeiq && cd nodeiq
python3 -m venv venv && source venv/bin/activate
pip install -e .
cp .env.example .env   # then set OPENAI_API_KEY in it
```

### Either way, then:

```bash
nodeiq --list
nodeiq --ask "how much disk space is free?"
nodeiq --chat
nodeiq --check                        # free health sweep, no LLM call, exit 0/1
nodeiq --diff                         # what changed since the last --diff run
nodeiq --report                       # save a full Markdown health report
sudo venv/bin/nodeiq --collect network   # for firewall-rule coverage
```

## Testing

```bash
python3 -m unittest discover -s tests -v
```

Covers `redact.py` and `healthcheck.py`'s rule logic — the two modules
with real branching and no live-system/network dependency. Collectors
are exercised via `nodeiq --collect <name>` against a real box instead
(see `docs/collectors/`).

## Docs

- [`docs/architecture.md`](docs/architecture.md) — flow, question routing, permissions/sudo rules, design principles
- [`docs/collectors/`](docs/collectors) — one file per collector: fields returned, decisions, edge cases
- [`docs/orchestrator.md`](docs/orchestrator.md) — routing, chat memory, robustness, terminal output
- [`docs/llm.md`](docs/llm.md) — model choice, system prompt, remediation advice, error handling
- [`docs/logging.md`](docs/logging.md) — nodeiq's own operational log (`logs/nodeiq.log`)
- [`docs/config.md`](docs/config.md) — every tunable setting, the LLM cost guardrails, and `--check` thresholds
- [`docs/redaction.md`](docs/redaction.md) — what secret-redaction catches, and its honest limits
- [`docs/setup.md`](docs/setup.md) — install, run, optional local test VM
- [`docs/packaging.md`](docs/packaging.md) — why releases are Cython-compiled, how to build/publish
- [`CHANGELOG.md`](CHANGELOG.md) — release history, what's built vs. planned

## Configuration

All in `nodeiq/config.py`, each overridable by an environment variable — see
`docs/config.md` for the full list and the cost-guardrail reasoning.

| Variable | Required | Default | Purpose |
|---|---|---|---|
| `OPENAI_API_KEY` | yes | — | LLM calls (see `.env.example`) |
| `NODEIQ_MODEL` | no | `gpt-5.4-nano` | OpenAI model used for both routing and answers |
| `NODEIQ_LOG_LEVEL` | no | `INFO` | Set to `DEBUG` for verbose operational logging |
| `NODEIQ_MAX_LLM_CALLS` | no | `40` | Hard cap on OpenAI calls per process — see `docs/config.md` |
| `NO_COLOR` | no | unset | Set to force plain-text terminal output |

## Status

All 9 collectors, hybrid routing, chat, LLM integration, colored/boxed
terminal output, remediation advice, per-source failure isolation,
operational logging, secret redaction, a no-LLM health sweep (`--check`),
change tracking (`--diff`), and a saved report artifact (`--report`) are
built and verified against a live Ubuntu box (and, for the
platform-independent pieces, live against real OpenAI calls). See
`CHANGELOG.md` for the full release history.
