• Stars
    star
    107
  • Rank 312,634 (Top 7 %)
  • Language
    Python
  • License
    ISC License
  • Created over 6 years ago
  • Updated over 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Visualize your shell usage with Highcharts!

Shell History

ci documentation pypi version

Inspired by bamos/zsh-history-analysis.

Visualize your usage of Bash/Zsh through a web app thanks to Flask and Highcharts!

Durationduration chart Lengthlength chart Typetype chart
Exit codeexit code chart Hourlyhourly chart Dailydaily chart
Over timeover time chart Markov chainmarkov chart Top commandstop chart

Post your charts ideas in this issue!

Requirements

Shell History requires Python 3.6 or above.

To install Python 3.6, I recommend using pyenv.
# install pyenv
git clone https://github.com/pyenv/pyenv ~/.pyenv

# setup pyenv (you should also put these three lines in .bashrc or similar)
export PATH="${HOME}/.pyenv/bin:${PATH}"
export PYENV_ROOT="${HOME}/.pyenv"
eval "$(pyenv init -)"

# install Python 3.6
pyenv install 3.6.12

# make it available globally
pyenv global system 3.6.12

Installation

With pip:

python3.6 -m pip install shellhistory

With pipx:

python3.6 -m pip install --user pipx

pipx install --python python3.6 shellhistory

Setup

shellhistory needs a lot of info to be able to display various charts. The basic shell history is not enough. In order to generate the necessary information, you have to enable the shell extension.

At shell startup, in .bashrc or .zshrc, put the following:

# only load it for interactive shells
if [[ $- == *i* ]] && command -v shellhistory-location &>/dev/null; then
    . $(shellhistory-location)
    shellhistory enable
fi

... and now use your shell normally!

If you want to stop shellhistory, simply run shellhistory disable.

Note: for performance reasons, you can also use the static, absolute path to the source file. Indeed, calling shellhistory-location spawns a Python process which can slow down your shell startup. Get the path once with shellhistory-location, and use . <ABS_PATH>. In my case it's . ~/.local/pipx/venvs/shellhistory/lib/python3.6/site-packages/shellhistory/shellhistory.sh.

Usage

Launch the web app with shellhistory-web. Now go to http://localhost:5000/ and enjoy!

You will need Internet connection since assets are not bundled.

Some technical info

How it works

When you enter a command, shellhistory will compute values before and after the command execution. In Bash, it uses a trap on DEBUG and the PROMPT_COMMAND variable (man bash for more information). For Zsh, it uses the preexec_functions and precmd_functions arrays (anyone knows where to find the official documentation for these? Some information in man zshmisc).

Before the command is executed, we start a timer, compute the command type, and store the current working directory and the command itself.

After the command has finished, we store the return code, and stop the timer.

History file format

Fields saved along commands are start and stop timestamps, hostname, username, uuid (generated), tty, process' parents, shell, shell level, command type, return code, and working directory (path), in the following format: :start:stop:uuid:parents:host:user:tty:path:shell:level:type:code:command.

  • multi-line commands are prepended with a semi-colon ; instead of a colon :, starting at second line
  • start and stop timestamps are in microseconds since epoch
  • process' parents and working directory are encoded in base64 to avoid delimiter corruption.

Example (multi-line command):

:1510588139930150:1510588139936608:40701d9b-1807-4a3e-994b-dde68692aa14:L2Jpbi9iYXNoCi91c3IvYmluL3B5dGhvbiAvdXNyL2Jpbi94LXRlcm1pbmFsLWVtdWxhdG9yCi91c3IvYmluL29wZW5ib3ggLS1zdGFydHVwIC91c3IvbGliL3g4Nl82NC1saW51eC1nbnUvb3BlbmJveC1hdXRvc3RhcnQgT1BFTkJPWApsaWdodGRtIC0tc2Vzc2lvbi1jaGlsZCAxMiAyMQovdXNyL3NiaW4vbGlnaHRkbQovc2Jpbi9pbml0Cg==:myhost:pawamoy:/dev/pts/1:L21lZGlhL3Bhd2Ftb3kvRGF0YS9naXQvc2hlbGxoaXN0Cg==:/bin/bash:1:builtin:0:echo "a
;b
;c" | wc -c

Note: later we could use CSV formatting, quoting strings and doubling double-quotes in those if any. It would make the file more readable for humans, and easily importable in other programs. See issue 26.

The previous example would look like this:

1510588139930150,1510588139936608,40701d9b-1807-4a3e-994b-dde68692aa14,"/bin/bash
/usr/bin/python /usr/bin/x-terminal-emulator
/usr/bin/openbox --startup /usr/lib/x86_64-linux-gnu/openbox-autostart OPENBOX
lightdm --session-child 12 21
/usr/sbin/lightdm
/sbin/init",myhost,pawamoy,/dev/pts/1,"/media/pawamoy/Data/git/shellhist",/bin/bash,1,builtin,0,"echo ""a
b
c"" | wc -c"

How we get the values

Start and stop time are obtained with date '+%s%N', return code is passed directly with $?, working directory is obtained with $PWD and command type with type for Bash and whence for Zsh.

Values for UUID, parents, hostname, and TTY are computed only once, when shellhistory.sh is sourced. Indeed they do not change during usage of the current shell process. Hostname and TTY are obtained through commands hostname and tty. UUID is generated with command uuidgen. Also note that UUID is exported in subshells so we know which shell is a subprocess of another, and so we are able to group shell processes by "sessions", a session being an opened terminal (be it a tab, window, pane or else). Parents are obtained with a function that iteratively greps ps result with PIDs (see shellhistory.sh).

Values for user, shell, and level are simply obtained through environment variables: $USER, $SHELL (though its use here is incorrect: see issue 24), and $SHLVL (also see issue 25).

The last command is obtained with the command fc. Using fc allows shellhistory to have the same behavior as your history:

  • if commands starting with spaces are ignored, they will be ignored in shellhistory as well.
  • same for duplicates (entering ls two or more times saves only the first instance). Note however that if you type the same command as the previous one in an other terminal, it will still be appended, unless you manage to synchronize your history between terminals, which is another story.

Additionally, if you enter an empty line, or hit Control-C before enter, nothing will be appended either. The trick behind this is to check the command number in the current history (see shellhistory.sh for technical details).

More Repositories

1

aria2p

Command-line tool and library to interact with an aria2c daemon process with JSON-RPC.
Python
439
star
2

docker-nginx-postgres-django-example

Example using Docker, Django, multiple Postgres databases, NginX, Gunicorn, pipenv, GitLab CI and tox.
Python
160
star
3

git-changelog

Automatic Changelog generator using Jinja2 templates.
Python
117
star
4

django-zxcvbn-password

Back-end and Front-end password validation with ZXCVBN
Python
86
star
5

django-suit-dashboard

Create a dashboard within Django admin interface.
Python
82
star
6

copier-pdm

Copier template for Python projects managed by PDM.
Jinja
77
star
7

duty

A simple task runner.
Python
76
star
8

copier-poetry

Copier template for Python projects managed by Poetry.
Jinja
74
star
9

markdown-exec

Utilities to execute code blocks in Markdown files.
Python
65
star
10

awesome-repository

A curated list of services, tools and standards about (open source) repository management.
60
star
11

cookiecutter-awesome

Cookiecutter to create an awesome list.
Python
39
star
12

website

My personal website.
Python
37
star
13

shellman

Write documentation in comments and render it with templates.
Python
32
star
14

dependenpy

Show the inter-dependencies between modules of Python packages.
Python
22
star
15

docker-nginx-auth-request-django-shiny-example

Example using Docker, Nginx with auth-request module, and Django acting as a authentication wrapper around a Shiny app.
Python
21
star
16

django-appsettings

Application settings helper for Django apps.
Python
15
star
17

django-meerkat

Security audit tool for Django sites
JavaScript
14
star
18

archan

Analysis of your architecture strength based on DSM data.
Python
12
star
19

mkdocs-coverage

MkDocs plugin to integrate your coverage HTML report into your site.
Python
12
star
20

mkdocs-gallery

A gallery of MkDocs themes, showing off a few plugins and extensions.
Python
10
star
21

pawabot

A Telegram Bot for many things: aria2 management, torrent sites crawling, media organization with filebot and Plex.
Python
9
star
22

django-archan

A Django app that displays dependency matrices and other project architecture information
Python
9
star
23

mkdocs-spellcheck

A spell checker plugin for MkDocs.
Python
9
star
24

moving-stars

⭐ Copy GitHub stars to GitLab 🌠
Python
9
star
25

cookie-poetry

Cookiecutter for Poetry projects.
Roff
8
star
26

failprint

Run a command, print its output only if it fails.
Python
8
star
27

neopy

Neo4j for Python. Manipulate graph data in Python with Neo4j as data storage.
Python
7
star
28

django-cerberus-ac

Django Cerberus Access Control, extended permission system.
JavaScript
7
star
29

ansito

Transform ANSI codes to any other format (currently only Conky style)
Python
7
star
30

pdm-multirun

A PDM plugin to run a command on multiple Python versions.
Python
5
star
31

copier-uv

Copier template for Python projects managed by uv.
Jinja
5
star
32

django-cs-models

A Django app that helps you creating models within a Complex System
Python
4
star
33

stars

My stars on GitHub, grouped by language.
4
star
34

shelldemo

Run a set of Bash commands as if typed by a robo- I mean, a person.
Shell
4
star
35

wps-light

The strictest and most opinionated python linter ever! (lighter fork)
Python
4
star
36

gestion-de-stock

Graphical UI in Qt for database management
C++
3
star
37

logan

Log analysis tool (alpha).
HTML
3
star
38

privibot

A Python library to add a privilege/permission system to your Telegram bot.
Python
3
star
39

rosetta-suit

Integration of django-rosetta into django-suit admin interface
HTML
2
star
40

suit-dashboard-demo

Demo site using django-suit-dashboard
Shell
2
star
41

pypi-insiders

Self-hosted PyPI server with automatic updates for Insiders versions of projects. Only available to sponsors.
2
star
42

fastapi-ref

API reference of FastAPI.
2
star
43

pawamoy.github.io

HTML
2
star
44

mvodb

Rename and move files using metadata from online databases.
Python
2
star
45

odoo-matrix

D3.js visualization for Odoo's inter-dependencies
Python
2
star
46

happy-path

Code and data flow visualization tool for Python. Available to sponsors only.
2
star
47

django-access-control

Control how users access resources in your Django project
Python
1
star
48

cookiecutter-cookiecutter

The cookiecutter that generated itself.
Python
1
star
49

keycut

A command line tool that helps you remembering ALL the numerous keyboard shortcuts of ALL your favorite programs
Python
1
star
50

pawamoy

My profile readme.
1
star
51

archan-pylint

Archan plugin for Pylint (number of messages per module).
Python
1
star
52

taskhub

[ALPHA] Task management tool, supporting import/export from/to different services, with multiple interfaces.
Python
1
star
53

cookiecutter-pypackage

Roff
1
star
54

Omnidia

Abstract elements manager (multimedia, data, stuff) in browser
HTML
1
star
55

mkdocs-logging

Logging utilities for MkDocs plugins.
Python
1
star