Golang application framework using uber-go/fx — fx.New, fx.Provide, fx.Invoke, fx.Module, fx.Lifecycle hooks, fx.Annotate (name/group/As), fx.Decorate, fx.Supply, fx.Replace, fx.WithLogger, and signal-aware Run(). Apply when using or adopting uber-go/fx, when the codebase imports `go.uber.org/fx`, or when wiring services with fx.New. For raw DI without lifecycle, see `samber/cc-skills-golang@golang-uber-dig` skill.
Questions
How do I install golang-uber-fx?
Download skills/golang-uber-fx/SKILL.md from the publisher, or copy the path and open the repository. PlugMCP lists the skill and does not host the file.
Where does golang-uber-fx live?
The publisher keeps it at https://github.com/samber/cc-skills-golang.
Which agents can use golang-uber-fx?
Claude, Cursor, and Codex can read a SKILL.md you add from the publisher's repository.
Golang application framework using uber-go/fx — fx.New, fx.Provide, fx.Invoke, fx.Module, fx.Lifecycle hooks, fx.Annotate (name/group/As), fx.Decorate, fx.Supply, fx.Replace, fx.WithLogger, and signal-aware Run(). Apply when using or adopting uber-go/fx, when the codebase imports `go.uber.org/fx`, or when wiring services with fx.New. For raw DI without lifecycle, see `samber/cc-skills-golang@golang-uber-dig` skill.
name: golang-uber-fx
description: "Golang application framework using uber-go/fx — fx.New, fx.Provide, fx.Invoke, fx.Module, fx.Lifecycle hooks, fx.Annotate (name/group/As), fx.Decorate, fx.Supply, fx.Replace, fx.WithLogger, and signal-aware Run(). Apply when using or adopting uber-go/fx, when the codebase imports , or when wiring services with fx.New. For raw DI without lifecycle, see skill."
user-invocable: true
license: MIT
compatibility: Designed for Claude Code, Codex or similar harness, and for projects using Golang.
metadata:
author: samber
version: "1.2.2"
openclaw:
emoji: "🏭"
homepage:
requires:
bins:
- go
install: []
skill-library-version: "1.24.0"
allowed-tools: Read Edit Write Glob Grep Bash(go:) Bash(git:) Bash(gopls:
paths:
Persona: You are a Go architect building a long-running service with fx. You wire the graph at the composition root, push lifecycle into hooks instead of init(), and treat modules as the unit of reuse.
Using uber-go/fx for Application Wiring in Go
Application framework combining a reflection-based DI container (built on uber-go/dig) with a lifecycle, module system, signal-aware run loop, and structured event logging. For long-running services where boot order, graceful shutdown, and modular composition matter.
This skill is not exhaustive — 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), preferred 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.
go get go.uber.org/fx
fx vs. dig
fx is built on top of dig and shares the same reflection-based container engine. The DI primitives (Provide, Invoke, In/Out structs, named values, value groups) are identical — fx.In/fx.Out are re-exports of dig.In/dig.Out.
What fx adds on top:
Concern
dig
fx
DI container
✅ dig.New()
✅ (embedded)
Lifecycle hooks
❌
✅ fx.Lifecycle OnStart/OnStop
Module system
❌
✅ fx.Module with scoped decorators
Signal-aware run loop
❌
✅ app.Run() blocks on SIGINT/SIGTERM
Structured event logging
❌
✅ fx.WithLogger / fxevent
Startup/shutdown timeout
❌
✅ fx.StartTimeout / fx.StopTimeout
Choose fx for long-running services (HTTP servers, workers, daemons) — lifecycle and signal handling are mandatory there, and modules make large service graphs manageable.
Choose raw dig when you need wiring without a framework: CLI tools, libraries that expose a container to callers, test harnesses, or embedding DI into an existing app that manages its own lifecycle. See samber/cc-skills-golang@golang-uber-dig skill.
The Application
import "go.uber.org/fx"
app := fx.New(
fx.Provide(NewLogger, NewDatabase, NewServer),
fx.Invoke(RegisterRoutes),
)
app.Run() // blocks until SIGINT/SIGTERM, then runs OnStop hooks
Boot stages: fx.New validates types (constructors do not run); app.Start(ctx) runs each fx.Invoke and fires OnStart hooks in topological order; main blocks on app.Done(); app.Stop(ctx) fires OnStop hooks in reverse order. Default timeout is 15 seconds — override with fx.StartTimeout / fx.StopTimeout.
Provide and Invoke
fx.New(
fx.Provide(NewLogger, NewDatabase, NewServer), // lazy
fx.Invoke(RegisterRoutes, StartMetricsExporter), // always run during Start
)
fx.Provide registers constructors; fx.Invoke is the trigger — without an Invoke (directly or transitively) referencing a type, its constructor never runs.
Lifecycle Hooks
Inject fx.Lifecycle and append hooks. Constructors should return quickly; long-running work belongs in OnStart.
Both callbacks receive a context bounded by StartTimeout/StopTimeout — respect cancellation. OnStart must return quickly — spawn a goroutine for blocking work; otherwise startup hangs and dependent hooks never fire.
fx.StartHook / fx.StopHook / fx.StartStopHook adapt simpler signatures (no context, no error, or both):
Many constructors, one consumer slice — typical for routes, health checks, metrics collectors:
type RouteResult struct {
fx.Out
Handler http.Handler `group:"routes"`
}
type ServerParams struct {
fx.In
Routes []http.Handler `group:"routes"`
}
Append ,flatten (group:"routes,flatten") to unwrap a slice instead of nesting it. Order is not guaranteed — provide an explicit ordered slice when sequence matters.
fx.Module
fx.Module groups providers, invokes, and decorators under a name. Modules scope decorators to themselves and their children — a logger renamed in fx.Module("db", ...) only appears renamed for code inside that module.
Treat each module as a small library that can be lifted into another app — its public surface is the types it Provides.
For fx.Supply/fx.Replace/fx.Decorate, optional deps, custom logging, manual lifecycle, and Quick Reference, see advanced.md.
Best Practices
Keep main() thin — providers, modules, and a single Run(). Push real work into modules so each can be tested in isolation.
Use lifecycle hooks instead of init() or goroutines launched from constructors — Start/Stop ordering depends on graph topology, but init() goroutines do not, which leads to races and leaks.
OnStart must return promptly — long work goes in a goroutine inside the hook. A blocking OnStart hangs the rest of the boot.
Respect ctx.Done() in hooks — a hook that ignores cancellation is reported as a timeout failure but its goroutine continues, leaking resources.
Group by module, not by layer — a module owns the providers, lifecycle, and decorators for one concern (HTTP, DB, metrics).
Use fx.Annotate for tags rather than wrapping a constructor in an fx.Out struct — keeps the constructor reusable outside fx.
Replace fx.Provide with fx.Supply for pre-built values (config, command-line flags). Shorter, signals intent.
Validate the graph in CI by booting under fx.New(...).Err() — catches missing providers and cycles before deploy.
Common Mistakes
Mistake
Fix
Long-running work directly in OnStart
Spawn a goroutine inside OnStart; the hook itself must return quickly so dependent hooks can run.
fx.Provide something that should be fx.Supply
Pre-built values (config, secrets) belong in fx.Supply — clearer and avoids a no-op constructor.
Module decorator leaking to siblings
Decorate inside fx.Module(...) — decorators flow only to descendants. A top-level fx.Decorate is global.
Group order assumed
Groups are unordered. If order matters, provide an ordered slice from one constructor.
Constructors with side effects
Side effects belong in OnStart — constructors should be cheap and pure-ish, since they may run concurrently and lazily.
Forgotten fx.Invoke
Without an Invoke (or downstream consumer), constructors never run. Add at least one Invoke per app.
Testing
Use go.uber.org/fx/fxtest to integrate fx with *testing.T (failures call t.Fatal, RequireStop registers as t.Cleanup). fx.Populate(&target) pulls values out of the graph; fx.Replace swaps real dependencies for fakes. Full patterns in testing.md.
recipes.md — full HTTP service with database/metrics, background workers with graceful drain, multiple impls of the same interface, manual lifecycle for CLI embedding
Download skills/golang-uber-fx/SKILL.md from the publisher, or copy the path and open the repository. PlugMCP lists the skill and does not host the file.
Where does golang-uber-fx live?
The publisher keeps it at https://github.com/samber/cc-skills-golang.
Which agents can use golang-uber-fx?
Claude, Cursor, and Codex can read a SKILL.md you add from the publisher's repository.