shellhist-core 0.1.0

Shell command-history reader: bash, zsh (extended), PowerShell PSReadLine, and fish history files → typed, timestamped entries
Documentation
  • Coverage
  • 85.71%
    24 out of 28 items documented0 out of 13 items with examples
  • Size
  • Source code size: 28.18 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 514.61 kB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 2s Average build duration of successful builds.
  • all releases: 2s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • Homepage
  • SecurityRonin/shellhist-forensic
    0 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • h4x0r

shellhist-core

shellhist-core shellhist-forensic Docs.rs License: Apache-2.0 CI Sponsor

A from-scratch shell command-history reader — bash, zsh (EXTENDED_HISTORY), fish, and PowerShell PSReadLine into one uniform, timestamped HistoryEntry stream. No unsafe, no regex engine, no C bindings — reads a history file authored on any OS.

[dependencies]
shellhist-core = "0.1"
use shellhist_core::{parse_auto, detect, Shell};

// Detect the format from the bytes (the filename only disambiguates ties)…
assert_eq!(detect(b": 1700000000:0;ls", None), Shell::Zsh);
assert_eq!(detect(b"#1700000000\nls\n", None), Shell::Bash);

// …or just parse. zsh EXTENDED_HISTORY entries carry both timestamp and elapsed.
let entries = parse_auto(b": 1700000000:5;make build\n", None);
assert_eq!(entries[0].command, "make build");
assert_eq!(entries[0].timestamp, Some(1_700_000_000));
assert_eq!(entries[0].elapsed, Some(5));

What it parses

parse_auto(data, filename) sniffs the format and parses; detect(data, filename) returns the [Shell] without committing; parse(data, shell) parses a known format. Per-format entry points live in shellhist_core::{bash, zsh, fish, powershell}::parse. Every path yields the same [HistoryEntry] (shell, command, timestamp, elapsed, paths):

  • bash (.bash_history) — plain one-command-per-line, plus #<epoch> timestamp lines (HISTTIMEFORMAT) and multi-line commands that keep their embedded newlines.
  • zsh (.zsh_history) — plain lines and EXTENDED_HISTORY : <start>:<elapsed>;<cmd> records with backslash continuation; both timestamp and elapsed are retained.
  • fish (fish_history) — the nearly-YAML - cmd: / when: / paths: record format with its 2-rule unescape; heuristically associated paths are kept on the entry.
  • PowerShell PSReadLine (ConsoleHost_history.txt) — plain commands with backtick line continuation; no timestamps (the format records none).

A leading UTF-8 BOM is stripped (strip_bom); an undetectable file parses as plain one-command-per-line (Shell::Unknown).

Trust, but verify

#![forbid(unsafe_code)]; panic-free on crafted input (the workspace denies clippy::unwrap_used / expect_used in production code, parsing is lenient lossy-UTF-8 and bounds-checked); fuzzed with cargo-fuzz targets per format (bash, zsh, fish, powershell); the reader is exercised against a history file generated by a real bash subshell, not only synthetic fixtures.

Forensic analysis

Severity-graded anomaly auditing (history-clearing / timestamp-regression / download-pipe-to-shell / encoded-PowerShell findings) lives in the sibling shellhist-forensic crate, built on this one — the reader/analyzer split mirrors ntfs-core/ntfs-forensic.


Privacy Policy · Terms of Service · © 2026 Security Ronin Ltd