rewrite-in-go
Skill2 starsChanged 7 months agoMITView on GitHub
Reimplement an existing application in Go while preserving observable behavior. Use when asked to port, rewrite, migrate, rebuild, or replace an existing app with a Go implementation, especially CLI tools, services, agents, scrapers, or source-driven automation systems. Avoid for greenfield Go features or small Go refactors.
In this repository26 other files it gives its agents.
- other/AGENTS.mdAGENTS.md
- beamng-modsSkill
- bootstrap-vueSkill
- charmbraceletSkill
- depsdotdevSkill
- find-domainSkill
- github-cliSkill
- go-cobraSkill
- goreleaserSkill
- go-viperSkill
- kasettoSkill
- laravel-actionsSkill
- lefthookSkill
- miseSkill
- pelican-panel-pluginsSkill
- php-monorepo-builderSkill
- php-saloonSkill
- prd-todo-slicerSkill
- prd-to-kandev-tasksSkill
- qodo-mergeSkill
- release-pleaseSkill
- shieldsioSkill
- skill-researcherSkill
- skill-scoutSkill
- taskfileSkill
- website-visual-testingSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
37 rules. About 0 are common, 35 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈35
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 15
Use this for full or substantial ports from an existing codebase.
- Distinctive: line 25
Keep secrets out of config files and source code.
- Distinctive: line 29
When given an existing repo or local project:
- Distinctive: line 33
Check the worktree and avoid overwriting existing user changes.
- Distinctive: line 34
Read source code before relying on documentation.
- Distinctive: line 35
Use a scouting sub-agent when available for large or unfamiliar repositories.
- Distinctive: line 39
Search for maintained Go replacements.
- Distinctive: line 42
If the user gives extra desired changes, incorporate them into the plan and clearly separate:
- Distinctive: line 51
Create a contract map before implementation.
- Distinctive: line 70
Use this table format:
- Distinctive: line 89
Search for actively maintained Go libraries that implement the same role.
- Distinctive: line 91
Prefer small, stable libraries with good docs, tests, recent maintenance, compatible license, low transitive dependency load, and idiomatic …
- Distinctive: line 92
Avoid packages that are abandoned, overbroad, license-incompatible, or unnecessary wrappers around simple HTTP calls.
- Distinctive: line 95
Use this decision table:
- Distinctive: line 127
default config search paths
- Distinctive: line 130
Always produce a typed config struct.
- Distinctive: line 153
Put business logic outside Cobra command handlers.
- Distinctive: line 154
Use interfaces at module boundaries, not everywhere.
- Very specific: line 155
Use context.Context for all network and long-running operations.
- Distinctive: line 156
Use explicit timeouts and cancellation.
- Distinctive: line 157
Use typed errors where they improve retries or user messages.
- Distinctive: line 158
Use dependency injection for clients, clocks, filesystem, and external APIs where tests need control.
- Distinctive: line 159
Prefer deterministic ordering after concurrent work.
- Distinctive: line 160
Keep adapters isolated so unsupported or flaky integrations can be disabled without breaking the whole app.
- Distinctive: line 214
Create Go module and project skeleton.
- Distinctive: line 215
Add typed config loader and validation.
- Distinctive: line 216
Add CLI command tree and bind flags when the original app has a CLI contract.
- Distinctive: line 217
Add domain models and core interfaces.
- Distinctive: line 219
Add remaining adapters and workflow layers incrementally.
- Distinctive: line 220
Add integration tests using fixtures/mocks.
- Distinctive: line 221
Add contract tests for CLI behavior, config migration, output formats, and exit codes.
- Very specific: line 222
Run gofmt, go test ./..., and static checks if available.
- Distinctive: line 226
Before considering the rewrite complete:
- Distinctive: line 241
Look for opportunities to improve:
- Distinctive: line 272
When reporting progress to the user:
- Distinctive: line 277
Do not claim package maintenance without checking current evidence.
- Distinctive: line 278
Do not ask for clarification when a reasonable best-effort plan can proceed.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Rewrite Existing Applications in Go
Purpose
Build a Go implementation of an existing application. Preserve the user-facing contract and core behavior, but do not blindly copy the old architecture. Prefer a clean Go design that is maintainable, testable, observable, and easy to extend.
Use this for full or substantial ports from an existing codebase. Do not activate it for ordinary Go bug fixes, small refactors, or new Go features with no legacy behavior to preserve.
This skill focuses on the project itself: source code, config, commands, behavior, tests, and runtime functionality. Ignore README/docs, packaging, publishing, release automation, and distribution unless the user explicitly asks for them or they are required to understand the app’s contract.
Default priorities
- Preserve the user-facing contract: commands, flags, config fields, environment variables, outputs, files, network/API behavior, exit codes, and workflows.
- Improve implementation quality where Go gives clear advantages: concurrency, typed config, interfaces, modular adapters, deterministic tests, error handling, retries, cancellation, and performance.
- Replace old-language dependencies with maintained Go packages where reasonable.
- For CLI/config-heavy apps, prefer Cobra for command structure and use Viper only when config discovery, env binding, or migration support materially helps; explain simpler choices.
- Keep secrets out of config files and source code. Prefer environment variables and explicit secret references.
Required first steps
When given an existing repo or local project:
- Inspect the repository structure.
- Identify the current language, runtime, app type, entrypoints, and execution modes.
- Check the worktree and avoid overwriting existing user changes.
- Read source code before relying on documentation. Treat docs as supporting evidence, not the source of truth.
- Use a scouting sub-agent when available for large or unfamiliar repositories; otherwise use targeted code search directly.
- Capture runnable baseline behavior when practical: commands, sample inputs, config examples, outputs, errors, and exit codes.
- Inventory the user-facing contract.
- Inventory dependencies and identify what each dependency actually does.
- Search for maintained Go replacements. Use a package-finder sub-agent when available for non-obvious choices; do not rely only on memory.
- Produce a concise implementation plan before building unless the user only asked for research.
If the user gives extra desired changes, incorporate them into the plan and clearly separate:
- preserved behavior
- intentionally changed behavior
- new improvements
- deferred or removed behavior
Contract inventory
Create a contract map before implementation. Include only behavior users or integrations can observe.
Capture:
- executable names and entrypoints
- commands and subcommands
- positional arguments
- flags, defaults, aliases, and precedence
- config files, schema, defaults, validation rules, and migration behavior
- environment variables and secret handling
- generated files and directory layout
- stdout/stderr behavior and log levels
- return codes and failure modes
- baseline command/output examples that the Go version must match or intentionally change
- network calls, API endpoints, rate limits, retry behavior, authentication, and user agents
- background jobs, schedules, polling, caches, state files, and databases
- externally consumed formats: JSON, Markdown, HTML, CSV, email bodies, webhook payloads, MCP tools, or API responses
- important non-functional behavior: concurrency, timeouts, ordering guarantees, deduplication, idempotency, localization, and determinism
Use this table format:
| Area | Existing behavior | Go rewrite behavior | Compatibility level | Notes |
| CLI | ... | ... | exact / compatible / improved / removed | ... |
Compatibility levels:
- exact: behavior should match unless tests prove otherwise
- compatible: same user outcome, improved implementation or minor format differences
- improved: intentionally better behavior with migration notes
- removed: intentionally omitted; must be justified
Dependency replacement process
For every non-trivial existing dependency:
- Identify its role from usage in source code.
- Determine whether Go stdlib is sufficient.
- Search for actively maintained Go libraries that implement the same role.
- Compare at least two candidates when the choice is not obvious.
- Prefer small, stable libraries with good docs, tests, recent maintenance, compatible license, low transitive dependency load, and idiomatic Go APIs.
- Avoid packages that are abandoned, overbroad, license-incompatible, or unnecessary wrappers around simple HTTP calls.
- Record package evidence and the decision.
Use this decision table:
| Existing dependency | Role in current app | Go candidate | Evidence of maintenance | Decision | Rationale |
| ... | ... | ... | releases, commits, docs, users, issues | use / avoid / stdlib | ... |
Maintenance evidence to check:
- latest release or commit recency
- Go module health on pkg.go.dev when available
- open issues/PRs and maintainer responsiveness
- security advisories or known CVEs
- project maturity and API stability
- license compatibility
- dependency footprint
- examples and tests
CLI and configuration rules
For CLI applications, use this division of responsibility by default:
- Cobra: command tree, arguments, flags, help, shell completion, command validation, command execution.
- pflag: flag definitions through Cobra.
- Viper: compatibility/convenience layer for discovery, defaults, env binding, and migration support when useful. Do not create two independent sources of truth.
Skip Cobra for libraries, daemons without a CLI contract, or small tools where the standard flag package preserves the contract with less complexity. Skip Viper when a typed config loader plus stdlib parsing is clearer.
Recommended precedence, highest to lowest:
- explicit CLI flags
- environment variables
- local config file specified by
--config - default config search paths
- compiled defaults
Always produce a typed config struct. Validate config after merging and before doing work.
Support env-var substitution in string config values if the old app supports it or the user requests it. Leave unresolved variables visible and fail loudly at validation time when the value is required.
Go project architecture
For medium or large CLI, service, or pipeline rewrites, adapt this layout unless the app strongly suggests another shape. Omit packages that are not part of the target domain.
cmd/<app>/main.go # thin entrypoint
internal/cli/ # Cobra commands and flag binding
internal/config/ # config loading, env expansion, validation, migration
internal/app/ # orchestration/use cases
internal/domain/ # domain types and core rules
internal/adapters/ # external system adapters and implementations
internal/store/ # cache/state/subscriber storage if needed
internal/httpx/ # shared HTTP client, retry, rate limit, user agent
internal/logging/ # structured logging setupRules:
- Keep
main.gotiny. - Put business logic outside Cobra command handlers.
- Use interfaces at module boundaries, not everywhere.
- Use
context.Contextfor all network and long-running operations. - Use explicit timeouts and cancellation.
- Use typed errors where they improve retries or user messages.
- Use dependency injection for clients, clocks, filesystem, and external APIs where tests need control.
- Prefer deterministic ordering after concurrent work.
- Keep adapters isolated so unsupported or flaky integrations can be disabled without breaking the whole app.
Implementation workflow
Phase 1: Reconnaissance
Deliver:
- repository summary
- app entrypoints
- feature inventory
- user-facing contract map
- dependency map
- test/fixture inventory
- known risks and unknowns
Phase 2: Go package scouting
Deliver:
- package replacement table
- selected packages and why
- packages intentionally avoided
- stdlib-only decisions
- license/security concerns
Phase 3: Config and contract plan
Deliver:
- proposed Go config schema
- migration plan from old config
- env-var handling plan
- CLI command/flag plan
- compatibility matrix
- intentional improvements
Phase 4: Architecture plan
Deliver:
- package/module layout
- data model
- main interfaces
- pipeline flow
- concurrency/rate-limit strategy
- persistence/state strategy
- test strategy
Phase 5: Build
Implement incrementally:
- Preserve or create baseline fixtures from the original app before replacing behavior.
- Create Go module and project skeleton.
- Add typed config loader and validation.
- Add CLI command tree and bind flags when the original app has a CLI contract.
- Add domain models and core interfaces.
- Port one vertical slice end-to-end with tests.
- Add remaining adapters and workflow layers incrementally.
- Add integration tests using fixtures/mocks.
- Add contract tests for CLI behavior, config migration, output formats, and exit codes.
- Run
gofmt,go test ./..., and static checks if available.
Phase 6: Validation
Before considering the rewrite complete:
go test ./...passes.- Contract tests compare representative old-app and Go-app behavior or document why direct comparison is not possible.
- CLI help and flags match the contract plan.
- Representative stdout/stderr, generated files, API payloads, and exit codes match the compatibility matrix.
- Config examples load and validate.
- Legacy config can be migrated or read where promised.
- Network adapters are covered by tests using fixtures or fake servers.
- Core pipeline can run in dry-run/mock mode without secrets.
- Errors are clear and actionable.
- Secrets are never printed in logs.
Improvement checklist
Look for opportunities to improve:
- typed config with validation and schema versioning
- migration from old config to new config
- source adapter plugin pattern
- rate limiting per source/API provider
- retry with exponential backoff and jitter
- circuit-breaker behavior for unreliable providers
- deterministic ordering after concurrency
- local cache/state to avoid repeated expensive calls
- partial-failure tolerance: one source failing should not fail the entire run unless configured
- structured logs with redaction
- dry-run mode
- fixture-based tests for scrapers and renderers
- snapshot/golden tests for generated output
- clear separation between fetch, dedupe, score, enrich, summarize, and deliver
- support for multiple LLM providers through one interface
- provider capability detection, such as whether temperature or streaming is supported
- strict output-size limits for chat/webhook/email channels
- idempotent delivery where possible
Optional target references
Load these only when the target app matches the scenario:
| Target type | Read |
| AI/news aggregation pipeline similar to Horizon | references/horizon-news-aggregation.md |
Output style during a run
When reporting progress to the user:
- Be concise.
- Show concrete findings as soon as they are known.
- Distinguish facts from recommendations.
- Do not claim package maintenance without checking current evidence.
- Do not ask for clarification when a reasonable best-effort plan can proceed.
- Be honest about unsupported features or uncertain package replacements.
Final completion report
End with:
- what was implemented
- compatibility status
- intentional differences from the original
- packages chosen and why
- tests run and results
- risks or features not implemented
- next concrete implementation step if the work is partial
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

