{"id":"aad131d6-adec-4a46-9384-ee6c039f76ae","entityType":"agent","slug":"clawhub-samber-golang-google-wire","name":"golang-google-wire","canonicalUrl":"https://www.xpersona.co/agent/clawhub-samber-golang-google-wire","canonicalPath":"/agent/clawhub-samber-golang-google-wire","generatedAt":"2026-10-11T07:41:13.319Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T04:37:47.996Z","emptyReason":null},"description":"Compile-time dependency injection in Golang using google/wire — wire.NewSet, wire.Build, wire.Bind (interface→concrete), wire.Struct, wire.Value, wire.InterfaceValue, wire.FieldsOf, cleanup functions, //go:build wireinject injector files, and generated wire_gen.go. Apply when using or adopting google/wire, when the codebase imports `github.com/google/wire`, or when wiring an application graph at compile time via `wire.Build`. For runtime DI with reflection, see `samber/cc-skills-golang@golang-uber-dig` skill.","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.2K downloads reported by the source. Last updated 10/11/2026.","installCommand":"clawhub skill install s173arkhs3131fq5jf769qq75583hdgt:golang-google-wire","sourceUrl":"https://clawhub.ai/samber/golang-google-wire","homepage":"https://clawhub.ai/samber/skills/golang-google-wire","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/samber/golang-google-wire","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/samber/skills/golang-google-wire","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":61,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"golang-google-wire technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-11T04:37:47.996Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T04:37:47.996Z","emptyReason":null},"stars":null,"forks":null,"downloads":1157,"packageName":null,"latestVersion":"1.1.0","tractionLabel":"1.2K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T04:37:47.922Z","emptyReason":null},"lastUpdatedAt":"2026-10-11T04:37:47.996Z","lastCrawledAt":"2026-10-11T04:37:47.922Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-12T04:37:47.922Z","lastVerifiedAt":null,"highlights":[{"version":"1.1.0","createdAt":"2026-08-21T02:42:39.519Z","changelog":"golang-google-wire 1.1.0 - Added support for new harnesses and tooling (Codex, gopls, godig). - Expanded documentation with pointers to `pkg.go.dev` and related skills for Go package details and code navigation. - Updated compatibility and metadata, including new `paths` and allowed tools (e.g., Bash(godig:*), Bash(gopls:*), LSP). - Removed legacy `skill-card.md`, streamlining documentation. - Improved guidance on how to prefer skills for code analysis and navigation.","fileCount":7,"zipByteSize":18930},{"version":"1.0.3","createdAt":"2026-06-10T14:19:28.181Z","changelog":"golang-google-wire 1.0.3 - Bumped version to 1.0.3 in metadata. - Added explicit \"Dependencies\" section for wire installation in documentation. - Minor wording improvements and clarified formatting in SKILL.md. - Removed outdated file: skill-card.md.","fileCount":7,"zipByteSize":18779},{"version":"1.0.2","createdAt":"2026-05-22T15:58:01.888Z","changelog":"- Update metadata version to 1.0.2. - Change install instructions to use go get -tool github.com/google/wire/cmd/wire@latest (was go install). - Minor wording and formatting tweaks for accuracy and consistency. - No functional changes to the skill logic.","fileCount":7,"zipByteSize":18614},{"version":"1.0.0","createdAt":"2026-05-02T15:42:47.754Z","changelog":"Initial release: compile-time dependency injection skill for Go using google/wire. - Explains core google/wire concepts: providers, provider sets, injectors, build tags, explicit interface bindings, struct/value providers, and codegen workflow. - Includes comparison table (Wire vs. runtime DI containers). - Covers usage of wire.NewSet, wire.Build, wire.Bind, wire.Struct, wire.Value, wire.InterfaceValue, and wire.FieldsOf. - Documents best practices for maintaining provider sets, injector files, and generated code. - Provides usage examples and links to official resources. - Notes archive status of google/wire (August 2025) and alternatives for runtime DI.","fileCount":6,"zipByteSize":17368}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s173arkhs3131fq5jf769qq75583hdgt:golang-google-wire","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s173arkhs3131fq5jf769qq75583hdgt:golang-google-wire` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/samber/golang-google-wire before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-google-wire/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-google-wire/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-google-wire/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-google-wire/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-google-wire/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-google-wire/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-11T07:41:13.316Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-google-wire/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-google-wire/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-google-wire/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-samber-golang-google-wire/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T04:37:47.996Z","emptyReason":null},"readme":"Skill: golang-google-wire\n\nOwner: samber\n\nSummary: Compile-time dependency injection in Golang using google/wire — wire.NewSet, wire.Build, wire.Bind (interface→concrete), wire.Struct, wire.Value, wire.InterfaceValue, wire.FieldsOf, cleanup functions, //go:build wireinject injector files, and generated wire_gen.go. Apply when using or adopting google/wire, when the codebase imports `github.com/google/wire`, or when wiring an application graph at compile time via `wire.Build`. For runtime DI with reflection, see `samber/cc-skills-golang@golang-uber-dig` skill.\n\nTags: latest:1.1.0\n\nVersion history:\n\nv1.1.0 | 2026-08-21T02:42:39.519Z | auto\n\ngolang-google-wire 1.1.0\n\n- Added support for new harnesses and tooling (Codex, gopls, godig).\n- Expanded documentation with pointers to `pkg.go.dev` and related skills for Go package details and code navigation.\n- Updated compatibility and metadata, including new `paths` and allowed tools (e.g., Bash(godig:*), Bash(gopls:*), LSP).\n- Removed legacy `skill-card.md`, streamlining documentation.\n- Improved guidance on how to prefer skills for code analysis and navigation.\n\nv1.0.3 | 2026-06-10T14:19:28.181Z | auto\n\ngolang-google-wire 1.0.3\n\n- Bumped version to 1.0.3 in metadata.\n- Added explicit \"Dependencies\" section for wire installation in documentation.\n- Minor wording improvements and clarified formatting in SKILL.md.\n- Removed outdated file: skill-card.md.\n\nv1.0.2 | 2026-05-22T15:58:01.888Z | auto\n\n- Update metadata version to 1.0.2.\n- Change install instructions to use go get -tool github.com/google/wire/cmd/wire@latest (was go install).\n- Minor wording and formatting tweaks for accuracy and consistency.\n- No functional changes to the skill logic.\n\nv1.0.0 | 2026-05-02T15:42:47.754Z | auto\n\nInitial release: compile-time dependency injection skill for Go using google/wire.\n\n- Explains core google/wire concepts: providers, provider sets, injectors, build tags, explicit interface bindings, struct/value providers, and codegen workflow.\n- Includes comparison table (Wire vs. runtime DI containers).\n- Covers usage of wire.NewSet, wire.Build, wire.Bind, wire.Struct, wire.Value, wire.InterfaceValue, and wire.FieldsOf.\n- Documents best practices for maintaining provider sets, injector files, and generated code.\n- Provides usage examples and links to official resources.\n- Notes archive status of google/wire (August 2025) and alternatives for runtime DI.\n\nArchive index:\n\nArchive v1.1.0: 7 files, 18930 bytes\n\nFiles: evals/evals.json (16019b), references/advanced.md (6966b), references/recipes.md (6718b), references/testing.md (5146b), skill-card.md (2521b), SKILL.md (11139b), _meta.json (137b)\n\nFile v1.1.0:SKILL.md\n\n---\nname: golang-google-wire\ndescription: \"Compile-time dependency injection in Golang using google/wire — wire.NewSet, wire.Build, wire.Bind (interface→concrete), wire.Struct, wire.Value, wire.InterfaceValue, wire.FieldsOf, cleanup functions, //go:build wireinject injector files, and generated wire_gen.go. Apply when using or adopting google/wire, when the codebase imports `github.com/google/wire`, or when wiring an application graph at compile time via `wire.Build`. For runtime DI with reflection, see `samber/cc-skills-golang@golang-uber-dig` skill.\"\nuser-invocable: true\nlicense: MIT\ncompatibility: Designed for Claude Code, Codex or similar harness, and for projects using Golang.\nmetadata:\n  author: samber\n  version: \"1.1.0\"\n  openclaw:\n    emoji: \"🪡\"\n    homepage: https://github.com/samber/cc-skills-golang\n    requires:\n      bins:\n        - go\n        - wire\n    install:\n      - kind: go\n        package: github.com/google/wire/cmd/wire@latest\n        bins: [wire]\n    skill-library-version: \"0.7.0\"\nallowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*) Bash(git:*) Agent WebFetch mcp__context7__resolve-library-id mcp__context7__query-docs Bash(wire:*) Bash(godig:*) Bash(gopls:*) LSP mcp__gopls__*\npaths:\n  - \"**/*.go\"\n---\n\n**Persona:** You are a Go architect using wire for compile-time DI. You let the compiler catch missing dependencies, treat `wire_gen.go` as committed source, and re-run `wire ./...` after every graph change.\n\n**Dependencies:**\n\n- wire: `go install github.com/google/wire/cmd/wire@latest`\n\n# Using google/wire for Compile-Time Dependency Injection in Go\n\nCode-generation DI toolkit. Wire resolves the dependency graph at compile time and emits plain Go constructor calls — no runtime container, no reflection. Errors appear when you run `wire ./...`, not at first request.\n\nNote: `google/wire` was archived in August 2025 (feature-complete; bug fixes still accepted).\n\n**Official Resources:** [pkg.go.dev](https://pkg.go.dev/github.com/google/wire) · [github.com/google/wire](https://github.com/google/wire) · [User Guide](https://github.com/google/wire/blob/main/docs/guide.md) · [Best Practices](https://github.com/google/wire/blob/main/docs/best-practices.md)\n\nThis skill is not exhaustive. Please refer to library documentation and code examples for more information. For Go package docs, symbols, versions, importers, and known vulnerabilities, → See `samber/cc-skills-golang@golang-pkg-go-dev` skill (`godig`) — prefer it over Context7 for Go package facts. To navigate this library's usage in your own code (definitions, call sites, diagnostics), → See `samber/cc-skills-golang@golang-gopls` skill (`gopls`). Context7 remains a fallback for docs not indexed on pkg.go.dev.\n\n```bash\ngo get -tool github.com/google/wire/cmd/wire@latest\ngo get github.com/google/wire\n```\n\n## wire vs. Runtime DI\n\n| Concern           | wire                      | dig / fx / samber/do   |\n| ----------------- | ------------------------- | ---------------------- |\n| Resolution        | Compile time (codegen)    | Runtime (reflection)   |\n| Error detection   | `wire ./...` fails        | First `Invoke`/startup |\n| Runtime container | None — plain Go calls     | Present                |\n| Lifecycle hooks   | Not built in              | fx: OnStart/OnStop     |\n| Generated files   | `wire_gen.go` (committed) | None                   |\n\nFor lifecycle, lazy loading, and a full matrix see `samber/cc-skills-golang@golang-dependency-injection`.\n\n## Providers\n\nA provider is any Go function — inputs are dependencies, outputs are provided types. Three return forms:\n\n```go\nfunc NewConfig() *Config                          { return &Config{Addr: \":8080\"} }\nfunc NewDB(cfg *Config) (*sql.DB, error)          { return sql.Open(\"postgres\", cfg.DSN) }\nfunc NewRedis(cfg *Config) (*redis.Client, func(), error) { // cleanup chained in reverse order\n    c := redis.NewClient(&redis.Options{Addr: cfg.RedisAddr})\n    return c, func() { c.Close() }, nil\n}\n```\n\n## Provider Sets\n\n`wire.NewSet` groups providers for reuse. Sets can reference other sets.\n\n```go\n// infra/wire.go\nvar InfraSet = wire.NewSet(\n    NewConfig,\n    NewDB,\n    NewRedis,\n)\n\n// service/wire.go\nvar ServiceSet = wire.NewSet(\n    NewUserRepo,\n    NewUserService,\n    wire.Bind(new(UserStore), new(*UserRepo)), // interface binding\n)\n```\n\nKeep sets small: library sets expose a stable surface (adding inputs or removing outputs breaks downstream injectors). One set per package is a useful default.\n\n## Injectors and `//go:build wireinject`\n\nThe injector file declares the initialization function. Wire generates its body into `wire_gen.go` and replaces the stub.\n\n```go\n//go:build wireinject\n\npackage main\n\nimport \"github.com/google/wire\"\n\n// Wire generates the body of this function.\nfunc InitApp() (*App, func(), error) {\n    wire.Build(InfraSet, ServiceSet, NewApp)\n    return nil, nil, nil // replaced by codegen\n}\n```\n\nThe `//go:build wireinject` tag prevents the stub from being compiled into the binary — only `wire_gen.go` (which has no such tag) makes it through `go build`. Without this tag, both files define the same function, causing a compile error.\n\nAlternative syntax when a dummy return is inconvenient:\n\n```go\nfunc InitApp() (*App, func(), error) {\n    panic(wire.Build(InfraSet, ServiceSet, NewApp))\n}\n```\n\n## Interface Bindings\n\nWire forbids implicit interface satisfaction — you must declare bindings explicitly so the graph is unambiguous when multiple types implement the same interface.\n\n```go\nvar Set = wire.NewSet(\n    NewPostgresUserRepo,\n    wire.Bind(new(UserStore), new(*PostgresUserRepo)), // tell wire: *PostgresUserRepo satisfies UserStore\n)\n```\n\nExplicit bindings prevent graph breakage when a new type implementing the same interface is added elsewhere.\n\n## Struct Providers and Values\n\n`wire.Struct` fills struct fields from the graph without a manual constructor. Tag fields `wire:\"-\"` to exclude them.\n\n```go\nwire.Struct(new(Server), \"Logger\", \"DB\") // inject named fields\nwire.Struct(new(Server), \"*\")            // inject all non-excluded fields\nwire.Value(Foo{X: 42})                   // constant expression (no fn calls / channels)\nwire.InterfaceValue(new(io.Reader), os.Stdin) // interface-typed literal\nwire.FieldsOf(new(Config), \"DSN\", \"Addr\")    // promote struct fields as graph nodes\n```\n\nSee [advanced.md](references/advanced.md) for the `wire:\"-\"` exclusion tag and `wire.FieldsOf` details.\n\n## Disambiguating Duplicate Types\n\nWire forbids two providers for the same type. Wrap the underlying type in distinct named types so each has exactly one provider:\n\n```go\ntype PrimaryDSN string\ntype ReplicaDSN string\n```\n\n## Full Application Example\n\n```go\n// wire.go — injector, excluded from binary via build tag\n//go:build wireinject\n\npackage main\n\nfunc InitApp() (*App, func(), error) {\n    wire.Build(config.ConfigSet, infra.InfraSet, service.ServiceSet, NewApp)\n    return nil, nil, nil\n}\n\n// main.go\nfunc main() {\n    app, cleanup, err := InitApp()\n    if err != nil { log.Fatal(err) }\n    defer cleanup()\n    app.Run()\n}\n```\n\nWire generates `wire_gen.go` (plain Go, committed, DO NOT EDIT). For a full example with per-package sets, cleanup-heavy graphs, and generated output, see [recipes.md](references/recipes.md).\n\n## Codegen Workflow\n\n```bash\nwire ./...           # regenerate all injectors in the module\nwire check ./...     # validate graph without regenerating (fast CI check)\n```\n\nRun `wire ./...` after every constructor signature change. Add `//go:generate go run github.com/google/wire/cmd/wire` to injector files so `go generate ./...` also works. Commit `wire_gen.go` — it must stay in sync for CI builds.\n\n## Best Practices\n\n1. Never edit `wire_gen.go` — it is overwritten on every `wire ./...` run. Treat it as a build artifact that happens to be committed; source of truth is the provider and injector files.\n2. Always add `//go:build wireinject` to injector files — omitting it causes duplicate-symbol compile errors because both the stub and the generated file define the same function.\n3. Use named types to distinguish values of the same underlying type — wire enforces one provider per type; named types like `type DSN string` let you have `PrimaryDSN` and `ReplicaDSN` coexist.\n4. Keep library provider sets minimal and backward-compatible — adding new required inputs breaks downstream injectors; removing outputs does too. Introduce only newly-created types in the same release.\n5. Return `(T, func(), error)` from cleanup providers and let wire chain them — wire generates the correct reverse-order cleanup and handles partial failures (if construction fails midway, only already-built cleanups run).\n6. Keep injector files focused — one function per file, one package import at a time. Fat injectors with dozens of `wire.Build` arguments are hard to reason about; delegate to per-package sets.\n\n## Common Mistakes\n\n| Mistake | Fix |\n| --- | --- |\n| Editing `wire_gen.go` manually | Never edit it. Change providers or injectors and re-run `wire ./...`. |\n| Missing `//go:build wireinject` | Add the tag as the very first line of every injector file. |\n| Two providers returning `*sql.DB` | Wrap with a named struct type: `type PrimaryDB struct { *sql.DB }` — Wire does not distinguish pointer type aliases. |\n| Injecting an interface without `wire.Bind` | Add `wire.Bind(new(MyInterface), new(*MyImpl))` to the provider set. |\n| Forgetting to re-run `wire ./...` after changes | Run wire before `go build`; add it to `go generate` or a Makefile target. |\n| Calling `cleanup()` without guarding for nil | Wire returns nil cleanup on construction error; guard with `if cleanup != nil { defer cleanup() }`. |\n\n## Testing\n\nWire generates plain Go constructors, so unit tests use manual injection — no container to clone or reset. For testing patterns (test injectors swapping real providers for fakes, CI stale-check for `wire_gen.go`), see [testing.md](references/testing.md).\n\n## Further Reading\n\n- [advanced.md](references/advanced.md) — cleanup chains, multiple injectors, set nesting, error catalogue, codegen flags, quick reference\n- [recipes.md](references/recipes.md) — HTTP server, multi-injector build, cleanup-heavy graph, CLI embedding\n- [testing.md](references/testing.md) — test injectors, fake bindings, CI stale check\n\n## Cross-References\n\n- → See `samber/cc-skills-golang@golang-dependency-injection` skill for DI concepts and library comparison\n- → See `samber/cc-skills-golang@golang-uber-dig` skill for runtime reflection-based DI without lifecycle\n- → See `samber/cc-skills-golang@golang-uber-fx` skill for runtime DI with lifecycle hooks, modules, and signal-aware Run()\n- → See `samber/cc-skills-golang@golang-samber-do` skill for generics-based DI without reflection\n- → See `samber/cc-skills-golang@golang-structs-interfaces` skill for interface design patterns\n- → See `samber/cc-skills-golang@golang-testing` skill for general testing patterns\n\nIf you encounter a bug or unexpected behavior in google/wire, open an issue at <https://github.com/google/wire/issues>.\n\nFile v1.1.0:_meta.json\n\n{\n  \"ownerId\": \"kn72rhnkwjfeex9wr1n7y24qa983cjn3\",\n  \"slug\": \"golang-google-wire\",\n  \"version\": \"1.1.0\",\n  \"publishedAt\": 1787280159519\n}\n\nFile v1.1.0:references/advanced.md\n\n# Advanced — google/wire\n\nDetail topics referenced from `SKILL.md`. Each section is self-contained.\n\n## Cleanup Chains\n\nWhen a provider returns `(T, func(), error)`, Wire adds the cleanup to a chain. The generated injector runs cleanups in **reverse construction order**: the last-built dependant is cleaned up first, ensuring dependants are torn down before their dependencies.\n\n```go\n// Provider with cleanup\nfunc NewDB(cfg *Config) (*sql.DB, func(), error) {\n    db, err := sql.Open(\"postgres\", string(cfg.DSN))\n    if err != nil { return nil, nil, err }\n    return db, func() { db.Close() }, nil\n}\n\nfunc NewCache(cfg *Config) (*redis.Client, func(), error) {\n    c := redis.NewClient(&redis.Options{Addr: cfg.CacheAddr})\n    return c, func() { c.Close() }, nil\n}\n```\n\nWire generates something like:\n\n```go\nfunc InitApp() (*App, func(), error) {\n    cfg := NewConfig()\n    db, dbCleanup, err := NewDB(cfg)\n    if err != nil { return nil, nil, err }\n    cache, cacheCleanup, err := NewCache(cfg)\n    if err != nil {\n        dbCleanup()  // already-built cleanups run on partial failure\n        return nil, nil, err\n    }\n    app := NewApp(db, cache)\n    return app, func() {\n        cacheCleanup()  // reverse order\n        dbCleanup()\n    }, nil\n}\n```\n\n**Caller pattern** — guard against nil cleanup on construction failure:\n\n```go\napp, cleanup, err := InitApp()\nif err != nil { log.Fatal(err) }\ndefer cleanup()\n```\n\nWire always returns a non-nil cleanup function when construction succeeds. If construction fails midway, the returned `cleanup` is nil — guard before calling.\n\n## Multiple Injectors in One Package\n\nA package can contain multiple injector functions. Each must live in a file with `//go:build wireinject`. All generated functions land in `wire_gen.go` in the same package.\n\n```go\n//go:build wireinject\n\npackage main\n\n// Production injector\nfunc InitProdApp() (*App, func(), error) {\n    wire.Build(ProdSet, NewApp)\n    return nil, nil, nil\n}\n\n// Development injector with debug providers\nfunc InitDevApp() (*App, func(), error) {\n    wire.Build(DevSet, NewApp)\n    return nil, nil, nil\n}\n```\n\nSelect at runtime with a flag, or at build time with separate `//go:build prod` / `//go:build !prod` constraints on the injector files.\n\n## wire.NewSet Nesting Strategies\n\nSets can contain other sets, building a hierarchy that mirrors your package structure.\n\n```go\n// pkg/config/wire.go\nvar ConfigSet = wire.NewSet(NewConfig)\n\n// pkg/infra/wire.go\nvar InfraSet = wire.NewSet(\n    config.ConfigSet, // embed upstream set\n    NewDB,\n    NewCache,\n)\n\n// pkg/service/wire.go\nvar ServiceSet = wire.NewSet(\n    NewUserService,\n    wire.Bind(new(UserStore), new(*UserRepo)),\n)\n\n// wire.go (injector)\nwire.Build(infra.InfraSet, service.ServiceSet, NewApp)\n```\n\n**Library set stability rules** (from upstream best practices):\n\n- Safe: replace one provider with another that has the same or fewer inputs, in the same release.\n- Safe: introduce a brand-new output type not previously provided.\n- Breaking: add a new required input to a provider — downstream injectors cannot satisfy it.\n- Breaking: remove a provided output type — downstream injectors that depend on it fail.\n- Breaking: add a type that the injector already provides — Wire reports a duplicate.\n\n## `wire:\"-\"` Exclusion Tag\n\nExclude a struct field from `wire.Struct` injection by tagging it:\n\n```go\ntype Server struct {\n    Logger  *zap.Logger\n    DB      *sql.DB\n    mu      sync.Mutex   `wire:\"-\"` // unexported — auto-excluded\n    Timeout time.Duration `wire:\"-\"` // exported but opt-out\n}\n\nwire.Struct(new(Server), \"*\") // injects Logger and DB; skips mu and Timeout\n```\n\nUnexported fields are always skipped regardless of the tag.\n\n## Common Codegen Errors\n\n| Error message | Root cause | Fix |\n| --- | --- | --- |\n| `no provider found for TYPE` | A dependency is not provided by any set in `wire.Build` | Add the missing provider or set |\n| `multiple bindings for TYPE` | Two providers return the same type | Use named types or remove the duplicate |\n| `argument N has no provider for TYPE` | An interface is requested but no `wire.Bind` maps to it | Add `wire.Bind(new(Iface), new(*Impl))` to a set |\n| `cycle detected` | A → B → A circular dependency | Break the cycle by introducing an interface or factory |\n| `wire.Build used outside of injector function` | `wire.Build` called from a non-injector function | Only call `wire.Build` inside functions with the build tag |\n| duplicate symbol / redeclared in this block | Injector file is missing `//go:build wireinject` | Add the build tag as the first line |\n\n## Codegen Flags\n\n```bash\n# Specify output file prefix (default: wire_gen)\nwire -output_file_prefix=init gen ./cmd/server\n\n# Apply build tags during generation\nwire -tags=integration gen ./...\n\n# Prepend a header file (e.g., license comment) to generated output\nwire -header_file=hack/boilerplate.go.txt gen ./...\n```\n\n## `panic(wire.Build(...))` Alternate Syntax\n\nWire accepts either a dummy return or a `panic` call as the injector body. The `panic` form avoids writing zero-value returns for complex types:\n\n```go\n// Preferred when return types are complex or error-prone to zero-initialize\nfunc InitApp(ctx context.Context) (*App, func(), error) {\n    panic(wire.Build(AppSet))\n}\n```\n\nWire detects both forms and replaces the body during codegen. The `panic` is never reached in the compiled binary — only the generated `wire_gen.go` version is compiled.\n\n## Accepting External Values as Injector Arguments\n\nWhen a value is constructed before wire runs (e.g., parsed flags, an `http.Client` from a test), pass it as a parameter to the injector rather than providing it from within the graph:\n\n```go\n//go:build wireinject\n\nfunc InitApp(cfg *Config) (*App, func(), error) {\n    wire.Build(InfraSet, ServiceSet, NewApp)\n    return nil, nil, nil\n}\n\n// main.go\ncfg := parseFlags()\napp, cleanup, err := InitApp(cfg)\n```\n\nWire treats injector parameters as pre-built providers — they satisfy dependencies without needing a `wire.NewSet` entry.\n\n## Quick Reference\n\n| Symbol | Purpose |\n| --- | --- |\n| `wire.NewSet(providers...)` | Group providers into a reusable set |\n| `wire.Build(sets...)` | Declare injector body (codegen replaces it) |\n| `wire.Bind(new(Iface), new(*Concrete))` | Bind interface to concrete type |\n| `wire.Struct(new(T), \"Field\", ...)` | Inject struct fields from the graph |\n| `wire.Struct(new(T), \"*\")` | Inject all non-excluded fields |\n| `wire.Value(expr)` | Bind a constant expression (no fn calls/channels) |\n| `wire.InterfaceValue(new(I), value)` | Bind a value to an interface type |\n| `wire.FieldsOf(new(T), \"Field\", ...)` | Promote struct fields as individual graph nodes |\n| `//go:build wireinject` | Build tag: exclude injector stub from binary |\n| `wire_gen.go` | Generated output — commit, never edit |\n| `wire ./...` | Regenerate all injectors in the module |\n| `wire check ./...` | Validate graph without regenerating |\n\nFile v1.1.0:references/recipes.md\n\n# Recipes — google/wire\n\nEnd-to-end examples. Each recipe is self-contained.\n\n## HTTP Server with Postgres and Redis\n\nA typical service: parsed config → DB (with cleanup) → Redis (with cleanup) → repo → service → HTTP server.\n\n```\nmyapp/\n├── config/\n│   ├── config.go\n│   └── wire.go\n├── infra/\n│   ├── db.go\n│   ├── cache.go\n│   └── wire.go\n├── repo/\n│   ├── user.go\n│   └── wire.go\n├── service/\n│   ├── user.go\n│   └── wire.go\n├── transport/\n│   ├── handler.go\n│   └── wire.go\n├── wire.go        // injector — //go:build wireinject\n├── wire_gen.go    // generated — commit this\n└── main.go\n```\n\n```go\n// config/config.go\ntype Config struct {\n    Addr      string\n    DSN       string\n    CacheAddr string\n}\n\nfunc NewConfig() *Config {\n    return &Config{\n        Addr:      env(\"ADDR\", \":8080\"),\n        DSN:       mustEnv(\"DATABASE_URL\"),\n        CacheAddr: env(\"REDIS_ADDR\", \"localhost:6379\"),\n    }\n}\n\n// config/wire.go\nvar ConfigSet = wire.NewSet(NewConfig)\n```\n\n```go\n// infra/db.go\nfunc NewDB(cfg *config.Config) (*sql.DB, func(), error) {\n    db, err := sql.Open(\"postgres\", cfg.DSN)\n    if err != nil { return nil, nil, err }\n    if err := db.Ping(); err != nil { db.Close(); return nil, nil, err }\n    return db, func() { db.Close() }, nil\n}\n\n// infra/cache.go\nfunc NewRedis(cfg *config.Config) (*redis.Client, func(), error) {\n    c := redis.NewClient(&redis.Options{Addr: cfg.CacheAddr})\n    if err := c.Ping(context.Background()).Err(); err != nil {\n        return nil, nil, err\n    }\n    return c, func() { c.Close() }, nil\n}\n\n// infra/wire.go\nvar InfraSet = wire.NewSet(NewDB, NewRedis)\n```\n\n```go\n// repo/user.go\ntype UserStore interface {\n    GetUser(ctx context.Context, id int64) (*User, error)\n}\n\ntype PostgresUserRepo struct{ db *sql.DB }\n\nfunc NewUserRepo(db *sql.DB) *PostgresUserRepo { return &PostgresUserRepo{db: db} }\n\n// repo/wire.go\nvar RepoSet = wire.NewSet(\n    NewUserRepo,\n    wire.Bind(new(UserStore), new(*PostgresUserRepo)),\n)\n```\n\n```go\n// service/user.go\ntype UserService struct {\n    store  repo.UserStore\n    cache  *redis.Client\n}\n\nfunc NewUserService(store repo.UserStore, cache *redis.Client) *UserService {\n    return &UserService{store: store, cache: cache}\n}\n\n// service/wire.go\nvar ServiceSet = wire.NewSet(NewUserService)\n```\n\n```go\n// wire.go\n//go:build wireinject\n\npackage main\n\nfunc InitApp() (*transport.Handler, func(), error) {\n    wire.Build(\n        config.ConfigSet,\n        infra.InfraSet,\n        repo.RepoSet,\n        service.ServiceSet,\n        transport.NewHandler,\n    )\n    return nil, nil, nil\n}\n```\n\n```go\n// main.go\nfunc main() {\n    handler, cleanup, err := InitApp()\n    if err != nil { log.Fatal(err) }\n    defer cleanup()\n\n    srv := &http.Server{Addr: \":8080\", Handler: handler}\n    log.Fatal(srv.ListenAndServe())\n}\n```\n\n## Multiple Build Variants (Prod vs Dev)\n\nUse separate injector files with `//go:build` constraints to select different provider sets at build time.\n\n```go\n// wire_prod.go\n//go:build wireinject && !dev\n\npackage main\n\nfunc InitApp() (*App, func(), error) {\n    wire.Build(ProdSet, NewApp)\n    return nil, nil, nil\n}\n\n// wire_dev.go\n//go:build wireinject && dev\n\npackage main\n\nfunc InitApp() (*App, func(), error) {\n    wire.Build(DevSet, NewApp) // DevSet swaps real DB for in-memory SQLite\n    return nil, nil, nil\n}\n```\n\nUse `-output_file_prefix` to write separate output files — both commands would otherwise overwrite the same `wire_gen.go`:\n\n```bash\nwire -tags dev -output_file_prefix=wire_gen_dev gen .\nwire -output_file_prefix=wire_gen_prod gen .\n```\n\nAdd build constraints to the generated files so only one compiles per build:\n\n```go\n// wire_gen_prod.go — add at the top (after wire writes it)\n//go:build !dev\n\n// wire_gen_dev.go — add at the top\n//go:build dev\n```\n\nCommit both generated files. At build time, only the matching file is compiled.\n\n## Cleanup-Heavy Graph\n\nWhen several providers need shutdown coordination, wire's reverse-order cleanup is essential.\n\n```go\n// Providers return (T, func(), error)\nfunc NewDBPool(cfg *Config) (*pgxpool.Pool, func(), error) {\n    pool, err := pgxpool.New(context.Background(), cfg.DSN)\n    if err != nil { return nil, nil, err }\n    return pool, func() { pool.Close() }, nil\n}\n\nfunc NewOTelExporter(cfg *Config) (*otlptrace.Exporter, func(), error) {\n    exp, err := otlptracegrpc.New(context.Background(), ...)\n    if err != nil { return nil, nil, err }\n    return exp, func() { exp.Shutdown(context.Background()) }, nil\n}\n\nfunc NewTracerProvider(exp *otlptrace.Exporter) (*trace.TracerProvider, func(), error) {\n    tp := trace.NewTracerProvider(trace.WithBatcher(exp))\n    return tp, func() { tp.Shutdown(context.Background()) }, nil\n}\n```\n\nWire generates shutdown in reverse: `TracerProvider` → `OTelExporter` → `DBPool`. Each cleanup runs before its dependencies shut down — guaranteeing in-flight spans are flushed before the exporter closes.\n\n## Embedding Wire in a CLI\n\nWire produces a struct, not an app framework. You control the lifecycle:\n\n```go\n// wire.go\n//go:build wireinject\n\npackage cmd\n\nfunc InitServer(cfg *Config) (*http.Server, func(), error) {\n    wire.Build(InfraSet, ServiceSet, NewHTTPServer)\n    return nil, nil, nil\n}\n\n// cmd/serve.go\nfunc runServe(cfg *Config) error {\n    srv, cleanup, err := InitServer(cfg)\n    if err != nil { return err }\n    defer cleanup()\n\n    quit := make(chan os.Signal, 1)\n    signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)\n\n    go func() {\n        if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {\n            log.Fatal(err)\n        }\n    }()\n    <-quit\n    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)\n    defer cancel()\n    return srv.Shutdown(ctx)\n}\n```\n\nUnlike `fx.Run()`, wire does not manage the lifecycle loop. Implement signal handling and graceful shutdown explicitly. This is a feature for CLI tools that spin up short-lived services and need precise control over the shutdown sequence.\n\n## Passing External Values to Wire\n\nValues built before wire runs (parsed config, test doubles) become injector parameters:\n\n```go\n//go:build wireinject\n\n// cfg is resolved outside the graph — treated as a provided *Config\nfunc InitApp(cfg *Config) (*App, func(), error) {\n    wire.Build(InfraSet, ServiceSet, NewApp)\n    return nil, nil, nil\n}\n\n// main.go\ncfg, err := config.Load()\nif err != nil { log.Fatal(err) }\napp, cleanup, err := InitApp(cfg)\n```\n\nThe parameter `cfg *Config` satisfies any downstream provider that requests `*Config` — no `wire.Value` or extra set entry needed.\n\nFile v1.1.0:references/testing.md\n\n# Testing — google/wire\n\nWire generates plain Go constructor calls, so tests work directly on the constructor layer — no container API to learn.\n\n## Unit Tests: Plain Constructor Injection\n\nThe generated code has no wire dependency. Test constructors directly:\n\n```go\nfunc TestUserService_GetUser(t *testing.T) {\n    mockStore := &MockUserStore{users: map[int64]*User{1: &User{ID: 1, Name: \"Alice\"}}}\n    cache := newTestRedis(t)\n    svc := service.NewUserService(mockStore, cache)\n\n    u, err := svc.GetUser(context.Background(), 1)\n    require.NoError(t, err)\n    assert.Equal(t, \"Alice\", u.Name)\n}\n```\n\nPass mocks directly as constructor arguments. No wire, no container, no file to generate. This is the idiomatic approach for unit tests.\n\n## Test Injectors: Swapping Providers\n\nFor integration or component tests where you want the full wired graph but with selected dependencies replaced, create a test-only injector in a `_test.go` file.\n\n```go\n// app_test.go\n//go:build wireinject\n\npackage main\n\nimport (\n    \"testing\"\n    \"github.com/google/wire\"\n)\n\n// TestSet replaces real infra with in-memory fakes\nvar TestSet = wire.NewSet(\n    NewTestConfig,\n    NewInMemoryUserStore,\n    wire.Bind(new(repo.UserStore), new(*InMemoryUserStore)),\n    NewTestRedis,\n)\n\nfunc InitTestApp(t *testing.T) (*App, func(), error) {\n    wire.Build(TestSet, service.ServiceSet, NewApp)\n    return nil, nil, nil\n}\n```\n\n```go\n// app_integration_test.go\n//go:build !wireinject  // compiles when the wireinject tag is NOT set\n\npackage main\n\nfunc TestApp_GetUser(t *testing.T) {\n    app, cleanup, err := InitTestApp(t)\n    require.NoError(t, err)\n    defer cleanup()\n\n    // test against the fully-wired app with fake dependencies\n    u, err := app.GetUser(context.Background(), 1)\n    require.NoError(t, err)\n    assert.NotNil(t, u)\n}\n```\n\nRun `wire ./...` to generate `wire_gen.go` — the test injector is included because the `_test.go` file is compiled as part of the package during `go test`.\n\n**Key pattern from upstream best practices:** Prefer creating a test-only provider set over passing mocks as injector arguments (though both work). The set approach keeps the test injector composable.\n\n## Passing Mocks as Injector Arguments\n\nAn alternative to a test set: pass the mock directly as an injector parameter. Wire treats it as a pre-built provider.\n\n```go\n//go:build wireinject\n\nfunc InitTestApp(store repo.UserStore) (*App, func(), error) {\n    wire.Build(config.ConfigSet, service.ServiceSet, NewApp)\n    return nil, nil, nil\n}\n\n// Test\nfunc TestApp(t *testing.T) {\n    mock := &MockUserStore{}\n    app, cleanup, err := InitTestApp(mock)\n    require.NoError(t, err)\n    defer cleanup()\n    // ...\n}\n```\n\nUse this form when you only need to replace one or two dependencies and a full `TestSet` is overkill.\n\n## CI: Detecting Stale `wire_gen.go`\n\nIf `wire_gen.go` is not regenerated after a provider change, CI builds pass but the graph is wrong. Enforce freshness in CI:\n\n```bash\n# Option 1: re-run wire and check for diffs\nwire ./...\ngit diff --exit-code -- '**/wire_gen.go'\n```\n\n```yaml\n# .github/workflows/ci.yml\n- name: Check wire_gen.go is up-to-date\n  run: |\n    go install github.com/google/wire/cmd/wire@v0.7.0\n    wire ./...\n    git diff --exit-code -- '**/wire_gen.go'\n```\n\n```bash\n# Option 2: use wire check (verifies graph without regenerating)\nwire check ./...\n```\n\n`wire check` exits non-zero if the graph is inconsistent but does **not** update `wire_gen.go`. Use it for a fast graph-validity check without modifying files.\n\n## Testing Interface Bindings\n\n`wire.Bind` can be used in test sets to bind a fake to the same interface:\n\n```go\n// Fake implements the same interface as the real provider\ntype FakeMailer struct{ sent []string }\nfunc (f *FakeMailer) Send(to, body string) error { f.sent = append(f.sent, to); return nil }\n\nvar TestMailerSet = wire.NewSet(\n    NewFakeMailer,\n    wire.Bind(new(notification.Mailer), new(*FakeMailer)),\n)\n\nvar TestSet = wire.NewSet(\n    TestMailerSet,\n    realServiceSet,  // everything else is real\n)\n```\n\nThis keeps the test injector narrow — only the Mailer is faked; the rest of the graph is real.\n\n## Table-Driven Tests Without Wire\n\nWire is an initialization tool. Once the object graph is built, table-driven tests on individual services need no wire involvement:\n\n```go\nfunc TestUserService(t *testing.T) {\n    cases := []struct {\n        name  string\n        id    int64\n        users map[int64]*User\n        want  string\n        err   bool\n    }{\n        {\"found\", 1, map[int64]*User{1: &User{Name: \"Alice\"}}, \"Alice\", false},\n        {\"not found\", 99, nil, \"\", true},\n    }\n    for _, tc := range cases {\n        t.Run(tc.name, func(t *testing.T) {\n            svc := service.NewUserService(&MockUserStore{users: tc.users}, nil)\n            u, err := svc.GetUser(context.Background(), tc.id)\n            if tc.err { require.Error(t, err); return }\n            assert.Equal(t, tc.want, u.Name)\n        })\n    }\n}\n```\n\nWire has no role here — the injector was only needed to build the object graph in `main` (or in an integration test). Unit tests construct dependencies directly.\n\nFile v1.1.0:skill-card.md\n\n## Description:\n\nProvides guidance for using google/wire compile-time dependency injection in Go projects, including provider sets, injectors, interface bindings, struct providers, values, cleanup functions, generated files, code generation, and testing patterns.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[samber](https://clawhub.ai/user/samber)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and engineers use this skill when adopting or maintaining google/wire in Go codebases. It helps agents explain dependency graph design, update provider sets and injectors, regenerate wire_gen.go, and troubleshoot common compile-time DI errors.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Installing Wire with @latest can change the code generator version used by a project.\n\nMitigation: Pin github.com/google/wire/cmd/wire to an approved version in stricter environments.\n\nRisk: Wire code generation rewrites generated Go files in the working tree.\n\nMitigation: Run generation in a least-privileged development or CI context and review diffs before committing generated files.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/samber/skills/golang-google-wire)\n- [cc-skills-golang repository](https://github.com/samber/cc-skills-golang)\n- [google/wire package documentation](https://pkg.go.dev/github.com/google/wire)\n- [google/wire repository](https://github.com/google/wire)\n- [google/wire user guide](https://github.com/google/wire/blob/main/docs/guide.md)\n- [google/wire best practices](https://github.com/google/wire/blob/main/docs/best-practices.md)\n- [Advanced google/wire reference](references/advanced.md)\n- [google/wire recipes](references/recipes.md)\n- [google/wire testing guidance](references/testing.md)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Markdown, Code, Shell commands, Configuration, Guidance]\n\n**Output Format:** [Markdown with Go code examples and shell command snippets]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May propose edits to Go source files, injector files, provider sets, generated-code workflow, and CI checks.]\n\n## Skill Version(s):\n\n1.1.0 (source: server release metadata and skill frontmatter)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nFile v1.1.0:evals/evals.json\n\n[\n  {\n    \"id\": 1,\n    \"name\": \"build-constraint-on-injector\",\n    \"description\": \"Tests that the model adds //go:build wireinject to injector files to prevent duplicate-symbol compile errors\",\n    \"prompt\": \"I'm setting up google/wire in my Go project. Here's my injector file:\\n\\n```go\\npackage main\\n\\nimport \\\"github.com/google/wire\\\"\\n\\nfunc InitApp() (*App, error) {\\n    wire.Build(InfraSet, ServiceSet, NewApp)\\n    return nil, nil\\n}\\n```\\n\\nWire generates wire_gen.go successfully, but when I run `go build`, I get a 'redeclared in this block' compile error for InitApp. What's wrong and how do I fix it?\",\n    \"trap\": \"Without the skill, the model may suggest renaming the function, reorganizing packages, or not identify that the missing //go:build wireinject tag is the cause — both the stub and wire_gen.go define InitApp, causing the duplicate.\",\n    \"assertions\": [\n      {\n        \"id\": \"1.1\",\n        \"text\": \"Identifies the missing //go:build wireinject build tag as the root cause\"\n      },\n      {\n        \"id\": \"1.2\",\n        \"text\": \"Shows //go:build wireinject as the first line of the injector file\"\n      },\n      {\n        \"id\": \"1.3\",\n        \"text\": \"Explains that the tag prevents the stub from being compiled into the binary (only wire_gen.go compiles)\"\n      },\n      {\n        \"id\": \"1.4\",\n        \"text\": \"Does NOT suggest renaming the function or reorganizing packages as the fix\"\n      },\n      {\n        \"id\": \"1.5\",\n        \"text\": \"Does NOT suggest deleting wire_gen.go as the fix\"\n      }\n    ]\n  },\n  {\n    \"id\": 2,\n    \"name\": \"interface-binding-required\",\n    \"description\": \"Tests that wire.Bind is required for interface-to-concrete mappings and cannot be inferred\",\n    \"prompt\": \"I have this Go code using google/wire:\\n\\n```go\\n// repo.go\\ntype UserStore interface {\\n    GetUser(id int64) (*User, error)\\n}\\n\\ntype PostgresUserRepo struct{ db *sql.DB }\\nfunc (r *PostgresUserRepo) GetUser(id int64) (*User, error) { ... }\\nfunc NewUserRepo(db *sql.DB) *PostgresUserRepo { return &PostgresUserRepo{db: db} }\\n\\n// service.go\\nfunc NewUserService(store UserStore) *UserService { return &UserService{store: store} }\\n\\n// wire_providers.go\\nvar AppSet = wire.NewSet(NewDB, NewUserRepo, NewUserService)\\n```\\n\\nWhen I run `wire ./...` I get: `no provider found for UserStore`. NewUserRepo returns *PostgresUserRepo which clearly implements UserStore. Why doesn't wire figure this out?\",\n    \"trap\": \"Without the skill, the model might suggest wire should automatically resolve the interface, or suggest wrapping NewUserRepo to return UserStore directly, missing the explicit wire.Bind requirement.\",\n    \"assertions\": [\n      {\n        \"id\": \"2.1\",\n        \"text\": \"Explains that wire never auto-resolves interface satisfaction — bindings must be explicit\"\n      },\n      {\n        \"id\": \"2.2\",\n        \"text\": \"Shows wire.Bind(new(UserStore), new(*PostgresUserRepo)) added to the provider set\"\n      },\n      {\n        \"id\": \"2.3\",\n        \"text\": \"Places wire.Bind inside the same wire.NewSet (or adds it to a set in wire.Build)\"\n      },\n      {\n        \"id\": \"2.4\",\n        \"text\": \"Explains WHY wire requires explicit bindings (predictability — avoids surprise rebinding when new implementations are added)\"\n      },\n      {\n        \"id\": \"2.5\",\n        \"text\": \"Does NOT suggest changing NewUserRepo to return UserStore directly as the primary fix\"\n      }\n    ]\n  },\n  {\n    \"id\": 3,\n    \"name\": \"duplicate-type-named-wrapper\",\n    \"description\": \"Tests the named-type pattern to disambiguate multiple values of the same underlying type\",\n    \"prompt\": \"I'm building a Go service with google/wire. I need to inject two database connection strings — one for the primary database and one for a read replica. I tried this:\\n\\n```go\\nfunc NewPrimaryDSN() string { return os.Getenv(\\\"PRIMARY_DSN\\\") }\\nfunc NewReplicaDSN() string { return os.Getenv(\\\"REPLICA_DSN\\\") }\\n\\nvar DBSet = wire.NewSet(NewPrimaryDSN, NewReplicaDSN, NewPrimaryDB, NewReplicaDB)\\n```\\n\\nWire complains about multiple bindings for string. How should I structure this?\",\n    \"trap\": \"Without the skill, the model might suggest using wire.Value or provider arguments, or use a config struct — missing the idiomatic named-type wrapper pattern that wire's own docs recommend.\",\n    \"assertions\": [\n      {\n        \"id\": \"3.1\",\n        \"text\": \"Introduces distinct named types (e.g., type PrimaryDSN string and type ReplicaDSN string)\"\n      },\n      {\n        \"id\": \"3.2\",\n        \"text\": \"Updates NewPrimaryDSN to return PrimaryDSN and NewReplicaDSN to return ReplicaDSN\"\n      },\n      {\n        \"id\": \"3.3\",\n        \"text\": \"Updates NewPrimaryDB and NewReplicaDB signatures to accept the named types\"\n      },\n      {\n        \"id\": \"3.4\",\n        \"text\": \"Explains that wire enforces one provider per type, so distinct named types are the correct solution\"\n      },\n      {\n        \"id\": \"3.5\",\n        \"text\": \"Does NOT suggest using a single Config struct with both DSNs as the primary fix (that avoids the problem rather than solving it with named types)\"\n      }\n    ]\n  },\n  {\n    \"id\": 4,\n    \"name\": \"cleanup-signature\",\n    \"description\": \"Tests the (T, func(), error) cleanup provider pattern instead of manual defer in main\",\n    \"prompt\": \"I'm using google/wire to wire my Go service. I need my *sql.DB connection pool to be closed when the app shuts down. Currently I'm doing this in main:\\n\\n```go\\nfunc main() {\\n    app, err := InitApp()\\n    if err != nil { log.Fatal(err) }\\n    defer db.Close() // but I don't have access to db here!\\n    app.Run()\\n}\\n```\\n\\nI realize I need the DB closed on shutdown, but InitApp() only returns *App. How should I wire cleanup with google/wire?\",\n    \"trap\": \"Without the skill, the model might suggest passing db out of InitApp as a second return value, or storing it as a global, missing the (T, func(), error) cleanup provider pattern.\",\n    \"assertions\": [\n      {\n        \"id\": \"4.1\",\n        \"text\": \"Changes NewDB to return (*sql.DB, func(), error) where the cleanup function calls db.Close()\"\n      },\n      {\n        \"id\": \"4.2\",\n        \"text\": \"Changes the injector function to return (*App, func(), error) to propagate the cleanup chain\"\n      },\n      {\n        \"id\": \"4.3\",\n        \"text\": \"Shows main calling defer cleanup() after the nil-check\"\n      },\n      {\n        \"id\": \"4.4\",\n        \"text\": \"Explains that wire chains cleanup functions and calls them in reverse construction order\"\n      },\n      {\n        \"id\": \"4.5\",\n        \"text\": \"Does NOT suggest passing db as an extra return value from InitApp alongside *App\"\n      }\n    ]\n  },\n  {\n    \"id\": 5,\n    \"name\": \"no-edit-wire-gen\",\n    \"description\": \"Tests that the model never edits wire_gen.go and instructs re-running wire ./... instead\",\n    \"prompt\": \"I added a new *Logger parameter to my NewServer constructor in my google/wire project:\\n\\n```go\\nfunc NewServer(db *sql.DB, log *zap.Logger) *Server { ... }\\n```\\n\\nNow `go build` fails with 'too few arguments in call to NewServer'. The error is inside wire_gen.go on line 47. Should I edit wire_gen.go to add the logger argument there, or is there another way?\",\n    \"trap\": \"Without the skill, a model may suggest editing wire_gen.go directly to 'fix' the build error quickly, which would be overwritten on the next wire run.\",\n    \"assertions\": [\n      {\n        \"id\": \"5.1\",\n        \"text\": \"Explicitly says NOT to edit wire_gen.go (it is always overwritten)\"\n      },\n      {\n        \"id\": \"5.2\",\n        \"text\": \"Instructs running wire ./... to regenerate wire_gen.go\"\n      },\n      {\n        \"id\": \"5.3\",\n        \"text\": \"Explains that *zap.Logger must be provided in the graph (either via a provider or wire.Value)\"\n      },\n      {\n        \"id\": \"5.4\",\n        \"text\": \"Shows how to add NewLogger (or wire.Value) to the appropriate wire.NewSet so the dependency is satisfied\"\n      },\n      {\n        \"id\": \"5.5\",\n        \"text\": \"Does NOT present editing wire_gen.go as an option\"\n      }\n    ]\n  },\n  {\n    \"id\": 6,\n    \"name\": \"provider-set-organization\",\n    \"description\": \"Tests per-package provider set organization instead of one giant set in main\",\n    \"prompt\": \"My Go service using google/wire is growing. I currently have everything in one place:\\n\\n```go\\n// wire.go\\n//go:build wireinject\\n\\nfunc InitApp() (*App, func(), error) {\\n    wire.Build(\\n        NewConfig, NewDB, NewCache, NewLogger,\\n        NewUserRepo, NewOrderRepo, NewProductRepo,\\n        wire.Bind(new(UserStore), new(*PostgresUserRepo)),\\n        wire.Bind(new(OrderStore), new(*PostgresOrderRepo)),\\n        wire.Bind(new(ProductStore), new(*PostgresProductRepo)),\\n        NewUserService, NewOrderService, NewProductService,\\n        NewHTTPServer, NewRouter,\\n        NewApp,\\n    )\\n    return nil, nil, nil\\n}\\n```\\n\\nThis is getting unwieldy. How should I organize this with google/wire?\",\n    \"trap\": \"Without the skill, the model may just split the providers into helper variables in the same package, missing the idiomatic per-package wire.NewSet pattern.\",\n    \"assertions\": [\n      {\n        \"id\": \"6.1\",\n        \"text\": \"Introduces per-package wire.NewSet variables (e.g., InfraSet, RepoSet, ServiceSet, TransportSet)\"\n      },\n      {\n        \"id\": \"6.2\",\n        \"text\": \"Each set lives in its own package's wire.go file (not all in main)\"\n      },\n      {\n        \"id\": \"6.3\",\n        \"text\": \"The injector wire.Build references the set variables rather than individual providers\"\n      },\n      {\n        \"id\": \"6.4\",\n        \"text\": \"wire.Bind declarations move into the relevant package's set (not into wire.Build directly)\"\n      },\n      {\n        \"id\": \"6.5\",\n        \"text\": \"Explains the benefit: per-package sets are independently composable and keep the injector readable\"\n      }\n    ]\n  },\n  {\n    \"id\": 7,\n    \"name\": \"injector-parameter-vs-value-provider\",\n    \"description\": \"Tests using wire.Value or injector parameters for pre-built values instead of wrapper constructors\",\n    \"prompt\": \"In my Go app using google/wire, I parse a *Config struct from command-line flags in main() before calling InitApp. I tried writing a no-op provider:\\n\\n```go\\nvar parsedCfg *Config\\n\\nfunc ProvideConfig() *Config { return parsedCfg }\\n\\nvar AppSet = wire.NewSet(ProvideConfig, ...)\\n```\\n\\nThis works but feels wrong — I'm using a global variable. Is there a cleaner way to pass a pre-built *Config into the wire graph?\",\n    \"trap\": \"Without the skill, the model might suggest keeping the global variable pattern or using init(), missing both wire.Value and the injector-parameter patterns.\",\n    \"assertions\": [\n      {\n        \"id\": \"7.1\",\n        \"text\": \"Shows the injector-parameter approach: func InitApp(cfg *Config) (*App, func(), error) with wire.Build\"\n      },\n      {\n        \"id\": \"7.2\",\n        \"text\": \"OR shows wire.Value(cfg) inside wire.Build — both are valid answers\"\n      },\n      {\n        \"id\": \"7.3\",\n        \"text\": \"Explains that injector parameters are treated as pre-built providers by wire\"\n      },\n      {\n        \"id\": \"7.4\",\n        \"text\": \"Does NOT use a global variable as the recommended solution\"\n      },\n      { \"id\": \"7.5\", \"text\": \"Does NOT suggest using init() to set the value\" }\n    ]\n  },\n  {\n    \"id\": 8,\n    \"name\": \"fields-of-struct\",\n    \"description\": \"Tests wire.FieldsOf to expose struct fields as individual graph nodes\",\n    \"prompt\": \"I have a single Config struct in my Go app with google/wire:\\n\\n```go\\ntype Config struct {\\n    DatabaseDSN  string\\n    CacheAddress string\\n    APIKey       string\\n}\\n\\nfunc NewConfig() *Config { return loadFromEnv() }\\n```\\n\\nNewDB needs a DatabaseDSN string, NewCache needs a CacheAddress string, NewExternalClient needs an APIKey string — but all three are plain strings. How do I make these available to the wire graph without creating three separate provider functions?\",\n    \"trap\": \"Without the skill, the model will suggest three named-type wrappers or three extraction functions, missing wire.FieldsOf which promotes struct fields directly.\",\n    \"assertions\": [\n      {\n        \"id\": \"8.1\",\n        \"text\": \"Uses wire.FieldsOf(new(Config), \\\"DatabaseDSN\\\", \\\"CacheAddress\\\", \\\"APIKey\\\") or a subset\"\n      },\n      {\n        \"id\": \"8.2\",\n        \"text\": \"Places wire.FieldsOf inside the provider set or wire.Build\"\n      },\n      {\n        \"id\": \"8.3\",\n        \"text\": \"Updates NewDB, NewCache, NewExternalClient to accept the string fields as parameters (or uses named types alongside FieldsOf)\"\n      },\n      {\n        \"id\": \"8.4\",\n        \"text\": \"Explains that wire.FieldsOf promotes struct fields as individual graph nodes without manual extraction functions\"\n      },\n      {\n        \"id\": \"8.5\",\n        \"text\": \"Does NOT suggest writing three separate func GetDatabaseDSN(c *Config) string extractor functions as the primary recommendation\"\n      }\n    ]\n  },\n  {\n    \"id\": 9,\n    \"name\": \"test-injector-pattern\",\n    \"description\": \"Tests the test-injector pattern with wire.Bind for fake dependencies instead of runtime mocking hacks\",\n    \"prompt\": \"My Go service is wired with google/wire. I have a Mailer interface implemented by SMTPMailer in production. I want integration tests that use a FakeMailer instead — recording sent emails — without modifying the production provider sets. The test must wire the full graph (not just NewUserService in isolation). How should I approach this?\",\n    \"trap\": \"Without the skill, the model may suggest monkey-patching, a global variable for the mailer, or a runtime DI container for tests — missing the test-injector pattern with a test-only wire.NewSet and wire.Bind.\",\n    \"assertions\": [\n      {\n        \"id\": \"9.1\",\n        \"text\": \"Creates a test-only provider set (e.g., TestMailerSet) with NewFakeMailer and wire.Bind(new(Mailer), new(*FakeMailer))\"\n      },\n      {\n        \"id\": \"9.2\",\n        \"text\": \"Creates a test injector function in a _test.go file with //go:build wireinject\"\n      },\n      {\n        \"id\": \"9.3\",\n        \"text\": \"The test injector's wire.Build composes the production sets with the test-only set\"\n      },\n      {\n        \"id\": \"9.4\",\n        \"text\": \"Does NOT suggest global variables, monkey-patching, or a runtime DI container for tests\"\n      },\n      {\n        \"id\": \"9.5\",\n        \"text\": \"Mentions that wire ./... (or go generate) must be run to produce the test-injector generated code\"\n      }\n    ]\n  },\n  {\n    \"id\": 10,\n    \"name\": \"wire-vs-fx-for-daemon\",\n    \"description\": \"Tests that the model recommends uber-go/fx over wire for long-running services that need lifecycle management\",\n    \"prompt\": \"I'm starting a new Go HTTP server project and evaluating DI options. A colleague suggested google/wire because 'it's simpler and type-safe at compile time.' The server needs graceful shutdown (drain in-flight requests), OnStart/OnStop hooks for the database pool and metrics exporter, and should handle SIGINT/SIGTERM. Should I use wire?\",\n    \"trap\": \"Without the skill, the model may agree that wire is suitable because it's simple and compile-time safe, not recognizing that lifecycle, signal handling, and hook ordering are exactly what fx provides and wire explicitly lacks.\",\n    \"assertions\": [\n      {\n        \"id\": \"10.1\",\n        \"text\": \"Identifies that wire has no built-in lifecycle management (no OnStart/OnStop hooks)\"\n      },\n      {\n        \"id\": \"10.2\",\n        \"text\": \"Identifies that wire has no built-in signal handling (SIGINT/SIGTERM)\"\n      },\n      {\n        \"id\": \"10.3\",\n        \"text\": \"Recommends uber-go/fx (or at minimum flags it as the better fit) for a long-running HTTP daemon with lifecycle needs\"\n      },\n      {\n        \"id\": \"10.4\",\n        \"text\": \"Does NOT recommend wire as sufficient for a service requiring graceful shutdown and lifecycle hooks\"\n      },\n      {\n        \"id\": \"10.5\",\n        \"text\": \"Mentions that with wire the developer must implement shutdown and signal handling manually\"\n      }\n    ]\n  }\n]\n\nArchive v1.0.3: 7 files, 18779 bytes\n\nFiles: evals/evals.json (14841b), references/advanced.md (6966b), references/recipes.md (6718b), references/testing.md (5146b), skill-card.md (2973b), SKILL.md (10709b), _meta.json (137b)\n\nFile v1.0.3:SKILL.md\n\n---\nname: golang-google-wire\ndescription: \"Compile-time dependency injection in Golang using google/wire — wire.NewSet, wire.Build, wire.Bind (interface→concrete), wire.Struct, wire.Value, wire.InterfaceValue, wire.FieldsOf, cleanup functions, //go:build wireinject injector files, and generated wire_gen.go. Apply when using or adopting google/wire, when the codebase imports `github.com/google/wire`, or when wiring an application graph at compile time via `wire.Build`. For runtime DI with reflection, see `samber/cc-skills-golang@golang-uber-dig` skill.\"\nuser-invocable: true\nlicense: MIT\ncompatibility: Designed for Claude Code or similar AI coding agents, and for projects using Golang.\nmetadata:\n  author: samber\n  version: \"1.0.3\"\n  openclaw:\n    emoji: \"🪡\"\n    homepage: https://github.com/samber/cc-skills-golang\n    requires:\n      bins:\n        - go\n        - wire\n    install:\n      - kind: go\n        package: github.com/google/wire/cmd/wire@latest\n        bins: [wire]\n    skill-library-version: \"0.7.0\"\nallowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*) Bash(git:*) Agent WebFetch mcp__context7__resolve-library-id mcp__context7__query-docs Bash(wire:*)\n---\n\n**Persona:** You are a Go architect using wire for compile-time DI. You let the compiler catch missing dependencies, treat `wire_gen.go` as committed source, and re-run `wire ./...` after every graph change.\n\n**Dependencies:**\n\n- wire: `go install github.com/google/wire/cmd/wire@latest`\n\n# Using google/wire for Compile-Time Dependency Injection in Go\n\nCode-generation DI toolkit. Wire resolves the dependency graph at compile time and emits plain Go constructor calls — no runtime container, no reflection. Errors appear when you run `wire ./...`, not at first request.\n\nNote: `google/wire` was archived in August 2025 (feature-complete; bug fixes still accepted).\n\n**Official Resources:** [pkg.go.dev](https://pkg.go.dev/github.com/google/wire) · [github.com/google/wire](https://github.com/google/wire) · [User Guide](https://github.com/google/wire/blob/main/docs/guide.md) · [Best Practices](https://github.com/google/wire/blob/main/docs/best-practices.md)\n\nThis skill is not exhaustive. Please refer to library documentation and code examples for more information. Context7 can help as a discoverability platform.\n\n```bash\ngo get -tool github.com/google/wire/cmd/wire@latest\ngo get github.com/google/wire\n```\n\n## wire vs. Runtime DI\n\n| Concern           | wire                      | dig / fx / samber/do   |\n| ----------------- | ------------------------- | ---------------------- |\n| Resolution        | Compile time (codegen)    | Runtime (reflection)   |\n| Error detection   | `wire ./...` fails        | First `Invoke`/startup |\n| Runtime container | None — plain Go calls     | Present                |\n| Lifecycle hooks   | Not built in              | fx: OnStart/OnStop     |\n| Generated files   | `wire_gen.go` (committed) | None                   |\n\nFor lifecycle, lazy loading, and a full matrix see `samber/cc-skills-golang@golang-dependency-injection`.\n\n## Providers\n\nA provider is any Go function — inputs are dependencies, outputs are provided types. Three return forms:\n\n```go\nfunc NewConfig() *Config                          { return &Config{Addr: \":8080\"} }\nfunc NewDB(cfg *Config) (*sql.DB, error)          { return sql.Open(\"postgres\", cfg.DSN) }\nfunc NewRedis(cfg *Config) (*redis.Client, func(), error) { // cleanup chained in reverse order\n    c := redis.NewClient(&redis.Options{Addr: cfg.RedisAddr})\n    return c, func() { c.Close() }, nil\n}\n```\n\n## Provider Sets\n\n`wire.NewSet` groups providers for reuse. Sets can reference other sets.\n\n```go\n// infra/wire.go\nvar InfraSet = wire.NewSet(\n    NewConfig,\n    NewDB,\n    NewRedis,\n)\n\n// service/wire.go\nvar ServiceSet = wire.NewSet(\n    NewUserRepo,\n    NewUserService,\n    wire.Bind(new(UserStore), new(*UserRepo)), // interface binding\n)\n```\n\nKeep sets small: library sets expose a stable surface (adding inputs or removing outputs breaks downstream injectors). One set per package is a useful default.\n\n## Injectors and `//go:build wireinject`\n\nThe injector file declares the initialization function. Wire generates its body into `wire_gen.go` and replaces the stub.\n\n```go\n//go:build wireinject\n\npackage main\n\nimport \"github.com/google/wire\"\n\n// Wire generates the body of this function.\nfunc InitApp() (*App, func(), error) {\n    wire.Build(InfraSet, ServiceSet, NewApp)\n    return nil, nil, nil // replaced by codegen\n}\n```\n\nThe `//go:build wireinject` tag prevents the stub from being compiled into the binary — only `wire_gen.go` (which has no such tag) makes it through `go build`. Without this tag, both files define the same function, causing a compile error.\n\nAlternative syntax when a dummy return is inconvenient:\n\n```go\nfunc InitApp() (*App, func(), error) {\n    panic(wire.Build(InfraSet, ServiceSet, NewApp))\n}\n```\n\n## Interface Bindings\n\nWire forbids implicit interface satisfaction — you must declare bindings explicitly so the graph is unambiguous when multiple types implement the same interface.\n\n```go\nvar Set = wire.NewSet(\n    NewPostgresUserRepo,\n    wire.Bind(new(UserStore), new(*PostgresUserRepo)), // tell wire: *PostgresUserRepo satisfies UserStore\n)\n```\n\nExplicit bindings prevent graph breakage when a new type implementing the same interface is added elsewhere.\n\n## Struct Providers and Values\n\n`wire.Struct` fills struct fields from the graph without a manual constructor. Tag fields `wire:\"-\"` to exclude them.\n\n```go\nwire.Struct(new(Server), \"Logger\", \"DB\") // inject named fields\nwire.Struct(new(Server), \"*\")            // inject all non-excluded fields\nwire.Value(Foo{X: 42})                   // constant expression (no fn calls / channels)\nwire.InterfaceValue(new(io.Reader), os.Stdin) // interface-typed literal\nwire.FieldsOf(new(Config), \"DSN\", \"Addr\")    // promote struct fields as graph nodes\n```\n\nSee [advanced.md](references/advanced.md) for the `wire:\"-\"` exclusion tag and `wire.FieldsOf` details.\n\n## Disambiguating Duplicate Types\n\nWire forbids two providers for the same type. Wrap the underlying type in distinct named types so each has exactly one provider:\n\n```go\ntype PrimaryDSN string\ntype ReplicaDSN string\n```\n\n## Full Application Example\n\n```go\n// wire.go — injector, excluded from binary via build tag\n//go:build wireinject\n\npackage main\n\nfunc InitApp() (*App, func(), error) {\n    wire.Build(config.ConfigSet, infra.InfraSet, service.ServiceSet, NewApp)\n    return nil, nil, nil\n}\n\n// main.go\nfunc main() {\n    app, cleanup, err := InitApp()\n    if err != nil { log.Fatal(err) }\n    defer cleanup()\n    app.Run()\n}\n```\n\nWire generates `wire_gen.go` (plain Go, committed, DO NOT EDIT). For a full example with per-package sets, cleanup-heavy graphs, and generated output, see [recipes.md](references/recipes.md).\n\n## Codegen Workflow\n\n```bash\nwire ./...           # regenerate all injectors in the module\nwire check ./...     # validate graph without regenerating (fast CI check)\n```\n\nRun `wire ./...` after every constructor signature change. Add `//go:generate go run github.com/google/wire/cmd/wire` to injector files so `go generate ./...` also works. Commit `wire_gen.go` — it must stay in sync for CI builds.\n\n## Best Practices\n\n1. Never edit `wire_gen.go` — it is overwritten on every `wire ./...` run. Treat it as a build artifact that happens to be committed; source of truth is the provider and injector files.\n2. Always add `//go:build wireinject` to injector files — omitting it causes duplicate-symbol compile errors because both the stub and the generated file define the same function.\n3. Use named types to distinguish values of the same underlying type — wire enforces one provider per type; named types like `type DSN string` let you have `PrimaryDSN` and `ReplicaDSN` coexist.\n4. Keep library provider sets minimal and backward-compatible — adding new required inputs breaks downstream injectors; removing outputs does too. Introduce only newly-created types in the same release.\n5. Return `(T, func(), error)` from cleanup providers and let wire chain them — wire generates the correct reverse-order cleanup and handles partial failures (if construction fails midway, only already-built cleanups run).\n6. Keep injector files focused — one function per file, one package import at a time. Fat injectors with dozens of `wire.Build` arguments are hard to reason about; delegate to per-package sets.\n\n## Common Mistakes\n\n| Mistake | Fix |\n| --- | --- |\n| Editing `wire_gen.go` manually | Never edit it. Change providers or injectors and re-run `wire ./...`. |\n| Missing `//go:build wireinject` | Add the tag as the very first line of every injector file. |\n| Two providers returning `*sql.DB` | Wrap with a named struct type: `type PrimaryDB struct { *sql.DB }` — Wire does not distinguish pointer type aliases. |\n| Injecting an interface without `wire.Bind` | Add `wire.Bind(new(MyInterface), new(*MyImpl))` to the provider set. |\n| Forgetting to re-run `wire ./...` after changes | Run wire before `go build`; add it to `go generate` or a Makefile target. |\n| Calling `cleanup()` without guarding for nil | Wire returns nil cleanup on construction error; guard with `if cleanup != nil { defer cleanup() }`. |\n\n## Testing\n\nWire generates plain Go constructors, so unit tests use manual injection — no container to clone or reset. For testing patterns (test injectors swapping real providers for fakes, CI stale-check for `wire_gen.go`), see [testing.md](references/testing.md).\n\n## Further Reading\n\n- [advanced.md](references/advanced.md) — cleanup chains, multiple injectors, set nesting, error catalogue, codegen flags, quick reference\n- [recipes.md](references/recipes.md) — HTTP server, multi-injector build, cleanup-heavy graph, CLI embedding\n- [testing.md](references/testing.md) — test injectors, fake bindings, CI stale check\n\n## Cross-References\n\n- → See `samber/cc-skills-golang@golang-dependency-injection` skill for DI concepts and library comparison\n- → See `samber/cc-skills-golang@golang-uber-dig` skill for runtime reflection-based DI without lifecycle\n- → See `samber/cc-skills-golang@golang-uber-fx` skill for runtime DI with lifecycle hooks, modules, and signal-aware Run()\n- → See `samber/cc-skills-golang@golang-samber-do` skill for generics-based DI without reflection\n- → See `samber/cc-skills-golang@golang-structs-interfaces` skill for interface design patterns\n- → See `samber/cc-skills-golang@golang-testing` skill for general testing patterns\n\nIf you encounter a bug or unexpected behavior in google/wire, open an issue at <https://github.com/google/wire/issues>.\n\nFile v1.0.3:_meta.json\n\n{\n  \"ownerId\": \"kn72rhnkwjfeex9wr1n7y24qa983cjn3\",\n  \"slug\": \"golang-google-wire\",\n  \"version\": \"1.0.3\",\n  \"publishedAt\": 1781101168181\n}\n\nFile v1.0.3:references/advanced.md\n\n# Advanced — google/wire\n\nDetail topics referenced from `SKILL.md`. Each section is self-contained.\n\n## Cleanup Chains\n\nWhen a provider returns `(T, func(), error)`, Wire adds the cleanup to a chain. The generated injector runs cleanups in **reverse construction order**: the last-built dependant is cleaned up first, ensuring dependants are torn down before their dependencies.\n\n```go\n// Provider with cleanup\nfunc NewDB(cfg *Config) (*sql.DB, func(), error) {\n    db, err := sql.Open(\"postgres\", string(cfg.DSN))\n    if err != nil { return nil, nil, err }\n    return db, func() { db.Close() }, nil\n}\n\nfunc NewCache(cfg *Config) (*redis.Client, func(), error) {\n    c := redis.NewClient(&redis.Options{Addr: cfg.CacheAddr})\n    return c, func() { c.Close() }, nil\n}\n```\n\nWire generates something like:\n\n```go\nfunc InitApp() (*App, func(), error) {\n    cfg := NewConfig()\n    db, dbCleanup, err := NewDB(cfg)\n    if err != nil { return nil, nil, err }\n    cache, cacheCleanup, err := NewCache(cfg)\n    if err != nil {\n        dbCleanup()  // already-built cleanups run on partial failure\n        return nil, nil, err\n    }\n    app := NewApp(db, cache)\n    return app, func() {\n        cacheCleanup()  // reverse order\n        dbCleanup()\n    }, nil\n}\n```\n\n**Caller pattern** — guard against nil cleanup on construction failure:\n\n```go\napp, cleanup, err := InitApp()\nif err != nil { log.Fatal(err) }\ndefer cleanup()\n```\n\nWire always returns a non-nil cleanup function when construction succeeds. If construction fails midway, the returned `cleanup` is nil — guard before calling.\n\n## Multiple Injectors in One Package\n\nA package can contain multiple injector functions. Each must live in a file with `//go:build wireinject`. All generated functions land in `wire_gen.go` in the same package.\n\n```go\n//go:build wireinject\n\npackage main\n\n// Production injector\nfunc InitProdApp() (*App, func(), error) {\n    wire.Build(ProdSet, NewApp)\n    return nil, nil, nil\n}\n\n// Development injector with debug providers\nfunc InitDevApp() (*App, func(), error) {\n    wire.Build(DevSet, NewApp)\n    return nil, nil, nil\n}\n```\n\nSelect at runtime with a flag, or at build time with separate `//go:build prod` / `//go:build !prod` constraints on the injector files.\n\n## wire.NewSet Nesting Strategies\n\nSets can contain other sets, building a hierarchy that mirrors your package structure.\n\n```go\n// pkg/config/wire.go\nvar ConfigSet = wire.NewSet(NewConfig)\n\n// pkg/infra/wire.go\nvar InfraSet = wire.NewSet(\n    config.ConfigSet, // embed upstream set\n    NewDB,\n    NewCache,\n)\n\n// pkg/service/wire.go\nvar ServiceSet = wire.NewSet(\n    NewUserService,\n    wire.Bind(new(UserStore), new(*UserRepo)),\n)\n\n// wire.go (injector)\nwire.Build(infra.InfraSet, service.ServiceSet, NewApp)\n```\n\n**Library set stability rules** (from upstream best practices):\n\n- Safe: replace one provider with another that has the same or fewer inputs, in the same release.\n- Safe: introduce a brand-new output type not previously provided.\n- Breaking: add a new required input to a provider — downstream injectors cannot satisfy it.\n- Breaking: remove a provided output type — downstream injectors that depend on it fail.\n- Breaking: add a type that the injector already provides — Wire reports a duplicate.\n\n## `wire:\"-\"` Exclusion Tag\n\nExclude a struct field from `wire.Struct` injection by tagging it:\n\n```go\ntype Server struct {\n    Logger  *zap.Logger\n    DB      *sql.DB\n    mu      sync.Mutex   `wire:\"-\"` // unexported — auto-excluded\n    Timeout time.Duration `wire:\"-\"` // exported but opt-out\n}\n\nwire.Struct(new(Server), \"*\") // injects Logger and DB; skips mu and Timeout\n```\n\nUnexported fields are always skipped regardless of the tag.\n\n## Common Codegen Errors\n\n| Error message | Root cause | Fix |\n| --- | --- | --- |\n| `no provider found for TYPE` | A dependency is not provided by any set in `wire.Build` | Add the missing provider or set |\n| `multiple bindings for TYPE` | Two providers return the same type | Use named types or remove the duplicate |\n| `argument N has no provider for TYPE` | An interface is requested but no `wire.Bind` maps to it | Add `wire.Bind(new(Iface), new(*Impl))` to a set |\n| `cycle detected` | A → B → A circular dependency | Break the cycle by introducing an interface or factory |\n| `wire.Build used outside of injector function` | `wire.Build` called from a non-injector function | Only call `wire.Build` inside functions with the build tag |\n| duplicate symbol / redeclared in this block | Injector file is missing `//go:build wireinject` | Add the build tag as the first line |\n\n## Codegen Flags\n\n```bash\n# Specify output file prefix (default: wire_gen)\nwire -output_file_prefix=init gen ./cmd/server\n\n# Apply build tags during generation\nwire -tags=integration gen ./...\n\n# Prepend a header file (e.g., license comment) to generated output\nwire -header_file=hack/boilerplate.go.txt gen ./...\n```\n\n## `panic(wire.Build(...))` Alternate Syntax\n\nWire accepts either a dummy return or a `panic` call as the injector body. The `panic` form avoids writing zero-value returns for complex types:\n\n```go\n// Preferred when return types are complex or error-prone to zero-initialize\nfunc InitApp(ctx context.Context) (*App, func(), error) {\n    panic(wire.Build(AppSet))\n}\n```\n\nWire detects both forms and replaces the body during codegen. The `panic` is never reached in the compiled binary — only the generated `wire_gen.go` version is compiled.\n\n## Accepting External Values as Injector Arguments\n\nWhen a value is constructed before wire runs (e.g., parsed flags, an `http.Client` from a test), pass it as a parameter to the injector rather than providing it from within the graph:\n\n```go\n//go:build wireinject\n\nfunc InitApp(cfg *Config) (*App, func(), error) {\n    wire.Build(InfraSet, ServiceSet, NewApp)\n    return nil, nil, nil\n}\n\n// main.go\ncfg := parseFlags()\napp, cleanup, err := InitApp(cfg)\n```\n\nWire treats injector parameters as pre-built providers — they satisfy dependencies without needing a `wire.NewSet` entry.\n\n## Quick Reference\n\n| Symbol | Purpose |\n| --- | --- |\n| `wire.NewSet(providers...)` | Group providers into a reusable set |\n| `wire.Build(sets...)` | Declare injector body (codegen replaces it) |\n| `wire.Bind(new(Iface), new(*Concrete))` | Bind interface to concrete type |\n| `wire.Struct(new(T), \"Field\", ...)` | Inject struct fields from the graph |\n| `wire.Struct(new(T), \"*\")` | Inject all non-excluded fields |\n| `wire.Value(expr)` | Bind a constant expression (no fn calls/channels) |\n| `wire.InterfaceValue(new(I), value)` | Bind a value to an interface type |\n| `wire.FieldsOf(new(T), \"Field\", ...)` | Promote struct fields as individual graph nodes |\n| `//go:build wireinject` | Build tag: exclude injector stub from binary |\n| `wire_gen.go` | Generated output — commit, never edit |\n| `wire ./...` | Regenerate all injectors in the module |\n| `wire check ./...` | Validate graph without regenerating |\n\nFile v1.0.3:references/recipes.md\n\n# Recipes — google/wire\n\nEnd-to-end examples. Each recipe is self-contained.\n\n## HTTP Server with Postgres and Redis\n\nA typical service: parsed config → DB (with cleanup) → Redis (with cleanup) → repo → service → HTTP server.\n\n```\nmyapp/\n├── config/\n│   ├── config.go\n│   └── wire.go\n├── infra/\n│   ├── db.go\n│   ├── cache.go\n│   └── wire.go\n├── repo/\n│   ├── user.go\n│   └── wire.go\n├── service/\n│   ├── user.go\n│   └── wire.go\n├── transport/\n│   ├── handler.go\n│   └── wire.go\n├── wire.go        // injector — //go:build wireinject\n├── wire_gen.go    // generated — commit this\n└── main.go\n```\n\n```go\n// config/config.go\ntype Config struct {\n    Addr      string\n    DSN       string\n    CacheAddr string\n}\n\nfunc NewConfig() *Config {\n    return &Config{\n        Addr:      env(\"ADDR\", \":8080\"),\n        DSN:       mustEnv(\"DATABASE_URL\"),\n        CacheAddr: env(\"REDIS_ADDR\", \"localhost:6379\"),\n    }\n}\n\n// config/wire.go\nvar ConfigSet = wire.NewSet(NewConfig)\n```\n\n```go\n// infra/db.go\nfunc NewDB(cfg *config.Config) (*sql.DB, func(), error) {\n    db, err := sql.Open(\"postgres\", cfg.DSN)\n    if err != nil { return nil, nil, err }\n    if err := db.Ping(); err != nil { db.Close(); return nil, nil, err }\n    return db, func() { db.Close() }, nil\n}\n\n// infra/cache.go\nfunc NewRedis(cfg *config.Config) (*redis.Client, func(), error) {\n    c := redis.NewClient(&redis.Options{Addr: cfg.CacheAddr})\n    if err := c.Ping(context.Background()).Err(); err != nil {\n        return nil, nil, err\n    }\n    return c, func() { c.Close() }, nil\n}\n\n// infra/wire.go\nvar InfraSet = wire.NewSet(NewDB, NewRedis)\n```\n\n```go\n// repo/user.go\ntype UserStore interface {\n    GetUser(ctx context.Context, id int64) (*User, error)\n}\n\ntype PostgresUserRepo struct{ db *sql.DB }\n\nfunc NewUserRepo(db *sql.DB) *PostgresUserRepo { return &PostgresUserRepo{db: db} }\n\n// repo/wire.go\nvar RepoSet = wire.NewSet(\n    NewUserRepo,\n    wire.Bind(new(UserStore), new(*PostgresUserRepo)),\n)\n```\n\n```go\n// service/user.go\ntype UserService struct {\n    store  repo.UserStore\n    cache  *redis.Client\n}\n\nfunc NewUserService(store repo.UserStore, cache *redis.Client) *UserService {\n    return &UserService{store: store, cache: cache}\n}\n\n// service/wire.go\nvar ServiceSet = wire.NewSet(NewUserService)\n```\n\n```go\n// wire.go\n//go:build wireinject\n\npackage main\n\nfunc InitApp() (*transport.Handler, func(), error) {\n    wire.Build(\n        config.ConfigSet,\n        infra.InfraSet,\n        repo.RepoSet,\n        service.ServiceSet,\n        transport.NewHandler,\n    )\n    return nil, nil, nil\n}\n```\n\n```go\n// main.go\nfunc main() {\n    handler, cleanup, err := InitApp()\n    if err != nil { log.Fatal(err) }\n    defer cleanup()\n\n    srv := &http.Server{Addr: \":8080\", Handler: handler}\n    log.Fatal(srv.ListenAndServe())\n}\n```\n\n## Multiple Build Variants (Prod vs Dev)\n\nUse separate injector files with `//go:build` constraints to select different provider sets at build time.\n\n```go\n// wire_prod.go\n//go:build wireinject && !dev\n\npackage main\n\nfunc InitApp() (*App, func(), error) {\n    wire.Build(ProdSet, NewApp)\n    return nil, nil, nil\n}\n\n// wire_dev.go\n//go:build wireinject && dev\n\npackage main\n\nfunc InitApp() (*App, func(), error) {\n    wire.Build(DevSet, NewApp) // DevSet swaps real DB for in-memory SQLite\n    return nil, nil, nil\n}\n```\n\nUse `-output_file_prefix` to write separate output files — both commands would otherwise overwrite the same `wire_gen.go`:\n\n```bash\nwire -tags dev -output_file_prefix=wire_gen_dev gen .\nwire -output_file_prefix=wire_gen_prod gen .\n```\n\nAdd build constraints to the generated files so only one compiles per build:\n\n```go\n// wire_gen_prod.go — add at the top (after wire writes it)\n//go:build !dev\n\n// wire_gen_dev.go — add at the top\n//go:build dev\n```\n\nCommit both generated files. At build time, only the matching file is compiled.\n\n## Cleanup-Heavy Graph\n\nWhen several providers need shutdown coordination, wire's reverse-order cleanup is essential.\n\n```go\n// Providers return (T, func(), error)\nfunc NewDBPool(cfg *Config) (*pgxpool.Pool, func(), error) {\n    pool, err := pgxpool.New(context.Background(), cfg.DSN)\n    if err != nil { return nil, nil, err }\n    return pool, func() { pool.Close() }, nil\n}\n\nfunc NewOTelExporter(cfg *Config) (*otlptrace.Exporter, func(), error) {\n    exp, err := otlptracegrpc.New(context.Background(), ...)\n    if err != nil { return nil, nil, err }\n    return exp, func() { exp.Shutdown(context.Background()) }, nil\n}\n\nfunc NewTracerProvider(exp *otlptrace.Exporter) (*trace.TracerProvider, func(), error) {\n    tp := trace.NewTracerProvider(trace.WithBatcher(exp))\n    return tp, func() { tp.Shutdown(context.Background()) }, nil\n}\n```\n\nWire generates shutdown in reverse: `TracerProvider` → `OTelExporter` → `DBPool`. Each cleanup runs before its dependencies shut down — guaranteeing in-flight spans are flushed before the exporter closes.\n\n## Embedding Wire in a CLI\n\nWire produces a struct, not an app framework. You control the lifecycle:\n\n```go\n// wire.go\n//go:build wireinject\n\npackage cmd\n\nfunc InitServer(cfg *Config) (*http.Server, func(), error) {\n    wire.Build(InfraSet, ServiceSet, NewHTTPServer)\n    return nil, nil, nil\n}\n\n// cmd/serve.go\nfunc runServe(cfg *Config) error {\n    srv, cleanup, err := InitServer(cfg)\n    if err != nil { return err }\n    defer cleanup()\n\n    quit := make(chan os.Signal, 1)\n    signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)\n\n    go func() {\n        if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {\n            log.Fatal(err)\n        }\n    }()\n    <-quit\n    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)\n    defer cancel()\n    return srv.Shutdown(ctx)\n}\n```\n\nUnlike `fx.Run()`, wire does not manage the lifecycle loop. Implement signal handling and graceful shutdown explicitly. This is a feature for CLI tools that spin up short-lived services and need precise control over the shutdown sequence.\n\n## Passing External Values to Wire\n\nValues built before wire runs (parsed config, test doubles) become injector parameters:\n\n```go\n//go:build wireinject\n\n// cfg is resolved outside the graph — treated as a provided *Config\nfunc InitApp(cfg *Config) (*App, func(), error) {\n    wire.Build(InfraSet, ServiceSet, NewApp)\n    return nil, nil, nil\n}\n\n// main.go\ncfg, err := config.Load()\nif err != nil { log.Fatal(err) }\napp, cleanup, err := InitApp(cfg)\n```\n\nThe parameter `cfg *Config` satisfies any downstream provider that requests `*Config` — no `wire.Value` or extra set entry needed.\n\nFile v1.0.3:references/testing.md\n\n# Testing — google/wire\n\nWire generates plain Go constructor calls, so tests work directly on the constructor layer — no container API to learn.\n\n## Unit Tests: Plain Constructor Injection\n\nThe generated code has no wire dependency. Test constructors directly:\n\n```go\nfunc TestUserService_GetUser(t *testing.T) {\n    mockStore := &MockUserStore{users: map[int64]*User{1: &User{ID: 1, Name: \"Alice\"}}}\n    cache := newTestRedis(t)\n    svc := service.NewUserService(mockStore, cache)\n\n    u, err := svc.GetUser(context.Background(), 1)\n    require.NoError(t, err)\n    assert.Equal(t, \"Alice\", u.Name)\n}\n```\n\nPass mocks directly as constructor arguments. No wire, no container, no file to generate. This is the idiomatic approach for unit tests.\n\n## Test Injectors: Swapping Providers\n\nFor integration or component tests where you want the full wired graph but with selected dependencies replaced, create a test-only injector in a `_test.go` file.\n\n```go\n// app_test.go\n//go:build wireinject\n\npackage main\n\nimport (\n    \"testing\"\n    \"github.com/google/wire\"\n)\n\n// TestSet replaces real infra with in-memory fakes\nvar TestSet = wire.NewSet(\n    NewTestConfig,\n    NewInMemoryUserStore,\n    wire.Bind(new(repo.UserStore), new(*InMemoryUserStore)),\n    NewTestRedis,\n)\n\nfunc InitTestApp(t *testing.T) (*App, func(), error) {\n    wire.Build(TestSet, service.ServiceSet, NewApp)\n    return nil, nil, nil\n}\n```\n\n```go\n// app_integration_test.go\n//go:build !wireinject  // compiles when the wireinject tag is NOT set\n\npackage main\n\nfunc TestApp_GetUser(t *testing.T) {\n    app, cleanup, err := InitTestApp(t)\n    require.NoError(t, err)\n    defer cleanup()\n\n    // test against the fully-wired app with fake dependencies\n    u, err := app.GetUser(context.Background(), 1)\n    require.NoError(t, err)\n    assert.NotNil(t, u)\n}\n```\n\nRun `wire ./...` to generate `wire_gen.go` — the test injector is included because the `_test.go` file is compiled as part of the package during `go test`.\n\n**Key pattern from upstream best practices:** Prefer creating a test-only provider set over passing mocks as injector arguments (though both work). The set approach keeps the test injector composable.\n\n## Passing Mocks as Injector Arguments\n\nAn alternative to a test set: pass the mock directly as an injector parameter. Wire treats it as a pre-built provider.\n\n```go\n//go:build wireinject\n\nfunc InitTestApp(store repo.UserStore) (*App, func(), error) {\n    wire.Build(config.ConfigSet, service.ServiceSet, NewApp)\n    return nil, nil, nil\n}\n\n// Test\nfunc TestApp(t *testing.T) {\n    mock := &MockUserStore{}\n    app, cleanup, err := InitTestApp(mock)\n    require.NoError(t, err)\n    defer cleanup()\n    // ...\n}\n```\n\nUse this form when you only need to replace one or two dependencies and a full `TestSet` is overkill.\n\n## CI: Detecting Stale `wire_gen.go`\n\nIf `wire_gen.go` is not regenerated after a provider change, CI builds pass but the graph is wrong. Enforce freshness in CI:\n\n```bash\n# Option 1: re-run wire and check for diffs\nwire ./...\ngit diff --exit-code -- '**/wire_gen.go'\n```\n\n```yaml\n# .github/workflows/ci.yml\n- name: Check wire_gen.go is up-to-date\n  run: |\n    go install github.com/google/wire/cmd/wire@v0.7.0\n    wire ./...\n    git diff --exit-code -- '**/wire_gen.go'\n```\n\n```bash\n# Option 2: use wire check (verifies graph without regenerating)\nwire check ./...\n```\n\n`wire check` exits non-zero if the graph is inconsistent but does **not** update `wire_gen.go`. Use it for a fast graph-validity check without modifying files.\n\n## Testing Interface Bindings\n\n`wire.Bind` can be used in test sets to bind a fake to the same interface:\n\n```go\n// Fake implements the same interface as the real provider\ntype FakeMailer struct{ sent []string }\nfunc (f *FakeMailer) Send(to, body string) error { f.sent = append(f.sent, to); return nil }\n\nvar TestMailerSet = wire.NewSet(\n    NewFakeMailer,\n    wire.Bind(new(notification.Mailer), new(*FakeMailer)),\n)\n\nvar TestSet = wire.NewSet(\n    TestMailerSet,\n    realServiceSet,  // everything else is real\n)\n```\n\nThis keeps the test injector narrow — only the Mailer is faked; the rest of the graph is real.\n\n## Table-Driven Tests Without Wire\n\nWire is an initialization tool. Once the object graph is built, table-driven tests on individual services need no wire involvement:\n\n```go\nfunc TestUserService(t *testing.T) {\n    cases := []struct {\n        name  string\n        id    int64\n        users map[int64]*User\n        want  string\n        err   bool\n    }{\n        {\"found\", 1, map[int64]*User{1: &User{Name: \"Alice\"}}, \"Alice\", false},\n        {\"not found\", 99, nil, \"\", true},\n    }\n    for _, tc := range cases {\n        t.Run(tc.name, func(t *testing.T) {\n            svc := service.NewUserService(&MockUserStore{users: tc.users}, nil)\n            u, err := svc.GetUser(context.Background(), tc.id)\n            if tc.err { require.Error(t, err); return }\n            assert.Equal(t, tc.want, u.Name)\n        })\n    }\n}\n```\n\nWire has no role here — the injector was only needed to build the object graph in `main` (or in an integration test). Unit tests construct dependencies directly.\n\nFile v1.0.3:skill-card.md\n\n## Description: <br>\nHelps coding agents use google/wire for compile-time dependency injection in Go projects, including provider sets, injectors, interface bindings, generated wire_gen.go files, cleanup functions, testing patterns, and related Wire commands. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[samber](https://clawhub.ai/user/samber) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nDevelopers and engineering agents use this skill to adopt or maintain google/wire dependency injection in Go codebases, generate and check injector output, and avoid common compile-time graph and build-tag mistakes. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The skill may install or run the wire CLI and Go-related commands in a project workspace. <br>\nMitigation: Use it only in intended Go repositories, review proposed shell commands before execution, and confirm tool installation sources match project policy. <br>\nRisk: The skill may modify Go source files and generated wire_gen.go files. <br>\nMitigation: Review generated diffs before committing and run the project test or build workflow after Wire regeneration. <br>\nRisk: Dependency-injection changes can alter application initialization, cleanup behavior, or provider selection. <br>\nMitigation: Check provider graph changes carefully, rerun wire ./... or wire check ./..., and validate affected startup and integration paths. <br>\n\n\n## Reference(s): <br>\n- [ClawHub skill page](https://clawhub.ai/samber/golang-google-wire) <br>\n- [Publisher profile](https://clawhub.ai/user/samber) <br>\n- [Skill homepage](https://github.com/samber/cc-skills-golang) <br>\n- [pkg.go.dev google/wire](https://pkg.go.dev/github.com/google/wire) <br>\n- [google/wire repository](https://github.com/google/wire) <br>\n- [google/wire user guide](https://github.com/google/wire/blob/main/docs/guide.md) <br>\n- [google/wire best practices](https://github.com/google/wire/blob/main/docs/best-practices.md) <br>\n- [Advanced google/wire reference](references/advanced.md) <br>\n- [google/wire recipes](references/recipes.md) <br>\n- [google/wire testing reference](references/testing.md) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [guidance, markdown, code, shell commands, configuration] <br>\n**Output Format:** [Markdown with Go and bash code blocks] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [May propose edits to Go source, injector files, generated wire_gen.go files, and Go or Wire command invocations.] <br>\n\n## Skill Version(s): <br>\n1.0.3 (source: server release metadata and skill frontmatter) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nFile v1.0.3:evals/evals.json\n\n[\n  {\n    \"id\": 1,\n    \"name\": \"build-constraint-on-injector\",\n    \"description\": \"Tests that the model adds //go:build wireinject to injector files to prevent duplicate-symbol compile errors\",\n    \"prompt\": \"I'm setting up google/wire in my Go project. Here's my injector file:\\n\\n```go\\npackage main\\n\\nimport \\\"github.com/google/wire\\\"\\n\\nfunc InitApp() (*App, error) {\\n    wire.Build(InfraSet, ServiceSet, NewApp)\\n    return nil, nil\\n}\\n```\\n\\nWire generates wire_gen.go successfully, but when I run `go build`, I get a 'redeclared in this block' compile error for InitApp. What's wrong and how do I fix it?\",\n    \"trap\": \"Without the skill, the model may suggest renaming the function, reorganizing packages, or not identify that the missing //go:build wireinject tag is the cause — both the stub and wire_gen.go define InitApp, causing the duplicate.\",\n    \"assertions\": [\n      {\"id\": \"1.1\", \"text\": \"Identifies the missing //go:build wireinject build tag as the root cause\"},\n      {\"id\": \"1.2\", \"text\": \"Shows //go:build wireinject as the first line of the injector file\"},\n      {\"id\": \"1.3\", \"text\": \"Explains that the tag prevents the stub from being compiled into the binary (only wire_gen.go compiles)\"},\n      {\"id\": \"1.4\", \"text\": \"Does NOT suggest renaming the function or reorganizing packages as the fix\"},\n      {\"id\": \"1.5\", \"text\": \"Does NOT suggest deleting wire_gen.go as the fix\"}\n    ]\n  },\n  {\n    \"id\": 2,\n    \"name\": \"interface-binding-required\",\n    \"description\": \"Tests that wire.Bind is required for interface-to-concrete mappings and cannot be inferred\",\n    \"prompt\": \"I have this Go code using google/wire:\\n\\n```go\\n// repo.go\\ntype UserStore interface {\\n    GetUser(id int64) (*User, error)\\n}\\n\\ntype PostgresUserRepo struct{ db *sql.DB }\\nfunc (r *PostgresUserRepo) GetUser(id int64) (*User, error) { ... }\\nfunc NewUserRepo(db *sql.DB) *PostgresUserRepo { return &PostgresUserRepo{db: db} }\\n\\n// service.go\\nfunc NewUserService(store UserStore) *UserService { return &UserService{store: store} }\\n\\n// wire_providers.go\\nvar AppSet = wire.NewSet(NewDB, NewUserRepo, NewUserService)\\n```\\n\\nWhen I run `wire ./...` I get: `no provider found for UserStore`. NewUserRepo returns *PostgresUserRepo which clearly implements UserStore. Why doesn't wire figure this out?\",\n    \"trap\": \"Without the skill, the model might suggest wire should automatically resolve the interface, or suggest wrapping NewUserRepo to return UserStore directly, missing the explicit wire.Bind requirement.\",\n    \"assertions\": [\n      {\"id\": \"2.1\", \"text\": \"Explains that wire never auto-resolves interface satisfaction — bindings must be explicit\"},\n      {\"id\": \"2.2\", \"text\": \"Shows wire.Bind(new(UserStore), new(*PostgresUserRepo)) added to the provider set\"},\n      {\"id\": \"2.3\", \"text\": \"Places wire.Bind inside the same wire.NewSet (or adds it to a set in wire.Build)\"},\n      {\"id\": \"2.4\", \"text\": \"Explains WHY wire requires explicit bindings (predictability — avoids surprise rebinding when new implementations are added)\"},\n      {\"id\": \"2.5\", \"text\": \"Does NOT suggest changing NewUserRepo to return UserStore directly as the primary fix\"}\n    ]\n  },\n  {\n    \"id\": 3,\n    \"name\": \"duplicate-type-named-wrapper\",\n    \"description\": \"Tests the named-type pattern to disambiguate multiple values of the same underlying type\",\n    \"prompt\": \"I'm building a Go service with google/wire. I need to inject two database connection strings — one for the primary database and one for a read replica. I tried this:\\n\\n```go\\nfunc NewPrimaryDSN() string { return os.Getenv(\\\"PRIMARY_DSN\\\") }\\nfunc NewReplicaDSN() string { return os.Getenv(\\\"REPLICA_DSN\\\") }\\n\\nvar DBSet = wire.NewSet(NewPrimaryDSN, NewReplicaDSN, NewPrimaryDB, NewReplicaDB)\\n```\\n\\nWire complains about multiple bindings for string. How should I structure this?\",\n    \"trap\": \"Without the skill, the model might suggest using wire.Value or provider arguments, or use a config struct — missing the idiomatic named-type wrapper pattern that wire's own docs recommend.\",\n    \"assertions\": [\n      {\"id\": \"3.1\", \"text\": \"Introduces distinct named types (e.g., type PrimaryDSN string and type ReplicaDSN string)\"},\n      {\"id\": \"3.2\", \"text\": \"Updates NewPrimaryDSN to return PrimaryDSN and NewReplicaDSN to return ReplicaDSN\"},\n      {\"id\": \"3.3\", \"text\": \"Updates NewPrimaryDB and NewReplicaDB signatures to accept the named types\"},\n      {\"id\": \"3.4\", \"text\": \"Explains that wire enforces one provider per type, so distinct named types are the correct solution\"},\n      {\"id\": \"3.5\", \"text\": \"Does NOT suggest using a single Config struct with both DSNs as the primary fix (that avoids the problem rather than solving it with named types)\"}\n    ]\n  },\n  {\n    \"id\": 4,\n    \"name\": \"cleanup-signature\",\n    \"description\": \"Tests the (T, func(), error) cleanup provider pattern instead of manual defer in main\",\n    \"prompt\": \"I'm using google/wire to wire my Go service. I need my *sql.DB connection pool to be closed when the app shuts down. Currently I'm doing this in main:\\n\\n```go\\nfunc main() {\\n    app, err := InitApp()\\n    if err != nil { log.Fatal(err) }\\n    defer db.Close() // but I don't have access to db here!\\n    app.Run()\\n}\\n```\\n\\nI realize I need the DB closed on shutdown, but InitApp() only returns *App. How should I wire cleanup with google/wire?\",\n    \"trap\": \"Without the skill, the model might suggest passing db out of InitApp as a second return value, or storing it as a global, missing the (T, func(), error) cleanup provider pattern.\",\n    \"assertions\": [\n      {\"id\": \"4.1\", \"text\": \"Changes NewDB to return (*sql.DB, func(), error) where the cleanup function calls db.Close()\"},\n      {\"id\": \"4.2\", \"text\": \"Changes the injector function to return (*App, func(), error) to propagate the cleanup chain\"},\n      {\"id\": \"4.3\", \"text\": \"Shows main calling defer cleanup() after the nil-check\"},\n      {\"id\": \"4.4\", \"text\": \"Explains that wire chains cleanup functions and calls them in reverse construction order\"},\n      {\"id\": \"4.5\", \"text\": \"Does NOT suggest passing db as an extra return value from InitApp alongside *App\"}\n    ]\n  },\n  {\n    \"id\": 5,\n    \"name\": \"no-edit-wire-gen\",\n    \"description\": \"Tests that the model never edits wire_gen.go and instructs re-running wire ./... instead\",\n    \"prompt\": \"I added a new *Logger parameter to my NewServer constructor in my google/wire project:\\n\\n```go\\nfunc NewServer(db *sql.DB, log *zap.Logger) *Server { ... }\\n```\\n\\nNow `go build` fails with 'too few arguments in call to NewServer'. The error is inside wire_gen.go on line 47. Should I edit wire_gen.go to add the logger argument there, or is there another way?\",\n    \"trap\": \"Without the skill, a model may suggest editing wire_gen.go directly to 'fix' the build error quickly, which would be overwritten on the next wire run.\",\n    \"assertions\": [\n      {\"id\": \"5.1\", \"text\": \"Explicitly says NOT to edit wire_gen.go (it is always overwritten)\"},\n      {\"id\": \"5.2\", \"text\": \"Instructs running wire ./... to regenerate wire_gen.go\"},\n      {\"id\": \"5.3\", \"text\": \"Explains that *zap.Logger must be provided in the graph (either via a provider or wire.Value)\"},\n      {\"id\": \"5.4\", \"text\": \"Shows how to add NewLogger (or wire.Value) to the appropriate wire.NewSet so the dependency is satisfied\"},\n      {\"id\": \"5.5\", \"text\": \"Does NOT present editing wire_gen.go as an option\"}\n    ]\n  },\n  {\n    \"id\": 6,\n    \"name\": \"provider-set-organization\",\n    \"description\": \"Tests per-package provider set organization instead of one giant set in main\",\n    \"prompt\": \"My Go service using google/wire is growing. I currently have everything in one place:\\n\\n```go\\n// wire.go\\n//go:build wireinject\\n\\nfunc InitApp() (*App, func(), error) {\\n    wire.Build(\\n        NewConfig, NewDB, NewCache, NewLogger,\\n        NewUserRepo, NewOrderRepo, NewProductRepo,\\n        wire.Bind(new(UserStore), new(*PostgresUserRepo)),\\n        wire.Bind(new(OrderStore), new(*PostgresOrderRepo)),\\n        wire.Bind(new(ProductStore), new(*PostgresProductRepo)),\\n        NewUserService, NewOrderService, NewProductService,\\n        NewHTTPServer, NewRouter,\\n        NewApp,\\n    )\\n    return nil, nil, nil\\n}\\n```\\n\\nThis is getting unwieldy. How should I organize this with google/wire?\",\n    \"trap\": \"Without the skill, the model may just split the providers into helper variables in the same package, missing the idiomatic per-package wire.NewSet pattern.\",\n    \"assertions\": [\n      {\"id\": \"6.1\", \"text\": \"Introduces per-package wire.NewSet variables (e.g., InfraSet, RepoSet, ServiceSet, TransportSet)\"},\n      {\"id\": \"6.2\", \"text\": \"Each set lives in its own package's wire.go file (not all in main)\"},\n      {\"id\": \"6.3\", \"text\": \"The injector wire.Build references the set variables rather than individual providers\"},\n      {\"id\": \"6.4\", \"text\": \"wire.Bind declarations move into the relevant package's set (not into wire.Build directly)\"},\n      {\"id\": \"6.5\", \"text\": \"Explains the benefit: per-package sets are independently composable and keep the injector readable\"}\n    ]\n  },\n  {\n    \"id\": 7,\n    \"name\": \"injector-parameter-vs-value-provider\",\n    \"description\": \"Tests using wire.Value or injector parameters for pre-built values instead of wrapper constructors\",\n    \"prompt\": \"In my Go app using google/wire, I parse a *Config struct from command-line flags in main() before calling InitApp. I tried writing a no-op provider:\\n\\n```go\\nvar parsedCfg *Config\\n\\nfunc ProvideConfig() *Config { return parsedCfg }\\n\\nvar AppSet = wire.NewSet(ProvideConfig, ...)\\n```\\n\\nThis works but feels wrong — I'm using a global variable. Is there a cleaner way to pass a pre-built *Config into the wire graph?\",\n    \"trap\": \"Without the skill, the model might suggest keeping the global variable pattern or using init(), missing both wire.Value and the injector-parameter patterns.\",\n    \"assertions\": [\n      {\"id\": \"7.1\", \"text\": \"Shows the injector-parameter approach: func InitApp(cfg *Config) (*App, func(), error) with wire.Build\"},\n      {\"id\": \"7.2\", \"text\": \"OR shows wire.Value(cfg) inside wire.Build — both are valid answers\"},\n      {\"id\": \"7.3\", \"text\": \"Explains that injector parameters are treated as pre-built providers by wire\"},\n      {\"id\": \"7.4\", \"text\": \"Does NOT use a global variable as the recommended solution\"},\n      {\"id\": \"7.5\", \"text\": \"Does NOT suggest using init() to set the value\"}\n    ]\n  },\n  {\n    \"id\": 8,\n    \"name\": \"fields-of-struct\",\n    \"description\": \"Tests wire.FieldsOf to expose struct fields as individual graph nodes\",\n    \"prompt\": \"I have a single Config struct in my Go app with google/wire:\\n\\n```go\\ntype Config struct {\\n    DatabaseDSN  string\\n    CacheAddress string\\n    APIKey       string\\n}\\n\\nfunc NewConfig() *Config { return loadFromEnv() }\\n```\\n\\nNewDB needs a DatabaseDSN string, NewCache needs a CacheAddress string, NewExternalClient needs an APIKey string — but all three are plain strings. How do I make these available to the wire graph without creating three separate provider functions?\",\n    \"trap\": \"Without the skill, the model will suggest three named-type wrappers or three extraction functions, missing wire.FieldsOf which promotes struct fields directly.\",\n    \"assertions\": [\n      {\"id\": \"8.1\", \"text\": \"Uses wire.FieldsOf(new(Config), \\\"DatabaseDSN\\\", \\\"CacheAddress\\\", \\\"APIKey\\\") or a subset\"},\n      {\"id\": \"8.2\", \"text\": \"Places wire.FieldsOf inside the provider set or wire.Build\"},\n      {\"id\": \"8.3\", \"text\": \"Updates NewDB, NewCache, NewExternalClient to accept the string fields as parameters (or uses named types alongside FieldsOf)\"},\n      {\"id\": \"8.4\", \"text\": \"Explains that wire.FieldsOf promotes struct fields as individual graph nodes without manual extraction functions\"},\n      {\"id\": \"8.5\", \"text\": \"Does NOT suggest writing three separate func GetDatabaseDSN(c *Config) string extractor functions as the primary recommendation\"}\n    ]\n  },\n  {\n    \"id\": 9,\n    \"name\": \"test-injector-pattern\",\n    \"description\": \"Tests the test-injector pattern with wire.Bind for fake dependencies instead of runtime mocking hacks\",\n    \"prompt\": \"My Go service is wired with google/wire. I have a Mailer interface implemented by SMTPMailer in production. I want integration tests that use a FakeMailer instead — recording sent emails — without modifying the production provider sets. The test must wire the full graph (not just NewUserService in isolation). How should I approach this?\",\n    \"trap\": \"Without the skill, the model may suggest monkey-patching, a global variable for the mailer, or a runtime DI container for tests — missing the test-injector pattern with a test-only wire.NewSet and wire.Bind.\",\n    \"assertions\": [\n      {\"id\": \"9.1\", \"text\": \"Creates a test-only provider set (e.g., TestMailerSet) with NewFakeMailer and wire.Bind(new(Mailer), new(*FakeMailer))\"},\n      {\"id\": \"9.2\", \"text\": \"Creates a test injector function in a _test.go file with //go:build wireinject\"},\n      {\"id\": \"9.3\", \"text\": \"The test injector's wire.Build composes the production sets with the test-only set\"},\n      {\"id\": \"9.4\", \"text\": \"Does NOT suggest global variables, monkey-patching, or a runtime DI container for tests\"},\n      {\"id\": \"9.5\", \"text\": \"Mentions that wire ./... (or go generate) must be run to produce the test-injector generated code\"}\n    ]\n  },\n  {\n    \"id\": 10,\n    \"name\": \"wire-vs-fx-for-daemon\",\n    \"description\": \"Tests that the model recommends uber-go/fx over wire for long-running services that need lifecycle management\",\n    \"prompt\": \"I'm starting a new Go HTTP server project and evaluating DI options. A colleague suggested google/wire because 'it's simpler and type-safe at compile time.' The server needs graceful shutdown (drain in-flight requests), OnStart/OnStop hooks for the database pool and metrics exporter, and should handle SIGINT/SIGTERM. Should I use wire?\",\n    \"trap\": \"Without the skill, the model may agree that wire is suitable because it's simple and compile-time safe, not recognizing that lifecycle, signal handling, and hook ordering are exactly what fx provides and wire explicitly lacks.\",\n    \"assertions\": [\n      {\"id\": \"10.1\", \"text\": \"Identifies that wire has no built-in lifecycle management (no OnStart/OnStop hooks)\"},\n      {\"id\": \"10.2\", \"text\": \"Identifies that wire has no built-in signal handling (SIGINT/SIGTERM)\"},\n      {\"id\": \"10.3\", \"text\": \"Recommends uber-go/fx (or at minimum flags it as the better fit) for a long-running HTTP daemon with lifecycle needs\"},\n      {\"id\": \"10.4\", \"text\": \"Does NOT recommend wire as sufficient for a service requiring graceful shutdown and lifecycle hooks\"},\n      {\"id\": \"10.5\", \"text\": \"Mentions that with wire the developer must implement shutdown and signal handling manually\"}\n    ]\n  }\n]\n\nArchive v1.0.2: 7 files, 18614 bytes\n\nFiles: evals/evals.json (14841b), references/advanced.md (6966b), references/recipes.md (6718b), references/testing.md (5146b), skill-card.md (2592b), SKILL.md (10629b), _meta.json (137b)\n\nFile v1.0.2:SKILL.md\n\n---\nname: golang-google-wire\ndescription: \"Compile-time dependency injection in Golang using google/wire — wire.NewSet, wire.Build, wire.Bind (interface→concrete), wire.Struct, wire.Value, wire.InterfaceValue, wire.FieldsOf, cleanup functions, //go:build wireinject injector files, and generated wire_gen.go. Apply when using or adopting google/wire, when the codebase imports `github.com/google/wire`, or when wiring an application graph at compile time via `wire.Build`. For runtime DI with reflection, see `samber/cc-skills-golang@golang-uber-dig` skill.\"\nuser-invocable: true\nlicense: MIT\ncompatibility: Designed for Claude Code or similar AI coding agents, and for projects using Golang.\nmetadata:\n  author: samber\n  version: \"1.0.2\"\n  openclaw:\n    emoji: \"🪡\"\n    homepage: https://github.com/samber/cc-skills-golang\n    requires:\n      bins:\n        - go\n        - wire\n    install:\n      - kind: go\n        package: github.com/google/wire/cmd/wire@latest\n        bins: [wire]\n    skill-library-version: \"0.7.0\"\nallowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*) Bash(git:*) Agent WebFetch mcp__context7__resolve-library-id mcp__context7__query-docs Bash(wire:*)\n---\n\n**Persona:** You are a Go architect using wire for compile-time DI. You let the compiler catch missing dependencies, treat `wire_gen.go` as committed source, and re-run `wire ./...` after every graph change.\n\n# Using google/wire for Compile-Time Dependency Injection in Go\n\nCode-generation DI toolkit. Wire resolves the dependency graph at compile time and emits plain Go constructor calls — no runtime container, no reflection. Errors appear when you run `wire ./...`, not at first request.\n\nNote: `google/wire` was archived in August 2025 (feature-complete; bug fixes still accepted).\n\n**Official Resources:** [pkg.go.dev](https://pkg.go.dev/github.com/google/wire) · [github.com/google/wire](https://github.com/google/wire) · [User Guide](https://github.com/google/wire/blob/main/docs/guide.md) · [Best Practices](https://github.com/google/wire/blob/main/docs/best-practices.md)\n\nThis skill is not exhaustive. Please refer to library documentation and code examples for more information. Context7 can help as a discoverability platform.\n\n```bash\ngo get -tool github.com/google/wire/cmd/wire@latest\ngo get github.com/google/wire\n```\n\n## wire vs. Runtime DI\n\n| Concern           | wire                      | dig / fx / samber/do   |\n| ----------------- | ------------------------- | ---------------------- |\n| Resolution        | Compile time (codegen)    | Runtime (reflection)   |\n| Error detection   | `wire ./...` fails        | First `Invoke`/startup |\n| Runtime container | None — plain Go calls     | Present                |\n| Lifecycle hooks   | Not built in              | fx: OnStart/OnStop     |\n| Generated files   | `wire_gen.go` (committed) | None                   |\n\nFor lifecycle, lazy loading, and a full matrix see `samber/cc-skills-golang@golang-dependency-injection`.\n\n## Providers\n\nA provider is any Go function — inputs are dependencies, outputs are provided types. Three return forms:\n\n```go\nfunc NewConfig() *Config                          { return &Config{Addr: \":8080\"} }\nfunc NewDB(cfg *Config) (*sql.DB, error)          { return sql.Open(\"postgres\", cfg.DSN) }\nfunc NewRedis(cfg *Config) (*redis.Client, func(), error) { // cleanup chained in reverse order\n    c := redis.NewClient(&redis.Options{Addr: cfg.RedisAddr})\n    return c, func() { c.Close() }, nil\n}\n```\n\n## Provider Sets\n\n`wire.NewSet` groups providers for reuse. Sets can reference other sets.\n\n```go\n// infra/wire.go\nvar InfraSet = wire.NewSet(\n    NewConfig,\n    NewDB,\n    NewRedis,\n)\n\n// service/wire.go\nvar ServiceSet = wire.NewSet(\n    NewUserRepo,\n    NewUserService,\n    wire.Bind(new(UserStore), new(*UserRepo)), // interface binding\n)\n```\n\nKeep sets small: library sets expose a stable surface (adding inputs or removing outputs breaks downstream injectors). One set per package is a useful default.\n\n## Injectors and `//go:build wireinject`\n\nThe injector file declares the initialization function. Wire generates its body into `wire_gen.go` and replaces the stub.\n\n```go\n//go:build wireinject\n\npackage main\n\nimport \"github.com/google/wire\"\n\n// Wire generates the body of this function.\nfunc InitApp() (*App, func(), error) {\n    wire.Build(InfraSet, ServiceSet, NewApp)\n    return nil, nil, nil // replaced by codegen\n}\n```\n\nThe `//go:build wireinject` tag prevents the stub from being compiled into the binary — only `wire_gen.go` (which has no such tag) makes it through `go build`. Without this tag, both files define the same function, causing a compile error.\n\nAlternative syntax when a dummy return is inconvenient:\n\n```go\nfunc InitApp() (*App, func(), error) {\n    panic(wire.Build(InfraSet, ServiceSet, NewApp))\n}\n```\n\n## Interface Bindings\n\nWire forbids implicit interface satisfaction — you must declare bindings explicitly so the graph is unambiguous when multiple types implement the same interface.\n\n```go\nvar Set = wire.NewSet(\n    NewPostgresUserRepo,\n    wire.Bind(new(UserStore), new(*PostgresUserRepo)), // tell wire: *PostgresUserRepo satisfies UserStore\n)\n```\n\nExplicit bindings prevent graph breakage when a new type implementing the same interface is added elsewhere.\n\n## Struct Providers and Values\n\n`wire.Struct` fills struct fields from the graph without a manual constructor. Tag fields `wire:\"-\"` to exclude them.\n\n```go\nwire.Struct(new(Server), \"Logger\", \"DB\") // inject named fields\nwire.Struct(new(Server), \"*\")            // inject all non-excluded fields\nwire.Value(Foo{X: 42})                   // constant expression (no fn calls / channels)\nwire.InterfaceValue(new(io.Reader), os.Stdin) // interface-typed literal\nwire.FieldsOf(new(Config), \"DSN\", \"Addr\")    // promote struct fields as graph nodes\n```\n\nSee [advanced.md](references/advanced.md) for the `wire:\"-\"` exclusion tag and `wire.FieldsOf` details.\n\n## Disambiguating Duplicate Types\n\nWire forbids two providers for the same type. Wrap the underlying type in distinct named types so each has exactly one provider:\n\n```go\ntype PrimaryDSN string\ntype ReplicaDSN string\n```\n\n## Full Application Example\n\n```go\n// wire.go — injector, excluded from binary via build tag\n//go:build wireinject\n\npackage main\n\nfunc InitApp() (*App, func(), error) {\n    wire.Build(config.ConfigSet, infra.InfraSet, service.ServiceSet, NewApp)\n    return nil, nil, nil\n}\n\n// main.go\nfunc main() {\n    app, cleanup, err := InitApp()\n    if err != nil { log.Fatal(err) }\n    defer cleanup()\n    app.Run()\n}\n```\n\nWire generates `wire_gen.go` (plain Go, committed, DO NOT EDIT). For a full example with per-package sets, cleanup-heavy graphs, and generated output, see [recipes.md](references/recipes.md).\n\n## Codegen Workflow\n\n```bash\nwire ./...           # regenerate all injectors in the module\nwire check ./...     # validate graph without regenerating (fast CI check)\n```\n\nRun `wire ./...` after every constructor signature change. Add `//go:generate go run github.com/google/wire/cmd/wire` to injector files so `go generate ./...` also works. Commit `wire_gen.go` — it must stay in sync for CI builds.\n\n## Best Practices\n\n1. Never edit `wire_gen.go` — it is overwritten on every `wire ./...` run. Treat it as a build artifact that happens to be committed; source of truth is the provider and injector files.\n2. Always add `//go:build wireinject` to injector files — omitting it causes duplicate-symbol compile errors because both the stub and the generated file define the same function.\n3. Use named types to distinguish values of the same underlying type — wire enforces one provider per type; named types like `type DSN string` let you have `PrimaryDSN` and `ReplicaDSN` coexist.\n4. Keep library provider sets minimal and backward-compatible — adding new required inputs breaks downstream injectors; removing outputs does too. Introduce only newly-created types in the same release.\n5. Return `(T, func(), error)` from cleanup providers and let wire chain them — wire generates the correct reverse-order cleanup and handles partial failures (if construction fails midway, only already-built cleanups run).\n6. Keep injector files focused — one function per file, one package import at a time. Fat injectors with dozens of `wire.Build` arguments are hard to reason about; delegate to per-package sets.\n\n## Common Mistakes\n\n| Mistake | Fix |\n| --- | --- |\n| Editing `wire_gen.go` manually | Never edit it. Change providers or injectors and re-run `wire ./...`. |\n| Missing `//go:build wireinject` | Add the tag as the very first line of every injector file. |\n| Two providers returning `*sql.DB` | Wrap with a named struct type: `type PrimaryDB struct { *sql.DB }` — Wire does not distinguish pointer type aliases. |\n| Injecting an interface without `wire.Bind` | Add `wire.Bind(new(MyInterface), new(*MyImpl))` to the provider set. |\n| Forgetting to re-run `wire ./...` after changes | Run wire before `go build`; add it to `go generate` or a Makefile target. |\n| Calling `cleanup()` without guarding for nil | Wire returns nil cleanup on construction error; guard with `if cleanup != nil { defer cleanup() }`. |\n\n## Testing\n\nWire generates plain Go constructors, so unit tests use manual injection — no container to clone or reset. For testing patterns (test injectors swapping real providers for fakes, CI stale-check for `wire_gen.go`), see [testing.md](references/testing.md).\n\n## Further Reading\n\n- [advanced.md](references/advanced.md) — cleanup chains, multiple injectors, set nesting, error catalogue, codegen flags, quick reference\n- [recipes.md](references/recipes.md) — HTTP server, multi-injector build, cleanup-heavy graph, CLI embedding\n- [testing.md](references/testing.md) — test injectors, fake bindings, CI stale check\n\n## Cross-References\n\n- → See `samber/cc-skills-golang@golang-dependency-injection` skill for DI concepts and library comparison\n- → See `samber/cc-skills-golang@golang-uber-dig` skill for runtime reflection-based DI without lifecycle\n- → See `samber/cc-skills-golang@golang-uber-fx` skill for runtime DI with lifecycle hooks, modules, and signal-aware Run()\n- → See `samber/cc-skills-golang@golang-samber-do` skill for generics-based DI without reflection\n- → See `samber/cc-skills-golang@golang-structs-interfaces` skill for interface design patterns\n- → See `samber/cc-skills-golang@golang-testing` skill for general testing patterns\n\nIf you encounter a bug or unexpected behavior in google/wire, open an issue at <https://github.com/google/wire/issues>.\n\nFile v1.0.2:_meta.json\n\n{\n  \"ownerId\": \"kn72rhnkwjfeex9wr1n7y24qa983cjn3\",\n  \"slug\": \"golang-google-wire\",\n  \"version\": \"1.0.2\",\n  \"publishedAt\": 1779465481888\n}\n\nFile v1.0.2:references/advanced.md\n\n# Advanced — google/wire\n\nDetail topics referenced from `SKILL.md`. Each section is self-contained.\n\n## Cleanup Chains\n\nWhen a provider returns `(T, func(), error)`, Wire adds the cleanup to a chain. The generated injector runs cleanups in **reverse construction order**: the last-built dependant is cleaned up first, ensuring dependants are torn down before their dependencies.\n\n```go\n// Provider with cleanup\nfunc NewDB(cfg *Config) (*sql.DB, func(), error) {\n    db, err := sql.Open(\"postgres\", string(cfg.DSN))\n    if err != nil { return nil, nil, err }\n    return db, func() { db.Close() }, nil\n}\n\nfunc NewCache(cfg *Config) (*redis.Client, func(), error) {\n    c := redis.NewClient(&redis.Options{Addr: cfg.CacheAddr})\n    return c, func() { c.Close() }, nil\n}\n```\n\nWire generates something like:\n\n```go\nfunc InitApp() (*App, func(), error) {\n    cfg := NewConfig()\n    db, dbCleanup, err := NewDB(cfg)\n    if err != nil { return nil, nil, err }\n    cache, cacheCleanup, err := NewCache(cfg)\n    if err != nil {\n        dbCleanup()  // already-built cleanups run on partial failure\n        return nil, nil, err\n    }\n    app := NewApp(db, cache)\n    return app, func() {\n        cacheCleanup()  // reverse order\n        dbCleanup()\n    }, nil\n}\n```\n\n**Caller pattern** — guard against nil cleanup on construction failure:\n\n```go\napp, cleanup, err := InitApp()\nif err != nil { log.Fatal(err) }\ndefer cleanup()\n```\n\nWire always returns a non-nil cleanup function when construction succeeds. If construction fails midway, the returned `cleanup` is nil — guard before calling.\n\n## Multiple Injectors in One Package\n\nA package can contain multiple injector functions. Each must live in a file with `//go:build wireinject`. All generated functions land in `wire_gen.go` in the same package.\n\n```go\n//go:build wireinject\n\npackage main\n\n// Production injector\nfunc InitProdApp() (*App, func(), error) {\n    wire.Build(ProdSet, NewApp)\n    return nil, nil, nil\n}\n\n// Development injector with debug providers\nfunc InitDevApp() (*App, func(), error) {\n    wire.Build(DevSet, NewApp)\n    return nil, nil, nil\n}\n```\n\nSelect at runtime with a flag, or at build time with separate `//go:build prod` / `//go:build !prod` constraints on the injector files.\n\n## wire.NewSet Nesting Strategies\n\nSets can contain other sets, building a hierarchy that mirrors your package structure.\n\n```go\n// pkg/config/wire.go\nvar ConfigSet = wire.NewSet(NewConfig)\n\n// pkg/infra/wire.go\nvar InfraSet = wire.NewSet(\n    config.ConfigSet, // embed upstream set\n    NewDB,\n    NewCache,\n)\n\n// pkg/service/wire.go\nvar ServiceSet = wire.NewSet(\n    NewUserService,\n    wire.Bind(new(UserStore), new(*UserRepo)),\n)\n\n// wire.go (injector)\nwire.Build(infra.InfraSet, service.ServiceSet, NewApp)\n```\n\n**Library set stability rules** (from upstream best practices):\n\n- Safe: replace one provider with another that has the same or fewer inputs, in the same release.\n- Safe: introduce a brand-new output type not previously provided.\n- Breaking: add a new required input to a provider — downstream injectors cannot satisfy it.\n- Breaking: remove a provided output type — downstream injectors that depend on it fail.\n- Breaking: add a type that the injector already provides — Wire reports a duplicate.\n\n## `wire:\"-\"` Exclusion Tag\n\nExclude a struct field from `wire.Struct` injection by tagging it:\n\n```go\ntype Server struct {\n    Logger  *zap.Logger\n    DB      *sql.DB\n    mu      sync.Mutex   `wire:\"-\"` // unexported — auto-excluded\n    Timeout time.Duration `wire:\"-\"` // exported but opt-out\n}\n\nwire.Struct(new(Server), \"*\") // injects Logger and DB; skips mu and Timeout\n```\n\nUnexported fields are always skipped regardless of the tag.\n\n## Common Codegen Errors\n\n| Error message | Root cause | Fix |\n| --- | --- | --- |\n| `no provider found for TYPE` | A dependency is not provided by any set in `wire.Build` | Add the missing provider or set |\n| `multiple bindings for TYPE` | Two providers return the same type | Use named types or remove the duplicate |\n| `argument N has no provider for TYPE` | An interface is requested but no `wire.Bind` maps to it | Add `wire.Bind(new(Iface), new(*Impl))` to a set |\n| `cycle detected` | A → B → A circular dependency | Break the cycle by introducing an interface or factory |\n| `wire.Build used outside of injector function` | `wire.Build` called from a non-injector function | Only call `wire.Build` inside functions with the build tag |\n| duplicate symbol / redeclared in this block | Injector file is missing `//go:build wireinject` | Add the build tag as the first line |\n\n## Codegen Flags\n\n```bash\n# Specify output file prefix (default: wire_gen)\nwire -output_file_prefix=init gen ./cmd/server\n\n# Apply build tags during generation\nwire -tags=integration gen ./...\n\n# Prepend a header file (e.g., license comment) to generated output\nwire -header_file=hack/boilerplate.go.txt gen ./...\n```\n\n## `panic(wire.Build(...))` Alternate Syntax\n\nWire accepts either a dummy return or a `panic` call as the injector body. The `panic` form avoids writing zero-value returns for complex types:\n\n```go\n// Preferred when return types are complex or error-prone to zero-initialize\nfunc InitApp(ctx context.Context) (*App, func(), error) {\n    panic(wire.Build(AppSet))\n}\n```\n\nWire detects both forms and replaces the body during codegen. The `panic` is never reached in the compiled binary — only the generated `wire_gen.go` version is compiled.\n\n## Accepting External Values as Injector Arguments\n\nWhen a value is constructed before wire runs (e.g., parsed flags, an `http.Client` from a test), pass it as a parameter to the injector rather than providing it from within the graph:\n\n```go\n//go:build wireinject\n\nfunc InitApp(cfg *Config) (*App, func(), error) {\n    wire.Build(InfraSet, ServiceSet, NewApp)\n    return nil, nil, nil\n}\n\n// main.go\ncfg := parseFlags()\napp, cleanup, err := InitApp(cfg)\n```\n\nWire treats injector parameters as pre-built providers — they satisfy dependencies without needing a `wire.NewSet` entry.\n\n## Quick Reference\n\n| Symbol | Purpose |\n| --- | --- |\n| `wire.NewSet(providers...)` | Group providers into a reusable set |\n| `wire.Build(sets...)` | Declare injector body (codegen replaces it) |\n| `wire.Bind(new(Iface), new(*Concrete))` | Bind interface to concrete type |\n| `wire.Struct(new(T), \"Field\", ...)` | Inject struct fields from the graph |\n| `wire.Struct(new(T), \"*\")` | Inject all non-excluded fields |\n| `wire.Value(expr)` | Bind a constant expression (no fn calls/channels) |\n| `wire.InterfaceValue(new(I), value)` | Bind a value to an interface type |\n| `wire.FieldsOf(new(T), \"Field\", ...)` | Promote struct fields as individual graph nodes |\n| `//go:build wireinject` | Build tag: exclude injector stub from binary |\n| `wire_gen.go` | Generated output — commit, never edit |\n| `wire ./...` | Regenerate all injectors in the module |\n| `wire check ./...` | Validate graph without regenerating |\n\nFile v1.0.2:references/recipes.md\n\n# Recipes — google/wire\n\nEnd-to-end examples. Each recipe is self-contained.\n\n## HTTP Server with Postgres and Redis\n\nA typical service: parsed config → DB (with cleanup) → Redis (with cleanup) → repo → service → HTTP server.\n\n```\nmyapp/\n├── config/\n│   ├── config.go\n│   └── wire.go\n├── infra/\n│   ├── db.go\n│   ├── cache.go\n│   └── wire.go\n├── repo/\n│   ├── user.go\n│   └── wire.go\n├── service/\n│   ├── user.go\n│   └── wire.go\n├── transport/\n│   ├── handler.go\n│   └── wire.go\n├── wire.go        // injector — //go:build wireinject\n├── wire_gen.go    // generated — commit this\n└── main.go\n```\n\n```go\n// config/config.go\ntype Config struct {\n    Addr      string\n    DSN       string\n    CacheAddr string\n}\n\nfunc NewConfig() *Config {\n    return &Config{\n        Addr:      env(\"ADDR\", \":8080\"),\n        DSN:       mustEnv(\"DATABASE_URL\"),\n        CacheAddr: env(\"REDIS_ADDR\", \"localhost:6379\"),\n    }\n}\n\n// config/wire.go\nvar ConfigSet = wire.NewSet(NewConfig)\n```\n\n```go\n// infra/db.go\nfunc NewDB(cfg *config.Config) (*sql.DB, func(), error) {\n    db, err := sql.Open(\"postgres\", cfg.DSN)\n    if err != nil { return nil, nil, err }\n    if err := db.Ping(); err != nil { db.Close(); return nil, nil, err }\n    return db, func() { db.Close() }, nil\n}\n\n// infra/cache.go\nfunc NewRedis(cfg *config.Config) (*redis.Client, func(), error) {\n    c := redis.NewClient(&redis.Options{Addr: cfg.CacheAddr})\n    if err := c.Ping(context.Background()).Err(); err != nil {\n        return nil, nil, err\n    }\n    return c, func() { c.Close() }, nil\n}\n\n// infra/wire.go\nvar InfraSet = wire.NewSet(NewDB, NewRedis)\n```\n\n```go\n// repo/user.go\ntype UserStore interface {\n    GetUser(ctx context.Context, id int64) (*User, error)\n}\n\ntype PostgresUserRepo struct{ db *sql.DB }\n\nfunc NewUserRepo(db *sql.DB) *PostgresUserRepo { return &PostgresUserRepo{db: db} }\n\n// repo/wire.go\nvar RepoSet = wire.NewSet(\n    NewUserRepo,\n    wire.Bind(new(UserStore), new(*PostgresUserRepo)),\n)\n```\n\n```go\n// service/user.go\ntype UserService struct {\n    store  repo.UserStore\n    cache  *redis.Client\n}\n\nfunc NewUserService(store repo.UserStore, cache *redis.Client) *UserService {\n    return &UserService{store: store, cache: cache}\n}\n\n// service/wire.go\nvar ServiceSet = wire.NewSet(NewUserService)\n```\n\n```go\n// wire.go\n//go:build wireinject\n\npackage main\n\nfunc InitApp() (*transport.Handler, func(), error) {\n    wire.Build(\n        config.ConfigSet,\n        infra.InfraSet,\n        repo.RepoSet,\n        service.ServiceSet,\n        transport.NewHandler,\n    )\n    return nil, nil, nil\n}\n```\n\n```go\n// main.go\nfunc main() {\n    handler, cleanup, err := InitApp()\n    if err != nil { log.Fatal(err) }\n    defer cleanup()\n\n    srv := &http.Server{Addr: \":8080\", Handler: handler}\n    log.Fatal(srv.ListenAndServe())\n}\n```\n\n## Multiple Build Variants (Prod vs Dev)\n\nUse separate injector files with `//go:build` constraints to select different provider sets at build time.\n\n```go\n// wire_prod.go\n//go:build wireinject && !dev\n\npackage main\n\nfunc InitApp() (*App, func(), error) {\n    wire.Build(ProdSet, NewApp)\n    return nil, nil, nil\n}\n\n// wire_dev.go\n//go:build wireinject && dev\n\npackage main\n\nfunc InitApp() (*App, func(), error) {\n    wire.Build(DevSet, NewApp) // DevSet swaps real DB for in-memory SQLite\n    return nil, nil, nil\n}\n```\n\nUse `-output_file_prefix` to write separate output files — both commands would otherwise overwrite the same `wire_gen.go`:\n\n```bash\nwire -tags dev -output_file_prefix=wire_gen_dev gen .\nwire -output_file_prefix=wire_gen_prod gen .\n```\n\nAdd build constraints to the generated files so only one compiles per build:\n\n```go\n// wire_gen_prod.go — add at the top (after wire writes it)\n//go:build !dev\n\n// wire_gen_dev.go — add at the top\n//go:build dev\n```\n\nCommit both generated files. At build time, only the matching file is compiled.\n\n## Cleanup-Heavy Graph\n\nWhen several providers need shutdown coordination, wire's reverse-order cleanup is essential.\n\n```go\n// Providers return (T, func(), error)\nfunc NewDBPool(cfg *Config) (*pgxpool.Pool, func(), error) {\n    pool, err := pgxpool.New(context.Background(), cfg.DSN)\n    if err != nil { return nil, nil, err }\n    return pool, func() { pool.Close() }, nil\n}\n\nfunc NewOTelExporter(cfg *Config) (*otlptrace.Exporter, func(), error) {\n    exp, err := otlptracegrpc.New(context.Background(), ...)\n    if err != nil { return nil, nil, err }\n    return exp, func() { exp.Shutdown(context.Background()) }, nil\n}\n\nfunc NewTracerProvider(exp *otlptrace.Exporter) (*trace.TracerProvider, func(), error) {\n    tp := trace.NewTracerProvider(trace.WithBatcher(exp))\n    return tp, func() { tp.Shutdown(context.Background()) }, nil\n}\n```\n\nWire generates shutdown in reverse: `TracerProvider` → `OTelExporter` → `DBPool`. Each cleanup runs before its dependencies shut down — guaranteeing in-flight spans are flushed before the exporter closes.\n\n## Embedding Wire in a CLI\n\nWire produces a struct, not an app framework. You control the lifecycle:\n\n```go\n// wire.go\n//go:build wireinject\n\npackage cmd\n\nfunc InitServer(cfg *Config) (*http.Server, func(), error) {\n    wire.Build(InfraSet, ServiceSet, NewHTTPServer)\n    return nil, nil, nil\n}\n\n// cmd/serve.go\nfunc runServe(cfg *Config) error {\n    srv, cleanup, err := InitServer(cfg)\n    if err != nil { return err }\n    defer cleanup()\n\n    quit := make(chan os.Signal, 1)\n    signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)\n\n    go func() {\n        if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {\n            log.Fatal(err)\n        }\n    }()\n    <-quit\n    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)\n    defer cancel()\n    return srv.Shutdown(ctx)\n}\n```\n\nUnlike `fx.Run()`, wire does not manage the lifecycle loop. Implement signal handling and graceful shutdown explicitly. This is a feature for CLI tools that spin up short-lived services and need precise control over the shutdown sequence.\n\n## Passing External Values to Wire\n\nValues built before wire runs (parsed config, test doubles) become injector parameters:\n\n```go\n//go:build wireinject\n\n// cfg is resolved outside the graph — treated as a provided *Config\nfunc InitApp(cfg *Config) (*App, func(), error) {\n    wire.Build(InfraSet, ServiceSet, NewApp)\n    return nil, nil, nil\n}\n\n// main.go\ncfg, err := config.Load()\nif err != nil { log.Fatal(err) }\napp, cleanup, err := InitApp(cfg)\n```\n\nThe parameter `cfg *Config` satisfies any downstream provider that requests `*Config` — no `wire.Value` or extra set entry needed.\n\nFile v1.0.2:references/testing.md\n\n# Testing — google/wire\n\nWire generates plain Go constructor calls, so tests work directly on the constructor layer — no container API to learn.\n\n## Unit Tests: Plain Constructor Injection\n\nThe generated code has no wire dependency. Test constructors directly:\n\n```go\nfunc TestUserService_GetUser(t *testing.T) {\n    mockStore := &MockUserStore{users: map[int64]*User{1: &User{ID: 1, Name: \"Alice\"}}}\n    cache := newTestRedis(t)\n    svc := service.NewUserService(mockStore, cache)\n\n    u, err := svc.GetUser(context.Background(), 1)\n    require.NoError(t, err)\n    assert.Equal(t, \"Alice\", u.Name)\n}\n```\n\nPass mocks directly as constructor arguments. No wire, no container, no file to generate. This is the idiomatic approach for unit tests.\n\n## Test Injectors: Swapping Providers\n\nFor integration or component tests where you want the full wired graph but with selected dependencies replaced, create a test-only injector in a `_test.go` file.\n\n```go\n// app_test.go\n//go:build wireinject\n\npackage main\n\nimport (\n    \"testing\"\n    \"github.com/google/wire\"\n)\n\n// TestSet replaces real infra with in-memory fakes\nvar TestSet = wire.NewSet(\n    NewTestConfig,\n    NewInMemoryUserStore,\n    wire.Bind(new(repo.UserStore), new(*InMemoryUserStore)),\n    NewTestRedis,\n)\n\nfunc InitTestApp(t *testing.T) (*App, func(), error) {\n    wire.Build(TestSet, service.ServiceSet, NewApp)\n    return nil, nil, nil\n}\n```\n\n```go\n// app_integration_test.go\n//go:build !wireinject  // compiles when the wireinject tag is NOT set\n\npackage main\n\nfunc TestApp_GetUser(t *testing.T) {\n    app, cleanup, err := InitTestApp(t)\n    require.NoError(t, err)\n    defer cleanup()\n\n    // test against the fully-wired app with fake dependencies\n    u, err := app.GetUser(context.Background(), 1)\n    require.NoError(t, err)\n    assert.NotNil(t, u)\n}\n```\n\nRun `wire ./...` to generate `wire_gen.go` — the test injector is included because the `_test.go` file is compiled as part of the package during `go test`.\n\n**Key pattern from upstream best practices:** Prefer creating a test-only provider set over passing mocks as injector arguments (though both work). The set approach keeps the test injector composable.\n\n## Passing Mocks as Injector Arguments\n\nAn alternative to a test set: pass the mock directly as an injector parameter. Wire treats it as a pre-built provider.\n\n```go\n//go:build wireinject\n\nfunc InitTestApp(store repo.UserStore) (*App, func(), error) {\n    wire.Build(config.ConfigSet, service.ServiceSet, NewApp)\n    return nil, nil, nil\n}\n\n// Test\nfunc TestApp(t *testing.T) {\n    mock := &MockUserStore{}\n    app, cleanup, err := InitTestApp(mock)\n    require.NoError(t, err)\n    defer cleanup()\n    // ...\n}\n```\n\nUse this form when you only need to replace one or two dependencies and a full `TestSet` is overkill.\n\n## CI: Detecting Stale `wire_gen.go`\n\nIf `wire_gen.go` is not regenerated after a provider change, CI builds pass but the graph is wrong. Enforce freshness in CI:\n\n```bash\n# Option 1: re-run wire and check for diffs\nwire ./...\ngit diff --exit-code -- '**/wire_gen.go'\n```\n\n```yaml\n# .github/workflows/ci.yml\n- name: Check wire_gen.go is up-to-date\n  run: |\n    go install github.com/google/wire/cmd/wire@v0.7.0\n    wire ./...\n    git diff --exit-code -- '**/wire_gen.go'\n```\n\n```bash\n# Option 2: use wire check (verifies graph without regenerating)\nwire check ./...\n```\n\n`wire check` exits non-zero if the graph is inconsistent but does **not** update `wire_gen.go`. Use it for a fast graph-validity check without modifying files.\n\n## Testing Interface Bindings\n\n`wire.Bind` can be used in test sets to bind a fake to the same interface:\n\n```go\n// Fake implements the same interface as the real provider\ntype FakeMailer struct{ sent []string }\nfunc (f *FakeMailer) Send(to, body string) error { f.sent = append(f.sent, to); return nil }\n\nvar TestMailerSet = wire.NewSet(\n    NewFakeMailer,\n    wire.Bind(new(notification.Mailer), new(*FakeMailer)),\n)\n\nvar TestSet = wire.NewSet(\n    TestMailerSet,\n    realServiceSet,  // everything else is real\n)\n```\n\nThis keeps the test injector narrow — only the Mailer is faked; the rest of the graph is real.\n\n## Table-Driven Tests Without Wire\n\nWire is an initialization tool. Once the object graph is built, table-driven tests on individual services need no wire involvement:\n\n```go\nfunc TestUserService(t *testing.T) {\n    cases := []struct {\n        name  string\n        id    int64\n        users map[int64]*User\n        want  string\n        err   bool\n    }{\n        {\"found\", 1, map[int64]*User{1: &User{Name: \"Alice\"}}, \"Alice\", false},\n        {\"not found\", 99, nil, \"\", true},\n    }\n    for _, tc := range cases {\n        t.Run(tc.name, func(t *testing.T) {\n            svc := service.NewUserService(&MockUserStore{users: tc.users}, nil)\n            u, err := svc.GetUser(context.Background(), tc.id)\n            if tc.err { require.Error(t, err); return }\n            assert.Equal(t, tc.want, u.Name)\n        })\n    }\n}\n```\n\nWire has no role here — the injector was only needed to build the object graph in `main` (or in an integration test). Unit tests construct dependencies directly.\n\nFile v1.0.2:skill-card.md\n\n## Description: <br>\nHelps Go developers add and maintain Google Wire compile-time dependency injection with provider sets, injectors, interface bindings, struct providers, generated wire_gen.go files, and related wire commands. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[samber](https://clawhub.ai/user/samber) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nDevelopers and engineers use this skill when adopting or maintaining google/wire in Go repositories, especially when building compile-time dependency graphs, provider sets, injectors, interface bindings, and committed generated files. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The skill may edit Go source files, run wire and go commands, and update committed generated files. <br>\nMitigation: Review generated code, source edits, and dependency changes before merging or deploying them. <br>\nRisk: The install metadata uses github.com/google/wire/cmd/wire@latest, which can change over time. <br>\nMitigation: Pin the wire tool version in production or reproducible build environments. <br>\n\n\n## Reference(s): <br>\n- [ClawHub release page](https://clawhub.ai/samber/golang-google-wire) <br>\n- [OpenClaw homepage](https://github.com/samber/cc-skills-golang) <br>\n- [Google Wire package documentation](https://pkg.go.dev/github.com/google/wire) <br>\n- [Google Wire repository](https://github.com/google/wire) <br>\n- [Google Wire user guide](https://github.com/google/wire/blob/main/docs/guide.md) <br>\n- [Google Wire best practices](https://github.com/google/wire/blob/main/docs/best-practices.md) <br>\n- [Advanced - google/wire](references/advanced.md) <br>\n- [Recipes - google/wire](references/recipes.md) <br>\n- [Testing - google/wire](references/testing.md) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [text, markdown, code, shell commands, configuration, guidance] <br>\n**Output Format:** [Markdown with Go code examples and shell command blocks] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [May propose edits to Go source files, generated wire_gen.go files, and project dependency or tool configuration.] <br>\n\n## Skill Version(s): <br>\n1.0.2 (source: server evidence and frontmatter) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nFile v1.0.2:evals/evals.json\n\n[\n  {\n    \"id\": 1,\n    \"name\": \"build-constraint-on-injector\",\n    \"description\": \"Tests that the model adds //go:build wireinject to injector files to prevent duplicate-symbol compile errors\",\n    \"prompt\": \"I'm setting up google/wire in my Go project. Here's my injector file:\\n\\n```go\\npackage main\\n\\nimport \\\"github.com/google/wire\\\"\\n\\nfunc InitApp() (*App, error) {\\n    wire.Build(InfraSet, ServiceSet, NewApp)\\n    return nil, nil\\n}\\n```\\n\\nWire generates wire_gen.go successfully, but when I run `go build`, I get a 'redeclared in this block' compile error for InitApp. What's wrong and how do I fix it?\",\n    \"trap\": \"Without the skill, the model may suggest renaming the function, reorganizing packages, or not identify that the missing //go:build wireinject tag is the cause — both the stub and wire_gen.go define InitApp, causing the duplicate.\",\n    \"assertions\": [\n      {\"id\": \"1.1\", \"text\": \"Identifies the missing //go:build wireinject build tag as the root cause\"},\n      {\"id\": \"1.2\", \"text\": \"Shows //go:build wireinject as the first line of the injector file\"},\n      {\"id\": \"1.3\", \"text\": \"Explains that the tag prevents the stub from being compiled into the binary (only wire_gen.go compiles)\"},\n      {\"id\": \"1.4\", \"text\": \"Does NOT suggest renaming the function or reorganizing packages as the fix\"},\n      {\"id\": \"1.5\", \"text\": \"Does NOT suggest deleting wire_gen.go as the fix\"}\n    ]\n  },\n  {\n    \"id\": 2,\n    \"name\": \"interface-binding-required\",\n    \"description\": \"Tests that wire.Bind is required for interface-to-concrete mappings and cannot be inferred\",\n    \"prompt\": \"I have this Go code using google/wire:\\n\\n```go\\n// repo.go\\ntype UserStore interface {\\n    GetUser(id int64) (*User, error)\\n}\\n\\ntype PostgresUserRepo struct{ db *sql.DB }\\nfunc (r *PostgresUserRepo) GetUser(id int64) (*User, error) { ... }\\nfunc NewUserRepo(db *sql.DB) *PostgresUserRepo { return &PostgresUserRepo{db: db} }\\n\\n// service.go\\nfunc NewUserService(store UserStore) *UserService { return &UserService{store: store} }\\n\\n// wire_providers.go\\nvar AppSet = wire.NewSet(NewDB, NewUserRepo, NewUserService)\\n```\\n\\nWhen I run `wire ./...` I get: `no provider found for UserStore`. NewUserRepo returns *PostgresUserRepo which clearly implements UserStore. Why doesn't wire figure this out?\",\n    \"trap\": \"Without the skill, the model might suggest wire should automatically resolve the interface, or suggest wrapping NewUserRepo to return UserStore directly, missing the explicit wire.Bind requirement.\",\n    \"assertions\": [\n      {\"id\": \"2.1\", \"text\": \"Explains that wire never auto-resolves interface satisfaction — bindings must be explicit\"},\n      {\"id\": \"2.2\", \"text\": \"Shows wire.Bind(new(UserStore), new(*PostgresUserRepo)) added to the provider set\"},\n      {\"id\": \"2.3\", \"text\": \"Places wire.Bind inside the same wire.NewSet (or adds it to a set in wire.Build)\"},\n      {\"id\": \"2.4\", \"text\": \"Explains WHY wire requires explicit bindings (predictability — avoids surprise rebinding when new implementations are added)\"},\n      {\"id\": \"2.5\", \"text\": \"Does NOT suggest changing NewUserRepo to return UserStore directly as the primary fix\"}\n    ]\n  },\n  {\n    \"id\": 3,\n    \"name\": \"duplicate-type-named-wrapper\",\n    \"description\": \"Tests the named-type pattern to disambiguate multiple values of the same underlying type\",\n    \"prompt\": \"I'm building a Go service with google/wire. I need to inject two database connection strings — one for the primary database and one for a read replica. I tried this:\\n\\n```go\\nfunc NewPrimaryDSN() string { return os.Getenv(\\\"PRIMARY_DSN\\\") }\\nfunc NewReplicaDSN() string { return os.Getenv(\\\"REPLICA_DSN\\\") }\\n\\nvar DBSet = wire.NewSet(NewPrimaryDSN, NewReplicaDSN, NewPrimaryDB, NewReplicaDB)\\n```\\n\\nWire complains about multiple bindings for string. How should I structure this?\",\n    \"trap\": \"Without the skill, the model might suggest using wire.Value or provider arguments, or use a config struct — missing the idiomatic named-type wrapper pattern that wire's own docs recommend.\",\n    \"assertions\": [\n      {\"id\": \"3.1\", \"text\": \"Introduces distinct named types (e.g., type PrimaryDSN string and type ReplicaDSN string)\"},\n      {\"id\": \"3.2\", \"text\": \"Updates NewPrimaryDSN to return PrimaryDSN and NewReplicaDSN to return ReplicaDSN\"},\n      {\"id\": \"3.3\", \"text\": \"Updates NewPrimaryDB and NewReplicaDB signatures to accept the named types\"},\n      {\"id\": \"3.4\", \"text\": \"Explains that wire enforces one provider per type, so distinct named types are the correct solution\"},\n      {\"id\": \"3.5\", \"text\": \"Does NOT suggest using a single Config struct with both DSNs as the primary fix (that avoids the problem rather than solving it with named types)\"}\n    ]\n  },\n  {\n    \"id\": 4,\n    \"name\": \"cleanup-signature\",\n    \"description\": \"Tests the (T, func(), error) cleanup provider pattern instead of manual defer in main\",\n    \"prompt\": \"I'm using google/wire to wire my Go service. I need my *sql.DB connection pool to be closed when the app shuts down. Currently I'm doing this in main:\\n\\n```go\\nfunc main() {\\n    app, err := InitApp()\\n    if err != nil { log.Fatal(err) }\\n    defer db.Close() // but I don't have access to db here!\\n    app.Run()\\n}\\n```\\n\\nI realize I need the DB closed on shutdown, but InitApp() only returns *App. How should I wire cleanup with google/wire?\",\n    \"trap\": \"Without the skill, the model might suggest passing db out of InitApp as a second return value, or storing it as a global, missing the (T, func(), error) cleanup provider pattern.\",\n    \"assertions\": [\n      {\"id\": \"4.1\", \"text\": \"Changes NewDB to return (*sql.DB, func(), error) where the cleanup function calls db.Close()\"},\n      {\"id\": \"4.2\", \"text\": \"Changes the injector function to return (*App, func(), error) to propagate the cleanup chain\"},\n      {\"id\": \"4.3\", \"text\": \"Shows main calling defer cleanup() after the nil-check\"},\n      {\"id\": \"4.4\", \"text\": \"Explains that wire chains cleanup functions and calls them in reverse construction order\"},\n      {\"id\": \"4.5\", \"text\": \"Does NOT suggest passing db as an extra return value from InitApp alongside *App\"}\n    ]\n  },\n  {\n    \"id\": 5,\n    \"name\": \"no-edit-wire-gen\",\n    \"description\": \"Tests that the model never edits wire_gen.go and instructs re-running wire ./... instead\",\n    \"prompt\": \"I added a new *Logger parameter to my NewServer constructor in my google/wire project:\\n\\n```go\\nfunc NewServer(db *sql.DB, log *zap.Logger) *Server { ... }\\n```\\n\\nNow `go build` fails with 'too few arguments in call to NewServer'. The error is inside wire_gen.go on line 47. Should I edit wire_gen.go to add the logger argument there, or is there another way?\",\n    \"trap\": \"Without the skill, a model may suggest editing wire_gen.go directly to 'fix' the build error quickly, which would be overwritten on the next wire run.\",\n    \"assertions\": [\n      {\"id\": \"5.1\", \"text\": \"Explicitly says NOT to edit wire_gen.go (it is always overwritten)\"},\n      {\"id\": \"5.2\", \"text\": \"Instructs running wire ./... to regenerate wire_gen.go\"},\n      {\"id\": \"5.3\", \"text\": \"Explains that *zap.Logger must be provided in the graph (either via a provider or wire.Value)\"},\n      {\"id\": \"5.4\", \"text\": \"Shows how to add NewLogger (or wire.Value) to the appropriate wire.NewSet so the dependency is satisfied\"},\n      {\"id\": \"5.5\", \"text\": \"Does NOT present editing wire_gen.go as an option\"}\n    ]\n  },\n  {\n    \"id\": 6,\n    \"name\": \"provider-set-organization\",\n    \"description\": \"Tests per-package provider set organization instead of one giant set in main\",\n    \"prompt\": \"My Go service using google/wire is growing. I currently have everything in one place:\\n\\n```go\\n// wire.go\\n//go:build wireinject\\n\\nfunc InitApp() (*App, func(), error) {\\n    wire.Build(\\n        NewConfig, NewDB, NewCache, NewLogger,\\n        NewUserRepo, NewOrderRepo, NewProductRepo,\\n        wire.Bind(new(UserStore), new(*PostgresUserRepo)),\\n        wire.Bind(new(OrderStore), new(*PostgresOrderRepo)),\\n        wire.Bind(new(ProductStore), new(*PostgresProductRepo)),\\n        NewUserService, NewOrderService, NewProductService,\\n        NewHTTPServer, NewRouter,\\n        NewApp,\\n    )\\n    return nil, nil, nil\\n}\\n```\\n\\nThis is getting unwieldy. How should I organize this with google/wire?\",\n    \"trap\": \"Without the skill, the model may just split the providers into helper variables in the same package, missing the idiomatic per-package wire.NewSet pattern.\",\n    \"assertions\": [\n      {\"id\": \"6.1\", \"text\": \"Introduces per-package wire.NewSet variables (e.g., InfraSet, RepoSet, ServiceSet, TransportSet)\"},\n      {\"id\": \"6.2\", \"text\": \"Each set lives in its own package's wire.go file (not all in main)\"},\n      {\"id\": \"6.3\", \"text\": \"The injector wire.Build references the set variables rather than individual providers\"},\n      {\"id\": \"6.4\", \"text\": \"wire.Bind declarations move into the relevant package's set (not into wire.Build directly)\"},\n      {\"id\": \"6.5\", \"text\": \"Explains the benefit: per-package sets are independently composable and keep the injector readable\"}\n    ]\n  },\n  {\n    \"id\": 7,\n    \"name\": \"injector-parameter-vs-value-provider\",\n    \"description\": \"Tests using wire.Value or injector parameters for pre-built values instead of wrapper constructors\",\n    \"prompt\": \"In my Go app using google/wire, I parse a *Config struct from command-line flags in main() before calling InitApp. I tried writing a no-op provider:\\n\\n```go\\nvar parsedCfg *Config\\n\\nfunc ProvideConfig() *Config { return parsedCfg }\\n\\nvar AppSet = wire.NewSet(ProvideConfig, ...)\\n```\\n\\nThis works but feels wrong — I'm using a global variable. Is there a cleaner way to pass a pre-built *Config into the wire graph?\",\n    \"trap\": \"Without the skill, the model might suggest keeping the global variable pattern or using init(), missing both wire.Value and the injector-parameter patterns.\",\n    \"assertions\": [\n      {\"id\": \"7.1\", \"text\": \"Shows the injector-parameter approach: func InitApp(cfg *Config) (*App, func(), error) with wire.Build\"},\n      {\"id\": \"7.2\", \"text\": \"OR shows wire.Value(cfg) inside wire.Build — both are valid answers\"},\n      {\"id\": \"7.3\", \"text\": \"Explains that injector parameters are treated as pre-built providers by wire\"},\n      {\"id\": \"7.4\", \"text\": \"Does NOT use a global variable as the recommended solution\"},\n      {\"id\": \"7.5\", \"text\": \"Does NOT suggest using init() to set the value\"}\n    ]\n  },\n  {\n    \"id\": 8,\n    \"name\": \"fields-of-struct\",\n    \"description\": \"Tests wire.FieldsOf to expose struct fields as individual graph nodes\",\n    \"prompt\": \"I have a single Config struct in my Go app with google/wire:\\n\\n```go\\ntype Config struct {\\n    DatabaseDSN  string\\n    CacheAddress string\\n    APIKey       string\\n}\\n\\nfunc NewConfig() *Config { return loadFromEnv() }\\n```\\n\\nNewDB needs a DatabaseDSN string, NewCache needs a CacheAddress string, NewExternalClient needs an APIKey string — but all three are plain strings. How do I make these available to the wire graph without creating three separate provider functions?\",\n    \"trap\": \"Without the skill, the model will suggest three named-type wrappers or three extraction functions, missing wire.FieldsOf which promotes struct fields directly.\",\n    \"assertions\": [\n      {\"id\": \"8.1\", \"text\": \"Uses wire.FieldsOf(new(Config), \\\"DatabaseDSN\\\", \\\"CacheAddress\\\", \\\"APIKey\\\") or a subset\"},\n      {\"id\": \"8.2\", \"text\": \"Places wire.FieldsOf inside the provider set or wire.Build\"},\n      {\"id\": \"8.3\", \"text\": \"Updates NewDB, NewCache, NewExternalClient to accept the string fields as parameters (or uses named types alongside FieldsOf)\"},\n      {\"id\": \"8.4\", \"text\": \"Explains that wire.FieldsOf promotes struct fields as individual graph nodes without manual extraction functions\"},\n      {\"id\": \"8.5\", \"text\": \"Does NOT suggest writing three separate func GetDatabaseDSN(c *Config) string extractor functions as the primary recommendation\"}\n    ]\n  },\n  {\n    \"id\": 9,\n    \"name\": \"test-injector-pattern\",\n    \"description\": \"Tests the test-injector pattern with wire.Bind for fake dependencies instead of runtime mocking hacks\",\n    \"prompt\": \"My Go service is wired with google/wire. I have a Mailer interface implemented by SMTPMailer in production. I want integration tests that use a FakeMailer instead — recording sent emails — without modifying the production provider sets. The test must wire the full graph (not just NewUserService in isolation). How should I approach this?\",\n    \"trap\": \"Without th\n\nArchive v1.0.0: 6 files, 17368 bytes\n\nFiles: evals/evals.json (14841b), references/advanced.md (6966b), references/recipes.md (6718b), references/testing.md (5146b), SKILL.md (10578b), _meta.json (137b)","readmeExcerpt":"Skill: golang-google-wire Owner: samber Summary: Compile-time dependency injection in Golang using google/wire — wire.NewSet, wire.Build, wire.Bind (interface→concrete), wire.Struct, wire.Value, wire.InterfaceValue, wire.FieldsOf, cleanup functions, //go:build wireinject injector files, and generated wire_gen.go. Apply when using or adopting google/wire, when the codebase imports github.com/google/wire, or when wirin","codeSnippets":[],"executableExamples":[{"language":"bash","snippet":"go get -tool github.com/google/wire/cmd/wire@latest\ngo get github.com/google/wire"},{"language":"go","snippet":"func NewConfig() *Config                          { return &Config{Addr: \":8080\"} }\nfunc NewDB(cfg *Config) (*sql.DB, error)          { return sql.Open(\"postgres\", cfg.DSN) }\nfunc NewRedis(cfg *Config) (*redis.Client, func(), error) { // cleanup chained in reverse order\n    c := redis.NewClient(&redis.Options{Addr: cfg.RedisAddr})\n    return c, func() { c.Close() }, nil\n}"},{"language":"go","snippet":"// infra/wire.go\nvar InfraSet = wire.NewSet(\n    NewConfig,\n    NewDB,\n    NewRedis,\n)\n\n// service/wire.go\nvar ServiceSet = wire.NewSet(\n    NewUserRepo,\n    NewUserService,\n    wire.Bind(new(UserStore), new(*UserRepo)), // interface binding\n)"},{"language":"go","snippet":"//go:build wireinject\n\npackage main\n\nimport \"github.com/google/wire\"\n\n// Wire generates the body of this function.\nfunc InitApp() (*App, func(), error) {\n    wire.Build(InfraSet, ServiceSet, NewApp)\n    return nil, nil, nil // replaced by codegen\n}"},{"language":"go","snippet":"func InitApp() (*App, func(), error) {\n    panic(wire.Build(InfraSet, ServiceSet, NewApp))\n}"},{"language":"go","snippet":"var Set = wire.NewSet(\n    NewPostgresUserRepo,\n    wire.Bind(new(UserStore), new(*PostgresUserRepo)), // tell wire: *PostgresUserRepo satisfies UserStore\n)"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: golang-google-wire\ndescription: \"Compile-time dependency injection in Golang using google/wire — wire.NewSet, wire.Build, wire.Bind (interface→concrete), wire.Struct, wire.Value, wire.InterfaceValue, wire.FieldsOf, cleanup functions, //go:build wireinject injector files, and generated wire_gen.go. Apply when using or adopting google/wire, when the codebase imports `github.com/google/wire`, or when wiring an application graph at compile time via `wire.Build`. For runtime DI with reflection, see `samber/cc-skills-golang@golang-uber-dig` skill.\"\nuser-invocable: true\nlicense: MIT\ncompatibility: Designed for Claude Code, Codex or similar harness, and for projects using Golang.\nmetadata:\n  author: samber\n  version: \"1.1.0\"\n  openclaw:\n    emoji: \"🪡\"\n    homepage: https://github.com/samber/cc-skills-golang\n    requires:\n      bins:\n        - go\n        - wire\n    install:\n      - kind: go\n        package: github.com/google/wire/cmd/wire@latest\n        bins: [wire]\n    skill-library-version: \"0.7.0\"\nallowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*) Bash(git:*) Agent WebFetch mcp__context7__resolve-library-id mcp__context7__query-docs Bash(wire:*) Bash(godig:*) Bash(gopls:*) LSP mcp__gopls__*\npaths:\n  - \"**/*.go\"\n---\n\n**Persona:** You are a Go architect using wire for compile-time DI. You let the compiler catch missing dependencies, treat `wire_gen.go` as committed source, and re-run `wire ./...` after every graph change.\n\n**Dependencies:**\n\n- wire: `go install github.com/google/wire/cmd/wire@latest`\n\n# Using google/wire for Compile-Time Dependency Injection in Go\n\nCode-generation DI toolkit. Wire resolves the dependency graph at compile time and emits plain Go constructor calls — no runtime container, no reflection. Errors appear when you run `wire ./...`, not at first request.\n\nNote: `google/wire` was archived in August 2025 (feature-complete; bug fixes still accepted).\n\n**Official Resources:** [pkg.go.dev](https://pkg.go.dev/github.com/google/wire) · [github.com/google/wire](https://github.com/google/wire) · [User Guide](https://github.com/google/wire/blob/main/docs/guide.md) · [Best Practices](https://github.com/google/wire/blob/main/docs/best-practices.md)\n\nThis skill is not exhaustive. Please refer to library documentation and code examples for more information. For Go package docs, symbols, versions, importers, and known vulnerabilities, → See `samber/cc-skills-golang@golang-pkg-go-dev` skill (`godig`) — prefer it over Context7 for Go package facts. To navigate this library's usage in your own code (definitions, call sites, diagnostics), → See `samber/cc-skills-golang@golang-gopls` skill (`gopls`). Context7 remains a fallback for docs not indexed on pkg.go.dev.\n\n```bash\ngo get -tool github.com/google/wire/cmd/wire@latest\ngo get github.com/google/wire\n```\n\n## wire vs. Runtime DI\n\n| Concern           | wire                      | dig / fx / samber/do   |\n| ----------------- | ------------------------- | ------------"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn72rhnkwjfeex9wr1n7y24qa983cjn3\",\n  \"slug\": \"golang-google-wire\",\n  \"version\": \"1.1.0\",\n  \"publishedAt\": 1787280159519\n}"},{"path":"references/advanced.md","content":"# Advanced — google/wire\n\nDetail topics referenced from `SKILL.md`. Each section is self-contained.\n\n## Cleanup Chains\n\nWhen a provider returns `(T, func(), error)`, Wire adds the cleanup to a chain. The generated injector runs cleanups in **reverse construction order**: the last-built dependant is cleaned up first, ensuring dependants are torn down before their dependencies.\n\n```go\n// Provider with cleanup\nfunc NewDB(cfg *Config) (*sql.DB, func(), error) {\n    db, err := sql.Open(\"postgres\", string(cfg.DSN))\n    if err != nil { return nil, nil, err }\n    return db, func() { db.Close() }, nil\n}\n\nfunc NewCache(cfg *Config) (*redis.Client, func(), error) {\n    c := redis.NewClient(&redis.Options{Addr: cfg.CacheAddr})\n    return c, func() { c.Close() }, nil\n}\n```\n\nWire generates something like:\n\n```go\nfunc InitApp() (*App, func(), error) {\n    cfg := NewConfig()\n    db, dbCleanup, err := NewDB(cfg)\n    if err != nil { return nil, nil, err }\n    cache, cacheCleanup, err := NewCache(cfg)\n    if err != nil {\n        dbCleanup()  // already-built cleanups run on partial failure\n        return nil, nil, err\n    }\n    app := NewApp(db, cache)\n    return app, func() {\n        cacheCleanup()  // reverse order\n        dbCleanup()\n    }, nil\n}\n```\n\n**Caller pattern** — guard against nil cleanup on construction failure:\n\n```go\napp, cleanup, err := InitApp()\nif err != nil { log.Fatal(err) }\ndefer cleanup()\n```\n\nWire always returns a non-nil cleanup function when construction succeeds. If construction fails midway, the returned `cleanup` is nil — guard before calling.\n\n## Multiple Injectors in One Package\n\nA package can contain multiple injector functions. Each must live in a file with `//go:build wireinject`. All generated functions land in `wire_gen.go` in the same package.\n\n```go\n//go:build wireinject\n\npackage main\n\n// Production injector\nfunc InitProdApp() (*App, func(), error) {\n    wire.Build(ProdSet, NewApp)\n    return nil, nil, nil\n}\n\n// Development injector with debug providers\nfunc InitDevApp() (*App, func(), error) {\n    wire.Build(DevSet, NewApp)\n    return nil, nil, nil\n}\n```\n\nSelect at runtime with a flag, or at build time with separate `//go:build prod` / `//go:build !prod` constraints on the injector files.\n\n## wire.NewSet Nesting Strategies\n\nSets can contain other sets, building a hierarchy that mirrors your package structure.\n\n```go\n// pkg/config/wire.go\nvar ConfigSet = wire.NewSet(NewConfig)\n\n// pkg/infra/wire.go\nvar InfraSet = wire.NewSet(\n    config.ConfigSet, // embed upstream set\n    NewDB,\n    NewCache,\n)\n\n// pkg/service/wire.go\nvar ServiceSet = wire.NewSet(\n    NewUserService,\n    wire.Bind(new(UserStore), new(*UserRepo)),\n)\n\n// wire.go (injector)\nwire.Build(infra.InfraSet, service.ServiceSet, NewApp)\n```\n\n**Library set stability rules** (from upstream best practices):\n\n- Safe: replace one provider with another that has the same or fewer inputs, in the same release.\n- Safe: introduce a brand-new output type not previously provided.\n- Bre"},{"path":"references/recipes.md","content":"# Recipes — google/wire\n\nEnd-to-end examples. Each recipe is self-contained.\n\n## HTTP Server with Postgres and Redis\n\nA typical service: parsed config → DB (with cleanup) → Redis (with cleanup) → repo → service → HTTP server.\n\n```\nmyapp/\n├── config/\n│   ├── config.go\n│   └── wire.go\n├── infra/\n│   ├── db.go\n│   ├── cache.go\n│   └── wire.go\n├── repo/\n│   ├── user.go\n│   └── wire.go\n├── service/\n│   ├── user.go\n│   └── wire.go\n├── transport/\n│   ├── handler.go\n│   └── wire.go\n├── wire.go        // injector — //go:build wireinject\n├── wire_gen.go    // generated — commit this\n└── main.go\n```\n\n```go\n// config/config.go\ntype Config struct {\n    Addr      string\n    DSN       string\n    CacheAddr string\n}\n\nfunc NewConfig() *Config {\n    return &Config{\n        Addr:      env(\"ADDR\", \":8080\"),\n        DSN:       mustEnv(\"DATABASE_URL\"),\n        CacheAddr: env(\"REDIS_ADDR\", \"localhost:6379\"),\n    }\n}\n\n// config/wire.go\nvar ConfigSet = wire.NewSet(NewConfig)\n```\n\n```go\n// infra/db.go\nfunc NewDB(cfg *config.Config) (*sql.DB, func(), error) {\n    db, err := sql.Open(\"postgres\", cfg.DSN)\n    if err != nil { return nil, nil, err }\n    if err := db.Ping(); err != nil { db.Close(); return nil, nil, err }\n    return db, func() { db.Close() }, nil\n}\n\n// infra/cache.go\nfunc NewRedis(cfg *config.Config) (*redis.Client, func(), error) {\n    c := redis.NewClient(&redis.Options{Addr: cfg.CacheAddr})\n    if err := c.Ping(context.Background()).Err(); err != nil {\n        return nil, nil, err\n    }\n    return c, func() { c.Close() }, nil\n}\n\n// infra/wire.go\nvar InfraSet = wire.NewSet(NewDB, NewRedis)\n```\n\n```go\n// repo/user.go\ntype UserStore interface {\n    GetUser(ctx context.Context, id int64) (*User, error)\n}\n\ntype PostgresUserRepo struct{ db *sql.DB }\n\nfunc NewUserRepo(db *sql.DB) *PostgresUserRepo { return &PostgresUserRepo{db: db} }\n\n// repo/wire.go\nvar RepoSet = wire.NewSet(\n    NewUserRepo,\n    wire.Bind(new(UserStore), new(*PostgresUserRepo)),\n)\n```\n\n```go\n// service/user.go\ntype UserService struct {\n    store  repo.UserStore\n    cache  *redis.Client\n}\n\nfunc NewUserService(store repo.UserStore, cache *redis.Client) *UserService {\n    return &UserService{store: store, cache: cache}\n}\n\n// service/wire.go\nvar ServiceSet = wire.NewSet(NewUserService)\n```\n\n```go\n// wire.go\n//go:build wireinject\n\npackage main\n\nfunc InitApp() (*transport.Handler, func(), error) {\n    wire.Build(\n        config.ConfigSet,\n        infra.InfraSet,\n        repo.RepoSet,\n        service.ServiceSet,\n        transport.NewHandler,\n    )\n    return nil, nil, nil\n}\n```\n\n```go\n// main.go\nfunc main() {\n    handler, cleanup, err := InitApp()\n    if err != nil { log.Fatal(err) }\n    defer cleanup()\n\n    srv := &http.Server{Addr: \":8080\", Handler: handler}\n    log.Fatal(srv.ListenAndServe())\n}\n```\n\n## Multiple Build Variants (Prod vs Dev)\n\nUse separate injector files with `//go:build` constraints to select different provider sets at build time.\n\n```go\n// wire_prod.go\n//go:build wireinject && !dev\n\npa"},{"path":"references/testing.md","content":"# Testing — google/wire\n\nWire generates plain Go constructor calls, so tests work directly on the constructor layer — no container API to learn.\n\n## Unit Tests: Plain Constructor Injection\n\nThe generated code has no wire dependency. Test constructors directly:\n\n```go\nfunc TestUserService_GetUser(t *testing.T) {\n    mockStore := &MockUserStore{users: map[int64]*User{1: &User{ID: 1, Name: \"Alice\"}}}\n    cache := newTestRedis(t)\n    svc := service.NewUserService(mockStore, cache)\n\n    u, err := svc.GetUser(context.Background(), 1)\n    require.NoError(t, err)\n    assert.Equal(t, \"Alice\", u.Name)\n}\n```\n\nPass mocks directly as constructor arguments. No wire, no container, no file to generate. This is the idiomatic approach for unit tests.\n\n## Test Injectors: Swapping Providers\n\nFor integration or component tests where you want the full wired graph but with selected dependencies replaced, create a test-only injector in a `_test.go` file.\n\n```go\n// app_test.go\n//go:build wireinject\n\npackage main\n\nimport (\n    \"testing\"\n    \"github.com/google/wire\"\n)\n\n// TestSet replaces real infra with in-memory fakes\nvar TestSet = wire.NewSet(\n    NewTestConfig,\n    NewInMemoryUserStore,\n    wire.Bind(new(repo.UserStore), new(*InMemoryUserStore)),\n    NewTestRedis,\n)\n\nfunc InitTestApp(t *testing.T) (*App, func(), error) {\n    wire.Build(TestSet, service.ServiceSet, NewApp)\n    return nil, nil, nil\n}\n```\n\n```go\n// app_integration_test.go\n//go:build !wireinject  // compiles when the wireinject tag is NOT set\n\npackage main\n\nfunc TestApp_GetUser(t *testing.T) {\n    app, cleanup, err := InitTestApp(t)\n    require.NoError(t, err)\n    defer cleanup()\n\n    // test against the fully-wired app with fake dependencies\n    u, err := app.GetUser(context.Background(), 1)\n    require.NoError(t, err)\n    assert.NotNil(t, u)\n}\n```\n\nRun `wire ./...` to generate `wire_gen.go` — the test injector is included because the `_test.go` file is compiled as part of the package during `go test`.\n\n**Key pattern from upstream best practices:** Prefer creating a test-only provider set over passing mocks as injector arguments (though both work). The set approach keeps the test injector composable.\n\n## Passing Mocks as Injector Arguments\n\nAn alternative to a test set: pass the mock directly as an injector parameter. Wire treats it as a pre-built provider.\n\n```go\n//go:build wireinject\n\nfunc InitTestApp(store repo.UserStore) (*App, func(), error) {\n    wire.Build(config.ConfigSet, service.ServiceSet, NewApp)\n    return nil, nil, nil\n}\n\n// Test\nfunc TestApp(t *testing.T) {\n    mock := &MockUserStore{}\n    app, cleanup, err := InitTestApp(mock)\n    require.NoError(t, err)\n    defer cleanup()\n    // ...\n}\n```\n\nUse this form when you only need to replace one or two dependencies and a full `TestSet` is overkill.\n\n## CI: Detecting Stale `wire_gen.go`\n\nIf `wire_gen.go` is not regenerated after a provider change, CI builds pass but the graph is wrong. Enforce freshness in CI:\n\n```bash\n# Option 1: re-run wire and "}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":1492,"uniquenessScore":44,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-11T04:37:47.996Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-11T04:37:47.996Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-11T07:41:13.319Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}