Skip to content

feat(skills): gosym answers a Go symbol question in one shell call - #17

Open
sebastian-iancu wants to merge 2 commits into
mainfrom
feat/gosym-helper
Open

sebastian-iancu wants to merge 2 commits into
mainfrom
feat/gosym-helper

Conversation

@sebastian-iancu

Copy link
Copy Markdown
Contributor

Summary

Over a week of agent sessions, go-reviewer and implementation workers asked gopls for a symbol's uses in under one run in six. They grepped Go files for identifiers about 3,400 times instead. Two things got in the way:

  • Two steps. The shell route ran gopls workspace_symbol, then copied a position by hand into gopls references.
  • A flaky first step. gopls workspace_symbol -matcher casesensitive <Name> lists at most 100 symbols and, past that cap, does not reliably keep the exact one. On a mid-sized module, Validate came back in one run of four.

This PR bundles skills/go-coding/scripts/gosym, which turns a symbol question into one call:

gosym [-C <checkout>] def|refs|impl|calls <Name> [<path part>]
  • It queries workspace_symbol anchored at the name's end ('<Name>$'). That stays under the cap, and is stable across runs, for all but the commonest method names; for those it warns and asks for Type.Method or a path part.
  • It keeps the exact name inside the checkout, then asks references, implementation or call_hierarchy at each definition, with paths printed relative to the checkout.
  • Exit 1 (no definition) or 3 (gopls missing or failing) means: use grep and say so.

The symbol-question procedure in the router, the Cursor rule, go-layout and go-reviewer now names gosym, and keeps the anchored query as the route by hand. The session-start banner names it too. install.md adds the allow rule Bash(*/skills/go-coding/scripts/gosym *); the leading * matters because the path carries the plugin version.

go-reviewer's tools. They stay Read, Grep, Glob, Bash, Skill, and gopls already runs through Bash. I did not add the LSP tool: the Claude Code docs do not say whether a deferred tool listed in an agent's tools: can be called, and they say an agent whose listed tools do not resolve may fail to launch, as it would in a session without gopls-lsp. Nor do they say that LSP answers for a git worktree, where most reviews run.

Verification

  • ./scripts/gosym-test.sh: 16 cases ok against a stub gopls. Can-fail: disabling the inside-the-checkout filter fails "def drops a definition outside the checkout".
  • Against a real module with gopls v0.24.0: def, refs … <path part>, impl, calls and -C answered in 1–9 s. def Validate was stable over three runs, and def Close printed the cap warning.
  • ./scripts/validate.sh and --selftest OK; ./scripts/hooks-test.sh OK with the banner case updated; claude plugin validate . passed.

Checklist

  • ./scripts/validate.sh passes
  • claude plugin validate . passes
  • Skill / command / agent triggering tested locally (not run in a live session)
  • Cursor install tested locally (the rule changed; not tested on Cursor)
  • Both manifests kept in sync when metadata changed (no metadata change)
  • Cursor rule files and the path map kept in step
  • CHANGELOG.md updated under Unreleased; version bump at release
  • Docs synced (AGENTS.md, README.md, hooks/session-start.sh, docs/install.md, docs/testing.md, docs/versioning.md)

🤖 Generated with Claude Code

sebastian-iancu and others added 2 commits October 29, 2026 23:26
A week of agent sessions showed reviewers and workers asking gopls for a
symbol's uses in under one run in six, and grepping Go files for identifiers
about 3,400 times instead. The shell route took two steps (workspace_symbol,
then copy its position into references), and its first step was flaky:
`gopls workspace_symbol -matcher casesensitive <Name>` lists at most 100
symbols and, past that cap, does not reliably keep the exact one (`Validate`
came back in one run of four on a mid-sized module).

The router now bundles skills/go-coding/scripts/gosym:

    gosym [-C <checkout>] def|refs|impl|calls <Name> [<path part>]

It queries workspace_symbol anchored at the name's end ('<Name>$', which
stays under the cap for all but the commonest method names, and says so
when it does not), keeps the exact name inside the checkout, asks
references, implementation or call_hierarchy at each definition, and prints
paths relative to the checkout. Exit 1 (no definition) or 3 (gopls missing
or failing) means: use grep and say so.

The symbol-question procedure in the router, the Cursor rule, go-layout and
go-reviewer now names gosym, with the anchored query as the by-hand route;
the session-start banner names it; install.md gives the allow rule
`Bash(*/skills/go-coding/scripts/gosym *)`, since the path carries the plugin
version. scripts/gosym-test.sh runs it against a stub gopls, and CI runs that.

go-reviewer's tools stay Read, Grep, Glob, Bash and Skill: gopls runs through
Bash. The LSP tool is not added, since the Claude Code docs do not say
whether a deferred tool in an agent's allowlist is callable, nor that the
LSP tool follows a worktree.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant