About
This Claude Skill provides a safe, behavior-preserving refactoring workflow for Go codebases, ensuring all changes are compiler-checked and backed by passing tests. It handles tasks like renaming across the codebase, extracting packages, breaking circular dependencies, and managing strangler migrations. Use it for structural cleanups without changing functionality, but not for architectural decisions, adopting new language features, or performance rewrites.
Quick Install
Claude Code
Recommendednpx skills add eduardo-sl/go-agent-skills -a claude-code/plugin add https://github.com/eduardo-sl/go-agent-skillsgit clone https://github.com/eduardo-sl/go-agent-skills.git ~/.claude/skills/go-refactoringCopy and paste this command in Claude Code to install this skill
Documentation
Go Refactoring Workflow
A refactor changes structure, never behavior. The definition of done is mechanical: same tests pass before and after every step, and every step is small enough to revert alone.
1. The Loop
- Baseline:
go build ./... && go test ./...must be green before touching anything. If tests are missing around the target code, write characterization tests FIRST — they pin current behavior, even if that behavior looks wrong. - One transformation from the catalog below.
- Verify: build + tests +
go vet ./.... - Commit. Never mix a refactor commit with a behavior change —
reviewers can skim a
refactor:commit; they must scrutinize a mixed one. - Repeat.
If step 3 fails and the fix isn't obvious in a minute, revert the step rather than debugging a half-applied transformation.
2. Renames — Let Tools Do Them
# Preferred: gopls (understands types, interfaces, embedding)
gopls rename -w internal/service/user.go:#offset newName
# Module path or package import path changes:
# update go.mod, then rewrite imports mechanically
find . -name '*.go' -exec sed -i 's|github.com/acme/old|github.com/acme/new|g' {} +
go build ./... # the compiler is the reviewer
Never rename an exported identifier of a published library without a
deprecation cycle: add the new name, mark the old one
// Deprecated: use NewName., delete in the next major version.
3. Extract Package
Moving code out of a god package, in compiler-checked steps:
- Create the new package; move one type and its methods (
goplsor cut/paste), leaving everything else. - In the old package, add type aliases so nothing breaks:
type User = user.User(aliases,=, not definitions). - Build. Migrate importers to the new path in batches; build each batch.
- Delete the aliases when no importer remains.
This keeps every commit green with an arbitrarily large caller base.
4. Break a Circular Dependency
Packages a → b and b → a won't compile; near-cycles show up as
god packages. Three escapes, in order of preference:
- Extract the shared core: both
aandbactually depend on a type — move it to a third packagecthat imports nothing. - Invert with an interface: if
storecalls back intoservice, define the callback interface INstore(consumer side) and letserviceimplement it. The arrow flips at compile time. - Merge: if two packages can't be described without each other, they were one package all along.
5. Change a Function Signature Safely
For exported functions with many callers:
// Step 1 — add the new form alongside the old
func (s *Service) ProcessCtx(ctx context.Context, id string) error { ... }
// Step 2 — old form delegates; mark deprecated
// Deprecated: use ProcessCtx.
func (s *Service) Process(id string) error {
return s.ProcessCtx(context.Background(), id)
}
// Step 3 — migrate callers batch by batch, building each batch
// Step 4 — delete the old form (same module) or keep until next major (library)
Inside a single module, prefer atomic signature changes when the compiler can find every caller for you: change it, then chase the build errors — that's the compiler enumerating your TODO list.
6. Strangler Migration for Subsystems
Replacing a subsystem (old store, legacy client) too big for one PR:
- Define the consumer-side interface the callers actually need.
- Make the OLD implementation satisfy it; wire callers to the interface.
- Build the new implementation behind the same interface; test both implementations against one shared conformance test suite.
- Switch the wiring in the composition root (one line, one commit, trivially revertible). Feature-flag it if risk warrants.
- Delete the old implementation in its own commit.
7. What Is NOT a Refactor
- "While I'm here" bug fixes — separate commit before or after.
- Reordering struct fields used with positional literals, changing exported error strings callers match on, changing JSON tags — these are behavior changes wearing refactor clothes.
- Rewrites without tests. If you can't pin behavior first, you're not refactoring; you're gambling.
Verification Checklist
- Baseline build + tests green before the first change
- Characterization tests added where coverage was missing
- Each commit is one transformation;
refactor:commits contain no behavior change - Renames done via gopls/compiler, not find-and-replace on identifiers
- Package extractions used type aliases to stay green mid-flight
- No new dependency cycles (
go build ./...proves it) - Public API changes follow the deprecation cycle
go vet ./...and the full test suite pass at every commit, not just the last- git log reads as a sequence of safe, revertible steps
GitHub Repository
Frequently asked questions
What is the go-refactoring skill?
go-refactoring is a Claude Skill by eduardo-sl. Skills package instructions and resources that Claude loads on demand, so Claude can perform go-refactoring-related tasks without extra prompting.
How do I install go-refactoring?
Use the install commands on this page: add go-refactoring to Claude Code as a plugin, or clone its repository into your skills directory, then restart Claude so it picks up the skill.
What category does go-refactoring belong to?
go-refactoring is in the Testing category, tagged testing and automation.
Is go-refactoring free to use?
Yes. go-refactoring is listed on AIMCP and free to install.
Related Skills
This Claude Skill runs the lm-evaluation-harness to benchmark LLMs across 60+ standardized academic tasks like MMLU and GSM8K. It's designed for developers to compare model quality, track training progress, or report academic results. The tool supports various backends including HuggingFace and vLLM models.
This skill provides comprehensive knowledge for implementing Cloudflare Cron Triggers to schedule Workers using cron expressions. It covers setting up periodic tasks, maintenance jobs, and automated workflows while handling common issues like invalid cron expressions and timezone problems. Developers can use it for configuring scheduled handlers, testing cron triggers, and integrating with Workflows and Green Compute.
This Claude Skill provides a Playwright-based toolkit for testing local web applications through Python scripts. It enables frontend verification, UI debugging, screenshot capture, and log viewing while managing server lifecycles. Use it for browser automation tasks but run scripts directly rather than reading their source code to avoid context pollution.
This skill helps developers complete finished work by verifying tests pass and then presenting structured integration options. It guides the workflow for merging, creating PRs, or cleaning up branches after implementation is done. Use it when your code is ready and tested to systematically finalize the development process.
