Skip to content

Latest commit

 

History

96 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

histclean

Clean duplicate shell commands from shell history files, while preserving the most recent occurrence of each command.

TL;DR

You can either download the latest binary from releases page.

Or clone the repo, then build it with the Zig compiler (zig >= 0.16)

git clone https://github.com/ABDsheikho/histclean.git
cd histclean
zig build install

If that's your first time running histclean, don't forget to pass --backup option to backup your history file:

histclean -b

Requirements

Zig compiler >= 0.16

Note

Since Zig is pre 1.0 release, histclean will always follow the latest Zig release.

Installation

Build

First clone the repo:

git clone https://github.com/ABDsheikho/histclean.git
cd histclean

Then build it using the Zig compiler:

zig build install

Or with a custom prefix:

zig build --prefix /usr/local

Download

If you downloaded the latest binary from releases, then you probably need to do the following commands:

mv histclean-v* histclean               # Clean the name
chmod +x histclean                      # Make it an executable
eval "$(histclean --completion bash)"   # Or zsh

via AUR on arch linux

histclean is available on the AUR. So you can install it using yay or any other AUR-helper

yay -S histclean-bin

Then you need to move the binary to your $PATH.

Usage

histclean [options]

When run without any options, histclean cleans the default history file on the system.

histclean determines the default history file from the HISTFILE environment variable. If HISTFILE is not set, histclean exits with an error.

Option Description
-h, --help Show help message and exit
-v, --version Show version and exit
-d, --dry-run Print the resulted output to stdout without modifying anything
-b, --backup Create a .backup copy before modifying the file
-w, --which-file Print the path to the detected history file and exit
-i, --input <FILE> Read history from the specified file
-o, --output <FILE> Write resulted output to the specified file
-s, --shell <SHELL> Override the shell type instead of auto-detecting from $SHELL. See Supported shells below.
-c, --completion <SHELL> Generate completion script for the specified shell. See Supported shells below.

Examples

# Deduplicate the default history file in-place
histclean

# Preview what would be removed
histclean --dry-run

# Clean a specific history file with a backup
histclean --input ~/.zsh_history --backup

# Write cleaned output to a new file
histclean --input ~/.bash_history --output ~/cleaned_history

How It Works

histclean scans the history file backwards, keeping only the most recent occurrence of each unique command line. Timestamp lines (prefixed with #) are preserved for their associated commands, and orphaned consecutive timestamps are collapsed.

Support

Shells

  • bash
  • zsh

Platforms

  • x86_64-linux
  • aarch64-macos
  • x86_64-macos
  • aarch64-freebsd
  • x86_64-freebsd

Build Options

zig build                 # Debug build
zig build test            # Run unit and integration tests
zig build man             # Generate man page (requires scdoc)

Optimization modes:

zig build -Doptimize=ReleaseSafe
zig build -Doptimize=ReleaseFast
zig build -Doptimize=ReleaseSmall

Shell Completions

Shell completion is available in completions/ directory.

# Source it (per session)
source completions/histclean.bash

# Or install system-wide (requires bash-completion v2.x)
sudo cp completions/histclean.bash /usr/share/bash-completion/completions/histclean

You can also generate the completion script using the --completion option by providing the associated shell (bash, zsh).

eval "$(histclean --completion zsh)"

FAQ

Doesn't this tool can be done in a one-liner POSIX shell? Yes, a core logic can be done in one line as:
tac "$HISTFILE" | awk '!seen[$0]++' | tac

If you prefer this kind of quick hacks, then go for it.

Why 1k LoC in Zig when you can write it in a much smaller Python or JS?

Shorter != better. LoC is a cost, not a virtue. What matters is what ships. Python and JS add a runtime. histclean is a statically-linked binary meant to be installed once and forgotten.

This tool doesn't have --watch option, what's good about it?

--watch turns a millisecond task into a daemon. That's what your shell's HISTCONTROL settings are for. histclean is for bulk cleanup, and you can run it from cron or a hook if you need to.

Not every CLI needs to sit in your terminal.

I downloaded the binary but can't run it. What's wrong?

You probably need to chmod +x it, then move it to a directory in your $PATH like ~/.local/bin or /usr/local/bin.

I ran histclean but my history file wasn't modified. Why?

Most likely HISTFILE isn't set, or histclean is targeting a different file than you expect. To confirm that it's pointing at the right file, run:

histclean --which-file
Running histclean broke my history file. What happened?

histclean only keeps the most recent occurrence of each command and preserves timestamp lines, and it doesn't invent or reorder lines. If your history file has entries that seem wrong, they were already in your file.

Restore your backup if you used --backup. If you didn't, consider file-recovery tools if necessary, but the data was already in that state before histclean ran.

Do I need Zig on my system to have this command?

If your OS/Architecture is listed on supported platforms, then no. The releases page provides a prebuilt binary. Download it, chmod +x it, done.
But if you're on a different OS/architecture, you'll need the Zig compiler to build from source.

Does histclean work with fish shell?

No. Fish already handles this natively, and it never stores duplicate history entries to begin with. You don't need histclean for that, and that's why we currently don't support it.

Can I ask to support my shell?

Yes, just fill an issue and provide a history format or history sample, and I'll work on it.

Does histclean handle history files larger than X?

Nothing you're likely to hit. A history file with 100k lines (~10MB) would use maybe 20-30MB of RAM when loaded fully into memory, which is well within range. Extremely large files (hundreds of MB) would be constrained by available memory.

Can I use histclean with a custom/non-standard history file path?

Yes. By default histclean reads $HISTFILE. If yours is non-standard, just make sure it's exported. Or use --input to bypass env detection entirely and target any file.

I use bash as my shell, but I passed --input to a zsh history file and nothing changed. Why?

By default, histclean detects your shell (and its parsing mechanism) from $SHELL, not from the file you pass with --input. So a zsh file gets parsed with bash rules. Pass --shell zsh alongside --input to override.

License

MIT

About

A cli tool to clean command shell history files

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages