Skip to content

About

go-sdk-generator is a contract-first generator for Go SDKs, CLI tools, and automation entrypoints (CI steps) to streamline and speed up the generation of tools written in go.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

386 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

GO SDK Generator

Go Badge License Manifest GHCR version Documentation Licence compliance SPDX SBOM

go-sdk-generator is a contract-first generator for Go SDKs, CLI tools, and automation entrypoints.

Like OpenAPI, it starts from a validated contract and generates consistent boilerplate from it. The difference is scope. OpenAPI is mainly about transport-level API contracts. go-sdk-generator is about user-facing operations and the Go package, CLI, and repository structure around those operations.

In practice, this means generating stable operations such as Compile, Verify, Deploy, DownloadArtifacts, or StoreCredentials: operations that may coordinate several lower-level calls, apply workflow rules, and expose one simpler interface to users and automation.

At a glance, this generator can produce:

  • a Go SDK surface for one concern
  • an optional CLI exposing the same intent
  • generated documentation and support files
  • generated GitHub Actions that wrap the generated tool for one workflow step

📖 This repository dogfoods the generator. The project manifest is generate.yml, and the generated outputs in this repository are produced from it.

⚙️ This project also comes with CLI tools and commands for ease of use

👷 The project also provides a GitHub Action which can ease integration into workflows

Start with the task guides to install the tool, write a manifest, generate a project, or use it in GitHub Actions. For every CLI flag and generated SDK type, see the command reference. The manifest schema is authoritative; go-sdk-generator schema prints it as JSON.

go-sdk-generator --help
go-sdk-generator generate --help

On systems with man pages installed, run man go-sdk-generator.

Installation

On supported Linux distributions, install package go-sdk-generator with the configured system package manager (apt, dnf, or yum). See install and inspect for commands, verification, and container usage.

Released Linux packages also install the skills related to the tool under /etc/go-sdk-generator/.agents/skills.

OCI images are also available at ghcr.io/arm-software/go-sdk-generator for CI and container-based use. The installation guide covers image selection, authentication, verification and troubleshooting.

Agent

Skills for working with go-sdk-generator:

Repository-maintained skills for manifest authoring, schema changes, and other development tasks live in .agents/skills/. The three skills above are generated; go-sdk-generator agent --init installs the embedded versions into a target repository.

Documentation

Choose a task:

The guide index links the task guides and references. The DOCUMENTATION.md file is the generated CLI and Go SDK reference; the development guide is for contributors. At each release, the guides are rendered and published alongside the API reference on GitHub Pages.

What "SDK" Means Here

SDK does not have one universal definition. In different ecosystems it can mean anything from a full application platform such as the Android SDK to a much smaller client library.

In this repository, SDK has a narrower and more practical meaning.

Internally, we often overload the term SDK to mean the library part of the generated project. That shorthand is useful in day-to-day conversation, but it is narrower than the actual goal of the manifest.

Here, an SDK is a Go package that exposes a stable, user-facing set of operations for a domain or tool. It usually includes:

  • exported configuration and domain types
  • one or more Go interfaces and implementations for the intended operations
  • optional CLI commands exposing the same intent at the command line
  • documentation and project structure that make the package easy to adopt and automate

It is not primarily a raw transport client and it is not a full framework. It sits in the middle: above low-level API clients or helper packages, but below application-specific business logic in the consuming project.

More importantly, the manifest is intended to define everything around one concern, and to define it fully. Following the spirit of the Unix philosophy as much as practical, each generated project should do one thing well. What gets exposed is up to the author of the manifest:

  • a Go library only
  • one CLI tool
  • multiple CLI tools or commands
  • dedicated actions for CI/CD
  • or a combination of these

The important part is not whether we call it an SDK, CLI, or action. The important part is that the generated project gives one coherent interface around one concern and handles that concern completely.

In practice, that means the generated SDK is the layer that turns lower-level details into operations that make sense to callers, such as Compile, Verify, Deploy, DownloadArtifacts, or StoreCredentials.

For comparison, a smaller client library might expose methods such as CreateJob, GetJob, and DeleteJob, each mapping closely to one API endpoint or RPC. In our sense, the SDK is the layer above that kind of client. It might expose one operation such as Compile that creates a job, uploads inputs, polls for completion, and downloads artefacts behind one Go method and one CLI command.

Why This Exists

This project exists to generate the repetitive parts of SDKs and CLIs while keeping the implementation code under our control.

The main problem is not generating HTTP clients. We already have tools for that. The main problem is generating the stable layer above those clients: the package structure, configuration types, CLI flags, documentation, and stubbed entrypoints for the operations we actually want people and automation to run.

We built the generator because, over time:

  • handwritten SDKs and CLIs drifted apart
  • teams had to repeatedly rebuild the same boilerplate for config, commands, docs, and packaging
  • OpenAPI solved transport-level API description, but not the higher-level operations we wanted to expose
  • CLI behaviour such as arguments, environment-variable loading, and signal handling was too easy to implement differently from one project to another

The generator addresses that by making the manifest the source of truth and emitting a consistent Go package and optional CLI around it.

That gives us:

  • Go types for the configuration and domain data we want to expose
  • an interface-first Go library surface for user-facing operations
  • a CLI that maps onto the same intent and configuration as the Go library
  • a foundation for GitHub Actions that can call a compiled Go tool instead of re-implementing logic in bash or JavaScript
  • a more consistent repository structure and documentation model across projects

It also helps uniformise how we define CLIs. Argument binding, environment-variable loading, config conventions, and signal handling can all be generated in one consistent way so that tools across projects have a single, simple look and feel. In practice this gives a more uniform Cobra-style CLI surface and Viper-style configuration loading across projects. That reduces cognitive load for both users and maintainers because each tool behaves more like the others.

How It Works

  1. Write a manifest in YAML or JSON that follows generator/schema/schema.yml.
  2. Describe your package metadata, global configuration, interface methods, and optional CLI commands.
  3. Run go-sdk-generator generate against that manifest.
  4. Implement or extend the generated stubs using the project's delegate pattern and normal Go code.

The manifest is the source of truth for generated structure. That makes the project contract-first and easy to regenerate when the SDK surface evolves. When that contract changes incompatibly, follow breaking changes and deprecation.

References:

What It Generates

Depending on the manifest, the generator creates a Go SDK and optionally a CLI, actions, documentation and supporting files. The output guide explains each surface, what you implement yourself and how the tool fits into automation.

Compared To Scaffolding Tools

It is useful to compare go-sdk-generator to scaffolding tools such as kickstart, yeoman, cookiecutter, plop, or slush.

Those tools usually optimise for flexibility. They are designed to let users compose templates, answer prompts, choose project variants, and adapt the generated structure to many unrelated use cases.

go-sdk-generator makes a different tradeoff. It is much more opinionated.

The goal is not to be a general-purpose scaffolding engine. The goal is to generate Go SDK and CLI repositories in one consistent way from a validated contract.

In practice that means:

  • fewer per-project decisions about repository layout, config loading, command structure, and support files
  • less freedom to shape every generated file differently
  • more consistency across generated SDKs, CLIs, actions, documentation, and packaging
  • more emphasis on one manifest describing one concern clearly and completely

In short:

  • scaffolding tools optimise for flexibility
  • go-sdk-generator optimises for consistency

That opinionated approach is intentional. It reduces boilerplate drift across repositories and lets improvements in the generator apply uniformly across many generated projects instead of being reimplemented one project at a time.

Compared To Task Runners

It is also useful to compare go-sdk-generator to task runners such as:

These tools solve a different problem.

Task runners help define and execute repeatable commands such as:

  • build
  • test
  • lint
  • release
  • deployment or local developer workflows

go-sdk-generator is not primarily a task runner. It is the tool that generates one focused Go tool surface around one concern: typically a CLI, a step-level action, or both, together with the supporting documentation and repository structure.

In practice, that means the two can complement each other well:

  • go-sdk-generator generates the tool and project structure for one concern
  • a task runner can then orchestrate how that generated tool is built, tested, invoked, or released as part of local workflows and CI/CD pipelines
  • go-sdk-generator can generate GitHub Actions for a specific step in a workflow, but the workflow itself still has to be defined elsewhere and the workflow orchestrator is a separate concern

For example, a generated CLI such as verify-cmsis-example-sdk can later be used inside a Taskfile.yml, justfile, Makefile, or CI workflow as one step in a larger automation pipeline.

Similarly, a generated composite GitHub Action can wrap one generated command, but a larger workflow such as build, test, release, or deployment orchestration still belongs in a higher-level workflow definition or task runner.

That mirrors the spirit of the Unix or POSIX model: generate one tool that does one concern well, then compose it with other tools inside a broader workflow.

If you think in CI terms:

  • go-sdk-generator can generate a tool and optionally a step-level action
  • GitHub Actions workflows define how several steps fit together
  • task runners such as Task or just define how commands are orchestrated locally or in CI

In short:

  • task runners optimise for command orchestration
  • workflow systems such as GitHub Actions orchestrate multi-step automation
  • go-sdk-generator optimises for consistent contract-driven tool generation for one concern, which those systems can then compose into larger workflows

Quick Start

Use the repo's own generate.yml as a concrete example manifest. See generate and regenerate a project for the complete workflow.

Example generation command:

go-sdk-generator generate -i generate.yml -o . --go-version 1.27.3

After generation, run go mod tidy and go generate ./... inside each generated Go module; this repository's generator/ and cli/ directories are separate modules. See generate and regenerate a project for the full sequence.

Common flags:

  • -i, --input: path to the manifest file
  • -o, --output: destination directory for generated code
  • -g, --go-version: target Go version to generate for
  • --overwrite: regenerate all files, including stateful/generated project files

The -g flag should normally match the Go version used by the target project.

Manifest Shape

At a high level, the manifest describes:

  • specification.package_name: the generated module or package identity
  • specification.main_module: the main generated Go module within the project
  • specification.repository_url and specification.public: repository location and public/private status for generated project metadata and hosting integrations
  • specification.interface: the SDK methods users call from Go
  • specification.command_line_commands: the CLI binary, commands, and flags
  • specification.global_configuration: shared configuration used across SDK and CLI
  • specification.additional_types: extra exported types the generated SDK should expose
  • specification.tag_latest: optionally keep a moving latest tag on the newest stable release (defaults to false); pin a version for reproducible builds
  • specification.update_copyright_headers: keep source-file attribution, years and SPDX licence identifiers current automatically (defaults to true)

At the field and parameter level, a few flags are especially important:

  • lang_type: the base type or built-in alias to generate from. See built-in types and formats.
  • enum: for string or *string shaped values, define a closed set of allowed manifest values that generate Go enums, validation, and clearer CLI help text
  • constraints: add explicit validation rules for string shape, numeric range, collection size, path-like values, conditional requirements, and other parameter semantics so invalid values are rejected as early as possible
  • example / examples: provide representative values for generated documentation, CLI help, GitHub Action input descriptions, and agent-facing skills. For list or iterator shapes, each example represents one item value.
  • reference: true: generate the value as a pointer to that type
  • list: true: generate the value as a list of that type, usually []T
  • iterator: true: generate the value as an iterator of that type, iter.Seq[T]

Rules:

  • list and iterator are mutually exclusive
  • enum is intended for string-like values and should not be combined with unrelated non-string shapes
  • if a method argument is the last argument and list: true, the generated method signature uses a variadic form ...T
  • reference, list, and iterator shape the generated Go type on top of the base lang_type

For validation-oriented manifests, prefer using as many meaningful constraints rules as the contract genuinely supports rather than leaving requirements implicit in descriptions or downstream runtime logic. The available constraint vocabulary is intended to stay roughly aligned with JSON Schema and OpenAPI-style rules where practical, while still fitting this generator's SDK and CLI model.

Typical examples include:

  • string-like rules such as pattern, min_length, max_length, contains, not_contains, prefix, suffix, and not_empty
  • numeric rules such as minimum, maximum, exclusive_minimum, exclusive_maximum, and multiple_of
  • collection rules such as min_items, max_items, unique_items, at_least_one, and exactly_one
  • path-like rules such as extension
  • conditional or cross-parameter rules such as dependent_required, conflicts_with, required_when, and forbidden_when

Using these rules keeps validation early and consistent across generated Go types, CLI configuration, documentation, and GitHub Actions.

Breaking Changes And Deprecation

Incompatible changes to a published manifest or generated surface need an explicit migration path. Prefer adding a replacement, marking the old concept with deprecation_notice, then documenting and allowing time for migration before removal. See breaking changes and deprecation for examples, versioning guidance and news-file conventions. For a starting contract, see write a manifest.

OpenAPI Analogy

If you already think in OpenAPI terms, the easiest way to understand this project is:

  • OpenAPI describes REST contracts and then generates API-facing clients and servers
  • go-sdk-generator describes operation contracts and then generates Go SDK and CLI boilerplate

That makes it useful when your main concern is the user-facing operation, configuration, and documentation shape rather than the transport protocol.

Alternatives

We considered several alternatives before settling on a bespoke generator.

Handwritten SDKs and CLIs

Writing each SDK and CLI by hand gives full control, but it repeats the same setup work for every project.

  • more manual effort for each new SDK
  • more inconsistency between projects
  • more maintenance for docs, config loading, commands, and packaging

This is viable for one-off tools, but it scales poorly when multiple SDKs should follow the same conventions.

OpenAPI Generators

OpenAPI generators are a strong fit for REST contracts.

  • best for endpoint-focused clients and server stubs
  • less suitable for operation-oriented SDKs that orchestrate several steps behind one user-facing operation
  • models HTTP transport well, but not the higher-level SDK and CLI patterns this project targets

We still use OpenAPI where the problem is API-description. go-sdk-generator is for the layer above that.

Smithy

Smithy is protocol-agnostic and closer to this problem space than OpenAPI, but it still was not the right fit here.

  • extra language and tooling to learn and maintain
  • Go support was not strong enough for the kind of operation-oriented SDK generation we wanted when this direction was evaluated
  • still leaves a lot of project-specific SDK flow and library design work for us to own

It was promising in theory, but it did not reduce enough of the work we actually needed to standardise.

Fern

Fern focuses on API and SDK generation with strong documentation tooling.

  • closer to an API-definition platform than an operation-oriented boilerplate generator
  • less aligned with our existing Go-first internal development patterns
  • not aimed at generating the exact interface, CLI, and project structure conventions we wanted

It solves a neighbouring problem, but not this one.

Why Bespoke Won

The bespoke approach let us keep the parts we cared about most:

  • a schema-driven, contract-first workflow
  • output tailored to our Go project conventions
  • consistent SDK, CLI, and documentation patterns across projects
  • uniform CLI behaviour around arguments, environment variables, and signal handling
  • generated Go tooling that can also power GitHub Actions with stronger testing and structure than ad hoc shell scripts
  • a way to raise the baseline quality of many projects at once as the generator evolves
  • an upgrade path where projects can usually move to newer generator versions to pick up improvements without disruptive rewrites
  • generated boilerplate without giving up control of implementation code

The main trade-off is maintaining the generator and the schema, but that was preferable to forcing a general-purpose tool into an operation-oriented problem it was not designed to solve.

Secret Management In Generated CLI Tools

Secret-marked CLI inputs can be collected into a generated Credentials command for supported system keyrings. See secret management in generated CLI tools for manifest examples, keyring behaviour and security boundaries.

Capabilities

The generator provides built-in formats, validation, computed defaults and functional options. See types, formats and defaults for the lang_type and default_value reference, configure functional options for Enabled, value_field and CLI bindings, or write a manifest to apply these capabilities in a project.

Using this SDK

To include and use this SDK in your go project, add the following line to your go.mod:

require (
    github.com/ARM-software/go-sdk-generator/generator   latest
    ...
)

run go mod tidy

Releases

For release notes and a history of changes of all production releases, please see the following:

Project Structure

The following describes the major aspects of the project structure:


    cli/ - Definition of the CLI to use the tool directly from a terminal.
    generator/ - Go source files describing the SDK.
    changes/ - Collection of news files for unreleased changes.
    guides/ - Markdown source for task-based guides rendered into docs/guides/.
    scripts/ - Automation scripts for continuous integration (CI) and package control tasks such as building, validating, and releasing packages.
    .*/ - Configuration for development tooling such as continuous integration, static analysis (linters), and version control (Git).

Getting Help

Contributing

About

go-sdk-generator is a contract-first generator for Go SDKs, CLI tools, and automation entrypoints (CI steps) to streamline and speed up the generation of tools written in go.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages