Yet-another-agent-harness agent-ready-go
git clone https://github.com/dirien/yet-another-agent-harness
T=$(mktemp -d) && git clone --depth=1 https://github.com/dirien/yet-another-agent-harness "$T" && mkdir -p ~/.claude/skills && cp -r "$T/.claude/skills/agent-ready-go" ~/.claude/skills/dirien-yet-another-agent-harness-agent-ready-go && rm -rf "$T"
.claude/skills/agent-ready-go/SKILL.mdAgent-Ready Go
Make Go applications work effectively with AI coding agents by ensuring all tooling produces machine-readable output, errors are structured, and commands run non-interactively by default.
Workflow
Making a Go app agent-ready involves these steps:
- Audit — identify gaps against the agent-readiness checklist
- Structured logging — add/configure slog, Zap, ZeroLog, or Logrus with JSON output
- Machine-readable output — ensure all commands can emit JSON
- Linting — add
with thorough config.golangci.yml - Testing — ensure
with coverage thresholdsgo test -race -count=1 -timeout=5m - Error handling — structured errors, meaningful exit codes
- Non-interactive design —
/--yes
flags, env vars over prompts-y - Makefile — standardize
,build
,test
,lint
targetscover
For greenfield projects, apply all steps. For existing projects, run the audit first and address only what's missing.
Step 1: Audit
Run this checklist against the project. Address each ❌:
- Structured logger configured (slog / Zap / ZeroLog / Logrus)
- Logger outputs JSON when not a TTY or when
LOG_FORMAT=json - CLI commands support
or--json
flag--output json -
exists with a thorough linter set.golangci.yml -
passesgo test -race - Code coverage ≥ 80% enforced
-
passes cleango vet ./... - All errors wrapped with context (
)fmt.Errorf("...: %w", err) - Exit codes: 0 = success, non-zero = failure (no panics in CLI entry)
-
threaded through all I/O-bound functionscontext.Context - Interactive prompts have
/--yes
bypass flag-y -
withMakefile
,build
,test
,lint
,cover
targetsci - Graceful shutdown on SIGTERM/SIGINT (HTTP services)
- Health check endpoints (
,/healthz
) for HTTP services/readyz -
passes cleangovulncheck ./... -
respected; no ANSI codes in non-TTY outputNO_COLOR - Config loaded from env vars with validation at startup
Step 2: Structured Logging
See references/logging.md for setup patterns for slog, Zap, ZeroLog, and Logrus.
Key requirements:
- Use JSON format when
or!isatty(os.Stdout.Fd())LOG_FORMAT=json - Include fields:
,level
,ts
, plus context fieldsmsg - Never use
for operational log outputfmt.Println - Log to stderr; keep stdout clean for machine-readable data
Step 3: Machine-Readable Output
Agents parse stdout to validate results. Every non-trivial command must support JSON output.
var outputJSON bool cmd.Flags().BoolVar(&outputJSON, "json", false, "output results as JSON") if outputJSON { enc := json.NewEncoder(os.Stdout) enc.SetIndent("", " ") _ = enc.Encode(result) } else { fmt.Printf("Created: %s\n", result.Name) }
Rule: structured data → stdout; progress/human messages → stderr.
fmt.Fprintln(os.Stderr, "Processing...") // progress to stderr json.NewEncoder(os.Stdout).Encode(result) // data to stdout
Step 4: Linting
Copy assets/.golangci.yml to the project root, then:
golangci-lint run ./...
Requires golangci-lint v1.59+ (v1.x series).
See references/testing.md for linter explanations and tuning guidance.
Step 5: Testing
See references/testing.md for full testing setup.
go test -race -count=1 -timeout=5m -coverprofile=coverage.out ./... go tool cover -func=coverage.out | tail -1
Enforce minimum coverage in CI:
COVERAGE=$(go tool cover -func=coverage.out | tail -1 | awk '{print $3}' | tr -d '%') [ $(echo "$COVERAGE >= 80" | bc -l) -eq 1 ] || { echo "Coverage ${COVERAGE}% < 80%"; exit 1; }
Step 6: Error Handling
See references/error-handling.md for structured error patterns and exit code conventions.
Quick rules:
- Always wrap:
fmt.Errorf("loading config: %w", err) - CLI
catches all errors and exits with appropriate codemain() - Never call
deep in business logic — return errors upos.Exit - Never
outside ofpanic
/ package-level setupinit()
Step 7: Non-Interactive Design
See references/non-interactive.md for patterns.
Any prompt that blocks agent execution must have a
--yes/-y bypass:
if !yes { confirmed, _ := promptConfirm("Delete all records?") if !confirmed { return nil } } // proceed
Step 8: Makefile
Copy assets/Makefile to the project root. Adjust
BINARY_NAME and MAIN_PKG for the project.
Standard targets:
make build, make test, make lint, make cover,
make ci (runs full pipeline).
Resources
| File | Contents |
|---|---|
| references/logging.md | slog, Zap, ZeroLog, Logrus JSON setup |
| references/testing.md | Race detector, coverage, golangci-lint tuning |
| references/error-handling.md | Structured errors, exit codes, context |
| references/non-interactive.md | flags, env vars, stdin detection |
| references/services.md | HTTP graceful shutdown, health checks, OTel, request ID |
| references/config.md | Configuration management, env var parsing, validation |
| assets/.golangci.yml | Production-ready linter config |
| assets/Makefile | Standard build/test/lint/cover targets |