# cheat.sh answers a curl, and the answer sometimes comes from StackOverflow

> cheat.sh is an HTTP service that returns cheat sheets for UNIX commands and programming language questions, backed by community sheet repositories and by answers pulled from StackOverflow. Command sheets are fetched at build time for self-hosting, while language answers are described as generated on the fly, which is where the reliability and the licence terms come from.

**chubin/cheat.sh** — the only cheat sheet you need

- Repository: https://github.com/chubin/cheat.sh
- Website: https://cheat.sh/
- Stars: 41,789 · Forks: 1,916
- Language: Python
- License: MIT
- Published: 2026-08-17 · Updated: 2026-08-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/chubin-cheat-sh

## Two service names and two protocols answer the same query

A request is a path, not a search form. The same four lines show the range of ways in:

```
    curl cheat.sh/tar
    curl cht.sh/curl
    curl https://cheat.sh/rsync
    curl https://cht.sh/tr
```

Both the long name and the short one resolve, over plain HTTP or over HTTPS. That matters more than it looks: the short form is what you can type in a hurry, and the HTTPS form is the one to use in a script, since the response body is code you are about to paste into a shell.

When you do not know the command name, the tilde notation searches instead of fetching: `curl cht.sh/~snapshot` returns commands and techniques related to making snapshots. A tilde query is the one route that goes through the fuzzy matcher in the dependency list rather than through a direct filename lookup, so it is the route most likely to return something adjacent to what you asked for.

## Command sheets are vendored, language answers are not

Two different mechanisms sit behind one URL. Programming language questions live in per-language namespaces, `curl cht.sh/go/Pointers`, `curl cht.sh/scala/Functions`, `curl cht.sh/python/lambda`, and a `:list` query enumerates what exists for a language. Each language also has a `:learn` page described as a direct mapping from the Learn X in Y project.

When no sheet matches, the service composes an answer from available cheat sheets and answers on StackOverflow. The documentation is direct about the quality of that path: there is no guarantee the result is a 100% hit, and it says so before showing examples like `curl cht.sh/js/parse+json`.

The consequence is that two identical-looking responses can have different origins, and the body does not always make it obvious which path produced it. A sheet-backed answer is stable. A generated answer changes when the upstream answers change, which means a query that worked last quarter can return something different now, with no version to compare against.

## /1 and /2 exist because the first answer is often not the one

The service keeps alternatives and lets you page through them by appending a number:

```
    curl cht.sh/python/random+string
    curl cht.sh/python/random+string/1
    curl cht.sh/python/random+string/2
```

That is an admission that ranking is imperfect, and the workaround is manual. For a language question with no sheet behind it, the difference between variant 0, 1 and 2 can be the difference between a working snippet and a wrong one, and nothing in the response tells you which is which.

Six query rules are given, and two of them change the answer rather than the phrasing. Be specific, since `/python/append+file` is preferred over `/python/file` and over `/python/append`. And exclude terms with `+-`, as in `python/multiply+matrices+-numpy`, which is how you stop a result that leans on a library you are trying to avoid. Words are joined with `+`, special characters are ignored, and the full option set is documented at `/:help`.

## Generated answers print a question id and a cc by-sa 3.0 marker

Answers arrive formatted as code in the queried language, with comments in that language's comment syntax. The Lua example shows what the trailer looks like:

```lua
    --[[
       [ Note that you cannot guarantee any order in keyset. If you want the
       [ keys in sorted order, then sort keyset with table.sort(keyset).
       [
       [ [lhf] [so/q/12674345] [cc by-sa 3.0]
       ]]
```

Three pieces of information sit in those brackets: a source handle, a StackOverflow question id, and a Creative Commons Attribution-ShareAlike 3.0 marker. That marker is attached to content derived from StackOverflow, and share-alike is an obligation rather than a courtesy.

If you strip the prose with `\?Q` and the highlighting with `\?T`, combined as `\?QT`, the attribution goes with it. So the tidy one-liner you wanted for a README is the version with the licensing trail removed, which is the one case where the convenience options and the provenance point in opposite directions. Worth deciding before you paste, not after.

## A self-hosted build fetches every sheet at image build time

Self-hosting runs the same service from the repository. The compose file defines an app that builds from the checkout and a Redis service it depends on:

```yaml
    environment:
      - CHEATSH_CACHE_REDIS_HOST=redis
    ports:
      - "8002:8002"
```

The Dockerfile is where the content comes from. It starts from `alpine:3.14`, installs the Python dependencies, then runs `python3 lib/fetch.py fetch-all` to pull the community cheat sheets into the image before the server ever starts, and finally runs `bin/srv.py` as its entry point. Redis is a cache, not a database of record.

Two things follow. Your instance serves whatever `fetch-all` retrieved on the day you built, so the content is frozen at build time while the hosted service keeps fetching. And the build pins `alpine:3.14` and `redis:4-alpine`, so a rebuild reproduces the stack as it was rather than as package maintainers ship it now.

## PyICU and pycld2 make the image build a native compile

The dependency list is short and mostly familiar: gevent, flask, requests, pygments, redis, fuzzywuzzy, python-Levenshtein, colorama, pyyaml, langdetect, polyglot, pytest and black. Four of them explain the architecture.

fuzzywuzzy with python-Levenshtein backs the `~KEYWORD` search. langdetect, pycld2, polyglot and PyICU exist to work out the language of an incoming question, which only makes sense if the upstream answer pool is multilingual, as StackOverflow is. colorama handles terminal output and is the one hard upper pin in the file, at `colored<1.4.3`.

PyICU and pycld2 are native extensions, so `pip install -r requirements.txt` is not the whole story. The Dockerfile installs `g++`, `python3-dev` and `libffi-dev` as a temporary build dependency group and removes it afterwards, which is exactly the step a hand-rolled install tends to skip and then fails on.

## The cht.sh client has tab completion, and the install line is not in view

The service needs nothing installed, which is its main argument. For offline use there is a separate command line client called `cht.sh`, and the documentation covers installation, client usage, tab completion for both Bash and ZSH, a stealth mode, and a Windows command line client.

The install command itself is not in the visible portion of the documentation, so the honest instruction is to take it from the Installation section of the project README rather than to guess at a curl-piped-to-shell line. That matters more than usual here, because the client is the piece you install on a machine, and the stealth mode in particular is a claim about behaviour on that machine that you should read rather than assume.

The repository has no GitHub releases and the last push was on 2026-09-22, so the client has no version to pin. Snapshot the commit you install if the machine matters.

## tldr pages gives you one fixed page, cheat.sh gives you a query

The comparison people actually make is with tldr pages, and the difference is architectural rather than a matter of coverage. tldr pages is a collection of hand-written pages, one per command, each holding a single worked example in a fixed format, distributed as a repository you clone or install. cheat.sh is a running service: you send a path and it decides at request time whether to serve a sheet or to compose an answer.

That gives each one a clear failure mode. tldr pages has no answer for your specific question, only the example its author wrote, and it works with no network at all. cheat.sh can attempt any question you can phrase in `+`-separated words, and it needs a reachable endpoint, since the client is a client and the sheets are the server's.

The practical split: offline or air-gapped, tldr pages. Online and asking something off-script, cheat.sh, accepting that a composed answer is a ranked guess and that `+-` exclusion plus the `/1` and `/2` variants are how you check it.

## Conclusion

Adopt cheat.sh when you want one endpoint that answers both `curl cht.sh/tar` and `curl cht.sh/python/lambda` without leaving the terminal, and when the hosted service at cheat.sh is reachable from your network. Do not adopt it on a locked-down host with no outbound HTTPS, do not treat a generated answer as verified documentation, and do not paste its output into published product copy without reading the attribution markers it prints. Verify three things: that `curl cht.sh/go/:list` returns a list you can browse, that the answer you got for your query is the one you want by comparing `/1` and `/2` variants, and that a self-hosted build at port 8002 answers the same query the public instance does, because the two paths differ in where the content came from.

## FAQ

### What is cheat sh?

cheat.sh is an HTTP service that returns cheat sheets as plain text over curl or a browser, covering 56 programming languages, several DBMSes and more than 1000 UNIX and Linux commands. It is described as returning answers within 100 ms as a rule, and it can also be self-hosted with Docker.

### How to use cheat sh?

Put the command name in the URL path, such as `curl cht.sh/tar` or `curl cheat.sh/rsync`, and use `~` plus a keyword when you do not know the name, for example `curl cht.sh/~snapshot`. Language questions go in a per-language namespace such as `curl cht.sh/python/lambda`, and `curl cht.sh/go/:list` enumerates what is available for a language.

### how to install cheat sh

No installation is needed to use the service, since it is reached over HTTP or HTTPS. For offline use there is a separate command line client named `cht.sh` with Bash and ZSH tab completion, a stealth mode and a Windows variant, and the installation command is given in the Installation section of the project README. Self-hosting is a Docker build that runs `python3 lib/fetch.py fetch-all` and serves on port 8002.

## Sources

- [Official documentation](https://cheat.sh/)
- [Official README](https://github.com/chubin/cheat.sh#readme)
- [Project repository](https://github.com/chubin/cheat.sh)

---

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