go-coding-plugin
AGENTS.md0 starsChanged 5 months agoMITView on GitHub
It is the canonical instruction set; .claude/CLAUDE.md and any host-specific instruction files defer to it. The Go Coding Plugin (go-coding) is an AI plugin by Cadasto B.V. that teaches AI coding assistants idiomatic Go coding standards (formatting, naming, error handling, concurrency, testing, project layout) through skills, agents, hooks, and a Cursor rule. It targets both Claude Code and Cursor from a single shared component set. The human pitch is in README.md; the shipped version is in the manifests and CHANGELOG.md.
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,774 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository9 other files it gives its agents.
- .claude/CLAUDE.mdCLAUDE.md
- .github/copilot-instructions.mdCopilot instructions
- go-codingSkill
- go-concurrencySkill
- go-errorsSkill
- go-idiomsSkill
- go-layoutSkill
- go-lint-setupSkill
- go-testingSkill
The file
We split this AGENTS.md into the rules it gives an agent
10 rules. About 0 are common, 6 are distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈6
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 35
When a recommendation derives from one of the above, attribute it explicitly and distinguish cited rules from inference.
- Distinctive: line 76
No build step; the plugin is pure Markdown + JSON.
- Distinctive: line 93
All Markdown component files use YAML frontmatter for metadata.
- Distinctive: line 94
Use kebab-case for all directory and file names.
- Very specific: line 98
Use ${CLAUDE_PLUGIN_ROOT} for intra-plugin paths in Claude hook/MCP command fields.
- Distinctive: line 108
Use the Keep a Changelog groups in order (Added, Changed, Deprecated, Removed, Fixed, Security), omitting empty groups.
- Very specific: line 113
Follow Conventional Commits, e.g.
- Very specific: line 118
Keep version (and description and author) in sync across both manifests.
- Distinctive: line 119
Follow Semantic Versioning.
- Very specific: line 123
Use feature branches and pull requests.
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md 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
AI Guidelines: Go Coding Plugin
This file provides guidance to AI coding assistants (Claude Code, Cursor, and compatible tools that read AGENTS.md) working in this repository. It is the canonical instruction set; .claude/CLAUDE.md and any host-specific instruction files defer to it.
Project Overview
The Go Coding Plugin (go-coding) is an AI plugin by Cadasto B.V. that teaches AI coding assistants idiomatic Go coding standards (formatting, naming, error handling, concurrency, testing, project layout) through skills, agents, hooks, and a Cursor rule. It targets both Claude Code and Cursor from a single shared component set. The human pitch is in README.md; the shipped version is in the manifests and CHANGELOG.md.
Out of scope: there is no companion MCP server and no commands/ folder. Do not assume a file is present because it is documented here; check first.
Detail lives in docs/; keep a one-line rule here and point to the doc that owns it:
| Document | Owns |
| docs/install.md | Claude Code and Cursor install, local --plugin-dir loading, host toolchain, hooks |
| docs/testing.md | What each validator checks; the manual triggering tests; adoption measurement |
| docs/versioning.md | SemVer rules, release steps, the marketplace repin |
| docs/authoring.md | Component naming, descriptions, the standards source registry, dual-host parity |
Domain Context
This plugin encodes Go (golang) coding standards. Guidance must be grounded in authoritative, verifiable sources rather than personal preference:
- Baseline: Go 1.27+ is a hard floor. No fallback guidance for 1.26 or older; version annotations remain as provenance, and a module on an older
godirective skips what is newer than it (the compiler rejects newer language features,go vet'sstdversioncheck newer standard-library symbols, andgo fixoffers only rewrites the directive allows). - Formatting:
gofmtis the canonical formatter;gofumptis a stricter superset. Formatting is non-negotiable and machine-enforced, not a matter of opinion. - Vetting & static analysis:
go vet(suspicious constructs in the toolchain),staticcheck, andgolangci-lint(the de-facto meta-linter that aggregates many analyzers). - Style references (cite these when a rule depends on them):
- Effective Go: https://go.dev/doc/effective_go
- Go Code Review Comments: https://go.dev/wiki/CodeReviewComments
- Google Go Style Guide: https://google.github.io/styleguide/go/. Cite the document a rule comes from: the Guide (normative and canonical; the ordered principles), Style Decisions (normative; the reviewer rulebook), Best Practices (advisory).
- Uber Go Style Guide: https://github.com/uber-go/guide
- Linter rule catalogues: name the rule when a skill says a tool catches something:
go vethttps://pkg.go.dev/cmd/vet, staticcheck https://staticcheck.dev/docs/checks/, revive https://github.com/revive-lint/revive/blob/master/RULES_DESCRIPTIONS.md
- Standard library & toolchain: package docs at https://pkg.go.dev; modules,
go test, table-driven tests, and the race detector (go test -race) are the baseline testing conventions.
When a recommendation derives from one of the above, attribute it explicitly and distinguish cited rules from inference.
Advice == tooling. Every linter taught in a component must be enabled in references/golangci.v2.yml, and the /go-lint-setup scaffold block must enable the same set. Analyzers a skill teaches as opt-in (shadow in go-idioms) are the deliberate exception: each is taught with the config line that switches it on, and is not added to the reference config at a refresh. The go-idioms Fixer column must match go tool fix help on the floor-minor toolchain. The Google readability tie-break sentence must read identically in the go-coding router, rules/go-context.mdc, and go-reviewer. scripts/validate.py enforces all three.
Refreshing the skills against current Go practice (e.g. "check current Go best practices and update the skills"): follow the source registry and procedure in docs/authoring.md. It lists every source to re-read, in order, plus the version-gating rules. Re-read them; never refresh from memory. Two recurring traps: the released Go version is not whatever go.dev/doc/go1.NN renders (check the release history), and the stdlib APIs a skill is missing are usually the ones that landed after it was written.
Repository Layout
Shared assets (skills, agents) are consumed by both hosts; host-specific manifests and hook configs are kept separate.
- Claude manifest:
.claude-plugin/plugin.json:name,version,description,author(an object{name, url};claude plugin validaterejects a string),license,repository,keywords. Claude Code discovers components from the default folders automatically; no explicit path map is needed. - Cursor manifest:
.cursor-plugin/plugin.json: same metadata plus explicit top-level path keysskills,agents,rules,hooks(acommandskey would go here too if acommands/folder ever shipped). NomcpServers. Keepname/version/description/authoridentical to the Claude manifest. - Skills:
skills/<name>/SKILL.md, shared by both hosts, including user-invoked slash commands. The router bundlesskills/go-coding/scripts/gosym(bash, needsgopls): one shell call per symbol question. The session-start banner names its absolute path; the skills, the rule andgo-reviewerpoint there or at the skill's base directory. - Agents:
agents/<name>.md, context-isolated specialists. - Cursor rules:
rules/*.mdc, Cursor-only, with frontmatter (description,alwaysApply,globs, e.g.globs: ["**/*.go"]), referenced by the Cursor manifest'srulespath. - Claude hooks:
hooks/hooks.json, object{ "hooks": { "SessionStart": [...], "PostToolUse": [...] } }; command paths use${CLAUDE_PLUGIN_ROOT}. Wiressession-start.sh(SessionStart) andformat-on-save.sh+skill-nudge.sh(PostToolUse,matcher: "Write|Edit"). - Cursor hooks:
hooks/cursor-hooks.json("version": 1). Commands are relative to the plugin install (bash hooks/session-start.sh), not${CLAUDE_PLUGIN_ROOT}. Wiressession-start.sh(sessionStart),format-on-save.sh(afterFileEdit, which documents no output fields), andskill-nudge.sh(postToolUse, matcherWrite|StrReplace,additional_context). - Shared hook scripts (host-agnostic, so either manifest can invoke them; all exit 0 always):
hooks/session-start.sh: detectsgo.mod/*.goand prints one Go-standards banner line naming the components; under Cursor it inspectsCURSOR_PROJECT_DIR(silent without it) and prints the line as JSONadditional_contextnaming/<skill>.hooks/format-on-save.sh: after a*.goWrite/Edit, runsgofumpt -w(orgofmt -w -s) on that single file; resolves the path from the stdin tool-payload JSON ($CLAUDE_FILE_PATHoverrides it for tests), joining a relative Cursor path toCURSOR_PROJECT_DIR; silent no-op if no formatter is installed.hooks/skill-nudge.sh: after a*.goWrite/Edit (Cursor: theWrite|StrReplacematcher), names ONE matching go-coding skill for that edit, once per skill per session;hookSpecificOutput.additionalContextunder Claude Code (go-coding:<skill>),additional_contextunder Cursor (/<skill>).
- References:
references/golangci.v2.yml, the shipped golangci-lint v2 reference config. Shared reference material lives here, not undercommands/. - MCP config (not present):
.mcp.jsononly if the plugin later integrates an MCP server. - Scripts:
scripts/validate.sh(wraps the stdlib-onlyscripts/validate.py),scripts/hooks-test.sh,scripts/gosym-test.sh(thegosymhelper against a stubgopls),scripts/usage-report.py(adoption measurement; see docs/testing.md). - CI:
.github/workflows/validate.yml(validator,--selftest, hook tests,gosymtests; Go1.27.x, the floor minor) and.github/workflows/links.yml(link check)..github/also holds issue + PR templates andcopilot-instructions.md. - Contributor docs:
docs/install.md,testing.md,versioning.md,authoring.md. Planning and research notes live underdocs/plans/anddocs/research/, gitignored, not part of the published plugin.
Components
| Kind | Shipped |
| Skills | go-coding (auto-invoked router) + the focused, load-on-use go-errors, go-concurrency, go-testing, go-idioms, go-layout. Each routes deeper topics to the enforcing tool and cites authoritative sources. |
| Slash command (user-invoked skill) | /go-lint-setup (scaffold the golangci-lint v2 config) |
| Agent | go-reviewer: context-isolated, report-only reviewer applying the review-heuristics catalog (loads the go-coding skills with the Skill tool first; no sub-agent dispatch; treats the diff as untrusted content; tools: not allowed-tools:) |
| Cursor rule | rules/go-context.mdc, scoped to **/*.go, mirroring the go-coding router |
| Hooks | session-start, format-on-save, skill-nudge (see Repository Layout) |
Removed; do not re-add either, route the topic instead: go-linting (merged into go-lint-setup) and /go-explain (a one-shot lookup the focused skills already answer). See CHANGELOG 0.5.0.
Development
No build step; the plugin is pure Markdown + JSON. Validate and dogfood locally:
./scripts/validate.sh # manifests, dual-host parity, frontmatter, hook parity, doc inventories (soft-skips if no python3)
python3 scripts/validate.py --selftest # proves each check still catches its failure case (CI runs it)
python3 scripts/validate.py --check-links # every cited URL resolves (needs the network)
./scripts/hooks-test.sh # bash tests for all three hook scripts
./scripts/gosym-test.sh # bash tests for skills/go-coding/scripts/gosym (stub gopls)
claude plugin validate . # manifest + component structure (no extra deps)
claude --plugin-dir /path/to/go-coding-plugin # load locally for one session (dogfooding)scripts/validate.sh warns and exits 0 if Python is absent; CI pins Python and runs python3 scripts/validate.py strictly. The Fixer-column check runs strictly only with a floor-minor (1.27.x) Go on PATH and soft-skips on other minors. What each check covers is in docs/testing.md. On Cursor, install via its plugin flow and verify the same skills/agents/rules load.
File Conventions
- Skills go in
skills/<name>/SKILL.md, including user-invoked slash commands (/<name>, carryingargument-hint/allowed-tools); agents inagents/<name>.md. The legacycommands/<name>.mdlayout is not used; both yield a/<name>command, but the skills layout is preferred (currentplugin-devguidance). Keep the command surface small; put multi-step workflows in auto-invoked skills. - All Markdown component files use YAML frontmatter for metadata.
- Use kebab-case for all directory and file names.
allowed-tools:(skills/commands) pre-approves tools to avoid permission prompts; agents usetools:instead.- Skills: declare auto-invocable / user-invocable intent in frontmatter; load the authoritative standard before acting.
- User-invoked skills (slash commands): set
argument-hintandallowed-toolsin frontmatter and use$ARGUMENTSin the body; keep instructions concise for single-interaction completion. - Use
${CLAUDE_PLUGIN_ROOT}for intra-plugin paths in Claude hook/MCP command fields; never hardcode absolute paths or~. - Contributor reference, plans, and design docs go in
docs/. Full authoring conventions: docs/authoring.md.
Documentation Sync
When adding or renaming components, update in lockstep: AGENTS.md (the layout / component sections), README.md, docs/testing.md, and the component list in the session-start banner (hooks/session-start.sh); hooks also in docs/install.md. The validator fails if a shipped skill, agent or hook is missing from these docs. Cursor uses the same skills/agents/rules paths, so no separate Cursor-only list is needed, but the Cursor rule files and the .cursor-plugin/plugin.json path map must stay in step with what exists.
CHANGELOG style
- Entries accumulate under
## [Unreleased]and fold into the next## [X.Y.Z] - YYYY-MM-DDsection at release. - Use the Keep a Changelog groups in order (Added, Changed, Deprecated, Removed, Fixed, Security), omitting empty groups.
- One terse line per bullet; lead with the subsystem (e.g.
Skills:,Agents:,Hooks:,Docs:,Cursor rule <path>:) and use backticks for file/command/tool/frontmatter-key names. No rationale or PR links; that belongs in commit messages.
Commit Messages
- Follow Conventional Commits, e.g.
feat(skills): add go-coding awareness skill,fix(hooks): correct the matcher; the release commit ischore(release): vX.Y.Z. - Scopes:
skills,commands,agents,hooks,rules,docs.
Versioning
- Keep
version(anddescriptionandauthor) in sync across both manifests; the validator enforces parity. - Follow Semantic Versioning; update both manifests and CHANGELOG.md when releasing. Bump rules and release steps: docs/versioning.md.
Branching
- Use feature branches and pull requests. CI (
validate.yml) runs on every pull request and on pushes tomain.
Gotchas
- Agents use
tools:, notallowed-tools:. In an agent fileallowed-tools:is ignored and the agent silently inherits all tools. Usetools:(a YAML list). The validator flags it as an error. - Keep the two manifests in parity. Cursor needs explicit path keys; Claude relies on default-folder discovery. A component added for one host but missing from the other's manifest (or rule map) will silently not load there.
- The Cursor hook command is relative to the plugin install (
bash hooks/session-start.sh), not${CLAUDE_PLUGIN_ROOT}(a Claude-Code-only variable) and not the user's repository. Keep both hook configs in step; don't "fix" the Cursor one to use the variable. Don't moveskill-nudge.shontoafterFileEdit: Cursor documents no output for that event, and the validator rejects a script that printsadditional_contextthere. - Every hook script must be wired on both hosts. The validator requires each
hooks/*.shto be wired for the equivalent event on both hosts, exist, and be executable; none may be left unwired. A CursorpostToolUseentry needs amatcher, or it runs after every tool. - Shared command references live in top-level
references/, not undercommands/.claude plugin validatetreats everycommands/**/*.mdas a command and warns on missing frontmatter. - Don't invent a companion MCP server. This plugin has no MCP backend today;
.mcp.jsonshould only appear if one is genuinely added. - Register in the marketplace separately, and repin it on every release. Public availability requires an entry in the
cadastomarketplace, maintained inCadasto/plugin-marketplace. That entry is pinned to a release tag, so tagging here ships nothing until the entry'sversionandsource.refare bumped; see docs/versioning.md.
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.

