Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

Back to skills

Code Golang Architecture

ASecurity

Apply Hexagonal Architecture, Clean Architecture, and Domain-Driven Design to Go package structure. Use when designing or reviewing a Go service's package layout, deciding how to split domain/application/adapter code, choosing between package-by-layer and package-by-feature, or right-sizing architecture for a Go project's actual complexity. Complements `code-architecture-best-practices` (language-agnostic principles) with Go-specific structural decisions.

8 stars
0 votes
0 copies
0 views
Added 9/20/2026
developmentpythongojavakotlinnodeexpresstestingcode-reviewapibackend

Works with

cliapimcp

Security Analysis

A100/100

Scanned 9/20/2026

Install to Claude Code

$npx -y skills add tstapler/dotfiles --skill code-golang-architecture --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Code Golang Architecture?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Code Golang Architecture
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tstapler-code-golang-architecture/badge)](https://www.skillsdirectory.com/skills/tstapler-code-golang-architecture)

More formats (shields.io, HTML) on the badges page.

Download Zip
Files
SKILL.md
---
name: code-golang-architecture
description: Apply Hexagonal Architecture, Clean Architecture, and Domain-Driven Design to Go package structure. Use when designing or reviewing a Go service's package layout, deciding how to split domain/application/adapter code, choosing between package-by-layer and package-by-feature, or right-sizing architecture for a Go project's actual complexity. Complements `code-architecture-best-practices` (language-agnostic principles) with Go-specific structural decisions.
---

# Go Package Architecture

Decision layer on top of two existing skill families — this skill does not re-derive their content,
it tells you which one to reach for and adds the Go-specific judgment calls none of them make.
`golang-design-patterns` (see its `references/hexagonal-architecture.md`, `clean-architecture.md`,
`ddd.md`) already has full file trees and code for all three styles — go there for the how.
`golang-depguard-architecture` already has ready-to-use linter rules for enforcement. This skill is for
*which style, how much of it, and what Go's own constraints (single-namespace packages, no import
cycles, small-interface culture) force you to decide differently than the Python/Java sections of
`code-architecture-best-practices`.

## Right-Size First

Apply the Reuse Check and the ladder from `code-architecture-best-practices` before picking a style
at all: a CLI or script under ~500 lines, or a service under ~1-2K lines with one storage backend,
does not need domain/application/adapter layers — a flat `internal/<name>/` package with a few files
is correct and `golang-project-layout` already says so ("NEVER over-structure small projects").
Layering earns its keep at multiple adapters (HTTP + gRPC + a worker), multiple bounded contexts, or
business rules complex enough to need isolated unit tests. State explicitly when you're skipping
layering — silent under-structuring is as much a review-blocking call as silent over-structuring.

Before adding a new port (interface), grep/ast-grep for one that already expresses the same
boundary. Go's small-interface culture means the common duplication failure mode isn't a copy-pasted
function, it's two near-identical single-method interfaces (`OrderRepository` vs `OrdersStore`)
defined at two call sites for the same concept.

## Extending Bad Architecture: Refactor, Isolate, or Extend

Same three-option framework as `code-architecture-best-practices` — refactor-first, isolate via
seam, or extend as-is, stated explicitly, never silently defaulted to "extend." The Go-specific
form of "isolate via seam": define a narrow interface at the *new* call site (per
`golang-structs-interfaces`'s "define interfaces where consumed") that only names the methods you
need from the legacy package, rather than exporting more of the legacy package or reworking it.

## Discover the Current Architecture First (kibitzer)

Before picking a target style or naming tiers, find out what the package structure *actually* is
today — don't design against a mental model that's drifted from the code. If `kibitzer` is
available (MCP connected, or `kibitzer` on `PATH`), it answers this with zero configuration:

| Question | MCP tool | CLI equivalent |
|---|---|---|
| Are there import cycles, layer-direction violations, or high-coupling packages right now? | `architecture_assessment` (`scope` to the package(s) under review — also renders a Mermaid dependency diagram) | `kibitzer run <dir> --trigger batch` (filter for `import-cycles`/`layering`/`coupling`) |
| Is a given type already a God Object — too many methods/fields for one struct? | `list_architecture_symbols` (`package: "<pkg>"`) | `kibitzer architecture export --path . --scope '<pkg-glob>' --dry-run --out /dev/null`, group the `symbols` array by `parent` and count |
| What exactly does one symbol look like right now? | `get_architecture_node` (`node: "<pkg>::<Type>.<Method>"`) | grep the `architecture export` JSON for the symbol id |

This runs with no `.claude/inspect.json` at all — it's the discovery step, not the enforcement step.
Two things it feeds directly:

- **The Refactor/Isolate/Extend decision above.** A package that `architecture_assessment` already
  flags for `component-deps`/`layering` is a bad "extend as-is" candidate — the violation you'd be
  adding to already exists and mechanical evidence beats a guess about how bad it is.
- **Which target style fits (below).** If the assessment shows the package already reads as
  vertical slices (each subpackage self-contained, cross-package imports rare), don't fight that by
  imposing a package-by-layer split; if it shows one flat package with growing fan-in, that's the
  signal to introduce layering at all, per Right-Size First above.

Degrades gracefully: if kibitzer isn't connected/on `PATH`, skip this silently and fall back to a
manual read of the package's imports (`go list -deps ./...` or just reading the files) — don't block
the review on kibitzer's absence.

## Three Styles, One Underlying Choice

Hexagonal, Clean Architecture, and DDD tactical patterns overlap heavily in Go — domain entities,
port interfaces, application/use-case orchestration, adapters — and mostly differ in directory
naming and framing, not in the dependency rule. The choice that actually changes your file layout is
orthogonal to which of the three you name:

| Axis | Package-by-layer | Package-by-feature (vertical slice) |
|------|-------------------|--------------------------------------|
| Layout | `domain/`, `application/`, `adapter/` at the top level | `order/domain`, `order/application`, `order/adapters`, `billing/domain`, ... |
| Encapsulation unit | The layer — but cross-layer types must be exported, so the layer boundary is convention, not compiler-enforced | The feature/bounded context — a rename or refactor inside `order/` never touches `billing/` |
| Go fit | Go has no `private`/`protected`; the **package** is the only real encapsulation boundary, so a layer package spanning many features leaks types across features by construction | Matches Go's package-as-boundary model directly |
| Best for | A single bounded context, one team, one deploy unit | 2+ bounded contexts, or a service that will be split later |
| Maps to | `golang-design-patterns/references/hexagonal-architecture.md`, `clean-architecture.md` | `golang-design-patterns/references/ddd.md` ("Project Structure" section) |

Default to package-by-feature once a second bounded context appears — it's strictly harder to
retrofit than to start with, and Go's lack of intra-package visibility modifiers means a
package-by-layer `domain/` package for three unrelated features gives up encapsulation between
those features that package-by-feature keeps for free.

## DDD Tactical Patterns — Go Mapping

Full code examples: `golang-design-patterns/references/ddd.md`. Table for quick lookup during review:

| Concept | Go shape | Rule |
|---|---|---|
| Entity | Struct with an ID field, mutated only through methods | Identity, not attribute equality |
| Value Object | Struct with unexported fields, no ID, returned by value or via a validating constructor | Immutable; `Add`/`With...` return a new value, never mutate in place |
| Aggregate | An entity whose exported methods are the only mutation path for its children | External code never reaches into `order.items` directly — no exported field, only `order.AddItem(...)` |
| Repository | Interface defined in the domain/consumer package; implemented in an adapter package | One per aggregate root; domain never imports the concrete implementation |
| Domain Service | A function or small stateless struct in the domain package | Only when logic genuinely spans multiple aggregates — don't reach for this before an entity method covers it |
| Application Service / Use Case | A struct depending only on domain ports, one method per use case (or a `Handle` method per command/query type) | No business logic here — it orchestrates; if a use case has an `if` on a business rule, that rule belongs on the entity |

Skip tactical DDD (explicit Aggregate/Repository/Domain Service vocabulary) below ~5K lines or a
single bounded context — plain entities plus a couple of interfaces get you the same testability
without the ceremony. Introduce it when a second bounded context or a genuinely cross-aggregate rule
shows up, not before.

## Enforcing the Boundaries Mechanically: kibitzer vs depguard

Once package tiers or bounded contexts are named — using the discovery step above, not guessed —
don't rely on review comments to catch a stray import. Two mechanisms cover overlapping ground; know
which one you're picking and why, since configuring both for the same tier split just doubles the
maintenance surface for one signal.

| | kibitzer | `golangci-lint` (depguard / arch-go / go-arch-lint) |
|---|---|---|
| Config | `.claude/inspect.json`'s `architecture.dependency_rules`/`content_rules`/`naming_rules` — same file the discovery step above already reads, so naming tiers there is a one-time cost | `.golangci.yml` — `golang-depguard-architecture` has ready-to-use rule blocks; `arch-go`/`go-arch-lint` for content/naming rules, same skill has the comparison |
| How it runs | `architecture_assessment`/`run_checks` (MCP) or `kibitzer run <dir> --trigger batch` (CLI) — agent- or editor-time, on demand | `golangci-lint run` — whatever already gates your CI |
| Gates a PR without new CI wiring | Only if kibitzer's CLI/MCP is already part of the pipeline | Yes, if `golangci-lint` already runs in CI — most Go repos already do |
| Language scope | Go, TS/TSX/JS, Java, Kotlin, Python — same config works across a polyglot repo | Go only |
| Works before any rule is configured | Yes — `architecture_assessment` reads current violations with zero config (the discovery step) | No — depguard/arch-go only flag what a rule already names |

**Default:** use kibitzer for the free discovery pass above every time it's available — there's no
setup cost. For the CI gate itself, pick whichever mechanism needs zero *new* tooling: `depguard` if
`golangci-lint` already runs in CI (the common case), kibitzer's checkers if this repo already scripts
kibitzer into CI/pre-commit and adding `golangci-lint` would be the new dependency instead. If you
configure both, classify tiers once and mirror the same split into `.claude/inspect.json` and
`.golangci.yml` — don't let two independently-maintained tier lists drift apart. Configure whichever
you pick only after the layout has settled: rules are only as good as the tier classification, and
that needs real packages to classify.

## Testing Boundaries (Go-Specific)

| Layer | Test type | Approach |
|---|---|---|
| Domain (entities, value objects) | Unit | Table-driven, no mocks — pure functions and methods |
| Application (use cases) | Unit | Hand-written fakes or `mockgen` against the small port interfaces — see `golang-testing` |
| Adapters (repositories, clients) | Integration | Real dependency via `testcontainers-go`, or a recorded-HTTP fixture for external APIs |
| Composition root (`cmd/`) | Smoke | One test that wires the real dependency graph and calls a use case end-to-end — catches wiring mistakes unit tests can't |

## Common Go-Specific Mistakes

- **Ports defined next to their implementation, not their consumer.** Forces the consumer package to
  import the adapter package for the interface, which is often the exact cycle the layering exists
  to prevent. See `golang-structs-interfaces`'s "Define Interfaces Where They're Consumed."
- **A shared `types.go`/`models.go` imported by every layer.** Nothing in Go stops any layer from
  reaching into it, so it silently defeats the dependency rule — split domain types into the domain
  package and DTOs into the layer that owns them.
- **Domain structs carrying ORM struct tags** (`db:"..."`, `gorm:"..."`). Couples the domain type to
  a specific persistence library and usually forces exporting fields that should stay behind
  methods. Keep a separate persistence-layer struct and map between them in the adapter.
- **Stuttering names across the boundary** (`order.OrderService`, `order.OrderRepository`). See
  `golang-naming`; the package name already carries "order" — the boundary/layering conventions here
  don't override normal Go naming rules.
- **Interfaces created before a second implementation or a test needs one.** Applies doubly at
  architecture boundaries — a `Repository` interface with exactly one caller and one implementation
  is speculative layering, not hexagonal architecture. Wait for the second adapter or the first unit
  test that needs a fake.

## Decision Guide

| Situation | Move |
|---|---|
| New service, single bounded context, one storage backend | Flat `internal/` package, no layers — revisit if it grows |
| New service, multiple entry points (HTTP + gRPC + worker) sharing logic | Hexagonal — ports + primary/secondary adapters |
| New service, 2+ bounded contexts or an eventual split into separate services | DDD vertical slices, package-by-feature |
| Existing flat package outgrowing itself | Refactor-first if small, isolate via a port at the new call site if not — never bolt on a 6th responsibility |
| Domain package importing an ORM, HTTP, or config package | Violates the dependency rule — extract a port interface (`golang-depguard-architecture` Step 4 has the exact before/after) |
| Two interfaces expressing the same concept at two call sites | Reuse Check failure — consolidate before adding a third |
| Repository/Aggregate vocabulary appearing in a single-entity CRUD service | Overkill — plain entity + one repository interface, skip the rest of tactical DDD |

## Related Skills

| Skill | When to reach for it |
|---|---|
| `code-architecture-best-practices` | Language-agnostic SOLID/Clean/Hexagonal/DDD principles this skill specializes for Go |
| `golang-design-patterns` | Full file trees and code examples for Hexagonal, Clean Architecture, and DDD in Go |
| `golang-project-layout` | Module/directory conventions (`cmd/`, `internal/`, `pkg/`), workspaces, project-type selection |
| `golang-structs-interfaces` | Interface placement, size, and "accept interfaces, return structs" |
| `golang-naming` | Package and identifier naming, avoiding stutter |
| `golang-depguard-architecture` | Turn the dependency rule into a linter failure; standalone-tool comparison |
| `type-driven-design` | Make aggregate/value-object invariants compiler-enforced instead of review-enforced |
| `golang-testing` | Table-driven tests, fakes/mocks for port interfaces, `testcontainers-go` |
| `code-hotspot-analysis` | Check whether a package is already a churn/complexity hotspot before restructuring it |
| `code-review` | Verify a layout decision meets these rules before merging |

Attribution

tstaplertstapler
View sourceMore from tstapler →
SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Related Skills

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

281612 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2132 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

9881 votes

Pentest

PTES-aligned adversarial security audit for backend, frontend, and mobile applications. Produces a CVSS-scored Hacker Report with verified PoCs and phased remediation.

5491 votes
View all in development →