Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions .agents/skills/use-modern-go/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
name: use-modern-go
description: Use the Modern Go Guidelines CLI whenever writing, modifying, fixing, or refactoring Go code. Apply its version-specific guidance to generated changes.
---

# Modern Go Guidelines CLI

Always write modern, idiomatic Go code. Use the Modern Go Guidelines CLI as the source of truth for modern Go idioms that may be newer than your knowledge cutoff.

Command:

- Linux or macOS: `sh "<skill-dir>/scripts/run-tool.sh"`
- Windows PowerShell: `& '<skill-dir>\scripts\run-tool.ps1'`

First run and approvals:

On first use, the wrapper installs the Modern Go Guidelines CLI in a local cache directory.

Subcommands:

- `list`
- `explain`

Before editing Go code:

1. Call the wrapper's `list` subcommand for the relevant Go file.

Prefer passing the file you are about to edit:

```sh
sh "<skill-dir>/scripts/run-tool.sh" list --file-path path/to/file.go
```

On Windows, use the PowerShell wrapper with the same arguments.

The CLI resolves the applicable Go version from go.mod, go.work, the local Go toolchain, or an explicit override.

2. If the target Go version is already known, you may pass it directly:

```sh
sh "<skill-dir>/scripts/run-tool.sh" list --go-version 1.24
```

3. Read the complete list output before deciding which guidelines apply.

The list output is ordered newest first. Read the full output because older supported guidelines may still apply.

Do not pipe the output through head, tail, grep, sed, or any other truncating/filtering command. Important guidelines may otherwise be missed.

4. Treat returned guidelines as authoritative for modern Go style choices in code you are editing.

If a guideline applies, follow it even when nearby code or repository convention uses an older pattern. Skip it only when it would not compile, would change behavior, or clearly does not match the edited code. Before skipping a returned guideline that seems relevant, call the wrapper's `explain` subcommand for that guideline ID.

Call `explain` only when a specific guideline may apply and you need the detailed explanation or examples. Request only the guideline IDs you intend to evaluate or apply:

```sh
sh "<skill-dir>/scripts/run-tool.sh" explain sync_waitgroup_go
```

Multiple guideline IDs may be requested as positional arguments:

```sh
sh "<skill-dir>/scripts/run-tool.sh" explain atomic_types errors_as_type
```

Do not call `explain` without guideline IDs. Use `list` first to discover the short guideline list for the target Go version, then call `explain` for the specific returned IDs that need more context.
1 change: 1 addition & 0 deletions .agents/skills/use-modern-go/scripts/VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v0.1.1
91 changes: 91 additions & 0 deletions .agents/skills/use-modern-go/scripts/run-tool.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
$ErrorActionPreference = "Stop"

$cliVersion = (Get-Content -LiteralPath (Join-Path $PSScriptRoot "VERSION") -TotalCount 1).Trim()
$modulePath = "github.com/JetBrains/go-modern-guidelines"
$binaryName = "go-modern-guidelines.exe"

if ($env:LOCALAPPDATA) {
$cacheRoot = Join-Path $env:LOCALAPPDATA "go-modern-guidelines"
} else {
Write-Error "go-modern-guidelines: LOCALAPPDATA must be set"
exit 1
}

# GO_MODERN_GUIDELINES_DEV runs the binary built by dev-install.
if ($env:GO_MODERN_GUIDELINES_DEV) {
$devBinary = Join-Path (Join-Path $cacheRoot "dev") $binaryName
if (-not (Test-Path -LiteralPath $devBinary -PathType Leaf)) {
Write-Error "go-modern-guidelines: GO_MODERN_GUIDELINES_DEV is set but no dev build found; run dev-install"
exit 1
}
& $devBinary @args
exit $LASTEXITCODE
}

$installDir = Join-Path $cacheRoot $cliVersion
$binaryPath = Join-Path $installDir $binaryName

if (-not (Test-Path -LiteralPath $binaryPath -PathType Leaf)) {
if (-not (Get-Command go -ErrorAction SilentlyContinue)) {
Write-Error "go-modern-guidelines: Go toolchain is required to install $modulePath@$cliVersion"
exit 1
}

$tmpDir = "$installDir.tmp.$PID"
Remove-Item -LiteralPath $tmpDir -Recurse -Force -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Path $tmpDir -Force | Out-Null

Write-Host "go-modern-guidelines: installing $modulePath@$cliVersion into $installDir" -ForegroundColor DarkGray

try {
$previousGoBin = $env:GOBIN
$previousGoFlags = $env:GOFLAGS
$previousGoWork = $env:GOWORK
$previousCgoEnabled = $env:CGO_ENABLED
$env:GOBIN = $tmpDir
$env:GOFLAGS = ""
$env:GOWORK = "off"
$env:CGO_ENABLED = "0"
Push-Location -LiteralPath $tmpDir
try {
go install "$modulePath@$cliVersion"
} finally {
Pop-Location
$env:GOBIN = $previousGoBin
$env:GOFLAGS = $previousGoFlags
$env:GOWORK = $previousGoWork
$env:CGO_ENABLED = $previousCgoEnabled
}

$tmpBinary = Join-Path $tmpDir $binaryName
if (-not (Test-Path -LiteralPath $tmpBinary -PathType Leaf)) {
Write-Error "go-modern-guidelines: go install did not produce $binaryName"
exit 1
}

$actualVersion = ""
try {
$actualVersion = (& $tmpBinary --version 2>$null)
} catch {
$actualVersion = ""
}
if ($actualVersion -ne $cliVersion) {
if (-not $actualVersion) {
$actualVersion = "unknown version"
}
Write-Error "go-modern-guidelines: installed $actualVersion, want $cliVersion"
exit 1
}

New-Item -ItemType Directory -Path $installDir -Force | Out-Null
$stagedBinary = "$binaryPath.tmp.$PID"
Move-Item -LiteralPath $tmpBinary -Destination $stagedBinary -Force
Move-Item -LiteralPath $stagedBinary -Destination $binaryPath -Force
Remove-Item -LiteralPath $tmpDir -Recurse -Force -ErrorAction SilentlyContinue
} finally {
Remove-Item -LiteralPath $tmpDir -Recurse -Force -ErrorAction SilentlyContinue
}
}

& $binaryPath @args
exit $LASTEXITCODE
68 changes: 68 additions & 0 deletions .agents/skills/use-modern-go/scripts/run-tool.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#!/usr/bin/env sh
set -eu

script_dir="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P)"

cli_version="$(cat "${script_dir}/VERSION")"
module_path="github.com/JetBrains/go-modern-guidelines"
binary_name="go-modern-guidelines"

if [ -n "${XDG_CACHE_HOME:-}" ]; then
cache_root="${XDG_CACHE_HOME}/go-modern-guidelines"
elif [ -n "${HOME:-}" ]; then
cache_root="${HOME}/.cache/go-modern-guidelines"
else
echo "go-modern-guidelines: HOME or XDG_CACHE_HOME must be set" >&2
exit 1
fi

# GO_MODERN_GUIDELINES_DEV runs the binary built by make dev-install.
if [ -n "${GO_MODERN_GUIDELINES_DEV:-}" ]; then
dev_binary="${cache_root}/dev/${binary_name}"
if [ ! -x "${dev_binary}" ]; then
echo "go-modern-guidelines: GO_MODERN_GUIDELINES_DEV is set but no dev build found; run make dev-install" >&2
exit 1
fi
exec "${dev_binary}" "$@"
fi

install_dir="${cache_root}/${cli_version}"
binary_path="${install_dir}/${binary_name}"

if [ ! -x "${binary_path}" ]; then
if ! command -v go >/dev/null 2>&1; then
echo "go-modern-guidelines: Go toolchain is required to install ${module_path}@${cli_version}" >&2
exit 1
fi

tmp_dir="${install_dir}.tmp.$$"
rm -rf "${tmp_dir}"
mkdir -p "${tmp_dir}"
trap 'rm -rf "${tmp_dir}"' EXIT HUP INT TERM

echo "go-modern-guidelines: installing ${module_path}@${cli_version} into ${install_dir}" >&2

(
cd "${tmp_dir}"
GOFLAGS= GOWORK=off CGO_ENABLED=0 GOBIN="${tmp_dir}" go install "${module_path}@${cli_version}"
)

tmp_binary="${tmp_dir}/${binary_name}"
if [ ! -x "${tmp_binary}" ]; then
echo "go-modern-guidelines: go install did not produce ${binary_name}" >&2
exit 1
fi

actual_version="$("${tmp_binary}" --version 2>/dev/null || true)"
if [ "${actual_version}" != "${cli_version}" ]; then
echo "go-modern-guidelines: installed ${actual_version:-unknown version}, want ${cli_version}" >&2
exit 1
fi

mkdir -p "${install_dir}"
mv "${tmp_binary}" "${binary_path}.tmp.$$"
mv "${binary_path}.tmp.$$" "${binary_path}"
rm -rf "${tmp_dir}"
fi

exec "${binary_path}" "$@"
4 changes: 4 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ GitHub issues (https://github.com/coder/chat/issues) are the public source of tr

This repo uses the default triage label vocabulary. See `docs/agents/triage-labels.md`.

### Modern Go

Before writing or refactoring Go code, consult the `use-modern-go` skill (`.agents/skills/use-modern-go/SKILL.md`) for version-specific modern Go idioms.

### Domain docs

This is a single-context repo with root `CONTEXT.md` and root `docs/adr/`. See `docs/agents/domain.md`.
6 changes: 6 additions & 0 deletions skills-lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@
"sourceType": "github",
"skillPath": "skills/engineering/triage/SKILL.md",
"computedHash": "2b6efb6da12d92551772fcc04acf331f4e0e6f7bd9d4cb23ce0b301e0b128feb"
},
"use-modern-go": {
"source": "JetBrains/go-modern-guidelines",
"sourceType": "github",
"skillPath": "plugin/skills/use-modern-go/SKILL.md",
"computedHash": "a965eabdf8e51c4cab6fcd08d6a7711176ac60c55a458d57f95df7115e93a6cb"
}
}
}