# hishtory: shell history that keeps the context, not just the command

> hishtory stores every command with its working directory, exit code and runtime, encrypts it end to end, and syncs it across machines. It suits engineers who work on several hosts and need the command they ran last week on a server.

**ddworken/hishtory** — Your shell history: synced, queryable, and in context

- Repository: https://github.com/ddworken/hishtory
- Website: https://hishtory.dev
- Stars: 3,120 · Forks: 74
- Language: Go
- License: MIT
- Published: 2026-09-24 · Updated: 2026-09-24 · Language: en
- Canonical page: https://hysenlabs.com/projects/ddworken-hishtory

## The problem hishtory solves for people who work across several machines

Plain shell history answers one question: what did I type. It does not answer where, as whom, whether it worked, or how long it took. If you spent an afternoon on a server debugging a pipeline, the command is in that server's history file and nowhere else. hishtory targets that gap. The README describes it as storing history "in context (what directory you ran the command in, whether it succeeded or failed, how long it took, etc)", kept locally and end-to-end encrypted for syncing to your other computers. The intended user is someone who moves between a laptop, a workstation and one or more servers, and who wants a single query surface over all of them. The demo in the README shows the same Control+R binding you already use, so the workflow change is small. That matters, because history tools fail when they demand a new habit.

## How hishtory records context and syncs it between computers

The client is written in Go and ships as a single binary, with the entry point at the repository root in hishtory.go and application code under client/ and shared/. The README states that history is stored locally and end-to-end encrypted before it is synced, which means the sync service moves ciphertext rather than readable commands. Querying happens in two places. The terminal UI opens on Control+R and accepts a query syntax with field prefixes: hostname:, user:, exit_code:, before: and after:, combined with plain terms. The same syntax is accepted by hishtory query and by hishtory redact. For anything the query language does not cover, the README points at the SQLite database directly with sqlite3 -cmd 'PRAGMA journal_mode = WAL' ~/.hishtory/.hishtory.db, so the local store is a normal file you can join against or export. The dependency list in go.mod is consistent with that design: glebarez/sqlite and gorm for storage, bubbletea and lipgloss for the TUI, cobra for the CLI. Two details are worth noticing. First, the displayed columns are configurable, and the README lists Hostname, CWD, Timestamp, Runtime, ExitCode, Command and User as the supported set. Second, custom columns run arbitrary shell commands to populate a value, which the README demonstrates with a git_remote column. That is a real extension point, and also a real execution surface: whatever you put in a custom column definition runs on your machine at record time.

## Installing hishtory and running a first query

The README gives one install command for the first machine, and it works for bash, zsh and fish:

```bash
curl https://hishtory.dev/install.py | python3 -
```

After that, hishtory is already managing your shell history. Pressing Control+R should open the terminal UI rather than your shell's built-in reverse search. To put the same history on a second machine, first read the secret key from the machine you already set up:

```bash
hishtory status
```

The output includes the secret key. On the second machine, run the installer again and then initialize with that key:

```bash
curl https://hishtory.dev/install.py | python3 -
hishtory init $YOUR_HISHTORY_SECRET
```

Once initialized, Control+R on either machine shows commands from both. A first real query can be run without the TUI at all:

```bash
hishtory query "docker run" hostname:my-server
```

That returns commands containing docker run that were executed on the host named my-server, which is the case plain history cannot answer. If something gets recorded that should not have been, hishtory redact takes the same query format, so hishtory redact psql removes every entry containing psql.

## Where hishtory gets in the way

The end-to-end encryption model has a direct cost: the sync service cannot read your history, and neither can anyone supporting you. If a query returns nothing on a second machine, the first thing to check is whether hishtory init ran with the correct secret key, because a wrong key produces a working install with an empty view rather than an error you would notice. The README does not document a rollback path for a bad key or for a corrupted local database, and the Makefile's backup and restore targets exist for local development, not as a supported user workflow. Recording itself can be turned off with hishtory disable and back on with hishtory enable, and Control+R integration can be removed entirely with hishtory config-set enable-control-r false, in which case you query manually through hishtory query. The AI completion feature is the other place to look closely. Typing ? in the TUI sends the query to a centrally hosted hishtory server by default; the README says you can set OPENAI_API_KEY to keep queries off that server, or disable the feature with hishtory config-set ai-completion false. If your history contains hostnames, paths or tokens, that default deserves a decision rather than an assumption. Finally, hishtory is a personal tool. Nothing in the README describes a server-side console for reading a team's history, so it is the wrong instrument for centralized audit or compliance collection.

## hishtory against Atuin

Atuin is the closest comparison and appears repeatedly in what people search for alongside this project. The difference is where the data lives and what the sync layer can see. hishtory's README describes local storage with end-to-end encrypted sync, so the service relays data it cannot decrypt, and the query language is built around record fields such as exit_code: and hostname: rather than around a general search box. Atuin's documentation describes a server component you can self-host, which shifts the question from what the hosted service can read to what your own server stores. If you want to run the sync endpoint yourself and keep everything inside your own infrastructure, that model is the one to evaluate. If you would rather not operate a server and want the encryption boundary to sit at the client, hishtory's README describes that arrangement directly. The two also differ in surface area: hishtory exposes the SQLite file for direct queries, while its TUI is configured through hishtory config-set for columns, key bindings and color scheme. Neither choice is free. Self-hosting means patching and backups; client-side encryption means losing server-side search and support.

## Maintenance, updates and the MIT licence

The last push to the repository was on 2026-03-18, and the most recent release listed is v0.335 from 2025-02-07. Updates are applied in place: the README states that running hishtory update securely downloads and applies the latest version, and go.mod includes github.com/slsa-framework/slsa-verifier/v2, which is consistent with verifying release artifacts rather than trusting the download blindly. That is a lower upgrade cost than most tools of this kind, since there is no package manager step and no server to redeploy. The trade-off is version drift: each machine updates when you run the command, so a laptop and a server can sit on different builds for a while. The project is MIT licensed, which permits commercial and private use and modification; the LICENSE file at the repository root is the authoritative text. The README does not discuss what happens to synced history if you stop running the service, so treat the local SQLite database at ~/.hishtory/.hishtory.db as the copy you control and back it up yourself. Nothing here is legal advice.

## Conclusion

Adopt hishtory if you routinely move between machines and want to search one history that carries the directory and exit code of every command. Skip it if you need a centrally managed audit trail: the README describes local storage plus end-to-end encrypted sync, not server-side inspection. Before rolling it out, run hishtory status on the first machine and confirm the secret key it prints, because hishtory init on every other machine depends on that key being correct.

## FAQ

### Which shells does hishtory support?

The README states that after installing, hishtory is already managing your shell history for bash, zsh and fish. The repository topics list the same three shells.

### How do I get my hishtory history onto a second computer?

Run hishtory status on the first machine to read the secret key, then run the installer on the second machine and initialize it with hishtory init $YOUR_HISHTORY_SECRET. After that, Control+R on either machine shows commands from both.

### Can I delete a command I did not mean to record?

Yes. hishtory redact accepts the same query format as hishtory query, so hishtory redact psql deletes every entry containing psql. You can also press Control+K on the selected entry inside the Control+R interface.

### Does hishtory send my queries to a server when I use the ? prefix?

By default the AI completion feature queries a centrally hosted hishtory server, according to the README. You can export OPENAI_API_KEY to use your own OpenAI key instead, or turn the feature off with hishtory config-set ai-completion false.

## Sources

- [ddworken/hishtory on GitHub](https://github.com/ddworken/hishtory)
- [License: MIT](https://github.com/ddworken/hishtory/blob/master/LICENSE)
- [Project website](https://hishtory.dev)
- [README](https://github.com/ddworken/hishtory/blob/master/README.md)
- [Releases](https://github.com/ddworken/hishtory/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/ddworken-hishtory
