Skip to main content

HITL-first Linux operations control plane with policy checks, audit trails, runbooks, and SSH guards.

Project description

LinuxAgent

LinuxAgent Logo

CI Release GitHub Release package Coverage Security Policy

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

简体中文完整文档 · Full English manual · v4.0.0 release notes


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

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:

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:

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:

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:

linuxagent check
linuxagent

Try a read-only request:

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 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

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 and Threat Model.

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:

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 All long-form docs in one place
docs/zh/README.md Full Chinese manual
docs/en/README.md Full English manual
Quick Start Installation and first run
Provider Matrix Provider setup paths and compatibility status
Operator Safety Model Plain-language safety boundaries for users
Runbook Authoring How to contribute safe YAML runbooks
Roadmap Maintainer priorities and good first issue areas
Migration Guide v3 to v4 breaking changes
Threat Model Assets, trust boundaries, and mitigations
Production Readiness Where LinuxAgent is and is not appropriate
Security Policy Vulnerability reporting and supported versions
Contributing Contribution workflow and review expectations
Changelog Release history

Mirrors and Community

Link Notes
GitHub Primary repository
GitCode Mirror
Gitee Mirror
QQ Group 281392454 Community
CSDN intro Project article

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

linuxagent-4.0.0.tar.gz (190.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

linuxagent-4.0.0-py3-none-any.whl (179.6 kB view details)

Uploaded Python 3

File details

Details for the file linuxagent-4.0.0.tar.gz.

File metadata

  • Download URL: linuxagent-4.0.0.tar.gz
  • Upload date:
  • Size: 190.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for linuxagent-4.0.0.tar.gz
Algorithm Hash digest
SHA256 46fe301b4c504b62590bf1839a62d63f3dd13e37f174fc05c47e584cd18ea023
MD5 9224cd24d63477e646bbd7509d3ae505
BLAKE2b-256 769a36ef7ccfd496cc29caa0a0975fad9d91edf066dc4a978a2b904a54fae5f4

See more details on using hashes here.

Provenance

The following attestation bundles were made for linuxagent-4.0.0.tar.gz:

Publisher: release.yml on Eilen6316/LinuxAgent

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file linuxagent-4.0.0-py3-none-any.whl.

File metadata

  • Download URL: linuxagent-4.0.0-py3-none-any.whl
  • Upload date:
  • Size: 179.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for linuxagent-4.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 bfdd60cb48b7eaebfa286bc56fc243b2a8c2984712321542e539628d824ca23a
MD5 cfae192d0bfe8f8dfc12ca93032053e3
BLAKE2b-256 751bf2631b98470c8c6580e9169d98b2b4e456b13eb4af721cbd2199f942e85b

See more details on using hashes here.

Provenance

The following attestation bundles were made for linuxagent-4.0.0-py3-none-any.whl:

Publisher: release.yml on Eilen6316/LinuxAgent

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page