improve-go-architecture
Find deepening opportunities in a Go codebase, informed by the domain language in CONTEXT.md and the decisions in docs/adr/.
Skill by els0r
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/els0r-improve-go-architecture
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
Network hosts it talks to 1
codeload.github.com· found in install command
Files it touches
~/.claude/skills/improve-go-architecture
What's inside
- Skill name
improve-go-architecture- Description
- Find deepening opportunities in a Go codebase, informed by the domain language in CONTEXT.md and the decisions in docs/adr/. Use when the user wants to improve Go architecture, kill shallow abstractions, consolidate tightly-coupled packages, resolve import-cycle pressure, or make a Go codebase more testable and AI-navigable. Fires alongside go-style — different lens (architecture vs idiom). Hands off to grill-with-docs once a candidate is picked.
- License
- MIT
- Instructions
- 109 lines in SKILL.md · view on GitHub
Files (1)
- SKILL.md
SKILL.md (first lines)
# Improve Go Architecture
Surface architectural friction and propose **deepening opportunities** — refactors that turn shallow modules into deep ones. Target: testability and AI-navigability.
- Companion to `go-style`, which covers idiom-level interface design (how to write an interface). This skill operates at the package level (whether an interface should exist).
- Process step 3 hands off to `grill-with-docs` for the design-tree walk and any CONTEXT.md / ADR updates.
## Glossary
Use these terms exactly. Consistent language is the point — don't drift into "component," "service," "boundary."
- **Module** — any unit with a contract and an implementation: function, type, file, *package*. Not a Go module (`go.mod` unit); say **go-module** when ambiguity threatens.
- **Module Interface** — the full contract a caller depends on: types, invariants, error set, ordering, `ctx` semantics, goroutine and channel ownership, receiver shape, config. **Not the Go `interface` keyword** — that's one adapter mechanism among several.
- **Implementation** — the code behind the contract.
- **Depth** — behaviour-per-contract-surface ratio. **Deep** modules hide a lot behind a small Module Interface. **Shallow** modules expose nearly everything they do.
- **Seam** — where the Module Interface meets callers; the place behaviour can be substituted.
- **Adapter** — a concrete satisfier of the Module Interface at the seam. In Go: a struct method set, a function-typed field, a generic type parameter with a constraint, an `internal/` boundary.
- **Leverage** — what callers receive from depth.
- **Locality** — what maintainers receive from depth: change, bugs, knowledge concentrated.
## Principles
- **Deletion test** — imagine the module gone. If complexity disappears, it was a pass-through. If complexity reappears across N callers, it was earning its keep.
- **The Module Interface is the test surface.**
- **One adapter = hypothetical seam. Two adapters = real seam.** Go corollary below.
This skill is *informed* by the project's domain model. CONTEXT.md gives names to good seams; ADRs record decisions the skill should not re-litigate.
## Process
### 1. Explore
Read CONTEXT.md and any ADRs in the area you're touching first.
Then walk the codebase: use the `Explore` subagent if available (Claude Code); otherwise read `go.mod`, top-level packages, then `internal/`. Don't follow rigid heuristics — note where friction shows up:
- Understanding one concept requires bouncing between many small modules.
- Module Interfaces are nearly as complex as the implementation behind them.
- Pure functions were extracted for testability, but real bugs hide in how they're called (no **locality**).
- Tightly-coupled packages leak across their seams.
- Parts that are untested or hard to test through the current interface.
Apply the deletion test to anything suspected shallow. "Concentrates complexity" is the signal.
### 2. Present candidates
Numbered list. For each:
- **Files / packages** involved.
- **Problem** — the friction.
- **Solution** — plain English; what changes.
- **Benefits** — locality, leverage, and how tests improve.
- **Package layout delta** — exact moves, including any new `internal/` boundary.
- **Interface location** — consumer-side or producer-side, and why.
- **Error contract** — which sentinels/typed errors cross the seam.
- **`ctx` and concurrency** — who owns goroutines and channels post-refactor.
Use CONTEXT.md vocabulary for the domain (`order/`, not `orderhandler/`) and the Glossary above for the architecture.
**ADR conflicts**: only surface a candidate that contradicts an ADR when the friction warrants reopening it. Mark clearly (*"contradicts ADR-0007 — worth reopening because…"*). Don't list every theoretical refactor an ADR forbids.
Do NOT propose interfaces yet. Ask: "Which would you like to explore?"
### 3. Hand off to `grill-with-docs`
Once a candidate is picked, invoke `grill-with-docs` to walk the design tree and persist decisions. That skill owns the rules for updating CONTEXT.md inline, sharpening domain terms, and offering ADRs when a load-bearing rejection lands. Do not duplicate those rules here.
Brief the grilling session with the chosen candidate: the friction, the proposed deepening, and the package-layout delta. Let `grill-with-docs` take it from there.
## Go-specific shallow smells
Run the deletion test against:
- **Producer-defined single-implementer interface.** A `Repository` interface only `PostgresRepository` satisfies. Delete the interface; export the struct. Reintroduce when a second adapter actually exists.
- **Catch-all packages** — `utils`, `helpers`, `common`, `pkg`, `internal/internal`. No contract, only contents.
- **Stdlib rewrappers** (`mylog` over `log/slog`, `myhttp` over `net/http`) adding nothing but renaming. If callers still need the wrapped API's mental model, the Module Interface is not smaller than the implementation.
- **Single-method "Service" structs** forwarding one call. Pure pass-through.
- **`any` / `interface{}` in exported signatures** outside genuinely polymorphic spots. Either a missing type parameter or a missing concrete type.
- **Getters and setters over plain fields.** The field is the interface.
- **Functional options** on a constructor with two options, neither defaulting meaningfully. The options *are* the constructor.
- **Files split by mechanical type** — `handlers.go`, `models.go`, `errors.go` — instead of by concept. Cross-file bouncing to read one feature is the friction signal.
## Go-specific deepening signals
- **Consumer-defined interfaces.** *Accept interfaces, return structs.* Interface declared next to the call site, satisfied implicitly by an existing concrete type → real seam. Declared next to the implementation → usually premature.
- **`internal/` as enforcement.** A package boundary without `internal/` is convention; with `internal/`, compiler-enforced. Deepening often means promoting a subpackage into `internal/<concept>/` so the exported surface shrinks.
- **`context.Context` discipline.** Every Module Interface doing I/O or blocking work takes `ctx` first. Modules storing `ctx` in a struct, or calling `context.Background()` internally to defeat caller cancellation, have a broken contract.
- **Error set as contract.** Sentinel and typed errors crossing a seam *are* part of the Module Interface. `fmt.Errorf("...: %w", err)` preserves it; bare `errors.New(...)` discards it. Callers having to read source to know what to `errors.Is` / `errors.As` against = leaky seam.
- **Goroutine and channel ownership.** Who launches, who closes, who waits. If not visible at the Module Interface, callers will get it wrong. Hidden goroutines started in constructors are an interface lie.
- **Cyclic-import pressure.** `import cycle not allowed` is the compiler telling you the seam is in the wrong place. Extract the shared concept into a third package, or merge the two — don't paper over with an interface.
- **Generics over interfaces.** When the seam is "any type with this shape," a type parameter with a constraint is often deeper: the constraint *is* the interface, with no boxing, no nil traps, full type info at the call site.
## Seam-doubling rule, Go corollary
Base rule: one adapter = hypothetical seam; two = real. In Go, **where the interface is declared** decides whether one-impl is premature:
- **Consumer-side, one impl** — fine. Anticipated for tests; the interface stays minimal because it lists only what the caller uses.
- **Producer-side, one impl** — premature. Delete it. If a test needs a fake, define the interface in the test package.
- **Producer-side, two-plus impls** — legitimate, but check size. A `Storer` with 14 methods is two shallow modules in a trenchcoat.
## Testing strategy as a depth signal
The Module Interface is the test surface. For Go:
- Prefer `package foo_test` (external test package). If a test only compiles as `package foo` because it needs unexported helpers, the interface is leaking.
- Prefer fakes (concrete in-memory types) over generated mocks. A mock-heavy test surface is the seam-doubling rule failing: every method had to be mocked because no second real adapter exists.
- `testcontainers`, `httptest`, `t.TempDir` exist so the real dependency *is* the test surface. Reach for an interface only when the real thing is unavailable or unbearably slow.From els0r/skills, MIT.
More from els0r/skills
- 0.547score
blast-radius
els0r
Produce a risk-ranked audit map of a codebase (especially AI-generated code the user hasn't read), so the human can spend limited reading time where failure…
SkillBFreshness: B★ 1Claude Code +9 - 0.497score
go-testing
els0r
Go testing standards: table-driven tests, testify/require, sentinel errors, mocking, fuzzing, race detection, and test file conventions.
SkillCFreshness: C★ 1Claude Code +9 - 0.497score
design-rubric
els0r
Use when critiquing, reviewing, or refining visual designs, wireframes, or UI layouts — especially for small/medium SPAs.
SkillCFreshness: C★ 1Claude Code +9 - 0.497score
go-instrumentation
els0r
Observability principles for Go services: structured logging, distributed tracing, metrics, context propagation, and HTTP service bootstrap.
SkillCFreshness: C★ 1Claude Code +9 - 0.497score
go-performance
els0r
Go performance analysis: memory allocation, CPU bottlenecks, concurrency contention, struct alignment, escape analysis, and benchmarking patterns.
SkillCFreshness: C★ 1Claude Code +9 - 0.497score
go-style
els0r
Go coding conventions, error handling, interface design, and idiomatic patterns.
SkillCFreshness: C★ 1Claude Code +9 - 0.497score
autonomous-orchestration
els0r
Use when the user explicitly hands over multi-PR coordination — asking Claude to follow through on a user story, work bundle, or backlog scope autonomously…
SkillCFreshness: C★ 1Claude Code +9 - 0.494score
coding-style
els0r
Use for all code generation, review, and refactoring regardless of language.
SkillCFreshness: C★ 1Claude Code +9 - 0.486score
Codebase Analyzer
els0r
Analyzes codebase implementation details.
SkillCFreshness: C★ 1Claude Code +9 - 0.486score
Codebase Locator
els0r
Locates files, directories, and components relevant to a feature or task.
SkillCFreshness: C★ 1Claude Code +9 - 0.472score
grill-with-docs
els0r
Grilling session that challenges your plan against the existing domain model, sharpens terminology, and updates documentation (CONTEXT.md, ADRs) inline as…
SkillCFreshness: C★ 1Claude Code +9 - 0.468score
diagnose
els0r
Disciplined diagnosis loop for hard bugs and performance regressions.
SkillCFreshness: C★ 1Claude Code +9
Signals
- Stars
- 1
- Forks
- 0
- Open issues
- 0
- Last commit (this folder)
- May 20, 2026 (5 months ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- Repository
- github.com/els0r/skills
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from els0r
- 0.547score
blast-radius
els0r
Produce a risk-ranked audit map of a codebase (especially AI-generated code the user hasn't read), so the human can spend limited reading time where failure…
SkillBFreshness: B★ 1Claude Code +9 - 0.497score
autonomous-orchestration
els0r
Use when the user explicitly hands over multi-PR coordination — asking Claude to follow through on a user story, work bundle, or backlog scope autonomously…
SkillCFreshness: C★ 1Claude Code +9 - 0.497score
go-performance
els0r
Go performance analysis: memory allocation, CPU bottlenecks, concurrency contention, struct alignment, escape analysis, and benchmarking patterns.
SkillCFreshness: C★ 1Claude Code +9 - 0.497score
go-instrumentation
els0r
Observability principles for Go services: structured logging, distributed tracing, metrics, context propagation, and HTTP service bootstrap.
SkillCFreshness: C★ 1Claude Code +9 - 0.497score
design-rubric
els0r
Use when critiquing, reviewing, or refining visual designs, wireframes, or UI layouts — especially for small/medium SPAs.
SkillCFreshness: C★ 1Claude Code +9 - 0.497score
go-style
els0r
Go coding conventions, error handling, interface design, and idiomatic patterns.
SkillCFreshness: C★ 1Claude Code +9
Cite this page
improve-go-architecture skill. Agent Mart. https://agentmart.dev/skills/els0r-improve-go-architecture (last updated 2026-10-24)