CLI tool
rcaloras/bashhub-client avatar
rcaloras/bashhub-client

bashhub-client: Shell History You Can Search From Any Machine

:cloud: Bash history in the cloud. Indexed and searchable.

1,311 stars85 forksPythonApache-2.0

At a glance

What is it?
The Bashhub client records every command you type across every machine and session and makes the result searchable by directory, system, session or exit status, with a bh command for search, an interactive mode that behaves like reverse search, and controls for filtering, ignoring and permanently deleting records. It installs with one curl line and runs on Bash and Zsh.
Who is it for?
bashhub-client fits a developer with several machines who keeps retyping the same long command, or who wants a shell history that survives a wiped home directory, because the searchable index is the whole point and it is the part a local history file cannot do. It is a poor fit if you are not comfortable sending shell history to a service, and for anyone whose commands contain secrets, because the filtering and ignore mechanisms are opt-in and a regex is easy to get wrong.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 16 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

History You Can Search From Any Machine

Bashhub saves every terminal command entered across all sessions and systems and provides querying across all of them, and the README describes it as bash history in the cloud, indexed and searchable.

The obvious question is why this exists when a shell already keeps a history file. The answer is in the list of features. The search is a super command search that uses context about how commands are executed, for example the directory, the session, the system, or the exit status. So the query is not only the text of a command but the situation it was run in, and a local history file cannot answer that because it does not record the directory or the exit status alongside the line.

The second feature is the reason a cloud service is used rather than a local file. The history is unlimited and detailed, stored in the cloud, privately and encrypted at rest, and the README links to a security and privacy page in the wiki for the details of that claim. And because the history is on the server, support across systems means your history is available from anywhere, not just from the machine where you typed the command.

The client supports Bash and Zsh, with a command line interface for everything, and the whole thing is driven from the shell, so nothing about it changes how you work.

The Install Is One Curl Line

The quick install is a single command that downloads a setup script and runs it with your shell:

shell
curl -OL https://bashhub.com/setup && $SHELL setup

The subtlety is the shell argument, and the README explains it. For non default login shells you specify the shell explicitly, for example bash setup, zsh setup or fish setup. The installer then uses uv to install Bashhub, and the detailed instructions live on the install wiki page.

So the install path is a script that fetches a script, which is worth thinking about before running it on a machine where you care about what ends up on disk. The alternative is the install wiki page, which is the documented route if you want to see the steps.

The repository carries the parts of this. There is an install-bashhub.sh file, a script/ directory for the shell integration, a bashhub/ directory with the Python client, a tests/ directory, a docs/ directory, and a pyproject.toml with the packaging metadata. The dependency list is small and ordinary: requests for the API, click for the command line, npyscreen for the interactive terminal screens, python-dateutil for timestamps, and inflection and humanize for formatting.

bh Searches, bashhub Does Everything Else

The command line is split in two, and the split is about how often you use each.

bh is for searching, and bashhub is for everything else. The search command defaults to outputting the most recently used unique commands to standard output, and bh --help has the specifics. Adding the -i argument to any bh search makes it interactive, and there are several more arguments to filter and to be more specific.

The examples in the README show the range of queries:

bash
$ bh
$ bh -n 20 "grep"
$ bh -i "wget github"

The first is the last 100 commands you executed anywhere, with 100 as the default limit when -n is not given. The second is the last 20 files you have grepped. The third finds a wget command with interactive search so you can execute it again.

The ordering rule is worth knowing, because it explains results you might otherwise think are wrong. By default results are sorted by most recently used and are unique, which means a frequent command like git status or ls appears once, in the position where it was most recently invoked. The -dups flag includes duplicates, so your git commands including duplicates come back with bh -dups "git".

The key binding is ctrl + b for quickly dropping into interactive search, which is the same idea as the reverse search on ctrl + r, except that it searches every machine rather than the current session.

Searching by Directory and by System

The context search is the feature that a local history file cannot do, and it comes in two forms in the examples.

The -d flag restricts the search to the current directory, so bh -d gives the last commands you executed in this directory, and bh -d -n 10 "vim" gives the last 10 things you edited in this directory. The -sys flag restricts by machine, so bh -sys -n 10 "curl" gives the last 10 curl commands you produced on this system.

The two compose, and the interactive mode takes them too, which is the combination that is genuinely useful in practice:

bash
$ bh -i -d
(bashhub-i-search): rsync

That is interactive search for all the rsync commands executed in this directory. The prompt in the example shows what the interactive mode looks like, a small menu where you select a command to run on the command line.

Inside that menu you can also reach detailed information about any listed command by pressing i or space, which is a separate view of the record rather than the line itself.

The README also documents a shortcut for people who already live in a fuzzy finder, using bashhub with fzf:

bash
function my_alias {
  eval $(bh | fzf)
}

which makes the function available globally in your terminal.

Keeping Commands Out: Filters, #ignore and the Recording Switch

A service that records every command you type needs the opposite feature, and Bashhub has three separate mechanisms for it.

The first is the BH_FILTER environment variable, which takes a regex set of commands that will be ignored and omitted from Bashhub:

bash
export BH_FILTER="(psql|ssh)"
ssh rcaloras@some-ip-address # will not be saved

You can check what a regex would match without running the command, with the bashhub filter subcommand, which prints whether the command is filtered and which part matched.

The second is the ignore marker. Adding #ignore to the end of any command omits it from being saved, which is the per-command escape hatch for the case a filter cannot anticipate.

The third is the recording switch. bashhub on and bashhub off turn recording on and off, and by default this only affects the current bash session, with the messages telling you that the command will not be saved and that recording is re-enabled. For all sessions, bashhub off --global sets save_commands to False in the config file.

The ordering of the three matters for a security decision. The filter is the one that applies to everything, so it belongs in your shell profile rather than in a session. The ignore marker is for the one command you know about. And the off switch is the blunt instrument for the moment you are running something you would rather not have recorded at all.

Deleting Records and the Privacy Model

Deletion is handled inside the interactive search, by pressing Delete or Backspace while a command is highlighted. A small dialog box opens to confirm, and if a command is deleted it is permanently removed from Bashhub.

That is a stronger guarantee than most history tools offer, and it is the right one for a service that holds a record of everything you have typed. There is no trash and no retention window, so a command you delete is gone, which also means you cannot use the history to recover something you deleted by accident.

The status command gives the other half of the picture. Running bashhub status gives a summary of your stats and status, most of which is also on the user profile page, and the README shows the shape of the output with the total number of commands, the total number of sessions and the total number of systems, followed by the details of the current session, its process id, when it started, how many commands it holds and how many commands you have run today.

The privacy model itself is described in the wiki page the README links, under security and privacy, where the storage is described as private and encrypted at rest. That is a claim about the server side, and the client side is that your commands are sent there, so the filter configuration is the part you control.

The Client Layout and How the Version Numbers Work

The repository is a Python package with a shell integration layer, and the packaging metadata is worth a look because it shows the supported range.

The package is named bashhub, requires Python 3.11 up to but not including 3.15, and declares classifiers for 3.11 through 3.14. The build uses setuptools with setuptools-scm, and the version is dynamic, written to a version file inside the package with a guess-next-dev version scheme and a local scheme of node-and-date, so a build from a checkout gets a version derived from the commit rather than a number typed into a file.

The two console scripts are the two commands the README documents, with bh mapped to the search module and bashhub to the main module. The type checking is strict for a project this size, with mypy configured to disallow untyped definitions and to check untyped ones, and the ignore for missing imports is explained in a comment, since npyscreen, inflection and humanize lack stubs. The linting is ruff with the E, F and I rules selected and the line length rule deliberately not enforced.

The release naming is unusual and quite good. The recent releases are 3.2.0 as Blue Labrador, 3.1.0 as Silver Springer Spaniel, with 3.1.0rc4 as the fourth release candidate of that line. A codename per release makes a changelog easier to talk about, and the release candidate is published under the same codename.

The project is Apache-2.0 licensed, the repository is not archived, and the last push was on 2026-10-07.

Editorial conclusion

bashhub-client fits a developer with several machines who keeps retyping the same long command, or who wants a shell history that survives a wiped home directory, because the searchable index is the whole point and it is the part a local history file cannot do. It is a poor fit if you are not comfortable sending shell history to a service, and for anyone whose commands contain secrets, because the filtering and ignore mechanisms are opt-in and a regex is easy to get wrong. Before installing, set BH_FILTER for anything sensitive, and read the security and privacy wiki page the README links, since the storage is described as private and encrypted at rest but the client still sends the commands. The client is Apache-2.0 licensed, requires Python 3.11 to 3.14, the newest release is 3.2.0 from 2026-08-30, and the last push was on 2026-10-07.

Frequently asked questions

What does the Bashhub client do?

It saves every terminal command entered across all sessions and systems and provides querying across all of them. The search uses context about how commands were executed, such as the directory, the session, the system or the exit status, and the history is stored in the cloud, privately and encrypted at rest.

How do I install the Bashhub client?

With `curl -OL https://bashhub.com/setup && $SHELL setup`, and for a non default login shell you specify the shell explicitly, for example bash setup or zsh setup. The installer uses uv to install Bashhub, and the detailed instructions are on the install wiki page.

How do I stop Bashhub from recording a sensitive command?

Set the BH_FILTER environment variable to a regex, for example `export BH_FILTER="(psql|ssh)"`, and matching commands are ignored. You can check what a regex matches with the bashhub filter subcommand, add #ignore to the end of a single command to omit just that one, and use bashhub off, or bashhub off --global for all sessions.

How does the Bashhub search differ from shell reverse search?

By default results are sorted by most recently used and are unique, so a frequent command appears once at its most recent position, and the -dups flag includes duplicates. Searches can be scoped to the current directory with -d or to a machine with -sys, and -i opens an interactive menu similar to reverse search.

Can I delete commands from Bashhub?

Yes. In interactive search, press Delete or Backspace while a command is highlighted, confirm in the dialog that opens, and the command is permanently removed from Bashhub.

Official sources

  1. License: Apache-2.0
  2. Project website
  3. rcaloras/bashhub-client on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/rcaloras-bashhub-client.svg)](https://hysenlabs.com/projects/rcaloras-bashhub-client)

Was this useful?