{"id":48675475,"url":"https://github.com/jlugagne/go-surgeon","last_synced_at":"2026-05-03T17:01:33.591Z","repository":{"id":349995654,"uuid":"1204291768","full_name":"JLugagne/go-surgeon","owner":"JLugagne","description":"Deterministic Go code editing for LLM agents. AST-based CLI and MCP server that replaces Edit, Read, and Grep on .go files for Claude Code, Cursor, and any agent.","archived":false,"fork":false,"pushed_at":"2026-05-01T22:19:43.000Z","size":11194,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-02T00:16:36.739Z","etag":null,"topics":["ai-agent","ast","claude","cli","code-editor","code-generation","copilot","cursor","developer-tools","gemini-cli","go","golang","llm","mcp","mcp-server","mocking","refactoring"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JLugagne.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-07T21:53:19.000Z","updated_at":"2026-05-01T22:06:34.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/JLugagne/go-surgeon","commit_stats":null,"previous_names":["jlugagne/go-surgeon"],"tags_count":22,"template":false,"template_full_name":null,"purl":"pkg:github/JLugagne/go-surgeon","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JLugagne%2Fgo-surgeon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JLugagne%2Fgo-surgeon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JLugagne%2Fgo-surgeon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JLugagne%2Fgo-surgeon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JLugagne","download_url":"https://codeload.github.com/JLugagne/go-surgeon/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JLugagne%2Fgo-surgeon/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32577126,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T06:36:36.687Z","status":"ssl_error","status_checked_at":"2026-05-03T06:36:09.306Z","response_time":103,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agent","ast","claude","cli","code-editor","code-generation","copilot","cursor","developer-tools","gemini-cli","go","golang","llm","mcp","mcp-server","mocking","refactoring"],"created_at":"2026-04-10T14:03:01.355Z","updated_at":"2026-05-03T17:01:33.582Z","avatar_url":"https://github.com/JLugagne.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# go-surgeon\n\n### **Deterministic Go code editing for LLM agents. No text patching. No broken builds.**\n\nYour agent shouldn't edit Go with Edit, Read, Grep, or Bash.\n\nGo isn't just text, it's a tree of declarations. go-surgeon gives your agent a real AST-based toolkit — precise symbol lookup, structural edits, automatic `goimports` — exposed as an MCP server it uses instead of generic file tools.\n\n**One tool call per edit. Valid Go every time.**\n\n[![Go](https://img.shields.io/badge/Go-1.25+-00ADD8?logo=go)](https://golang.org)\n[![MCP](https://img.shields.io/badge/MCP-ready-8A2BE2)](https://modelcontextprotocol.io)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n\n[**Quick Start**](#quick-start) • [**Why**](#why-go-surgeon) • [**MCP**](#-mcp-server) • [**Highlights**](#highlighted-features) • [**Safety**](#-safety)\n\n\u003c/div\u003e\n\n---\n\n## The problem nobody admits\n\nAsk your agent to update a single function in a 200-line Go file. Watch what happens:\n\n1. It `Read`s the file, finds the function, plans the edit\n2. It calls `Edit` with a string replacement — misses a trailing tab\n3. The patch fails. It re-reads the file. Tries again with the whole function body\n4. This time it forgets the `context.Context` import\n5. `go build` fails. It edits the import block — badly. Curly brace drift.\n6. Three turns later you have a working file and no idea what changed.\n\nEvery Go dev using an LLM agent has lived this. The problem isn't the model's reasoning — **text-level patching is fundamentally wrong for a structured language**. Indentation, imports, braces: these aren't content, they're grammar. And grammar breaks loudly.\n\n## The fix\n\n```\nupdate(object=\"func\", file=\"internal/catalog/domain/book.go\", identifier=\"NewBook\", content=\"\"\"\nfunc NewBook(title, author string) (*Book, error) {\n    return \u0026Book{Title: title, Author: author}, nil\n}\n\"\"\")\n```\n\n```\n✅ SUCCESS (update func): Updated NewBook in internal/catalog/domain/book.go\n```\n\nLocated by **AST identifier**. Replaced by **structural edit**. Imports handled by **`goimports`** automatically.\nThe agent stops counting tabs and starts shipping logic.\n\n---\n\n## Why go-surgeon\n\n### 1. It replaces generic file tools for Go — everywhere\n\nThe MCP server ships with instructions telling the agent: **for any `.go` file, use these tools instead of Edit / Write / Read / Grep / Glob / Bash**. No more `sed` on Go source. No more `grep -r` that misses method receivers. No more `Edit` that forgets imports.\n\n### 2. Edits are atomic, not conversational\n\nEvery tool is a structured operation. Either it succeeds or you get a clear error like `ERROR (update func): node 'Book.Validate' not found in ...`. No silent half-edits. No \"it kind of worked\".\n\n### 3. Your agent never manages imports or formatting\n\nContent is raw Go source — no package declaration, no imports, no indentation. `goimports` runs on every mutation. An entire category of agent mistakes, permanently eliminated.\n\n### 4. Interfaces and mocks stay in sync\n\n`add_interface` and `update_interface` regenerate a function-field mock atomically. The compile-time assertion (`var _ Repo = (*MockRepo)(nil)`) blocks drift. `extract_interface` pulls an interface out of an existing struct in one command.\n\n### 5. Edits can be as granular as a single field or line\n\nThe unified `patch` tool makes scoped edits with a `target` selector: edit inside a function body, add/rename/retype a single struct field, add or remove a single interface method and regenerate the mock — all without re-emitting the whole declaration.\n\n### 6. Type-aware references and renames across the module\n\n`find_definition`, `find_references`, and `rename_symbol` resolve the target via `go/packages` so they only touch identifiers that bind to the same `types.Object` — not other symbols that happen to share a name. They also accept `module=` to resolve into a dependency.\n\n---\n\n## When go-surgeon helps vs. when Edit is fine\n\n**Use go-surgeon for:**\n- Exploring unfamiliar Go code (`symbol body=true context=file` gives you a function body + full file outline in one call)\n- Resolving a `file:line` build/stack diagnostic to a declaration (`symbol file=... at_line=...`)\n- Structural edits: adding/renaming struct fields, interface methods, managing imports\n- Batch edits across many functions or files in one atomic operation\n- Multi-step sessions where AST validation prevents compounding errors\n- Any edit where import management matters\n\n**Edit is fine or better when:**\n- Single-line tweak in a file you already have open and know well\n- Files outside Go: `.yaml`, `.md`, `.sh`, `Dockerfile`, etc.\n- One-off prototyping where you don't need AST guarantees\n- 3-line changes where the 200–500 ms MCP overhead isn't amortized\n\n\u003e Each go-surgeon MCP call adds ~200–500 ms overhead vs a direct Edit. The break-even is roughly 5+ structural edits, or any task requiring AST-level guarantees (import management, type-aware renames, struct/interface modifications). For a single 3-line tweak in a file you already know, Edit is faster.\n\n---\n\n## Install\n\n**Linux / macOS**\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/JLugagne/go-surgeon/main/install.sh | sh\n```\n\nInstalls the latest release binary to `~/.local/bin` (no root required). Override with `INSTALL_DIR`:\n\n```bash\nINSTALL_DIR=/usr/local/bin curl -fsSL https://raw.githubusercontent.com/JLugagne/go-surgeon/main/install.sh | sh\n```\n\n**Self-update** — once installed, keep the binary current with:\n\n```bash\ngo-surgeon upgrade\n```\n\n**Homebrew / Scoop / Windows** — coming soon.\n\n---\n\n## Quick Start\n\n```bash\n# Verify installation\ngo-surgeon --version\n\n# Run as MCP server (stdio)\ngo-surgeon mcp\n\n# Or use the CLI directly\ngo-surgeon graph\ngo-surgeon symbol BookHandler.Handle --body\n```\n\nConfigure your MCP client (example for Claude Code / Cursor):\n\n```json\n{\n  \"mcpServers\": {\n    \"go-surgeon\": {\n      \"command\": \"go-surgeon\",\n      \"args\": [\"mcp\"]\n    }\n  }\n}\n```\n\nThe server auto-advertises instructions telling the agent to use go-surgeon tools for every operation on `.go` files — no prompt engineering required on your side.\n\n---\n\n## 🔌 MCP Server\n\n```bash\ngo-surgeon mcp\n```\n\nTools over stdio, grouped by purpose:\n\n| Tools | Purpose |\n|---|---|\n| `overview`, `symbol` | Explore packages and look up symbols — **replaces Read / Grep / Glob**. `symbol` also resolves a `file:at_line` diagnostic directly to its declaration. |\n| `find_definition`, `find_references`, `rename_symbol` | Type-aware cross-package symbol lookup and rename — powered by `go/packages`. All three accept `module=` to resolve into a dependency. |\n| `create`, `update`, `delete` | Add, replace, or remove a file, function, or struct by AST identifier — **replaces Edit / Write**. `object=\"auto\"` infers from the content; `delete object=\"file\"` removes the file from disk. |\n| `patch` | Unified surgical editor — one tool, five targets (`function`, `struct`, `interface`, `file`, `decl`). Scoped in-place edits without re-emitting whole declarations. Function ops include `replace`, `insert_before`/`insert_after`, `delete`, `wrap`, and `set_signature` (rewrite params/returns without touching the body). |\n| `patch_function_bulk`, `patch_struct_bulk` | Apply many `patch` operations to many targets in a single atomic call — useful when one refactor touches dozens of functions or structs. |\n| `insert_call` | Insert a single statement into a function body (`before-return`, `end-of-body`, or `after:\u003cmarker\u003e`); auto-lifts out of nested scopes |\n| `add_interface`, `update_interface`, `delete_interface` | Manage interfaces with auto-generated (and auto-deleted) mocks |\n| `implement`, `mock`, `extract_interface` | Generate stubs, standalone mocks, and extract interfaces from structs |\n| `test`, `tag` | Generate test skeletons and struct field tags |\n| `build_check`, `test_run` | Compile-verify and run tests in-loop. Both accept `affected_by=\u003cfile\u003e` to narrow to the file's reverse-dep closure; `test_run` also accepts `symbols=[\"pkg.MyFunc\"]` to auto-resolve owning packages and build a `-run` filter, plus `verbosity=summary` for compact output on large suites. |\n| `execute_plan` | Run up to 15 edits atomically from a YAML/JSON plan — supports every action type including every `patch` target |\n| `batch_query` | Run up to 10 read-only queries (`symbol` / `overview` / `find_definition` / `find_references`) in one round-trip |\n| `describe_tool` | Queryable catalog of every tool — no args for the grouped list, `name=X` for detail |\n\nEvery write tool supports `preview=true` to return a unified diff without writing. Errors carry a structured `{code, message}` in StructuredContent so agents can retry on `CONFLICT`, `NOT_FOUND`, `PATCH_FAILED`, `PATCH_REPLACE_NOT_APPLIED`, `PATCH_DROPPED_CONTENT`, `PATCH_PRODUCES_INVALID_GO`, etc. without string-matching.\n\nSee [`USAGE.md`](USAGE.md) for the full parameter reference.\n\n---\n\n## Highlighted features\n\n### `symbol body=true context=file` — explore a 1000-line file in 4 calls\n\n`symbol` with `body=true` and `context=\"file\"` returns the full body of the target function **and** an outline of every sibling declaration in the same file — in one call.\n\n```\nsymbol(query=\"BookHandler.Create\", body=true, context=\"file\")\n```\n\nThis replaces what used to be: read the file, grep for the function, read again with offset, grep for related symbols. Measured on a 1000-line file: **4 calls instead of 15**.\n\nUse this as your first move when entering any unfamiliar file — you get the implementation you care about plus a map of everything around it.\n\n### `symbol file=… at_line=…` — resolve a build error to a declaration\n\nWhen `build_check` or a stack trace gives you `internal/foo/bar.go:142`, you don't need to look up the symbol name. Pass the line and `symbol` returns the outermost named declaration that spans it:\n\n```\nsymbol(file=\"internal/foo/bar.go\", at_line=142, body=true)\n```\n\nMutually exclusive with `query`/`pattern`. Saves the \"grep for the function around this line\" step entirely.\n\n### `execute_plan` — atomic multi-step refactors\n\nRefactoring a feature often means changing a struct, updating three methods, regenerating a mock, and wiring a new call. Doing this as 8 separate `Edit` operations is where agents drift the most.\n\n```yaml\nactions:\n  - action: update_struct\n    file: internal/catalog/domain/book.go\n    identifier: Book\n    content: |\n      type Book struct {\n          ID        BookID\n          Title     string\n          Status    BookStatus\n          CreatedAt time.Time\n      }\n  - action: update_func\n    file: internal/catalog/domain/book.go\n    identifier: NewBook\n    content: |\n      func NewBook(title string, status BookStatus) (*Book, error) {\n          return \u0026Book{ID: NewBookID(), Title: title, Status: status}, nil\n      }\n  - action: update_interface\n    file: internal/catalog/domain/repositories/book/book.go\n    identifier: BookRepository\n    mock_file: internal/catalog/domain/repositories/book/booktest/mock.go\n    mock_name: MockBookRepository\n    content: |\n      type BookRepository interface {\n          Create(ctx context.Context, book domain.Book) error\n          UpdateStatus(ctx context.Context, id BookID, status BookStatus) error\n      }\n  - action: insert_call\n    file: internal/catalog/app/init.go\n    identifier: NewApp\n    content: handlers.RegisterBookStatusHandler(mux, repo)\n    position: before-return\n```\n\nOne tool call. One success or one rollback. No drift between steps. Every individual `patch_*` action type is also accepted, so atomic multi-step plans can mix in-place patches with whole-declaration replacements.\n\n### `patch` — one tool, five targets, surgical edits\n\nClassic AST edit tools make you resend the whole declaration to change one line. The unified `patch` tool applies scoped, text-match-or-line-targeted edits to a single function body, struct, interface, whole file, or const/var — all atomic, all `goimports`-aware, all optionally previewable as a diff.\n\n**Target a function body:**\n\n```\npatch(\n  target=\"function\",\n  file=\"internal/catalog/app/commands/book_handler.go\",\n  identifier=\"BookHandler.Create\",\n  patches=[\n    {op: \"replace\", match: \"return err\", replace: \"return fmt.Errorf(\\\"create book: %w\\\", err)\"},\n  ],\n)\n```\n\nLine targeting (`at_line`, `from_line`/`to_line`) is preferred when you have line numbers from a build error or stack trace — faster and unambiguous. Text matching (`match`, `match_regex`) is the fallback. Use `occurrence=-1` to apply a patch to every match instead of just the first.\n\n**Rewrite a function's signature without touching its body:**\n\n```\npatch(\n  target=\"function\",\n  file=\"internal/catalog/app/commands/book_handler.go\",\n  identifier=\"BookHandler.Create\",\n  patches=[\n    {op: \"set_signature\",\n     params: [\"ctx context.Context\", \"input CreateBookInput\"],\n     returns: \"(*Book, error)\"},\n  ],\n)\n```\n\n**Target a struct's field list:**\n\n```\npatch(\n  target=\"struct\",\n  file=\"internal/catalog/domain/user.go\",\n  identifier=\"User\",\n  patches=[\n    {op: \"add_field\", name: \"Email\", type: \"string\", tag: \"json:\\\"email\\\"\"},\n    {op: \"rename_field\", from: \"Name\", to: \"DisplayName\"},\n    {op: \"remove_field\", name: \"LegacyID\"},\n  ],\n)\n```\n\n**Target an interface's method list (with automatic mock regeneration):**\n\n```\npatch(\n  target=\"interface\",\n  file=\"internal/catalog/domain/repositories/book/book.go\",\n  identifier=\"BookRepository\",\n  mock_file=\"internal/catalog/domain/repositories/book/booktest/mock.go\",\n  mock_name=\"MockBookRepository\",\n  patches=[\n    {op: \"add_method\", signature: \"Archive(ctx context.Context, id BookID) error\"},\n  ],\n)\n```\n\nOther targets: `file` for cross-function batch substitutions, `decl` for const/var values. See [`USAGE.md`](USAGE.md) for the full operation catalog per target.\n\n### `patch_*_bulk` — fan one refactor across many declarations atomically\n\nWhen the same shape of change has to land on dozens of structs or functions (e.g. add a `CreatedAt` field everywhere, or wrap every `return err` in a domain package), `patch_struct_bulk` and `patch_function_bulk` accept a list of `{file, identifier, patches}` items and apply all of them in one transaction. If any one item fails, nothing is written.\n\n### `rename_symbol` — type-aware rename across the module\n\nRenaming a symbol with `sed` or generic Edit is how you rename the wrong thing: same-named identifiers in other packages, shadowing variables, method receivers that happen to share the name. `rename_symbol` resolves the target via `go/packages` and rewrites only the identifiers that bind to the same `types.Object`.\n\n```\nrename_symbol(name=\"BookRepo\", new_name=\"BookRepository\")\nrename_symbol(name=\"Handle\", new_name=\"Serve\", receiver=\"BookHandler\")\nrename_symbol(name=\"Config\", new_name=\"Settings\", preview=true)\n```\n\nRefuses export-status flips and in-scope name collisions. `find_references` (same resolver) lets you preview impact without touching files; set `include_definition=true` to see the declaration alongside the uses.\n\n### `build_check` / `test_run` — verify in-loop, scoped to what changed\n\nAfter an edit, run the compiler or the tests directly without leaving the agent loop:\n\n```\nbuild_check(affected_by=\"internal/catalog/domain/book.go\", tests=true)\ntest_run(symbols=[\"catalog.NewBook\", \"catalog.Book.Validate\"], verbosity=\"summary\")\n```\n\n`affected_by=\u003cfile\u003e` narrows the build/test to the file's owning package plus its in-module reverse-dep closure — orders of magnitude faster than `./...` on a monorepo. `test_run` additionally accepts `symbols=[\"pkg.Func\", ...]`: it resolves the owning packages and synthesizes a `-run ^(TestFunc|...)$` filter for you. `verbosity=\"summary\"` keeps the structured payload around 1KB even on huge suites; `auto` (default) flips to summary past 50 tests.\n\n### `module=` — read third-party code the right way\n\nInstead of your agent shelling into `$GOMODCACHE` with `find` and `cat`:\n\n```\noverview(module=\"github.com/spf13/cobra\", symbols=true)\nsymbol(query=\"Command.Execute\", body=true, module=\"github.com/spf13/cobra\")\nfind_references(name=\"Execute\", receiver=\"Command\", module=\"github.com/spf13/cobra\")\n```\n\nResolved via `go/packages`. Same output format as your own project. Works for stdlib, third-party, and project-local interfaces alike.\n\n---\n\n## CLI\n\nEverything the MCP server exposes is also available from the CLI — useful for scripting, CI, and quick exploration:\n\n```bash\n# Orient yourself\ngo-surgeon graph --symbols --dir internal/catalog/domain\n\n# Read a symbol\ngo-surgeon symbol BookHandler.Handle --body\n\n# Find every reference to a symbol, type-aware\ngo-surgeon find-references BookRepository --include-definition\n\n# Rename a symbol and every reference across the module\ngo-surgeon rename-symbol BookRepo BookRepository --preview\n\n# Edit a function (stdin = raw Go, no package/imports)\ncat \u003c\u003c'EOF' | go-surgeon update-func --file internal/catalog/domain/book.go --id NewBook\nfunc NewBook(title, author string) (*Book, error) {\n    return \u0026Book{Title: title, Author: author}, nil\n}\nEOF\n\n# Generate stubs for an interface you don't own\ngo-surgeon implement io.ReadCloser --receiver \"*MyReader\" --file internal/pkg/reader.go\n\n# Self-update to the latest release\ngo-surgeon upgrade\n```\n\nPass `--dry-run` on any command to preview changes as a unified diff without writing to disk.\n\n\u003e The granular `patch` family (in-place edits to function/struct/interface/file/decl) is **MCP-only** for now. The CLI exposes the whole-declaration `update-func` / `update-struct` / `update-interface` commands instead.\n\nSee [`USAGE.md`](USAGE.md) for the full CLI reference.\n\n---\n\n## 🔒 Safety\n\n\u003e ⚠️ **Edits modify your source code directly.** Use `--dry-run` (CLI) or `preview=true` (MCP `patch` and other write tools) to see the unified diff before applying.\n\n- **`--dry-run` / `--diff`** (CLI) prints the unified diff for every change without writing to disk\n- **`preview=true`** (MCP `patch` and other write tools) returns the diff without writing\n- **Atomic operations** — each edit either fully succeeds or returns a structured error; `patch` aborts the whole batch on any single failure\n- **Brace and body guards** — `patch` on `function` rejects edits with unbalanced braces or that would erase the entire function body, with hints pointing at the correct syntax\n- **Post-splice validation** — `patch` on `function`/`file` re-parses the result and refuses replacements whose substring went missing or that silently dropped declarations (`PATCH_REPLACE_NOT_APPLIED`, `PATCH_DROPPED_CONTENT`); the file is left untouched\n- **No silent fallbacks** — failed lookups produce explicit errors with hints (`Hint: use 'go-surgeon symbol X' to locate it`)\n- **Mocks stay in sync** — `delete_interface` with `delete_mock=true` also removes the mock struct, its methods, and the compile-time assertion. Without it, the broken assertion forces explicit cleanup by design\n\n**Performance note:** each MCP call adds ~200–500 ms overhead compared to a direct file edit. This cost is amortized when you're doing structural work (imports, renames, multi-step edits). For a single short tweak in a file you already know, a direct Edit is faster. See [When go-surgeon helps vs. when Edit is fine](#when-go-surgeon-helps-vs-when-edit-is-fine).\n\n---\n\n## Works well with scaffor\n\nSame philosophy, different scope:\n\n- **[scaffor](https://github.com/JLugagne/scaffor)** — deterministic scaffolding. Generate the file structure of a new feature.\n- **go-surgeon** — deterministic editing. Modify the code that already exists.\n\nUse scaffor to bootstrap, go-surgeon to evolve. Both ship as MCP servers.\n\n---\n\n## Installation\n\n```bash\n# curl installer (Linux / macOS) — recommended\ncurl -fsSL https://raw.githubusercontent.com/JLugagne/go-surgeon/main/install.sh | sh\n\n# Build from source\ngit clone https://github.com/JLugagne/go-surgeon.git\ncd go-surgeon \u0026\u0026 go build -o go-surgeon ./cmd/go-surgeon\n\n# Self-update an existing install\ngo-surgeon upgrade\n\n# Shell completion\ngo-surgeon completion bash \u003e /etc/bash_completion.d/go-surgeon\ngo-surgeon completion zsh  \u003e \"${fpath[1]}/_go-surgeon\"\n```\n\n---\n\n## Going further\n\n- [`USAGE.md`](USAGE.md) — full command reference for MCP and CLI\n- [`AI_INSTRUCTIONS.md`](AI_INSTRUCTIONS.md) — drop-in instructions for Cursor / Claude / Copilot system prompts\n\n---\n\n\u003cdiv align=\"center\"\u003e\n\n[MIT License](LICENSE) · Feedback and contributions welcome\n\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjlugagne%2Fgo-surgeon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjlugagne%2Fgo-surgeon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjlugagne%2Fgo-surgeon/lists"}