Add Go to an existing workspace
Wire up the gonx inference plugin in an existing Nx workspace that was not created with the gonx preset.
Step 1: Register the plugin
Section titled “Step 1: Register the plugin”The idiomatic way is nx add, which installs the package and runs the init generator to register the plugin:
nx add @naxodev/gonx
This registers @naxodev/gonx under plugins in nx.json. Once registered, the plugin scans your workspace for go.mod files and infers Nx targets from them automatically.
If the package is already installed, run the init generator directly instead — it does the same registration:
nx g @naxodev/gonx:init
Options
Section titled “Options”| Option | Type | Default | Description |
|---|---|---|---|
addGoDotWork | boolean | false | Add a go.work file to the project. |
Pass --addGoDotWork (to init) if you want a Go workspace (go.work) at the repo root:
nx g @naxodev/gonx:init --addGoDotWork
Step 2: Add Go projects
Section titled “Step 2: Add Go projects”After init, add Go projects in one of two ways:
Generate a new application or library:
nx g @naxodev/gonx:application apps/my-api
nx g @naxodev/gonx:library libs/my-lib
Or drop a go.mod into an existing directory. The inference plugin picks it up automatically — no project.json required.
Inferred targets
Section titled “Inferred targets”Once a go.mod is present in a directory, the plugin infers the following targets:
| Target | Available on | Description |
|---|---|---|
build | Applications only | Compile the Go binary. |
serve | Applications only | Run the application locally. |
test | Applications and libs | Run go test. |
tidy | Applications and libs | Run go mod tidy. |
lint | Applications and libs | Run the configured Go linter. |
generate | Applications and libs | Run go generate. |
nx-release-publish | Applications and libs | Publish via nx release. |
Applications are detected by the presence of a main.go containing package main and func main(, or a cmd/ directory.
Caching and inputs
Section titled “Caching and inputs”build, test, lint, and tidy are cacheable and hash ["goSource", "^goSource"]. goSource is an Nx named input the plugin defines on every inferred Go project, resolving to:
{projectRoot}/go.mod
{projectRoot}/go.sum
{projectRoot}/**/*.go
{workspaceRoot}/go.work
{workspaceRoot}/go.work.sum
The ^goSource entry pulls in the same named input from every project this one depends on, transitively. This matters because Go compiles, vets, and resolves module dependencies against the source of everything it imports, not just the project’s own files — in a go.work or replace-directive monorepo, an app can depend on a local library whose source lives in another Nx project. Without ^goSource, editing that library wouldn’t invalidate the app’s cached build/test/lint/tidy results. go.work/go.work.sum are included because they change module resolution for every Go project in the workspace, not just the one that owns them.
generate hashes only ["goSource"] (no ^goSource) — its go:generate directives only read the local module, and correctness relative to dependencies is already handled by its dependsOn: ["^generate"].
init (and nx add @naxodev/gonx) also writes a workspace-level goSource fallback into nx.json’s namedInputs if one isn’t already defined there — this only matters if you add a dependency edge from a Go project to a non-Go project (e.g. via implicitDependencies), since Nx needs every project reachable through ^goSource to define that named input. It never overwrites a goSource you’ve already defined yourself.
Verify
Section titled “Verify”nx show project my-api
The project appears in the graph with its inferred targets — no project.json required.