From go-specialist
Recommends and scaffolds idiomatic Go project layouts for CLI, API, library, or monorepo based on type and size. Flags anti-patterns and suggests migrations.
npx claudepluginhub sgaunet/claude-plugins --plugin go-specialistThis skill is limited to using the following tools:
Recommend and scaffold idiomatic Go project layouts. Matches structure to project type and size — start simple, grow when needed.
Guides setup of Go project layouts for CLI tools, libraries, services, monorepos, and workspaces. Use for new project initialization or codebase restructuring.
Reviews Go project architecture: package structure, dependency direction, layering, separation of concerns, domain modeling, and module boundaries. Use for architecture reviews, package layout design, dependency graphs, or monolith refactoring.
Guides Go code organization: package structure, naming conventions, project layout, imports, file splitting. Reviews PRs, audits, and refactors boundaries.
Share bugs, ideas, or general feedback.
Recommend and scaffold idiomatic Go project layouts. Matches structure to project type and size — start simple, grow when needed.
Simplicity first, complexity when necessary. Do not impose structure upfront. Let it emerge from actual needs. A single main.go is a valid starting point.
| Anti-Pattern | Problem | Fix |
|---|---|---|
Generic package names (utils, helpers, common, base) | Become dumping grounds, convey no intent | Rename to specific purpose: validator, auth, cache |
Over-nesting (internal/services/user/handlers/http/v1/) | Cognitive load, cumbersome imports | Flatten to internal/user/handler.go |
Circular dependencies (A imports B, B imports A) | Compilation error, poor separation | Extract shared types into a separate package or use interfaces |
| Business logic in HTTP handlers | Couples domain to transport, hard to test | Move to service layer, handlers only do HTTP concerns |
Using pkg/ for non-library code | Misleading signal, unnecessary indirection | Move to internal/ or project root |
Premature cmd/ for single-binary projects | Unnecessary nesting | Keep main.go at root until multiple binaries are needed |
Analyze the codebase to classify:
| Signal | Project Type |
|---|---|
Single main.go at root, flag/cobra imports | CLI tool |
net/http or framework imports (gin, chi, echo, fiber) | REST API service |
No main.go, only library packages | Reusable library |
Multiple main.go or go.work file | Monorepo / multi-binary |
go.mod only, empty or minimal | New project (ask user) |
Based on project type and current size, recommend the appropriate layout from the reference patterns below.
Sizing rules:
internal/ with feature-based packagescmd/ + internal/ structureFor existing projects, present a table of findings:
| Finding | Severity | Recommendation |
|---|---|---|
utils/ package detected | Warning | Rename to specific purpose |
Business logic in handler.go | Warning | Extract to service.go |
No internal/ for private code | Info | Consider internal/ as project grows |
For single-purpose tools and prototypes. Grow from here.
mytool/
├── main.go
├── go.mod
├── go.sum
└── README.md
mytool/
├── main.go
├── command/
│ ├── root.go
│ └── version.go
├── go.mod
└── README.md
Organize by feature/domain, not by technical layer.
myapi/
├── cmd/
│ └── api/
│ └── main.go # Minimal: wire deps, load config, start
├── internal/
│ ├── config/
│ │ └── config.go
│ ├── middleware/
│ │ └── auth.go
│ ├── user/ # Feature package
│ │ ├── handler.go # HTTP concerns only
│ │ ├── handler_test.go
│ │ ├── service.go # Business logic
│ │ ├── service_test.go
│ │ ├── repository.go # Data access interface + implementation
│ │ └── repository_test.go
│ └── product/
│ ├── handler.go
│ ├── service.go
│ └── repository.go
├── go.mod
└── README.md
Key rule: cmd/*/main.go is minimal — only dependency wiring, config loading, and server start. All logic lives in internal/.
For complex domain logic with clear port/adapter separation.
myservice/
├── cmd/
│ └── api/
│ └── main.go
├── internal/
│ ├── domain/
│ │ └── user/
│ │ ├── entity.go # Domain models, value objects
│ │ ├── repository.go # Port (interface)
│ │ └── service.go # Domain services
│ ├── application/
│ │ └── user/
│ │ ├── create_user.go # Use case
│ │ ├── get_user.go # Use case
│ │ └── service.go # Orchestration
│ └── adapter/
│ ├── http/
│ │ └── user_handler.go # Inbound adapter
│ ├── postgres/
│ │ └── user_repo.go # Outbound adapter (implements port)
│ └── redis/
│ └── cache.go # Outbound adapter
├── api/
│ └── openapi.yaml
├── go.mod
└── README.md
Dependency rule: Dependencies flow inward. Domain has zero external imports. Adapters implement domain interfaces.
Only use pkg/ when code is intended for external import.
mylib/
├── mylib.go # Public API at package root
├── mylib_test.go
├── internal/
│ └── parser/ # Private implementation
│ ├── parser.go
│ └── parser_test.go
├── go.mod
└── README.md
myproject/
├── cmd/
│ ├── api/
│ │ └── main.go
│ ├── worker/
│ │ └── main.go
│ └── scheduler/
│ └── main.go
├── internal/
│ ├── shared/ # Shared internal packages
│ ├── api/ # API-specific code
│ ├── worker/ # Worker-specific code
│ └── scheduler/ # Scheduler-specific code
├── go.work # Go workspace file
├── go.mod
└── README.md
When creating a new project or restructuring:
Ask user to confirm the detected or intended project type if ambiguous.
Create only the directories needed for the chosen layout. Do not create empty placeholder directories.
For new projects, create:
main.go with minimal bootstrap code (for binaries)go build ./...
go vet ./...
Prefer feature-based organization:
# Good: organized by domain
internal/
├── user/
│ ├── handler.go
│ ├── service.go
│ └── repository.go
└── order/
├── handler.go
├── service.go
└── repository.go
# Avoid: organized by layer
internal/
├── handlers/
│ ├── user.go
│ └── order.go
├── services/
│ ├── user.go
│ └── order.go
└── repositories/
├── user.go
└── order.go
Feature-based packages are self-contained, reduce cross-package imports, and make it easy to understand a domain in one place.
| Condition | Action |
|---|---|
No go.mod found | Ask if user wants to run go mod init |
| Project type ambiguous | Ask user to confirm type before recommending |
| Circular dependency detected | Report the cycle and suggest extraction of shared types |
utils/ or helpers/ package found | Flag as anti-pattern, suggest specific name |