Off The Grid
   Simple listserv
   xml tools
Karel as an adult


His is a replacement for your shell's history command. It collects your typed commands and stores them in a little Sqlite3 database. Whatever was typed, is immediately searchable (also in other terminals) and you can quickly find it later, also using wildcard searches. To get his, download the archive his.tar.gz, unpack it somewhere, and make install. This installs his into your own directory $HOME/bin. To install elsewhere (e.g., to /usr/local/bin, type:
  BINDIR=/usr/local/bin make install
Below is the usage information and the README. Note that the below information may be a bit stale, I am not promising that I'll update it with every change. For the most recent information see the distro.


What it's about

    Have you ever wanted to keep your shell commands stored for your
    convenience indefinitely, so you can search for anything you typed, even
    years ago? As a sysadmin you might have solved some problem a year ago
    using some obscure seldom-used tool and now you're wondering what that
    invocation was. Or do you want to be able to sync your shell history across
    machines, so that previously entered commands on one system can be seen in
    the history list on another system?

    With his you can. It stores each command that you enter in a database,
    right as the next prompt appears. The history list is immediately
    searchable - independent of your terminal or shell session.

General Usage

    his is self-describing, in the sense that if you type either of
        his --help
	his -h
	his -?
    you will see what flags and arguments are supported.

  Searching for a command that you ran before

    Typing just
    will display the most recent commands, by default limited to the last 20.
    This is similar to the bash builtin 'history'. You can limit the
    selection by providing a timeframe (--first and --last) and/or a count

    To find specific commands, use the form
        his ARG1 ARG2 ARG3
    which will search the command history, and display anything that was typed
    on the commandline earlier having ARG1 and ARG2 and ARG3. SQL-like
    wildcards (% and _) are supported (because the underlying database,
    sqlite3, knows about them). Searching can be limited to a given date/time
    using --first and --last. If you want to see only the last three
    occurrences, use --count=3 (shorthand -c3). Example:
        his --first=2017-01-01/00:00:00 --last=2017-01-01/01:00:00 ls
    shows your 'ls' invocations during the first hour of the year 2017.

  What adding does

    To add commands to the database, his --add .... is used. Normally you want
    this to run automatically, triggered by your shell. How to set that up is
    described below, but you can play around with it from the commandline and
    provided that you supply the right 'parsing format'. This is how his pulls
    out a timestamp and previous commandline from its arguments. The default
    parsing format is the one that bash uses when you
        export HISTTIMEFORMAT="[%Y-%m-%d %H:%M:%S %z] "
    You can see that history format by running the Bash builtin command
    'history'. Try for an overview of formats.

    Normally his won't store its own invocations (i.e., anything that starts
    with 'his); it only pollutes the saved list. If you want to, you can use
    flag --accept-his when adding commands to make sure that even such
    invocations end up in the list.

    Adding is 'smart' in the sense that it doesn't duplicate already present
    entries. So you can enter the same command over and over again and `his'
    will only log it as occurring at different timestamps; it won't duplicate
    everything. This even holds true for arguments (parts of a command
    line). E.g., two commands `ls -l /tmp' and 'ls -l /usr' will be stored by
    re-using the parts 'ls' and '-l'. See also DATAMODEL.txt in the
    distribution archive.


    Exporting and listing can be used together, e.g. to sync lists between
    different machines:
        his --count 0 --utc | ssh user@remotesystem his --utc --import
    (For a full export, you want --count=0 or -c0, since the arbitrary default
    is 20. Adding --utc makes sure that timestamps are relative to UTC, so
    that this works even across timezones.)

    Or, you can ask the 'remote side' what its most recent timestamp is, and
    export only from that point on:
    	TIMESTAMP=$(ssh user@remotesystem his -c1 -u | awk '{print $1}')
	his -u -f=${TIMESTAMP?} | ssh user@remotesystem his -u -i
    Here, flag -c1 means --count=1, which is: list only the one most recent
    command. Flag -f=${TIMESTAMP?} means: list entries on or after $TIMESTAMP.

Making --add work automatically


    If your shell is bash, edit your ~/.profile (or ~/.bashrc) and put in:

    function preprompt() {
       his --add -- "$(history 1)"
    export HISTTIMEFORMAT="[%Y-%m-%d %H:%M:%S %z] "

    What this does, is instruct bash that there is a $PREPROMPT_COMMAND to run,
    which is in this case a bash function preprompt. That function runs his
    --add. The lone flag -- makes sure that his doesn't consider the remainder
    as flags; ie. whatever is in "$(history 1)". The statement "$(history 1)"
    will ask bash to evaluate this as the last command.

    You can of course put more stuff in the preprompt function; anything
    that bash should run for you before displaying the next prompt.

    Et voila, your commands are saved into a sqlite database called


    For tcsh users, edit your ~/.cshrc and put in:

      alias precmd 'his --multi-args --add --format=3 `date +%s` $_'

    tcsh will happily run the precmd alias before displaying the next prompt.
    In this case, this is an invoction to 'his --add' using addition format 3
    (try 'his --list-formats' to see what that is). The information to add is
    the UTC timestamp in seconds and the previous command ($_).


Welcome to his 1.00, a CLI history tracker and finder of old invocations.
Copyright (c) Karel Kubat . 2017ff. Distributed under GNU GPLV3.
See for more info. Use his as follows:

his [--flags] [ARGS]

  Displays history having ARGS or the last entered ones. Use 'what' to exactly
  match, or 'what%' to match anything starting with what, or '%what' for
  anything ending in what, or '%what%' for whatever has what in it, or '__at'
  for anything that is 4 characters long and ends with at.

  Use flags --first=FROM and --last=TO if you want to time-limit.
  Use flag  --count=NR to limit the displayed entries, default is 20 last.
  Use flag  --utc to output timestams relative to GMT, default is local.

his [--flags] -a,--add LINE
  Adds LINE to the history, see --list-formats for the supported parsing
  formats of LINE and --format=X to select a format.

his [--flags] -i,--import
  Import from stdin in the same format as a listing. Flags --first=FROM and
  --last=TO can be used to limit what to import. Implies --format=2.
  Add flag --utc if the list to import was generated with --utc (recommended).

his [--flags] -p,--purge
  Remove entries from the database. Flags -f,--first and -l,--last must be
  given to avoid mistakenly removing everything.

his -R
  Shows the README and stops.

Supported general flags:
  -d,--db=DB        : Sets Sqlite3 database path, default is $HOME/.his.db
  -f,--first=STAMP  : Limits exports and searches to later or equal to STAMP,
                      with STAMP having the format: YYYY-MM-DD/HH:MM:SS
  -F,--format=FMT   : Sets the format for parsing during --add
  -l,--last=STAMP   : Limits exports and searches to earlier or equal to STAMP
  -L,--list-formats : Shows available parsing formats and stops
  -m,--multi-args   : During --add, LINE is assumed to to have all args
                      separately (as in ls -Flag). Default is all in one string
                      (as in 'ls -Flag').
  -u,--utc          : Timestamps in listed output or imported input are assumed
                      UTC (default: local time)
  -v,--verbose      : Increases verbosity
  -h,-?,--help      : Shows this text and stops
  --                : Stops parsing flags. Very useful in
                        his --add -- $WHATEVER
                      (when WHATEVER starts with a --flag)