Metadata-Version: 2.4
Name: linuxagent
Version: 4.0.0
Summary: HITL-first Linux operations control plane with policy checks, audit trails, runbooks, and SSH guards.
Project-URL: Repository, https://github.com/Eilen6316/LinuxAgent
Project-URL: Documentation, https://github.com/Eilen6316/LinuxAgent#readme
Project-URL: Roadmap, https://github.com/Eilen6316/LinuxAgent/blob/master/ROADMAP.md
Project-URL: Changelog, https://github.com/Eilen6316/LinuxAgent/blob/master/CHANGELOG.md
Project-URL: Issues, https://github.com/Eilen6316/LinuxAgent/issues
Project-URL: Security, https://github.com/Eilen6316/LinuxAgent/security/policy
Author: LinuxAgent contributors
License: MIT
Keywords: agent,cli,langgraph,linux,llm,ops
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: System :: Systems Administration
Requires-Python: >=3.11
Requires-Dist: langchain-core<2.0,>=1.3
Requires-Dist: langchain-openai<1.3,>=1.1
Requires-Dist: langgraph<1.2,>=1.1
Requires-Dist: openai<3.0,>=2.26
Requires-Dist: paramiko<4.0,>=3.4
Requires-Dist: prompt-toolkit<4.0,>=3.0
Requires-Dist: psutil<7.0,>=6.0
Requires-Dist: pydantic<3.0,>=2.7
Requires-Dist: pyyaml<7.0,>=6.0
Requires-Dist: rich<15.0,>=13.0
Requires-Dist: tenacity<10.0,>=8.0
Provides-Extra: anthropic
Requires-Dist: langchain-anthropic<1.5,>=1.3; extra == 'anthropic'
Provides-Extra: dev
Requires-Dist: bandit<2.0,>=1.7; extra == 'dev'
Requires-Dist: build<2.0,>=1.2; extra == 'dev'
Requires-Dist: hatchling<2.0,>=1.25; extra == 'dev'
Requires-Dist: mypy<2.0,>=1.10; extra == 'dev'
Requires-Dist: pip-tools<8.0,>=7.4; extra == 'dev'
Requires-Dist: pre-commit<5.0,>=3.7; extra == 'dev'
Requires-Dist: pytest-asyncio<1.0,>=0.23; extra == 'dev'
Requires-Dist: pytest-cov<7.0,>=5.0; extra == 'dev'
Requires-Dist: pytest<9.0,>=8.0; extra == 'dev'
Requires-Dist: ruff<1.0,>=0.5; extra == 'dev'
Requires-Dist: types-pyyaml; extra == 'dev'
Requires-Dist: types-requests; extra == 'dev'
Provides-Extra: pyinstaller
Requires-Dist: pyinstaller<7.0,>=6.0; extra == 'pyinstaller'
Description-Content-Type: text/markdown

<div align="center">
  <h1>LinuxAgent</h1>
  <img src="logo.jpg" alt="LinuxAgent Logo" width="280" />

  <p>
    <a href="https://github.com/Eilen6316/LinuxAgent/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/Eilen6316/LinuxAgent/ci.yml?branch=master&style=flat-square&label=CI" alt="CI"></a>
    <a href="https://github.com/Eilen6316/LinuxAgent/releases/tag/v4.0.0"><img src="https://img.shields.io/github/v/release/Eilen6316/LinuxAgent?style=flat-square" alt="Release"></a>
    <a href="https://github.com/Eilen6316/LinuxAgent/releases/tag/v4.0.0"><img src="https://img.shields.io/badge/package-GitHub%20Release-blue?style=flat-square" alt="GitHub Release package"></a>
    <a href="README.md#quality-gate"><img src="https://img.shields.io/badge/coverage-86.30%25-brightgreen?style=flat-square" alt="Coverage"></a>
    <a href="SECURITY.md"><img src="https://img.shields.io/badge/security-policy-green?style=flat-square" alt="Security Policy"></a>
  </p>

  <p><strong>A HITL-first Linux operations control plane that keeps LLM plans behind policy checks, audit trails, SSH guards, and operator approval.</strong></p>

  <p>
    <a href="docs/zh/README.md">简体中文完整文档</a> ·
    <a href="docs/en/README.md">Full English manual</a> ·
    <a href="docs/releases/v4.0.0.md">v4.0.0 release notes</a>
  </p>
</div>

---

LinuxAgent is a production-minded CLI for Linux operations. It is not a free-form shell chatbot: it lets an LLM propose plans, but execution stays behind explicit policy checks, Human-in-the-Loop confirmation, SSH safety guards, output redaction, and a hash-chained audit log.

It is built on **LangGraph**, **LangChain**, and **Pydantic v2**. No local deep-learning stack is required.

## Why It Exists

LLM command agents usually fail at the exact point operators care about: trust.

LinuxAgent's default stance is different:

| Principle | What LinuxAgent does |
|---|---|
| The model is not trusted | First-time LLM-generated commands require confirmation |
| Safety is policy, not substring matching | Commands are tokenized and evaluated by a capability-based policy engine |
| Production output may contain secrets | Tool output is guarded and redacted before LLM-facing analysis |
| SSH must not silently trust hosts | Remote execution uses known-host verification and shell-syntax guards |
| Every approval should be reviewable | HITL decisions are written to a `0o600` hash-chained audit log |

## One-Minute Start

```bash
git clone https://github.com/Eilen6316/LinuxAgent.git
cd LinuxAgent
./scripts/bootstrap.sh
source .venv/bin/activate
```

Then edit `./config.yaml` and set your provider API key:

```yaml
api:
  provider: deepseek
  api_key: "replace-me"
```

For API relays or third-party OpenAI-compatible endpoints, use
`openai_compatible` or a provider shortcut such as `qwen`, `kimi`, `glm`,
`minimax`, `gemini`, or `hunyuan`:

```yaml
api:
  provider: openai_compatible
  base_url: https://relay.example.com/v1
  model: gpt-4o-mini
  api_key: "replace-me"
  token_parameter: max_tokens
```

For locally deployed OpenAI-compatible models, use `ollama`, `vllm`, `lmstudio`,
or generic `local`. Local providers do not require a real API key:

```yaml
api:
  provider: ollama
  base_url: http://127.0.0.1:11434/v1
  model: llama3.1
  api_key: ""
  token_parameter: max_tokens
```

Anthropic-format relays can use `provider: anthropic_compatible` with their own
`base_url`; Xiaomi MiMo can use `provider: xiaomi_mimo`.

Validate and start:

```bash
linuxagent check
linuxagent
```

Try a read-only request:

```text
check the Linux version
```

When a first LLM-generated command appears, choose `Yes` for one execution,
`Yes, don't ask again` for matching commands only in this conversation and the
same `/resume` thread, or `No` to refuse. Use `!uname -a` for direct
operator-authored command mode.

Provider quick reference:

| Provider | Protocol | Typical `base_url` | Token parameter |
|---|---|---|---|
| `deepseek` | OpenAI-compatible | `https://api.deepseek.com/v1` | `max_completion_tokens` |
| `openai` | OpenAI | `https://api.openai.com/v1` | `max_completion_tokens` |
| `openai_compatible` | OpenAI-compatible relay | relay-specific `/v1` URL | often `max_tokens` |
| `local` | Local OpenAI-compatible | `http://127.0.0.1:8000/v1` | `max_tokens` |
| `ollama` | Local OpenAI-compatible | `http://127.0.0.1:11434/v1` | `max_tokens` |
| `vllm` | Local OpenAI-compatible | `http://127.0.0.1:8000/v1` | `max_tokens` |
| `lmstudio` | Local OpenAI-compatible | `http://127.0.0.1:1234/v1` | `max_tokens` |
| `qwen` | OpenAI-compatible | `https://dashscope.aliyuncs.com/compatible-mode/v1` | `max_tokens` |
| `kimi` | OpenAI-compatible | `https://api.moonshot.ai/v1` | `max_tokens` |
| `glm` | OpenAI-compatible | `https://open.bigmodel.cn/api/paas/v4` | `max_tokens` |
| `minimax` | OpenAI-compatible | `https://api.minimax.io/v1` | `max_tokens` |
| `gemini` | OpenAI-compatible | `https://generativelanguage.googleapis.com/v1beta/openai/` | `max_tokens` |
| `hunyuan` | OpenAI-compatible | `https://api.hunyuan.cloud.tencent.com/v1` | `max_tokens` |
| `anthropic` | Anthropic | provider default | n/a |
| `anthropic_compatible` | Anthropic-compatible relay | relay-specific URL | n/a |
| `xiaomi_mimo` | Anthropic-compatible | relay-specific URL | n/a |

See the maintained [Provider Compatibility Matrix](docs/en/provider-matrix.md)
for status, local model notes, and compatibility report details.

`config.yaml` must be owned by the current user and `chmod 600`; secrets are not loaded from `.env`.

## What a Turn Looks Like

```text
you: find services listening on port 8080

parse_intent  -> LLM proposes: ss -tlnp sport = :8080
safety_check  -> CONFIRM (LLM_FIRST_RUN)
confirm       -> operator approves in terminal
execute       -> asyncio subprocess, no shell=True
analyze       -> concise operator summary
audit.log     -> hash-chained JSONL decision record
```

For ordinary conversation, LinuxAgent first asks an LLM-owned intent router for
`DIRECT_ANSWER`, `COMMAND_PLAN`, or `CLARIFY`. Direct answers do not create a
command plan and therefore do not show the confirmation panel. Operational
methods are not hard-coded in Python; successful command patterns are learned in
the local learner memory after sensitive values are redacted. Deterministic
safety policy data lives in YAML, while Python code only loads, validates, and
applies those policies.

Each CLI launch starts with an empty conversation context. Saved sessions are
available only when the operator asks for it with `/resume`; then enter the
shown number or use the interactive picker to resume that saved session. If the
selected session stopped at a HITL confirmation, LinuxAgent reloads the local
checkpoint and reopens the confirmation flow. Use `/new` to reset context inside
a running CLI session and `/tools` to see available slash/tool entry points.
Typing `/` opens the slash-command completion menu. Command confirmations use
an arrow-key menu with `Yes`, `Yes, don't ask again`, and `No` when conversation
permissions are allowed. `Yes, don't ask again` is scoped to the current
conversation thread and the same thread when resumed with `/resume`. New
conversations do not inherit it, and destructive or `never_whitelist` policy
matches still ask every time.
Input beginning with `!` is direct command mode: LinuxAgent executes the
operator-authored command, streams stdout/stderr live, and records both
`!<command>` and the system result into the active conversation context. It does
not ask the LLM to explain or generate a reply for that turn.

## Core Capabilities

| Capability | Why it matters |
|---|---|
| Capability-based policy engine | Produces `SAFE` / `CONFIRM` / `BLOCK`, risk scores, capabilities, and matched rules |
| YAML policy defaults | Command policy data is loaded from `configs/policy.default.yaml`, not Python rule tables |
| Structured `CommandPlan` | LLM output must validate as JSON before any policy or execution path |
| Structured file patches | Script/code/config edits use transactional `FilePatchPlan` apply, unified-diff validation, path policy, and HITL review |
| Read-only workspace tools | Planner can inspect allowed files with `read_file`, `list_dir`, and `search_files` before proposing patches |
| AI-owned intent routing | Conversation vs operation vs clarification is decided by `prompts/intent_router.md`, not Python keyword rules |
| Explicit resume control | New sessions do not inherit previous chats unless `/resume` is used; pending HITL checkpoints resume there too |
| Direct `!` command mode | Runs operator-authored commands without an AI reply and adds command/output to current context |
| Sandbox metadata boundary | Commands carry a selected sandbox profile into audit and telemetry; default `noop` records metadata only |
| YAML runbooks | Common ops procedures are injected as planner guidance, not pre-LLM hard routes |
| Learner memory | Successful command patterns are persisted locally after secret redaction |
| LangGraph HITL | Confirmation uses `interrupt()` and checkpointing rather than inline `input()` |
| SSH cluster guard | Batch confirmation, remote shell metacharacter blocking, remote profile audit |
| Output protection | Command results are redacted and bounded before model-facing analysis |
| Hash-chained audit | `linuxagent audit verify` detects local audit-log tampering |
| Reproducible release | `constraints.txt`, wheel verification, and packaged config/prompt/runbook checks |

## File Changes

Requests such as "create a shell script", "update this Python file", or "edit
this config" do not bypass the safety model. LinuxAgent asks the planner for a
structured `FilePatchPlan`, then validates and previews the unified diff before
writing anything. The plan carries a structured `request_intent` field
(`create`, `update`, or `unknown`) instead of relying on Python keyword
matching.

The planner can first inspect the environment with read-only tools:

- `read_file(path, offset, limit)` reads a bounded window from an allowed file.
- `list_dir(path)` lists an allowed directory.
- `search_files(pattern, root)` searches literal text under an allowed root; regex
  metacharacters are treated as ordinary text.
- `get_system_info`, `search_logs`, and safety-gated `execute_command` provide
  system context when needed.

Tool calls run through the tool sandbox runtime before output reaches the model:
each tool carries explicit permissions (`read_files`, `write_files`,
`execute_commands`, `system_inspect`, `network_access`, and `hitl` mode),
workspace/log roots are checked, per-tool timeouts and output limits are
applied, oversized output is marked as truncated, and tool errors are returned
as structured model-visible events while telemetry records `allowed`, `denied`,
`timeout`, or `truncated`.

The terminal shows observable tool activity such as `LinuxAgent is reading
...` / `LinuxAgent is listing ...`. Patch confirmation shows per-file stats,
compact `+` / `-` diff snippets, high-risk path warnings, permission changes,
large-diff pagination, and per-file acceptance for multi-file patches. Full
diffs are not shown twice; extra review prompts appear only when hidden pages
exist.

Command confirmation also shows planned sandbox context: requested profile,
runner, enforcement state, cwd, allowed roots, network policy, and fallback
reason when the configured runner cannot enforce isolation.

After approval, patch application runs as a transaction. LinuxAgent validates
target paths before reading file content, rejects symlink path components,
hardlinks, directories, device files, FIFOs, sockets, oversized targets, and
non-UTF-8 text, then writes through a temporary file and atomic replace. Existing
targets are backed up under a local `.linuxagent-patch-*` sandbox directory and
rolled back automatically if a later file or permission change fails. Audit
metadata records changed files, permission changes, backup path hashes, rollback
outcome, and the sandbox root.

By default, file patch reads and writes are limited to the current workspace and
`/tmp` through `file_patch.allow_roots`. Sensitive roots such as `/etc` and SSH
key directories are highlighted as high risk, and permission changes such as
`0755` for generated scripts appear explicitly in the confirmation panel.
Automatic patch repair defaults to two rounds and can be tuned with
`file_patch.max_repair_attempts` (`0` disables automatic patch repair).
Failed command-plan repair is separately capped by
`command_plan.max_repair_attempts` (`0` disables failed-command replanning).

## Sandbox Status

LinuxAgent local command execution now goes through a sandbox runner boundary.
The default remains `sandbox.enabled: false` with `runner: noop`, which preserves
compatibility while recording sandbox metadata only. `runner: local` applies
process lifecycle controls such as clean environment, closed stdin, timeout,
process-group cleanup, resource limits, output limits, and configured cwd roots,
but it does not claim filesystem or network isolation for safe profiles.
`runner: bubblewrap` is optional and capability-probed; if `bwrap` is missing or
cannot enforce the requested profile or network policy, safe profiles fail
closed while explicit passthrough profiles remain auditable passthrough.

## Safety Model

| Operation | Default behavior |
|---|---|
| User-authored read-only command | May run when policy returns `SAFE` |
| First LLM-generated command | `CONFIRM` |
| Conversation-approved LLM command | May skip repeat confirmation only in the same conversation thread, including `/resume` of that thread |
| Destructive command | `CONFIRM` every time; never conversation-whitelisted |
| Command targeting root or sensitive paths | `BLOCK` when matched by policy |
| SSH batch across two or more hosts | Explicit batch confirmation with target hosts and remote profiles |
| Non-TTY confirmation request | Auto-deny |
| Unknown SSH host | Reject by default |
| Default sandbox runner | Records profile metadata only; no process isolation |
| Enabled safe sandbox profile unavailable | Fail closed before spawning |

LinuxAgent is **not** an autonomous remediator. The current default `noop`
sandbox runner is also not a command sandbox; it is intended for controlled
operator-in-the-loop use. See [Production Readiness](docs/en/production-readiness.md) and [Threat Model](docs/en/threat-model.md).

SSH execution is not protected by local OS sandboxing. Configure cluster hosts
with least-privilege users, pre-registered `known_hosts`, a remote working
directory, and explicit sudo allowlists when sudo is required.

## Built-In Runbooks

LinuxAgent v4 ships with eleven YAML runbooks for common diagnostics:

| Runbook area | Examples |
|---|---|
| Disk and filesystem | `df`, top directories, journal usage |
| Ports and networking | listeners, port ownership, connectivity checks |
| Services and logs | systemd status, recent unit logs, error search |
| System health, OS, load, and memory | overall host health, OS release, CPU pressure, memory pressure, OOM clues |
| Containers, packages, and certificates | container status, installed packages, certificate expiry |

Runbooks no longer perform natural-language hard matching before LLM planning.
They are loaded, policy-validated, and supplied to the planner as advisory
examples. The planner may use, adapt, or ignore that guidance based on the
actual request. If it produces a multi-step plan inspired by a runbook, every
step still goes through normal policy, HITL, audit, and analysis flow.

## Quality Gate

Current documented baseline from `make test` on 2026-05-01:

| Gate | Status |
|---|---|
| Unit tests | 577 passing |
| Optional provider compatibility | covered by `make optional-anthropic` when the extra is installed |
| Sandbox boundary suite | covered by `make sandbox` |
| Harness scenarios | scenario-driven HITL / runbook / cluster / sandbox coverage |
| Integration smoke tests | 10 passing |
| Coverage | 86.30% (`--cov-fail-under=80`) |
| Static checks | `ruff`, `mypy`, `bandit`, project code-rule checks |
| Build verification | wheel + sdist + packaged data install check |

Useful commands:

```bash
make test
make sandbox
make lint
make type
make security
make harness
make verify-build
```

## Install Paths

| Path | Use when |
|---|---|
| `./scripts/bootstrap.sh` | You are working from a source checkout |
| `pip install -c constraints.txt https://github.com/Eilen6316/LinuxAgent/releases/download/v4.0.0/linuxagent-4.0.0-py3-none-any.whl` | You want the published GitHub Release wheel |
| `pip install linuxagent` | You want the PyPI package after the release is published |
| `pip install -e ".[dev]"` | You are developing or running the full local gate |
| `pip install -e ".[anthropic]"` | You need the optional Anthropic provider |

## Documentation

| Document | Purpose |
|---|---|
| [Documentation index](docs/README.md) | All long-form docs in one place |
| [docs/zh/README.md](docs/zh/README.md) | Full Chinese manual |
| [docs/en/README.md](docs/en/README.md) | Full English manual |
| [Quick Start](docs/en/quickstart.md) | Installation and first run |
| [Provider Matrix](docs/en/provider-matrix.md) | Provider setup paths and compatibility status |
| [Operator Safety Model](docs/en/operator-safety.md) | Plain-language safety boundaries for users |
| [Runbook Authoring](docs/en/runbook-authoring.md) | How to contribute safe YAML runbooks |
| [Roadmap](ROADMAP.md) | Maintainer priorities and good first issue areas |
| [Migration Guide](docs/en/migration-v3-to-v4.md) | v3 to v4 breaking changes |
| [Threat Model](docs/en/threat-model.md) | Assets, trust boundaries, and mitigations |
| [Production Readiness](docs/en/production-readiness.md) | Where LinuxAgent is and is not appropriate |
| [Security Policy](SECURITY.md) | Vulnerability reporting and supported versions |
| [Contributing](CONTRIBUTING.md) | Contribution workflow and review expectations |
| [Changelog](CHANGELOG.md) | Release history |

## Mirrors and Community

| Link | Notes |
|---|---|
| [GitHub](https://github.com/Eilen6316/LinuxAgent.git) | Primary repository |
| [GitCode](https://gitcode.com/qq_69174109/LinuxAgent.git) | Mirror |
| [Gitee](https://gitee.com/xinsai6316/LinuxAgent.git) | Mirror |
| [QQ Group 281392454](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=o2ByKsl_gBN-fODJxH4Ps4Xboa_hCSI3&authKey=nVfsLJBin1CnZBd9pPNkxFk%2FGFqCe1FLsRMQmmxv%2FQnM78bC%2FjcWyMSeQcJDZC1U&noverify=0&group_code=281392454) | Community |
| [CSDN intro](https://blog.csdn.net/qq_69174109/article/details/146365413) | Project article |

## License

MIT
