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.
How this skill is triggered — by the user, by Claude, or both
Slash command
/go-specialist:go-structureThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Recommend and scaffold idiomatic Go project layouts. Matches structure to project type and size — start simple, grow when needed.
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 |
npx claudepluginhub sgaunet/claude-plugins --plugin go-specialistGuides Go project layout decisions: CLI vs library vs service vs monorepo, module naming, architecture selection, and dependency injection. Activates when starting a new Go project or restructuring an existing codebase.
Analyzes Go projects during discovery phase when go.mod detected. Extracts layout (cmd/internal/pkg), error handling, context.Context, concurrency patterns, code generation, build tags, testing, DI, and logging conventions.
Guides Go code organization: package structure, naming conventions, project layout, imports, file splitting. Reviews PRs, audits, and refactors boundaries.