# hcloud: the Hetzner Cloud CLI, and how it marks commands as experimental

> hcloud is the Go command line client for Hetzner Cloud, built on cobra, viper and the hcloud-go API library, with an explicit experimental feature tier that can break within a minor release. It is the tool for scripting a Hetzner account, and the place to look before scripting a provider that does not have one.

**hetznercloud/cli** — A command-line interface for Hetzner Cloud

- Repository: https://github.com/hetznercloud/cli
- Stars: 1,848 · Forks: 106
- Language: Go
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/hetznercloud-cli

## A cobra command tree on top of the hcloud-go API client

hcloud is a command-line interface for interacting with Hetzner Cloud, and the dependency list in go.mod tells you how it is built.

The command layer is spf13/cobra at 1.10.2 with spf13/pflag for flags, which is the standard Go combination and gives you subcommands, help text and shell completion for free. Configuration is spf13/viper at 1.21.0, with spf13/cast for type coercion, and the format support comes from BurntSushi/toml at 1.6.0 and goccy/go-yaml at 1.19.2. The API client is github.com/hetznercloud/hcloud-go/v2 at v2.52.0, which is the same organisation's Go SDK, so the CLI is a thin, well defined layer over a library that you could also call directly.

The module requires Go 1.26.0 with a go1.27.2 toolchain directive, so building from source needs a current toolchain. The repository is laid out the way a cobra application usually is: cmd/ holds the command entry points, internal/ holds the implementation, test/ holds the tests, docs/ holds the reference manual and tutorials, and examples/ holds a sample file. There is also a .golangci.yml for linting, a .goreleaser.yml for the release build, a codecov.yml for coverage, a mise.toml for tool versions, and a renovate.json for dependency updates.

The top level is deliberately thin, which tells you the interesting part is inside internal/. The examples directory contains a single file, firewall_rules.json, which is a good hint about what the CLI is for: turning a declarative file into cloud resources rather than making a series of ad hoc calls.

## The experimental tier, and the warning it prints at you

This is the part of the project that deserves the most attention from anyone writing scripts against it, and it is documented in its own README section rather than buried in the manual.

The rules are stated precisely. Experimental features are published as part of the regular releases, for example a product public beta. During an experimental phase, breaking changes on those features may occur within minor releases. The stability of experimental features is not related to the stability of its upstream API. Experimental features have different levels of maturity, such as experimental, alpha or beta, based on the maturity of the upstream API.

Two practical consequences follow. First, the maturity label is inherited from the API the feature sits on, not from how long the CLI command has existed. A command can be labelled beta because the underlying Hetzner API is beta, and the CLI says so rather than pretending otherwise.

Second, the CLI tells you at runtime. Experimental commands will be announced in the release notes, you can find out whether a command is experimental in its help text, and using an experimental command shows a warning when you run it. That warning can be suppressed by enabling the no-experimental-warnings option.

That last point is where a careful reader should slow down. Suppressing the warning is a decision to accept silent breakage in a minor release, and it is a configuration option, which means it can be set in a shared config file that a colleague enables once and everyone inherits. The sane engineering approach is to leave the warning on in scripts and read the release notes, rather than switching it off to make the output tidy.

## Output that is designed for both a human and a script

The dependency list shows that hcloud takes terminal output seriously, and the set of libraries is a catalogue of the features.

For rendering, jedib0t/go-pretty at 6.8.3 provides the tables, cheggaaa/pb at 3.2.1 is the progress bar, guptarohit/asciigraph at 0.10.0 draws ASCII graphs, dustin/go-humanize formats sizes and counts, and fatih/color adds colour. So a listing is a formatted table, a long running operation shows a progress bar, and a metric can be drawn as a chart in the terminal.

For machine consumption, the structured assertion library swaggest/assertjson is a direct dependency, which points at machine-readable output as well. The presence of assertjson among the direct dependencies, along with stretchr/testify and go.uber.org/mock, tells you the test suite asserts on the JSON output rather than on the pretty output. That is the right way to test a CLI, because the pretty output is a presentation layer on top of a structured one.

Two smaller details are worth noting. golang.org/x/term and mattn/go-isatty and mattn/go-colorable are in the tree, which means the CLI detects whether it is writing to a terminal, so colour and interactive elements are suppressed when the output is a pipe. And BurntSushi/toml being a direct dependency, alongside goccy/go-yaml, means configuration files can be written in either TOML or YAML, and the indirect pelletier/go-toml/v2 dependency shows the TOML path is wired up.

The practical rule for scripting is to read the structured output, not the table, and to leave the terminal detection to do its job.

## Installation and configuration live in the docs, not the README

The README is short, and it points rather than explains. For instructions on how to install and configure the CLI there is a setup tutorial at docs/tutorials/setup-hcloud-cli.md, and for a list of all available commands and their options there is the manual at docs/reference/manual/hcloud.md. Additional information is in the docs directory.

That means the README does not give the install command itself, and there is nothing to copy from it. The route is the setup tutorial, and if you want the full command surface before installing anything, the manual is the reference for it.

What the repository layout does tell you is where the practical content is. The docs/ directory holds both the tutorial and the generated manual, which means the manual is produced from the command definitions rather than maintained by hand. The examples/ directory holds firewall_rules.json, a declarative example of how you would express firewall rules as a file, and the presence of the config layer in the dependency list tells you the same file could be read by the CLI to create the rules rather than you pasting them into an editor.

The other thing worth knowing is that the documentation is versioned alongside the code. The docs link to the setup tutorial in the repository rather than to a hosted site for the latest release, so the instructions you read match the version of the binary you built.

## Where a Hetzner specific client is the wrong tool

The honest limits of hcloud are worth stating, because a cloud CLI is easy to over-trust.

The first is scope. Every command, flag and output format in hcloud describes Hetzner Cloud's resources and its API. It is not a multi cloud abstraction, and it will not grow into one, because the command tree, the hcloud-go client it sits on and the resource model are all Hetzner specific. If your organisation runs infrastructure across more than one provider, you will end up maintaining a script per provider, and hcloud is one of those scripts rather than the layer that unifies them.

The second is the experimental tier described earlier, which is the real cost of adopting the tool for automation. The project is explicit that breaking changes may land in a minor release for experimental commands, and while the warning system and the release notes are good practice, a pipeline that depends on a beta command has accepted that risk.

The third is that a CLI is a convenience, not a guarantee. It is a client for a REST API, and it carries the API's own semantics. Its output is a rendering of what the API returns, and the API's pagination, rate limits and error model are the ones you inherit. The CLI will give you a table, and the reliability of your automation is the reliability of the API underneath it.

The fourth is that if you already have infrastructure as code for Hetzner, the CLI may be redundant. A file of firewall rules, applied by a tool, is reproducible and reviewable in a way that a shell script invoking hcloud repeatedly is not.

## Releases, tooling, and a project that publishes its own manual

The release cadence is fast and the version numbers say so. The newest listed release is v1.70.1 from 2026-10-06, preceded by v1.70.0 on 2026-10-05 and v1.69.0 on 2026-09-24. The last push to the repository was on 2026-10-19, and the repository is not archived.

Two minor versions in a fortnight and a patch on top is the pattern of a project shipping continuously rather than on a schedule. That is good news for a tool that talks to a live API, because it means compatibility fixes and new resources land without a long wait.

The build tooling in the repository root is what makes that cadence possible. The.goreleaser.yml file drives the multi platform release, the ci.yml and build.yml workflows handle the pipeline, codecov.yml tracks coverage, and renovate.json keeps the dependency list current. The dependency set itself is broad, with more than twenty direct requirements including the Hetzner SDK, the cobra stack, the terminal libraries and the x/crypto, x/net, x/term and x/text packages. A renovate configuration alongside a go.sum means the updates are automated, which is how a project like this avoids a security advisory in a transitive dependency sitting unfixed for months.

The CHANGELOG.md at the root and the CONTRIBUTING.md beside it complete a repository that follows the standard conventions for a Go command line tool, and the MIT license with a LICENSE file requires keeping the copyright and license notice.

## Conclusion

hcloud fits an operator or engineer who manages Hetzner Cloud resources from a shell, in a script, or from a CI job, and who wants typed output rather than scraped JSON. It does not fit a workflow that needs a stable command surface for every feature, because the project reserves the right to break experimental commands within a minor release. Check three things before you script against it. Check which commands are experimental, since the help text marks them and the CLI prints a warning when you use one, and you can turn that off with the no-experimental-warnings option only if you have decided you accept the risk. Check the output format you will parse, because the dependency list includes table rendering, a progress bar, humanised sizes and a JSON encoder, so both human and machine output are first class. And check the config file format, because the CLI reads TOML and YAML through viper with BurntSushi/toml and goccy/go-yaml in the dependency list, so a config written for one provider's tool is unlikely to move. The last push was on 2026-10-19, the newest release is v1.70.1 from 2026-10-06, and the license is MIT.

## FAQ

### How do I install and configure the hcloud CLI?

The project points to a setup tutorial at docs/tutorials/setup-hcloud-cli.md for installation and configuration instructions, and to docs/reference/manual/hcloud.md for the list of all available commands and their options.

### What does hcloud use for configuration files?

Configuration is handled by spf13/viper with spf13/cast for coercion, and the module lists BurntSushi/toml and goccy/go-yaml as direct dependencies, so TOML and YAML are both supported formats.

### What are experimental features in the hcloud CLI?

Experimental features ship as part of the regular releases, for example a product public beta, and breaking changes on them may occur within minor releases. Their maturity label such as experimental, alpha or beta is based on the maturity of the upstream API, they are announced in the release notes, and the help text marks them, with a warning shown at runtime.

### How can I turn off the experimental feature warning in hcloud?

By enabling the no-experimental-warnings option. The README notes that experimental commands show a warning when running, and that the stability of an experimental feature is not related to the stability of its upstream API.

### Can I script hcloud and rely on its output?

The CLI renders tables with jedib0t/go-pretty, a progress bar with cheggaaa/pb, and supports a JSON output format, and the test suite asserts against the JSON with swaggest/assertjson. Reading the structured output rather than the table is the way to script it, and terminal detection suppresses colour when output is piped.

### What license is the hcloud CLI released under?

The MIT license, with a LICENSE file at the root of the repository. The newest listed release is v1.70.1 from 2026-10-06, and the last push was on 2026-10-19.

## Sources

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

---

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