Skip to content
AppliedIRPublic

About

Valhuntir CLI — AI-augmented incident response platform

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

113 stars

Watchers

0 watching

Forks

Repository files navigation

Valhuntir

Valhuntir

CI Docs License: MIT

Valhuntir turns a single incident response analyst into the manager of an agentic AI incident response team. A host of MCP tools allows the AI to quickly ingest, process, and analyze massive amounts of digital forensic artifacts while keeping the human in control of the investigation and decision making process. Curated forensic knowledge bases, guidance and context hints, and processing suggestions are built into the system, but ultimately the human examiner drives the response.

Platform Documentation · CLI Reference

Important Note — While extensively tested, this is a new platform. ALWAYS verify results and guide the investigative process. If you just tell Valhuntir to "Find Evil" it will more than likely hallucinate rather than provide meaningful results. The AI can accelerate, but the human must guide it and review all decisions.

Valhuntir — AI-Assisted Forensic Investigation

Valhuntir ensures accountability and enforces human review of findings through signed approvals (each examiner's own key, unlocked by their passphrase) and multiple layered controls.

Valhuntir is LLM client agnostic — connect any locally installed MCP-compatible client through the gateway. Supported clients include Claude Code and Codex (agents with a shell, set up with Valhuntir's controls), self-hosted LibreChat and Open WebUI (MCP-only, with a locked configuration), and any client that supports Streamable HTTP transport with Bearer token authentication. The client must run on your machine or local network — cloud-hosted services cannot reach internal gateway addresses. Forensic discipline is provided structurally at the gateway and MCP layer, not through client-specific prompt engineering, so the same rigor applies regardless of which AI model or client drives the investigation.

Looking for a simpler setup without the gateway or OpenSearch? See Valhuntir Lite.

Evidence Indexing with OpenSearch (Optional)

With opensearch-mcp, evidence is parsed programmatically and indexed into OpenSearch, giving the LLM 21 purpose-built query tools instead of consuming billions of tokens reading raw artifacts. A 30-host triage collection with 50 million records becomes instantly searchable. Triage baseline and threat intelligence enrichment run programmatically — zero LLM tokens consumed.

15 parsers cover the forensic evidence spectrum: Windows Event Logs (evtx), 10 EZ Tool artifact types (Shimcache, Amcache, MFT, USN, Registry, Shellbags, Jumplists, LNK, Recyclebin, Timeline), Volatility 3 memory forensics, JSON/JSONL (Suricata, tshark, Velociraptor), delimited (CSV, TSV, Zeek, bodyfile, supertimelines), Apache/Nginx access logs, W3C (IIS, HTTPERR, Windows Firewall), Windows Defender MPLog, Scheduled Tasks XML, Windows Error Reporting, SSH auth logs, PowerShell transcripts, Prefetch/SRUM (via Plaso or wintools-mcp), and Linux and macOS volumes, folders and disk images (via Plaso).

Every parser produces deterministic content-based document IDs (re-ingest = zero duplicates), full provenance (host.name, vhir.source_file, vhir.ingest_audit_id), and proper @timestamp with timezone handling. Hayabusa auto-detection runs after EVTX ingest, applying 3,700+ Sigma rules and indexing alerts for structured querying.

Investigation Workflow

  1. Create a case — set case name, examiner identity, case directory
  2. Register evidence — hash files, establish chain of custody
  3. Ingest and index — parse evidence into OpenSearch for structured querying (or analyze files directly without OpenSearch)
  4. Scope the investigation — review what's indexed, identify hosts and artifact types, check for Hayabusa detection alerts
  5. Enrich programmatically — validate files/services against known-good baselines, check IOCs against threat intelligence (zero LLM tokens with opensearch-mcp)
  6. Search and analyze — query across millions of records, aggregate patterns, build timelines
  7. Record findings — LLM stages findings and timeline events as DRAFT with full evidence provenance
  8. Human review — examiner approves or rejects each finding via the Examiner Portal or CLI (each decision signed with the examiner's key)
  9. Generate report — produce IR report from approved findings with MITRE mappings and IOC aggregation

Without OpenSearch, steps 3-6 are replaced by the LLM doing direct tool execution and analysis. Still very effective, but slower and with much higher token cost. Findings, timeline, approval workflow, and reporting are identical either way.

Required Resources

Component Role RAM (min) RAM (rec) Disk Notes
Valhuntir with sift-mcp Gateway + 8 MCP backends 16 GB 16 GB 50 GB + evidence/extractions SIFT Workstation (Ubuntu). Gateway capped at 4 GB. 24 GB for memory analysis with Volatility 3.
Valhuntir + OpenSearch Above + evidence indexing 32 GB 32 GB 100 GB + evidence/extractions/indices OpenSearch JVM 6 GB, container 8 GB. Can run on separate host.
Valhuntir Lite Stdio MCPs only, no gateway 8 GB 16 GB 30 GB + evidence/extractions No OpenSearch. Direct MCP from LLM client.
OpenSearch (remote) Dedicated indexing host 12 GB 16 GB 100 GB + indices Alternative to co-located. Connects via HTTPS.
wintools-mcp Windows forensic tools 8 GB 16 GB 60 GB Separate Windows VM to run Windows-only tools.
REMnux Malware analysis 4 GB 8 GB 100 GB Optional. Separate VM. Docs.
OpenCTI Threat intelligence 16 GB 32 GB 50 GB SSD Optional. Separate host. Docs.

Platform Architecture

The examiner interacts with Valhuntir through three interfaces: the LLM client (AI-assisted investigation), the Examiner Portal (browser-based review and approval), and the vhir CLI (case management, evidence handling, and verification).

Deployment Overview

The typical deployment runs three VMs on a single host: SIFT (primary workstation), REMnux (malware analysis), and Windows (forensic tool execution). The examiner works on the SIFT VM — running the LLM client, the Examiner Portal in a browser, and the vhir CLI. REMnux and Windows are headless worker VMs. All three communicate over a VM-local network. Internet access is through NAT for external MCP services.

graph TB
    subgraph host ["Host Machine"]
        subgraph sift ["SIFT VM"]
            CC["LLM Client<br/>(human interface)"]
            BR["Browser<br/>(Examiner Portal)"]
            CLI["vhir CLI"]
            GW["sift-gateway :4508"]
            OSD["OpenSearch :9200<br/>(optional)"]
            CASE["Case Directory"]

            CC -->|"streamable-http"| GW
            BR -->|"HTTP"| GW
            GW -.->|"via opensearch-mcp"| OSD
            CLI --> CASE
        end

        subgraph remnux ["REMnux VM (optional)"]
            RAPI["remnux-mcp :3000"]
        end

        subgraph winbox ["Windows VM (optional)"]
            WAPI["wintools-mcp :4624"]
        end

        CC -->|"streamable-http"| RAPI
        GW -->|"HTTPS"| WAPI
        WAPI -->|"SMB"| CASE
    end

    subgraph internet ["Internet"]
        ML["MS Learn MCP"]
        ZE["Zeltser IR Writing MCP"]
        OCTI["OpenCTI (if external)"]
    end

    CC -->|"HTTPS"| ML
    CC -->|"HTTPS"| ZE
    GW -.->|"HTTP(S)"| OCTI
Loading

REMnux, Windows, and OpenSearch are optional. SIFT alone provides 73 MCP tools across 7 backends (90 with opensearch-mcp, 100 with wintools-mcp), the Examiner Portal, and full case management.

SIFT Platform Components

The sift-gateway aggregates up to 8 MCP backends as stdio subprocesses behind a single HTTP endpoint. Each backend is also available individually. The Examiner Portal is served by the gateway for browser-based review and approval. opensearch-mcp connects to a local or remote OpenSearch instance for evidence indexing and querying at scale.

graph LR
    GW["sift-gateway :4508"]

    FM["forensic-mcp<br/>23 tools · findings, timeline,<br/>evidence, discipline"]
    CM["case-mcp<br/>15 tools · case management,<br/>audit queries, backup"]
    RM["report-mcp<br/>6 tools · report generation,<br/>IOC aggregation"]
    SM["sift-mcp<br/>5 tools · Linux forensic<br/>tool execution"]
    RAG["forensic-rag<br/>3 tools · semantic search<br/>22K records"]
    WT["windows-triage<br/>13 tools · offline baseline<br/>validation"]
    OC["threatintel-mcp<br/>8 tools · threat<br/>intelligence"]
    OS["opensearch-mcp<br/>21 tools · evidence indexing,<br/>query, enrichment"]
    CD["Examiner Portal<br/>browser review + commit"]
    FK["forensic-knowledge<br/>shared YAML data"]
    CASE["Case Directory"]
    OSD["OpenSearch<br/>Docker :9200"]

    GW -->|stdio| FM
    GW -->|stdio| CM
    GW -->|stdio| RM
    GW -->|stdio| SM
    GW -->|stdio| RAG
    GW -->|stdio| WT
    GW -->|stdio| OC
    GW -->|stdio| OS
    GW --> CD
    FM --> FK
    SM --> FK
    FM --> CASE
    CM --> CASE
    RM --> CASE
    CD --> CASE
    OS --> OSD
Loading

Human-in-the-Loop Workflow

All findings and timeline events are staged as DRAFT by the AI. Only a human examiner can approve or reject them — via the Examiner Portal (browser) or the vhir CLI. Both paths sign each decision with the examiner's own key into the case's ledger, which vhir review --verify checks. The AI cannot approve its own findings. MCP guidance provides reminders to the LLM to check in with the human frequently for review and guidance.

sequenceDiagram
    participant AI as LLM + MCP Tools
    participant Case as Case Directory
    participant Human as Examiner<br/>(Portal or CLI)

    AI->>Case: record_finding() → DRAFT
    AI->>Case: record_timeline_event() → DRAFT
    Note over Case: Staged for review

    Human->>Case: Review, edit, approve/reject
    Human->>Case: Sign (passphrase unlocks the examiner's key)

    Note over Case: Only APPROVED items<br/>appear in reports
    Human->>Case: vhir report --full
Loading

The Examiner Portal (vhir portal) is the primary review interface — an 8-tab browser UI where examiners review, edit, approve, and reject findings and timeline events. The Commit button lists every decision, then signs them with the examiner's passphrase. The CLI's vhir approve provides the same capability from the terminal.

Examiners review findings in the Examiner Portal — validating artifacts, observations, and interpretations, with the full command audit trail from original evidence to final result.

Examiner Portal — Findings

The timeline view places findings and other observables in chronological context across the investigation.

Examiner Portal — Timeline

Forensic Knowledge Reinforcement

Valhuntir reinforces forensic discipline through multiple layers built into the MCP servers, client configuration, and gateway — not through a single system prompt that the LLM can drift from during long sessions.

  • Forensic Knowledge (FK) package — When a forensic tool is executed, the response is enriched with tool-specific caveats, corroboration suggestions, and field interpretation guidance. Delivered at the MCP response level, not in the system prompt, so it arrives exactly when the LLM needs it.
  • Discipline reminders — Each tool response includes a rotating forensic methodology reminder. Finding validation checks submissions against methodology standards and returns actionable feedback.
  • MCP server instructions — Each backend provides structured instructions during session initialization. The gateway aggregates them into a single coherent briefing.
  • Client configuration — For Claude Code, vhir setup client deploys forensic discipline docs, investigation rules, and tool reference guides as persistent context, and Valhuntir's workflows as Agent Skills. Other clients receive guidance through MCP server instructions.
  • Forensic RAG — Semantic search across 22,000+ records from 23 authoritative sources (Sigma, MITRE ATT&CK, LOLBAS, Atomic Red Team, and more). Grounds LLM analysis in authoritative references rather than training data.
  • Windows triage baseline — Offline validation against 2.6 million known-good records. No network calls required.

These layers reinforce each other through consistent, contextual repetition across all interaction surfaces. See the Architecture documentation for full details.

Where Things Run

Component Runs on Port Purpose
sift-gateway SIFT 4508 Aggregates SIFT-local MCPs behind one HTTP endpoint
forensic-mcp SIFT (via gateway) Findings, timeline, evidence, TODOs, IOCs, discipline (23 tools)
case-mcp SIFT (via gateway) Case management, audit queries, evidence registration, backup (15 tools)
report-mcp SIFT (via gateway) Report generation with profiles, IOC aggregation, MITRE mapping (6 tools)
sift-mcp SIFT (via gateway) Denylist-protected forensic tool execution on Linux/SIFT (5 tools)
opensearch-mcp SIFT (via gateway) Evidence indexing, structured querying, enrichment (21 tools). Optional.
forensic-rag-mcp SIFT (via gateway) Semantic search across Sigma, MITRE ATT&CK, Atomic Red Team, and more (3 tools)
windows-triage-mcp SIFT (via gateway) Offline Windows baseline validation (13 tools)
threatintel-mcp SIFT (via gateway) Threat intelligence: lookup_ioc returns each configured platform's records (OpenCTI, MISP), with no verdict; the other tools search OpenCTI. Also answers to opencti-mcp (8 tools)
OpenSearch SIFT (Docker) 9200 Evidence search engine. Local or remote. Optional.
Examiner Portal SIFT (via gateway) Browser-based review and approval. Primary review UI.
wintools-mcp Windows 4624 Catalog-gated forensic tool execution on Windows (10 tools)
vhir CLI SIFT -- Human-only: case init, evidence management, verification, exec. Approval also available via Examiner Portal. Remote examiners need SSH only for CLI-exclusive operations.
forensic-knowledge anywhere -- Shared YAML data package (tools, artifacts, discipline)

The gateway exposes each backend as a separate MCP endpoint. Clients can connect to the aggregate endpoint or to individual backends:

http://localhost:4508/mcp              # Aggregate (all tools)
http://localhost:4508/mcp/forensic-mcp
http://localhost:4508/mcp/case-mcp
http://localhost:4508/mcp/report-mcp
http://localhost:4508/mcp/sift-mcp
http://localhost:4508/mcp/opensearch-mcp
http://localhost:4508/mcp/windows-triage-mcp
http://localhost:4508/mcp/forensic-rag-mcp
http://localhost:4508/mcp/threatintel-mcp   # also /mcp/opencti-mcp

Multi-Examiner Team

graph LR
    subgraph e1 ["Examiner 1 — SIFT Workstation"]
        CC1["LLM Client<br/>(human interface)"]
        BR1["Browser<br/>(human interface)"]
        CLI1["vhir CLI"]
        GW1["sift-gateway<br/>:4508"]
        MCPs1["forensic-mcp · case-mcp · report-mcp<br/>sift-mcp · forensic-rag-mcp · opensearch-mcp<br/>windows-triage-mcp · threatintel-mcp"]
        CASE1["Case Directory"]

        CC1 -->|"streamable-http"| GW1
        BR1 -->|"HTTP"| GW1
        GW1 -->|stdio| MCPs1
        MCPs1 --> CASE1
        CLI1 --> CASE1
    end

    subgraph e2 ["Examiner 2 — SIFT Workstation"]
        CC2["LLM Client<br/>(human interface)"]
        BR2["Browser<br/>(human interface)"]
        CLI2["vhir CLI"]
        GW2["sift-gateway<br/>:4508"]
        MCPs2["forensic-mcp · case-mcp · report-mcp<br/>sift-mcp · forensic-rag-mcp · opensearch-mcp<br/>windows-triage-mcp · threatintel-mcp"]
        CASE2["Case Directory"]

        CC2 -->|"streamable-http"| GW2
        BR2 -->|"HTTP"| GW2
        GW2 -->|stdio| MCPs2
        MCPs2 --> CASE2
        CLI2 --> CASE2
    end

    CASE1 <-->|"export / merge"| CASE2
Loading

Case Directory Structure

cases/INC-2026-0219/
├── CASE.yaml                    # Case metadata (name, status, examiner)
├── evidence/                    # Original evidence (lock with vhir evidence lock)
├── extractions/                 # Extracted artifacts
├── reports/                     # Generated reports
├── findings.json                # F-alice-001, F-alice-002, ...
├── timeline.json                # T-alice-001, ...
├── todos.json                   # TODO-alice-001, ...
├── iocs.json                    # IOC-alice-001, ... (auto-extracted from findings)
├── evidence.json                # Evidence registry
├── actions.jsonl                # Investigative actions (append-only)
├── evidence_access.jsonl        # Chain-of-custody log
├── approvals.jsonl              # Approval audit trail
├── pending-reviews.json         # Portal edits awaiting approval
└── audit/
    ├── forensic-mcp.jsonl
    ├── sift-mcp.jsonl
    ├── claude-code.jsonl       # PostToolUse hook captures (Claude Code only)
    └── ...

External Dependencies

Quick Start

SIFT Workstation

Requires Python 3.10+ and sudo access. The installer handles everything: MCP servers, gateway, vhir CLI, the signed decision ledger and signing-key folders, examiner identity, and LLM client configuration. When you select Claude Code, additional forensic controls are deployed (kernel-level sandbox, case data deny rules, PreToolUse guard hook, PostToolUse audit hook, provenance enforcement, signed human approval). Other clients get MCP config only.

Quick — Core platform only, no databases (~70 MB):

curl -fsSL https://raw.githubusercontent.com/AppliedIR/sift-mcp/main/quickstart.sh -o /tmp/vhir-quickstart.sh && bash /tmp/vhir-quickstart.sh

Recommended — Adds the RAG knowledge base (22,000+ records from 23 authoritative sources) and Windows triage databases (2.6M baseline records), downloaded as pre-built snapshots. Requires ~14 GB disk space:

  • ~7 GB — ML dependencies (PyTorch, CUDA) required by the RAG embedding model
  • ~6 GB — Windows triage baseline databases (2.6M rows, decompressed)
  • ~1 GB — RAG index, source code, and everything else
curl -fsSL https://raw.githubusercontent.com/AppliedIR/sift-mcp/main/quickstart.sh -o /tmp/vhir-quickstart.sh && bash /tmp/vhir-quickstart.sh --recommended

Recommended with OpenSearch — Everything above plus evidence indexing at scale. Parses and indexes evidence into OpenSearch, giving the LLM 17 structured query tools instead of reading raw artifacts. Requires Docker.

curl -fsSL https://raw.githubusercontent.com/AppliedIR/sift-mcp/main/quickstart.sh -o /tmp/vhir-quickstart.sh && bash /tmp/vhir-quickstart.sh --recommended --opensearch

Custom — Individual package selection, OpenCTI integration, or remote access with TLS:

git clone https://github.com/AppliedIR/sift-mcp.git && cd sift-mcp
./setup-sift.sh

Windows Forensic Workstation (optional)

# Option 1: git clone
git clone https://github.com/AppliedIR/wintools-mcp.git; cd wintools-mcp

# Option 2: download ZIP (no git required)
Invoke-WebRequest https://github.com/AppliedIR/wintools-mcp/archive/refs/heads/main.zip -OutFile wintools.zip
Expand-Archive wintools.zip -DestinationPath .; cd wintools-mcp-main

Then run the installer:

.\scripts\setup-windows.ps1

Security Considerations

All Valhuntir components are assumed to run on a private forensic network, protected by firewalls, and not exposed to incoming connections from the Internet or potentially hostile systems. The design assumes dedicated, isolated systems are used throughout.

Any data loaded into the system or its component VMs, computers, or instances runs the risk of being exposed to the underlying AI. Only place data on these systems that you are willing to send to your AI provider.

Outgoing Internet connections are required for report generation (Zeltser IR Writing MCP) and optionally used for threat intelligence (OpenCTI, MISP) and documentation (MS Learn MCP). No incoming connections from external systems should be allowed.

Valhuntir is designed so that AI interactions flow through MCP tools, enabling security controls and audit trails. Clients with direct shell access (like Claude Code) get additional forensic controls deployed by vhir setup client — sandbox, deny rules, audit hooks, and provenance enforcement. Signed approval (each examiner's key, unlocked by their passphrase) is the primary security control and applies to all clients; what it does and doesn't prove is in the stated limits. Valhuntir is not designed to defend against a malicious AI or to constrain the AI client that you deploy. See the Security Model for details.

Commands

Most vhir CLI operations have MCP equivalents via case-mcp, forensic-mcp, and report-mcp. When working with an MCP-connected client, you can ask the AI to handle case management, evidence registration, report generation, and more — the AI operates through audited MCP tools rather than direct CLI invocation.

The commands below are intentional human-in-the-loop checkpoints. Approving and rejecting sign each decision with the examiner's key, which only their passphrase unlocks; verify checks every signature. The passphrase is read from the terminal, which a plain shell pipe can't supply. What that does and doesn't stop (a pseudo-terminal, a process with administrative rights) is in the stated limits.

Human-Only Commands (require the passphrase or a terminal)

These commands are for the examiner at a terminal. Valhuntir's Claude Code settings deny vhir approve and vhir reject to the assistant's shell tool, which guards against an accidental or instructed run; it isn't a security boundary.

approve

vhir approve                                             # Interactive review of all DRAFT items
vhir approve F-alice-001 F-alice-002 T-alice-001         # Approve specific IDs
vhir approve F-alice-001 --edit                          # Edit in $EDITOR before approving
vhir approve F-alice-001 --note "Malware family unconfirmed"  # Approve with examiner note
vhir approve --by jane                                   # Filter to IDs with jane's examiner prefix
vhir approve --findings-only                             # Skip timeline events
vhir approve --timeline-only                             # Skip findings
vhir approve --review                                    # Sign reviews staged in the portal
vhir approve --reattest F-alice-005                      # Fresh signed approval of an item approved before 0.6.4

Every decision is signed with the examiner's own Ed25519 key, which their passphrase unlocks. Every item to be signed, including each item decided with it ("cascade from F-…"), is shown before the passphrase prompt. A finding's evidence chain and grade are shown too, and its approval checks run first: the evidence it starts from is still registered and unchanged, its audit lines are unchanged, and each cited OpenSearch document still has its recorded hash (imported findings and findings from before 0.6.4 aren't checked again; a registered folder is checked by its manifest; a cited document is checked again only if its hash was recorded). A failed check needs a reason typed at the terminal, signed with the approval; with none, the item stays DRAFT. The --review flag signs the reviews staged in the Examiner Portal (pending-reviews.json): your own entries, and another examiner's only if you include them; exactly the entries signed leave the file. Alternatively, use the portal's Commit button (Shift+C): the browser signs in, unlocks the key and signs the decisions it lists, and the passphrase never leaves the browser.

reject

vhir reject F-alice-003 --reason "Insufficient evidence for attribution"
vhir reject F-alice-003 T-alice-002 --reason "Contradicted by memory analysis"
vhir reject --review                                     # Interactive walk-through of DRAFT items

Signed like an approval; it can also reject an APPROVED item.

exec

vhir exec --purpose "Extract MFT from image" -- fls -r -m / image.E01

Requires terminal confirmation. Logged to audit/cli-exec.jsonl. Use this for manual tool execution with audit trail when not operating through MCP.

evidence unlock

vhir unlock-evidence                       # Directory chmod 755, files remain 444
vhir evidence unlock

Requires terminal confirmation. Unlocking evidence allows writes to the evidence directory.

Passphrase and signing key

vhir config --setup-password               # Passphrase and signing key (at least 8 characters; 15+ recommended)
vhir config --reset-password               # Change the passphrase (the same key, re-encrypted)
vhir config --forgot-password              # New key under a new passphrase; the old one is kept as retired
vhir config --upgrade-key                  # Signing key for a 0.6 passphrase
vhir enrol --name lab2                     # A LAN examiner enrols at the SIFT terminal (also --reset, --forgot, --upgrade)

The passphrase is read from the terminal without echo. That stops a plain shell pipe from supplying it; it doesn't stop a program that runs vhir under a pseudo-terminal, or a process with administrative rights. See the Security Model.

Verification

vhir review --findings --verify                                      # Verify every signed decision
vhir review --findings --verify --expect-key alice=SHA256:… --expect-head 41:…   # Anchored to your records

No passphrase or terminal needed. Exit 0 means every approved item verifies (or was approved before 0.6.4, labelled so) with no failure. Verify prints every signing key with its full fingerprint and each chain's head. Without --expect-key and --expect-head it prints "Not anchored": compare the fingerprint with a copy kept off this machine (any earlier report, export or backup).

All Commands

The remaining commands can also be performed through MCP tools (case-mcp, forensic-mcp, report-mcp) when working with an MCP-connected client. The CLI equivalents are listed here for reference and for use outside MCP sessions.

portal

vhir portal                                              # Open the Examiner Portal in your browser

Opens the Examiner Portal for the active case. The portal is the primary review interface — examiners can review, edit, approve, reject, and commit findings entirely in the browser. The Commit button (Shift+C) lists every decision, then signs them with the examiner's passphrase. Alternatively, vhir approve --review signs the staged reviews from the CLI.

backup

vhir backup /path/to/destination                         # Back up case data (interactive)
vhir backup /path/to/destination --all                   # Evidence + extractions + OpenSearch
vhir backup /path/to/destination --include-opensearch    # Include OpenSearch indices
vhir backup /path/to/destination --include-evidence      # Include evidence files
vhir backup /path/to/destination --include-extractions   # Include extraction files
vhir backup --verify /path/to/backup/                    # Verify backup integrity

Creates a timestamped backup with SHA-256 manifest. It carries the case's signed history and public signing keys (ledger/), and no passphrase verifier or signing-key file. The --all flag includes evidence, extractions, and OpenSearch indices (if available). Without flags, interactive mode prompts per category with size estimates.

restore

vhir restore /path/to/backup/INC-2026-0411-2026-04-13   # Restore from backup
vhir restore /path/to/backup/... --skip-opensearch       # Skip OpenSearch restore
vhir restore /path/to/backup/... --skip-ledger           # Skip restoring the 0.6 approval records
vhir restore /path/to/backup/... --target /cases/INC-1   # Restore here, without asking

Restores a case from backup. Restore asks where to put the case, offering the folder it was backed up from; without a terminal (scripts), --target is required. A folder left by an interrupted restore is removed only after you answer yes (default no); without a terminal, remove it yourself first. Includes case files, the case's signed history, and OpenSearch indices (if present in backup). Each signing key the case's chains hold is added to this box as a retired public key ("KEY ADDED"), so the case verifies here. No credential is restored. Never auto-activates — run vhir case activate after restore.

case

vhir case init                                           # Interactive — prompts for name, ID, directory
vhir case init "Ransomware Investigation"                # Create with name, auto-generated ID
vhir case init "Investigation" --case-id INC-2026-001    # Create with custom case ID
vhir case activate INC-2026-02191200                     # Set active case
vhir case close INC-2026-02191200                        # Close a case by ID
vhir case reopen INC-2026-02191200                       # Reopen a closed case
vhir case list                                           # List available cases
vhir case status                                         # Show active case summary
vhir case migrate                                        # Migrate to flat layout (see below)

review

vhir review                                # Case summary (counts by status)
vhir review --findings                     # Findings table
vhir review --findings --detail            # Full finding detail
vhir review --iocs                         # IOCs grouped by approval status
vhir review --timeline                     # Timeline events
vhir review --timeline --status APPROVED   # Filter timeline by status
vhir review --timeline --start 2026-01-01 --end 2026-01-31   # Filter by date range
vhir review --timeline --type execution    # Filter by event type
vhir review --evidence                     # Evidence registry and access log
vhir review --audit --limit 100            # Audit trail (last N entries)
vhir review --todos --open                 # Open TODOs

todo

vhir todo                                                          # List open TODOs
vhir todo --all                                                    # Include completed
vhir todo add "Run volatility on server-04" --assignee jane --priority high --finding F-alice-003
vhir todo complete TODO-alice-001
vhir todo update TODO-alice-002 --note "Waiting on third party" --priority low

evidence

vhir evidence register /path/to/image.E01 --description "Disk image"   # Asks you to confirm at the terminal
vhir evidence list
vhir evidence verify
vhir evidence log [--path <filter>]
vhir evidence lock                         # All files chmod 444, directory chmod 555
vhir evidence unlock

Legacy aliases (vhir register-evidence, vhir lock-evidence, vhir unlock-evidence) still work.

export / merge

vhir export --file steve-findings.json      # Export findings for sharing
vhir merge --file jane-findings.json        # Merge another examiner's findings

report

vhir report --full [--save <path>]
vhir report --executive-summary [--save <path>]
vhir report --timeline [--from <date> --to <date>] [--save <path>]
vhir report --ioc [--save <path>]
vhir report --findings F-alice-001,F-alice-002 [--save <path>]
vhir report --status-brief [--save <path>]

audit

vhir audit log [--limit 100] [--mcp sift-mcp] [--tool run_command]
vhir audit summary

service

vhir service status                    # Show running backends + health
vhir service start forensic-rag        # Start a backend
vhir service stop windows-triage       # Stop a backend
vhir service restart sift-mcp          # Restart a backend

case migrate

vhir case migrate                                      # Migrate primary examiner data to flat layout
vhir case migrate --examiner alice                     # Specify examiner
vhir case migrate --import-all                         # Merge all examiners' data

config

vhir config --examiner "jane-doe"          # Set examiner identity
vhir config --show                         # Show current configuration

update

vhir update                       # Pull latest, reinstall, redeploy, restart
vhir update --check               # Check for updates without applying
vhir update --no-restart          # Skip gateway restart after update

join

vhir join --sift SIFT_URL --code CODE                            # Join from remote machine using join code
vhir join --sift SIFT_URL --code CODE --wintools                 # Join as wintools machine (registers backend)

Exchange a one-time join code for gateway credentials. Run on the remote machine (analyst laptop or Windows forensic workstation). The join code is generated on SIFT via vhir setup join-code. Credentials are saved to ~/.vhir/config.yaml with restricted permissions (0600).

setup

vhir setup client                          # Interactive client configuration (recommended)
vhir setup test                            # Test MCP server connectivity

setup client

Generate Streamable HTTP config for your LLM client:

vhir setup client                                                          # Interactive wizard
vhir setup client --client=claude-code --sift=http://127.0.0.1:4508 -y    # Local solo
vhir setup client --sift=SIFT_IP:4508 --windows=WIN_IP:4624               # SIFT + Windows

For remote orchestrator setups (Path 2), remote examiners run a platform-specific setup script that creates a ~/vhir/ workspace with MCP config, forensic controls, and discipline docs:

# Linux
curl -sSL https://raw.githubusercontent.com/AppliedIR/Valhuntir/main/setup-client-linux.sh \
  | bash -s -- --sift=https://SIFT_IP:4508 --code=XXXX-XXXX

# macOS
curl -sSL https://raw.githubusercontent.com/AppliedIR/Valhuntir/main/setup-client-macos.sh \
  | bash -s -- --sift=https://SIFT_IP:4508 --code=XXXX-XXXX
# Windows
Invoke-WebRequest -Uri https://raw.githubusercontent.com/AppliedIR/Valhuntir/main/setup-client-windows.ps1 -OutFile setup-client-windows.ps1
.\setup-client-windows.ps1 -Sift https://SIFT_IP:4508 -Code XXXX-XXXX

Always launch your LLM client from ~/vhir/ or a subdirectory. Forensic controls only apply when started from within the workspace. To uninstall, re-run the setup script with --uninstall (Linux/macOS) or -Uninstall (Windows).

Client Platforms Config file Extras
Claude Code Linux, macOS, Windows ~/vhir/.mcp.json or ~/.claude.json (SIFT) CLAUDE.md, settings.json, sandbox, audit hooks
Codex Linux, macOS, Windows ~/.codex/valhuntir.config.toml (codex -p valhuntir) Instructions in the profile, skills in ~/.agents/skills/, Codex's sandbox
LibreChat Any (browser) librechat.yaml (mcpServers section) Valhuntir generates librechat_mcp.yaml reference to merge
Open WebUI Any (browser) Admin Panel (steps printed) Lock profile openwebui-vhir.env and openwebui-system-prompt.md; see sift-mcp docs/open-webui-setup.md
Other Any vhir-mcp-config.json Manual integration

Claude Code on Windows requires Git for Windows (provides Git Bash) or WSL. Any MCP client that supports Streamable HTTP transport with Bearer token authentication will work — the gateway is not client-specific.

Examiner Identity

Every approval, rejection, and command execution is logged with examiner identity. Resolution order:

Priority Source Example
1 --examiner flag vhir approve --examiner jane-doe F-jane-001
2 VHIR_EXAMINER env var export VHIR_EXAMINER=jane-doe
3 ~/.vhir/config.yaml examiner: jane-doe
4 VHIR_ANALYST env var Deprecated fallback
5 OS username Warns if unconfigured

Operator environment variables (opensearch-mcp ingest resilience)

Env var Default Purpose
HAYABUSA_RULES_DIR (autodetect) Path to hayabusa-rules directory (must contain a config/ subdirectory). Set when hayabusa rules are installed outside the default locations (/usr/local/share/hayabusa-rules, /usr/share/hayabusa-rules, /opt/hayabusa*/rules). Example: Environment=HAYABUSA_RULES_DIR=/srv/forensics/hayabusa-rules in the gateway systemd unit file.
VHIR_SHARD_BREAKER_THRESHOLD 3 Consecutive shard-limit batch failures before the bulk-write circuit breaker halts ingest.
VHIR_INTEL_BREAKER_THRESHOLD 10 Consecutive lookup errors, or consecutive unavailable answers from every configured threat-intel provider, before enrichment halts. Rate limits don't count.
VHIR_INTEL_RATE_LIMIT_RETRIES 5 Per-IOC retry cap when a threat-intel provider rate-limits.
VHIR_INTEL_MIN_INTERVAL_MS 100 Minimum milliseconds between threat-intel lookups (default ~10 QPS). Prevents self-inflicted rate limits. Clamped to a 10ms floor.

All thresholds clamp to a sane lower bound (operator typo of 0 won't disable safety).

Repo Map

Repo Purpose
sift-mcp Monorepo: 11 SIFT packages (forensic-mcp, case-mcp, report-mcp, sift-mcp, sift-gateway, case-dashboard, forensic-knowledge, forensic-rag, windows-triage, opencti, sift-common)
opensearch-mcp Evidence indexing + querying via OpenSearch (21 tools, 15 parsers). Optional.
wintools-mcp Windows forensic tool execution (10 tools, 31 catalog entries)
Valhuntir CLI, architecture reference

Updating

Valhuntir

vhir update              # Pull latest code, reinstall packages, redeploy controls, restart gateway
vhir update --check      # Check for updates without applying
vhir update --no-restart # Update without restarting the gateway

The update command pulls the latest code from all configured repos (sift-mcp, vhir, opensearch-mcp, wintools-mcp), reinstalls all packages, redeploys forensic controls, restarts the gateway, and runs a connectivity smoke test.

Valhuntir Lite

In its simplest form, Valhuntir Lite provides Claude Code with forensic knowledge and instructions on how to enforce forensic rigor, present findings for human review, and audit actions taken. MCP servers enhance accuracy by providing authoritative information — a forensic knowledge RAG and a Windows triage database — plus optional OpenCTI threat intelligence and REMnux malware analysis.

Quick — Forensic discipline, MCP packages, and config. No databases (<70 MB):

git clone https://github.com/AppliedIR/sift-mcp.git
cd sift-mcp
./quickstart-lite.sh --quick

Recommended — Adds the RAG knowledge base (22,000+ records from 23 authoritative sources) and Windows triage databases (2.6M baseline records). Requires ~14 GB disk space:

  • ~7 GB — ML dependencies (PyTorch, CUDA) required by the RAG embedding model
  • ~6 GB — Windows triage baseline databases (2.6M rows, decompressed)
  • ~1 GB — RAG index, source code, and everything else
git clone https://github.com/AppliedIR/sift-mcp.git
cd sift-mcp
./quickstart-lite.sh

This one-time setup takes approximately 15-30 minutes depending on internet speed and CPU. Subsequent runs reuse existing databases and index.

claude
/welcome

To update an existing Valhuntir Lite installation, re-run the installer from an updated clone:

cd sift-mcp
git pull
./quickstart-lite.sh

The installer is idempotent — it reuses the existing venv, skips databases and RAG index if already present, and redeploys config files.

Lite Architecture

graph LR
    subgraph analyst ["Analyst Machine"]
        CC["Claude Code<br/>(human interface)"]
        FR["forensic-rag-mcp<br/>Knowledge search"]
        WTR["windows-triage-mcp<br/>Baseline validation"]

        CC -->|stdio| FR
        CC -->|stdio| WTR
    end
Loading

Lite with Optional Add-ons

graph LR
    subgraph analyst ["Analyst Machine"]
        CC["Claude Code<br/>(human interface)"]
        FR["forensic-rag-mcp<br/>Knowledge search"]
        WTR["windows-triage-mcp<br/>Baseline validation"]
        OC["threatintel-mcp<br/>Threat intelligence"]

        CC -->|stdio| FR
        CC -->|stdio| WTR
        CC -->|stdio| OC
    end

    subgraph octi ["OpenCTI Instance"]
        OCTI[OpenCTI]
    end

    subgraph remnux ["REMnux Workstation"]
        RAPI["remnux-mcp API<br/>:3000"]
        RMX["remnux-mcp<br/>Malware analysis"]
        RAPI --> RMX
    end

    subgraph internet ["Internet"]
        ML["MS Learn MCP<br/>(HTTPS)"]
        ZE["Zeltser IR Writing MCP<br/>(HTTPS)"]
    end

    CC -->|"streamable-http"| RAPI
    CC -->|"HTTPS"| ML
    CC -->|"HTTPS"| ZE
    OC -->|"HTTP(S)"| OCTI
Loading
Connection Protocol Notes
Claude Code → forensic-rag-mcp stdio Local Python process, always present
Claude Code → windows-triage-mcp stdio Local Python process, always present
Claude Code → threatintel-mcp stdio Local Python process, connects out to OpenCTI (and MISP, if configured) via HTTP(S)
threatintel-mcp → OpenCTI or MISP instance HTTP(S) threatintel-mcp runs locally, calls out to each configured platform
Claude Code → remnux-mcp streamable-http Remote, on its own REMnux workstation
Claude Code → MS Learn MCP HTTPS https://learn.microsoft.com/api/mcp — streamable-http type in .mcp.json
Claude Code → Zeltser IR Writing MCP HTTPS https://website-mcp.zeltser.com/mcp — streamable-http type in .mcp.json

No gateway, no sandbox, no deny rules. Claude runs forensic tools directly via Bash. Forensic discipline is suggested and reinforced via prompt hooks and reference documents, but Claude Code can choose to ignore them. See the sift-mcp README for optional add-on install flags (--opencti, --remnux, --mslearn, --zeltser).

What changes for AI clients in this release

After vhir update (or vhir setup client) redeploys the client controls:

  • Claude Code refuses to start without its sandbox. On a host where bubblewrap can't run, Claude Code now stops with a message instead of running Bash unconfined. vhir setup client --allow-unsandboxed (with a typed phrase) deploys the old behaviour, and the controls block then says SANDBOX OFF.
  • The AI's shell can't read the signing and approval store (/var/lib/vhir). vhir backup, vhir case close and vhir export run from inside the AI's sandbox now stop with a message instead of leaving the signed history out; run them in your own terminal.
  • The Write(...) deny rules are gone (the Edit(...) rules already cover writing tools); a redeploy takes vhir's old ones off, and your own rules stay.
  • Failed and refused commands are audited too. A failed command, a call the permission mode refused and a refusal by the case-data guard each leave a line in the case's audit file. Deny-rule refusals still leave none.
  • Codex is supported on the SIFT workstation. Setting it up installs Codex's managed requirements (/etc/codex/requirements.toml, with your consent), which apply to every Codex session on the machine: its sandbox stays on, its shell can't read the store or the gateway's tokens, and its commands are audited into the active case (marked outside_case when the session runs elsewhere). A ~/.codex/config.toml that asks for danger-full-access then stops Codex from starting: setup names the line. To turn the requirements off, see sift-mcp docs/codex.md#opt-out.
  • Setup prints what each control protects and what it doesn't (the same table is in docs/security.md). In short: run_command still runs as you, with sudo, outside every sandbox, so client-side controls prevent accidents and record what happened; an approved finding's signature catches a later change.

Upgrading from Lite to Valhuntir

Both modes share the same Python venv, triage databases, and RAG index. Valhuntir adds the gateway (up to 8 MCP backends behind one HTTP endpoint), 4+ additional MCP servers (forensic-mcp, case-mcp, report-mcp, sift-mcp, and optionally opensearch-mcp), a web-based review portal (Examiner Portal), structured case management, sandbox enforcement, and signed approvals.

To upgrade, run setup-sift.sh from your existing sift-mcp clone. The installer reuses the existing venv and databases. Lite case data (markdown files) does not auto-migrate to Valhuntir case data (structured JSON) — start fresh or transfer findings manually.

Evidence Handling

Never place original evidence on any Valhuntir system. Only use working copies for which verified originals or backups exist. Valhuntir workstations process evidence through AI-connected tools, and any data loaded into these systems may be transmitted to the configured AI provider. Treat all Valhuntir systems as analysis environments, not evidence storage.

Evidence integrity is verified by SHA-256 hashes recorded at registration. Examiners can optionally lock evidence to read-only via vhir evidence lock. Proper evidence integrity depends on verified hashes, write blockers, and chain-of-custody procedures that exist outside this platform.

Case directories can reside on external or removable media. ext4 is preferred for full permission support. NTFS and exFAT are acceptable but file permission controls (read-only protection) will be silently ineffective. FAT32 is discouraged due to the 4 GB file size limit.

Responsible Use and Legal

While steps have been taken to enforce human-in-the-loop controls, it is ultimately the responsibility of each examiner to ensure that their findings are accurate and complete. The AI, like a hex editor, is a tool to be used by properly trained incident response professionals. Users are responsible for ensuring their use complies with applicable laws, regulations, and organizational policies. Use only on systems and data you are authorized to analyze.

This software is provided "as is" without warranty of any kind. See LICENSE for full terms.

MITRE ATT&CK is a registered trademark of The MITRE Corporation. SIFT Workstation is a product of the SANS Institute.

Acknowledgments

Architecture and direction by Steve Anson. Implementation by Claude Code (Anthropic). Code review by Codex (OpenAI). Design inspiration drawn from Lenny Zeltser's REMnux MCP.

Clear Disclosure

I do DFIR. I am not a developer. This project would not exist without Claude Code handling the implementation. While an immense amount of effort has gone into design, testing, and review, I fully acknowledge that I may have been working hard and not smart in places. My intent is to jumpstart discussion around ways this technology can be leveraged for efficiency in incident response while ensuring that the ultimate responsibility for accuracy remains with the human examiner.

License

MIT License - see LICENSE

About

Valhuntir CLI — AI-augmented incident response platform

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

113 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages