# sgpt, a Go rewrite of shell-gpt whose Ansible path skips package verification

> sgpt is a Go command-line client for OpenAI models that also speaks to OpenRouter, Requesty, Gemini and local endpoints, and it installs five different ways. The two things worth reading before you pick one are the automated install path, which sets allow_unauthenticated on a .deb, and a Dockerfile whose builder stage is pinned to the build platform rather than the target.

**tbckr/sgpt** — SGPT is a command-line tool that provides a convenient way to interact with OpenAI models, enabling users to run queries, generate shell commands and produce code directly from the terminal.

- Repository: https://github.com/tbckr/sgpt
- Stars: 460 · Forks: 34
- Language: Go
- License: MIT
- Published: 2026-09-14 · Updated: 2026-09-14 · Language: en
- Canonical page: https://hysenlabs.com/projects/tbckr-sgpt

## The Ansible path installs a remote .deb with allow_unauthenticated

Five install routes are documented and one of them skips package verification. Querying the GitHub API for the latest release, the Ansible playbook reads `tag_name` into a fact and hands apt a constructed download URL with authentication explicitly disabled:

```yaml
    - name: Install sgpt for debian based, amd64 systems
      ansible.builtin.apt:
        deb: https://github.com/tbckr/sgpt/releases/download/{{ sgpt_latest_version }}/sgpt_{{ sgpt_latest_version[1:] }}_amd64.deb
        allow_unauthenticated: true
```

The `[1:]` slice is the interesting part of the URL, because it documents the release asset naming convention: tags carry a leading `v`, and the built package does not, so the file is `sgpt_<version>_amd64.deb` with the `v` removed. That much is tidy. What is not tidy is `allow_unauthenticated: true`, which tells apt to accept a package with no valid signature. Presented as a base to adapt, that playbook will install an unverified binary with root privileges across a fleet if you adapt it without noticing the line.

Everything else about the playbook is reasonable. Pinning to `latest` rather than a chosen version means a rerun moves you forward without a deliberate decision, which is convenient on a personal machine and worth changing for anything else.

## Five install routes, and a Dockerfile that cannot cross-compile

Four mainstream routes are documented: a Homebrew tap, a Scoop bucket, `go install`, and a container image.

```bash
brew install tbckr/tap/sgpt
```

```bash
go install github.com/tbckr/sgpt/v2/cmd/sgpt@latest
```

```bash
docker pull ghcr.io/tbckr/sgpt:latest
```

The Go route is the one that tells you the most about the project. Module path `github.com/tbckr/sgpt/v2` puts the major version in the path and the command lives at `cmd/sgpt`, so `go install` resolves a tagged major release rather than a branch.

Two defects in the container image are worth reading past. Declaring the build stage as `FROM --platform=$BUILDPLATFORM` alongside `ARG BUILDPLATFORM=linux/amd64` means the compiler runs on the build machine's platform and the resulting binary is for that platform, so asking buildx for another architecture produces a binary that does not match. And the version story is inconsistent with the module: go.mod declares `go 1.26.8` while the builder image is `golang:1.27`.

What the image does well is worth noting too. Both base images are pinned by digest rather than by tag, including one whose tag still says `latest`, the binary is built with `CGO_ENABLED=0`, and the runtime is a Chainguard static base running as a nonroot user with `ENV HOME /home/nonroot` and a volume mounted there. One consequence for users: configuration and any key the tool writes land in that home directory, so a container started without a volume loses them.

## One OpenAI-compatible client fronts five providers

Provider support runs wider than a single OpenAI key suggests. Sections in the usage guide cover GPT-4o, the GPT-4 Vision API, o1, OpenRouter, Requesty, Google Gemini, local LLM support and chat capabilities, which means one binary can be pointed at OpenAI directly, at an aggregator, or at something on your own machine.

What makes that cheap is a dependency choice rather than five separate integrations. go.mod requires `github.com/sashabaranov/go-openai`, a client for OpenAI-compatible endpoints. Everything that speaks the OpenAI wire format, which is most hosted providers and most local servers, is reached through that one library by changing configuration. Gemini is the outlier that stands out precisely because the others need no special path.

Configuration runs through `spf13/viper`, which brings `fsnotify`, `afero`, `cast`, `mapstructure` and `gotenv` along with it. That set is what lets the tool read from files, environment variables and a home directory without a bespoke config layer, and it is also why there is a `.envrc` and a `.bashrc` committed at the repository root: this is a project that expects to be configured from the shell environment.

Rest of the dependency list is small, and it tells you what the tool does at its edges. `atotto/clipboard` copies output to the system clipboard, `spf13/cobra` provides the command tree, and `muesli/roff` with `muesli/mango-cobra` generate a man page, so `sgpt` ships proper manual pages rather than only `--help`.

## Prompt templating pipes YAML or JSON in through stdin

One feature in the list is a real mechanism rather than a restatement of asking a model a question: prompt templating. Structured data goes into the prompt using Go `text/template` syntax, with YAML or JSON variables piped through stdin so the same prompt pattern can be reused with different inputs. `gopkg.in/yaml.v3` is a direct dependency, which is the YAML half of that.

This is the feature to reach for if your prompts have structure. A question that embeds a log excerpt, a diff or a config file becomes a template with a named field, and the data arrives on stdin rather than being pasted into a shell argument where quoting would mangle it. That is a better fit for scripting than string interpolation in a shell function, and it is the clearest example in the project of the tool being designed for pipelines rather than for one-off questions.

Most of the front page goes to a table of contents rather than to this, so the mechanics live in the hosted documentation at sgpt.readthedocs.io instead. If templating is why you are considering this tool, read the documentation section first, because the feature list alone does not tell you the template syntax or how variables arrive.

## Versions come from commit messages, and secrets are scanned in CI

File names at the repository root expose the release pipeline, which is worth a look before you decide how to track releases. `release-please-config.json` and `.release-please-manifest.json` mean the version number is derived from commit messages rather than chosen by hand, which is why the README links the Conventional Commits specification. `.goreleaser.yaml` plus a separate `Dockerfile.goreleaser` handle the build matrix, and `CHANGELOG.md` is generated by the same process.

Two more automation files sit alongside. `renovate.json` keeps dependencies moving, and the badge for gitleaks together with `.gitleaksignore` means the CI runs secret scanning over the repository. That last one is a deliberate fit for this project, since the thing it asks users to do is put an API key in a shell profile.

Elsewhere the root is a well-equipped Go repository: `Taskfile.yml` for task running, `.golangci.yaml` for linting, `.pre-commit-config.yaml`, `.mdl_config.yaml` for markdown linting, `flake.nix` with `flake.lock` for Nix, `CODEOWNERS`, `SECURITY.md`, and `mkdocs.yml` with `.readthedocs.yaml` for the documentation site. There is also a `personas/` directory that the visible text does not explain, which is the one part of the layout a reader cannot place.

## The feature list repeats the introduction in sales language

A practical warning about the front page: the introduction and the feature bullets make the same claims twice, in the vocabulary of software advertising rather than in the vocabulary of mechanisms. Words about power and frictionless use recur across both, and the closing line of the introduction restates the opening. Bullets underneath do add specifics the introduction lacks, such as the vision API and the o1 section, so the information exists, buried under the repetition.

Smaller inconsistencies are worth a glance. Licence naming is inconsistent: the badge at the top of the README points at `LICENSE.md`, the repository root has `LICENSE` with no extension, and the Dockerfile carries its own MIT header with an SPDX identifier alongside a separate `licenses/` directory. One line credits the tool with having been developed with the help of the tool itself, which reads like an editing leftover from the port.

Then there is the truncation. Setup walks through obtaining a key and begins an export statement for it in `.bashrc` or `.zshrc`, then the visible text stops partway through the variable name. So the one piece of configuration a first-time user needs is the piece you cannot read here, and you will have to take the variable name from the hosted documentation.

## Generating a command and running it are separate steps

Headline capability is producing shell commands from a description, alongside sections for executing them and for interactive shell sessions. That combination is what makes it useful and what makes it worth thinking about before you wire it into anything. A model asked for a command will produce something plausible, and a plausible command is exactly what you cannot check by reading quickly.

Two smaller edges are named in the feature list. Output can go to the system clipboard through the `atotto/clipboard` dependency, which means a response containing a secret can end up somewhere it persists. And the bash functions and aliases section describes wiring responses into your shell, which is how a tool that writes to your prompt becomes a tool that writes to your command line.

The Python project this one was ported from is the alternative. Shell-gpt is named as the original implementation, with a request to keep that in mind when reporting issues, because the two share a lineage and a name but not a tracker. What differs in approach is the rewrite: a Go implementation with a `/v2` module path, its own release pipeline, a man page generator, and prompt templating driven by `text/template` over stdin. Same idea, different runtime, different set of trade-offs, and a bug you find here probably belongs upstream rather than here.

## Conclusion

Adopt sgpt if you want a single static binary that talks to OpenAI and to OpenAI-compatible endpoints, and if you install it with brew, scoop or go install rather than the Ansible playbook. Do not adopt the Ansible route on a machine where package authenticity matters, because that task sets `allow_unauthenticated: true` on a remote .deb, and do not assume the Docker image cross-compiles, because the builder stage is pinned to `$BUILDPLATFORM`. Verify three things first: which provider your key belongs to, since one binary fronts OpenAI, OpenRouter, Requesty, Gemini and local models through the same OpenAI-compatible client; where your configuration lands, since the container image sets `HOME /home/nonroot` and mounts a volume there, so a key passed only at build time is not there at run time; and whether you have read the shell execution path before you let generated commands run, because generating a command and running it are separate steps in a tool whose purpose is both.

## FAQ

### How do I install sgpt on macOS and Windows?

On macOS with Homebrew run brew install tbckr/tap/sgpt. On Windows with Scoop, add the bucket with scoop bucket add tbckr pointing at the scoop-bucket repository, then run scoop install tbckr/sgpt. With Go, use go install github.com/tbckr/sgpt/v2/cmd/sgpt@latest.

### Does the sgpt Ansible playbook verify the package it installs?

No. The playbook's apt task installs the release .deb with allow_unauthenticated: true, so apt accepts it without a valid signature. The playbook is described as a base to adapt accordingly, which means that line needs removing before use on anything that matters.

### Which model providers can sgpt talk to?

The usage guide has separate sections for GPT-4o, the GPT-4 Vision API, o1, OpenRouter, Requesty, Google Gemini, local LLM support and chat. The mechanism is a client for OpenAI-compatible endpoints, so providers speaking that format are reached by configuration rather than by a separate integration.

### What does prompt templating in sgpt do?

It injects structured data into prompts using Go text/template syntax, with YAML or JSON variables piped through stdin so a prompt pattern can be reused with different inputs. gopkg.in/yaml.v3 is a direct dependency, and the front page does not give the template syntax itself.

### Where does sgpt store its configuration in the Docker image?

The image sets ENV HOME /home/nonroot and declares a volume at that path, and configuration and any written key land under the home directory. Both base images are pinned by digest and the binary is built with CGO_ENABLED=0, but the builder stage is pinned to $BUILDPLATFORM, so the compiled binary follows the build machine's architecture.

### Is sgpt the same project as shell-gpt?

No. sgpt is a Go implementation, and the README points to shell-gpt as the original Python implementation, asking that you keep the distinction in mind when reporting issues. sgpt carries its own module path with a v2 major version, its own release pipeline driven by release-please, and its own packaging for brew, scoop, go install and containers.

## Sources

- [Issues](https://github.com/tbckr/sgpt/issues)
- [License: MIT](https://github.com/tbckr/sgpt/blob/main/LICENSE)
- [README](https://github.com/tbckr/sgpt/blob/main/README.md)
- [Releases](https://github.com/tbckr/sgpt/releases)
- [tbckr/sgpt on GitHub](https://github.com/tbckr/sgpt)

---

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