sharkdp/hexyl
A command-line hex viewer
Healthy across the board
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 1w ago
- ✓22+ active contributors
- ✓Apache-2.0 licensed
Show all 6 evidence items →Show less
- ✓CI configured
- ✓Tests present
- ⚠Concentrated ownership — top contributor handles 52% of recent commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/sharkdp/hexyl)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/sharkdp/hexyl on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: sharkdp/hexyl
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/sharkdp/hexyl shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across the board
- Last commit 1w ago
- 22+ active contributors
- Apache-2.0 licensed
- CI configured
- Tests present
- ⚠ Concentrated ownership — top contributor handles 52% of recent commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live sharkdp/hexyl
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/sharkdp/hexyl.
What it runs against: a local clone of sharkdp/hexyl — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in sharkdp/hexyl | Confirms the artifact applies here, not a fork |
| 2 | License is still Apache-2.0 | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 38 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of sharkdp/hexyl. If you don't
# have one yet, run these first:
#
# git clone https://github.com/sharkdp/hexyl.git
# cd hexyl
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of sharkdp/hexyl and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "sharkdp/hexyl(\\.git)?\\b" \\
&& ok "origin remote is sharkdp/hexyl" \\
|| miss "origin remote is not sharkdp/hexyl (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
&& ok "license is Apache-2.0" \\
|| miss "license drift — was Apache-2.0 at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "src/main.rs" \\
&& ok "src/main.rs" \\
|| miss "missing critical file: src/main.rs"
test -f "src/lib.rs" \\
&& ok "src/lib.rs" \\
|| miss "missing critical file: src/lib.rs"
test -f "src/colors.rs" \\
&& ok "src/colors.rs" \\
|| miss "missing critical file: src/colors.rs"
test -f "src/input.rs" \\
&& ok "src/input.rs" \\
|| miss "missing critical file: src/input.rs"
test -f "Cargo.toml" \\
&& ok "Cargo.toml" \\
|| miss "missing critical file: Cargo.toml"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 38 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~8d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/sharkdp/hexyl"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
hexyl is a command-line hex viewer written in Rust that displays binary file contents in the terminal with color-coded byte categories (NULL bytes, printable ASCII, whitespace, other ASCII, and non-ASCII). It solves the problem of inspecting binary files interactively with human-readable colored output that distinguishes byte types at a glance, replacing the generic hexdump utility with a modern, terminal-aware alternative. Single-binary crate structure: src/main.rs is the entry point (CLI via clap derive macros), src/lib.rs exports core logic, src/colors.rs handles byte categorization and terminal color output, src/input.rs manages file reading. tests/integration_tests.rs runs end-to-end tests against example files in tests/examples/ (ascii, empty, hello_world_elf64). No monorepo; all code is in src/ with examples/ for demonstrations.
👥Who it's for
Systems engineers, reverse engineers, and developers debugging binary protocols or file formats who need to inspect raw bytes in the terminal. Also useful for anyone working with compiled binaries, network packets, or corrupted file recovery who wants better visual distinction than traditional hex utilities.
🌱Maturity & risk
Production-ready and actively maintained. At version 0.17.0 with CICD automation (GitHub Actions in .github/workflows/CICD.yml), dual licensing (MIT/Apache-2.0), official packages in Debian/Ubuntu/Fedora/Arch/macOS, and integration tests (tests/integration_tests.rs). The Rust 1.88 MSRV and modern build settings (LTO enabled in release profile) indicate stability.
Low risk. Minimal dependency surface (anyhow, clap, owo-colors, terminal_size, thiserror, libc) with stable versions pinned in Cargo.lock. Single maintainer (David Peter) but strong community adoption across major Linux distributions. No hidden breaking-change indicators visible; the project is well-scoped and unlikely to introduce incompatibilities.
Active areas of work
No specific recent changes are visible from the provided file list, but the project is actively maintained with version 0.17.0 released. CICD pipeline is active (CICD.yml), suggesting ongoing validation and release management. The README shows comprehensive platform support being maintained across Linux, macOS, FreeBSD, Windows, and even Termux.
🚀Get running
Clone the repo and build with Cargo (Rust 1.88+): git clone https://github.com/sharkdp/hexyl && cd hexyl && cargo build --release. The binary will be in target/release/hexyl. Test it immediately: ./target/release/hexyl tests/examples/hello_world_elf64.
Daily commands:
Development: cargo run -- [FILE] (e.g., cargo run -- tests/examples/hello_world_elf64). Release: cargo build --release then run target/release/hexyl directly. Tests: cargo test (runs both unit tests in src/tests.rs and integration tests in tests/integration_tests.rs).
🗺️Map of the codebase
src/main.rs— Entry point and CLI argument parsing using clap; every contributor must understand the command structure and how input arguments flow to the viewersrc/lib.rs— Core library interface exposing the hex viewer logic; essential for understanding the public API and how file data is processed into outputsrc/colors.rs— Byte classification and color mapping system that distinguishes NULL, ASCII, whitespace, and non-ASCII bytes; critical for the tool's core visual featuresrc/input.rs— File reading and input handling abstractions; essential for understanding how data flows from disk into the viewer pipelineCargo.toml— Project metadata, dependencies (clap, owo-colors, terminal_size), and release optimizations; must-read for build and dependency decisionstests/integration_tests.rs— End-to-end test suite validating hex output correctness; contributors adding features must verify tests still pass
🧩Components & responsibilities
- CLI & Argument Parsing (main.rs) (clap with derive macros) — Accepts user arguments, validates file paths, initializes the hex viewer engine with options
- Failure mode: Invalid arguments cause early exit with error message; missing/unreadable files propagate I/O errors
- Input Abstraction (input.rs) (libc, std::io) — Opens and buffers data from various input sources (files, stdin); provides unified stream interface
- Failure mode: Permission errors, file not found, I/O failures abort display; incomplete reads may display partial hex
- Hex Viewer Engine (lib.rs) (Rust iterators, formatting) — Orchestrates byte reading, categorization, formatting, and colored output generation; core business logic
- Failure mode: Logic errors in formatting or offset calculation produce misaligned hex/ASCII output
- Byte Categorizer (colors.rs) (owo-colors, ANSI color codes) — Classifies each byte (NULL, printable ASCII, whitespace, other ASCII, non-ASCII) and assigns colors
- Failure mode: Incorrect classification leads to wrong colors; color codes fail silently on non-color terminals (handled by supports-color)
- Terminal Output (owo-colors, supports-color, terminal_size) — Writes formatted, colored hex rows to stdout with proper line breaks and ANSI codes
- Failure mode: Terminal width detection errors may cause line wrapping; color stripping gracefully degrades on unsupported terminals
🔀Data flow
User Shell→main.rs (CLI Parser)— Command-line arguments and file pathmain.rs→input.rs (File Reader)— Requested file path or descriptor; mode (file or stdin)input.rs→lib.rs (Hex Engine)— Raw bytes from file/stream in chunkslib.rs→colors.rs (Categorizer)— Each byte value for classificationcolors.rs→lib.rs— Byte category and assigned color codelib.rs→Terminal Output— Formatted hex rows with ANSI color codes and ASCII representation
🛠️How to make changes
Add a new byte category and color
- Define new ByteCategory variant in the byte classification enum in src/colors.rs (
src/colors.rs) - Implement color mapping for the new category in the color assignment function (
src/colors.rs) - Update the categorization logic that assigns bytes to categories based on their value (
src/colors.rs) - Add integration test in tests/integration_tests.rs to verify the new category is rendered correctly (
tests/integration_tests.rs)
Add a new command-line option
- Add a new field with #[arg(...)] attribute to the CLI struct in src/main.rs (
src/main.rs) - Pass the option value to the library function call in src/main.rs (
src/main.rs) - Modify the relevant function signature in src/lib.rs to accept the new parameter (
src/lib.rs) - Implement the feature logic in src/lib.rs or src/colors.rs as appropriate (
src/lib.rs) - Add integration test cases in tests/integration_tests.rs covering the new option (
tests/integration_tests.rs)
Support a new input source (e.g., network, pipe)
- Create a new input type or extend the input abstraction in src/input.rs (
src/input.rs) - Update the input handling logic in src/main.rs to recognize and construct the new input type (
src/main.rs) - Ensure the new input type implements the expected trait/interface for the hex viewer engine (
src/lib.rs) - Add test files to tests/examples/ directory with sample data for the new source (
tests/examples) - Add integration tests in tests/integration_tests.rs to validate reading from the new source (
tests/integration_tests.rs)
🔧Why these technologies
- Rust + Cargo — Memory-safe, compiled, high-performance CLI tool with zero-cost abstractions; ideal for low-level byte processing
- clap (derive macros) — Declarative CLI parsing with automatic help generation and validation; reduces boilerplate for argument handling
- owo-colors — Lightweight, zero-runtime-cost color abstraction for terminal output; enables colored byte categorization display
- supports-color — Detects terminal color support at runtime; gracefully degrades output on non-color terminals
- terminal_size — Queries terminal dimensions to format output to available width; essential for responsive hex display
⚖️Trade-offs already made
-
Use colored output as primary visual feature rather than interactive GUI
- Why: Keep tool lightweight, scriptable, and composable with Unix pipes; maximize accessibility in remote/embedded environments
- Consequence: Users cannot interactively search or navigate large files; output is read-only stream
-
Fixed 16 bytes per row in hex display
- Why: Standard convention, fits common terminal widths, easy to parse visually by humans
- Consequence: Limited flexibility in output layout; not optimizable for ultra-wide or narrow terminals
-
Process entire file or stream into memory before display
- Why: Simplifies color assignment and formatting logic; allows complete view of file structure
- Consequence: High memory usage for very large files; not suitable for streaming gigabyte-scale datasets
🚫Non-goals (don't propose these)
- Does not provide interactive hex editing; read-only viewer
- Does not support searching or filtering within hex output
- Does not implement GUI or TUI; terminal/CLI only
- Does not provide binary diff or comparison tools
- Does not support custom color themes or theming system
⚠️Anti-patterns to avoid
- Potential unbounded memory usage: undefined
🪤Traps & gotchas
No major gotchas, but note: (1) Color output detection uses supports-color crate (checks env vars like NO_COLOR, FORCE_COLOR); piping to a file will auto-disable colors unless FORCE_COLOR=1. (2) Terminal width detection via terminal_size may fail in non-TTY contexts (e.g., CI logs); graceful fallback to 80 columns likely exists but worth confirming. (3) MSRV is 1.88 (relatively recent); older Rust toolchains will not build this. (4) libc dependency means platform-specific behavior on Windows vs Unix.
🏗️Architecture
💡Concepts to learn
- ANSI/VT100 color codes — hexyl uses owo-colors to emit ANSI escape sequences for terminal colors; understanding how color codes work (e.g., \x1b[38;5;196m) is essential to grokking why output differs between TTY and non-TTY contexts
- Byte categorization heuristics — The core insight of hexyl is classifying bytes (NULL, printable ASCII, whitespace, non-ASCII) to visually distinguish them; this requires understanding ASCII ranges (0x00, 0x20–0x7E, 0x7F–0xFF) and why those boundaries matter
- Terminal capability detection — hexyl uses the supports-color crate to detect if the terminal actually supports colors (checking isatty(), env vars like NO_COLOR, FORCE_COLOR); this determines whether to emit ANSI codes or fall back to plain text
- Hex dump format conventions — hexyl outputs the standard hex dump layout (address | hex bytes | ASCII repr); understanding padding, spacing, and row alignment (typically 16 bytes per row) is needed to modify the display format in src/lib.rs
- Streaming file I/O buffering — hexyl reads files in chunks via src/input.rs to handle large binaries without loading entire files into memory; understanding buffer sizes and read semantics is key for performance optimization
- Derive macros in clap — hexyl's CLI is defined via clap derive macros in src/main.rs (not builder pattern); learning how #[derive(Parser)] and #[arg(...)] attributes work is essential to adding new flags or subcommands
- UTF-8 vs binary-safe string handling — Hex viewers must handle arbitrary bytes, including non-UTF-8 sequences; hexyl uses Rust's u8 slices and avoids String coercion to preserve binary fidelity in src/colors.rs and src/lib.rs
🔗Related repos
xxd-rs/xxd— Pure Rust reimplementation of the classic xxd hex dumper; similar scope but less emphasis on coloringsharkdp/bat— Same author; cat clone with syntax highlighting; demonstrates terminal color handling patterns reusable in hexylBurntSushi/ripgrep— Rust CLI tool ecosystem reference; shows modern clap usage, terminal detection, and fast binary-safe processingogham/exa— Rust ls replacement; similar problem domain (terminal UI, color output, file inspection) with cross-platform constraintsbootandy/dust— Rust disk usage visualizer; shares hexyl's terminal-UI and owo-colors dependency patterns for colored output
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add integration tests for color output validation
The repo has color-related functionality (src/colors.rs, owo-colors dependency) but tests/integration_tests.rs likely doesn't validate colored output. Add tests to verify ANSI color codes are correctly applied based on byte categories (NULL, printable ASCII, whitespace, etc.) mentioned in README.
- [ ] Review existing tests in tests/integration_tests.rs to understand current test patterns
- [ ] Add test cases that capture hexyl output with color flags and validate ANSI escape sequences
- [ ] Test color output for each byte category defined in src/colors.rs (NULL bytes, printable ASCII, whitespace, non-ASCII)
- [ ] Test --no-squeezing flag interaction with colors to ensure consistency
Add edge-case unit tests for src/input.rs
The input.rs module handles file reading and stdin processing, which are critical for a hex viewer but likely have minimal unit test coverage. Add specific tests for boundary conditions and error cases.
- [ ] Examine src/input.rs to identify public functions and error paths
- [ ] Add unit tests in src/tests.rs or directly in src/input.rs for: empty files, very large files, non-existent files, permission errors, and stdin EOF handling
- [ ] Test behavior with partial reads and interrupted input streams
- [ ] Validate proper error propagation using thiserror types defined in the crate
Expand doc/hexyl.1.md man page with advanced usage examples
The man page exists but README shows the installation section is incomplete (truncated at 'If you use an older versi'). Complete the README and add practical examples to the man page for common use cases like piping, filtering, and integration with other tools.
- [ ] Complete the truncated installation instructions in README.md for older Ubuntu versions and other platforms
- [ ] Add sections to doc/hexyl.1.md for: combining hexyl with pipes/filters, examining binary files, limiting output with --length, and comparing files
- [ ] Include example commands showing hexyl with common tools (grep, head, tail, xxd comparisons)
- [ ] Verify man page renders correctly with
man ./doc/hexyl.1.mdor similar tools
🌿Good first issues
- Add a --no-colors / --monochrome flag: Currently color output respects supports-color detection, but no explicit flag exists. Modify src/main.rs to add a clap boolean field and thread it through src/lib.rs to skip owo-colors calls.
- Expand integration test coverage: tests/integration_tests.rs only references 3 example files (ascii, empty, hello_world_elf64). Add test cases for edge cases like binary files with high-bit bytes, large files (>1MB), or files with BOM markers.
- Document the byte classification algorithm: src/colors.rs categorizes bytes (NULL=0x00, printable ASCII=0x20-0x7E, etc.) but lacks inline comments. Add a detailed doc comment block explaining the category ranges and why each exists for maintainability.
⭐Top contributors
Click to expand
Top contributors
- @sharkdp — 52 commits
- @sharifhsn — 20 commits
- @GrigorenkoPV — 3 commits
- @Its-Just-Nans — 2 commits
- @dan-hipschman — 2 commits
📝Recent commits
Click to expand
Recent commits
6ecc29b— Remove sponsors (sharkdp)8eb6d47— Bump version to v0.17.0 (sharkdp)5d05382— Update README (sharkdp)626f03b— Fix #254 (sharkdp)04d74ba— feat: handle standard input "-" (#257) (Its-Just-Nans)96e427c— Improve crate && fix CI (#256) (Its-Just-Nans)7f8db4f— Add colors to --help (#253) (starsep)2e26437— Add option to output result in C include file style (#242) (#246) (wpcwzy)269860b— Update README (sharkdp)2c8be77— Update README (sharkdp)
🔒Security observations
The hexyl codebase demonstrates good security posture overall. As a command-line hex viewer utility written in Rust, it benefits from Rust's memory safety guarantees. The main security considerations are: (1) careful auditing of unsafe libc FFI bindings used for terminal operations, (2) validation of file paths to prevent directory traversal, and (3) establishing a vulnerability disclosure policy. Dependencies appear well-maintained and appropriate for the use case. No hardcoded secrets, SQL injection risks, or obvious injection vulnerabilities were identified. The application does not expose network services or have Docker deployment complexity based on the visible file structure.
- Low · Use of unsafe libc bindings —
Cargo.toml (libc = "0.2" dependency), src/input.rs. The crate includes 'libc' as a direct dependency. While libc itself is a legitimate and widely-used FFI binding, any usage of libc functions requires 'unsafe' blocks in Rust. The security impact depends on how libc is used in the codebase (e.g., terminal I/O operations). Review src/input.rs and other files for proper error handling and bounds checking when calling libc functions. Fix: Audit all libc function calls for proper error handling, validate all inputs before passing to libc functions, and document the safety invariants of unsafe blocks. Consider whether libc usage can be minimized in favor of pure Rust alternatives. - Low · Potential unvalidated command-line input handling —
src/main.rs, src/input.rs. The crate uses clap 4 for command-line argument parsing. While clap is generally safe, the application should validate file paths and other inputs to prevent directory traversal or other path-based attacks when processing user-supplied file arguments. Fix: Validate and canonicalize file paths before opening them. Implement checks to prevent path traversal attacks (e.g., using std::fs::canonicalize and validating paths are within expected directories if applicable). Use clap's built-in validators where possible. - Low · Missing SECURITY.md or vulnerability disclosure policy —
Repository root. There is no visible security.md or documented vulnerability disclosure policy in the repository. This makes it unclear how security researchers should report vulnerabilities. Fix: Create a SECURITY.md file documenting how to responsibly report security vulnerabilities. Include contact information and a clear process for handling security reports.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.