The Minimalist
Go Build Utility

A focused wrapper around the Go toolchain. Automate cross-compilation, dynamic version injection, and hot-reload development without the bloat of task runners.

go install github.com/onurartan/craft@latest

Why Craft?

The Old Way (Makefile)

Bloated

Hard to maintain, fails on Windows, requires bash syntax, and clutters your project root.

Makefile
VERSION := 1.0.0
LDFLAGS := -s -w -X main.Version=$(VERSION)

build-all:
	GOOS=linux GOARCH=amd64 go build -ldflags="$(LDFLAGS)" -trimpath -o bin/app-linux .
	GOOS=windows GOARCH=amd64 go build -ldflags="$(LDFLAGS)" -trimpath -o bin/app.exe .
	GOOS=darwin GOARCH=arm64 go build -ldflags="$(LDFLAGS)" -trimpath -o bin/app-mac .

The Craft Way

Streamlined

Declarative YAML, native Go execution, cross-platform by default. No bash required.

terminal
$ craft build --all

│ Project    app
│ Version    1.0.0
│ Targets    3 Platform(s)

PLATFORM        STATUS    SIZE       TIME      ARTIFACT
linux/amd64     Done      4.20 MB    1.2s      bin/app-linux-amd64
windows/amd64   Done      4.35 MB    1.5s      bin/app-windows-amd64.exe
darwin/arm64    Done      4.15 MB    1.1s      bin/app-darwin-arm64

Installation

1. Go Toolchain (Recommended)

If you are a Go developer, use the native toolchain. It complies Craft specifically for your host machine in seconds.

$ go install github.com/onurartan/craft@latest

Ensure your ~/go/bin is added to your system's PATH variable.

2. Pre-Compiled Binaries

Want to use Craft in CI/CD without installing Go? Download the standalone executable directly from GitHub Releases. Zero dependencies.

Download for Windows / Mac / Linux

Configuration Anatomy

Click any block in the configuration file below to explore its advanced capabilities. Craft's declarative design hides a massive amount of complexity under the hood.

.craft.yaml
# --- METADATA & PATHS ---
name: "craft"
entry_point: "."
output_dir: "bin"
exact_name: true
# --- VERSIONING & LDFLAGS ---
version: "in_go:main.AppVersion"
version_pkg: "main.Version"
# --- PLATFORM TARGETS ---
build_all: false
platforms:
  - "current"
# --- BUILD PROFILES ---
profiles:
  npm:
    output_dir: "npm/bin"
    build_all: true
    exact_name: false
  release:
    output_dir: "releases/v1"
    platforms: ["linux/amd64", "windows/amd64"]
# --- OPTIMIZATION ---
strip_debug: true
trimpath: true
cgo_enabled: false
race: false
tags: []
# --- HOT-RELOAD ENGINE ---
dev:
  watch:
    enabled: false
    delay_ms: 500
    include_exts: ["go", "env"]
    exclude_dirs: ["bin", "vendor"]
Inspector

Dynamic Versioning Engine

Superpower

Craft features a native AST (Abstract Syntax Tree) and file parser. Instead of hardcoding versions in YAML, Craft can dynamically extract them directly from your source code or configuration files.

1. The 'in_go' Parser (AST Extraction)

Reads the target Go file using the native compiler AST, safely extracting the value without dirty regex.

# Extracts value of AppVersion from main.go
version: "in_go:main.AppVersion"

2. The 'file' Parser (Struct Extraction)

Parses raw text, JSON, or YAML files to extract specific keys. Perfect for monorepos sharing a package.json.

# Reads raw content of .version file
version: "file:.version"
# Parses package.json -> version key
version: "file:package.json|version"
# Nested YAML keys (e.g. app.metadata.version)
version: "file:config.yaml|app.metadata.version"

LDFLAGS Injection (version_pkg)

Once the version is extracted via the methods above, defining version_pkg: "main.Version" automatically injects that value into your binary at compile time via -ldflags "-X main.Version=...".

Build Profiles

Workflows

Profiles eliminate the need for complex Makefiles. Define specific environments (like npm or release) and override the global configuration.

How it works

If you run craft build -P npm, the engine merges the npm profile over the base settings. In the example on the left, it changes the output directory to npm/bin, forces build_all: true, and turns off exact_name.

$ craft build --profile release
  • Overrides `output_dir`
  • Overrides `name`
  • Overrides `platforms` array
  • Overrides `build_all` boolean
  • Overrides `exact_name` boolean

Core Metadata

The foundational structure and routing for your Go compilation.

output_dir

The root destination. Craft will dynamically recursively create deep directories if needed (e.g., bin/server/linux/).

exact_name

By default, building for multiple platforms appends suffixes (e.g., craft-linux-amd64). Setting this to true forces the output to be exactly the name string. Useful for Docker container entrypoints.

entry_point

Points to the directory containing your func main(). Defaults to ".".

Target Matrix

Cross-compilation orchestration.

build_all

If true, overrides the platforms list and compiles concurrently for Linux (amd64/arm64), Windows (amd64), and macOS (amd64/arm64).

platforms

An array of GOOS/GOARCH strings. The special keyword "current" reads your machine's local OS and Architecture for rapid local testing.

Compiler Directives

Control how the Go toolchain builds and optimizes your artifact.

strip_debug

Passes -s -w to the linker. Strips DWARF symbol tables, drastically reducing binary size.

trimpath

Removes local filesystem absolute paths from compiled stack traces. Crucial for privacy and reproducible builds.

cgo_enabled

Turns on CGO. Warning: Cross-compilation with CGO requires external C compilers (like Zig or GCC cross-compilers).

tags

Array of Go build tags. Example: ["pro", "enterprise"] injects -tags pro,enterprise into the build command.

Hot-Reload Engine

dev mode

Settings for craft dev. Craft watches your project intelligently, consuming zero unnecessary memory.

delay_ms

Debounce timer. If you rapidly save a file 5 times, Craft waits 500ms before triggering the build to prevent system lockups.

include_exts

Craft only monitors these extensions. Ensures it ignores massive assets like images or SQLite databases.

exclude_dirs

Crucial for performance. Craft completely ignores heavy folders like node_modules, vendor, and .git.

CLI Reference

Build Orchestrator

Compiles your project based on .craft.yaml. Injects LDFLAGS, strips debug symbols, and handles multi-target compilation in a single pass.

Shortcut Alias

Running just craft without any command automatically defaults to craft build.

$ craft build [flags]

Available Flags

  • --name, -n Override the binary output name specified in yaml.
  • --version, -v Override the application version string.
  • --entry, -e Set the main package path (default is .).
  • --out, -o Define destination directory for artifacts (default: bin/).
  • --ver-pkg Target Go variable path for LDFLAGS version injection.
  • --all Cross-compile for all common operating systems and architectures.
  • --platform, -p Specify custom targets. E.g., linux/amd64,windows/amd64
  • --strip Omit DWARF symbol tables to drastically reduce binary size (default: true).
  • --exact-name Omit OS/Arch suffixes. Outputs app instead of app-linux.

Advanced Workflows

Intelligent Hot-Reloading

Craft's dev engine doesn't just restart processes. It isolates the build in your OS's temp directory, debounces rapid file saves, and automatically ignores vendor/ and node_modules/ directories to save memory.

$ craft dev
→ Watching 420 files. Rebuilding on save...

Frictionless Cross-Compilation

Stop exporting GOOS and GOARCH manually. Define your targets in .craft.yaml or pass the --all flag. Craft handles the environment matrix and concurrently generates Windows, Linux, and Mac binaries.

$ craft build --all

Dynamic Version Injection

Inject the version string from your .craft.yaml directly into your Go code during build via LDFLAGS. No hardcoded versions.

1. In .craft.yaml:

version: "v1.5.0"
version_pkg: "main.AppVersion"

2. In main.go:

package main
var AppVersion = "dev" // Overridden by Craft

Smart Log Parsing

Raw Go toolchain errors are noisy. Craft intercepts go vet, go test, and compiler outputs, formatting them into human-readable, tree-structured logs.

$ craft check
Validation Suite
Static analysis found issues.
main.go:15:2undefined: fmt.Printl

CI/CD Ready

Craft is engineered to thrive in automated environments like GitHub Actions or GitLab CI. Use craft check to ensure code quality halts on failure, and use craft build --all to generate pristine release artifacts effortlessly.

.github/workflows/release.yml
name: Production Release
on:
  push:
    tags:
      - 'v*'

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-go@v5
        with:
          go-version: '1.21'
          
      - name: Install Craft Engine
        run: go install github.com/onurartan/craft@latest
        
      - name: Pre-flight Checks (fmt, vet, test)
        run: craft check
        
      - name: Compile Cross-Platform Artifacts
        run: craft build --all --strip
        
      - name: Publish to GitHub Releases
        uses: softprops/action-gh-release@v2
        with:
          files: bin/* # Craft's default output directory
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Troubleshooting & FAQ

Command not found: craft

If you ran go install but your terminal doesn't recognize craft, your Go binary path isn't in your system's PATH. Add ~/go/bin (or %USERPROFILE%\go\bin on Windows) to your environment variables.

CGO Cross-Compilation Fails

Cross-compiling across different OS (e.g., Mac to Windows) while cgo_enabled: true requires an external C compiler toolchain like MinGW or Zig. If your project doesn't strictly need C libraries, set it to false in .craft.yaml.

Why not just use Taskfile or Make?

Task runners execute shell commands. Craft is a dedicated Go utility that understands the Go ecosystem. It parses compiler logs, handles LDFLAGS natively, and executes strictly without relying on OS-level bash/powershell differences.

Can I use it on legacy projects?

Yes. Just navigate to your project root and run craft init. Craft will safely scan your go.mod and create a non-destructive .craft.yaml without touching your source code.