This is the full developer documentation for GoNx
# Quick start
> Get up and running with gonx in under a minute.
Create a Go application with Nx, then run, test, and build it using targets that gonx infers from `go.mod`.
See the [introduction](/getting-started/introduction) for background on gonx’s nx-go origins.
## Before you start
[Section titled “Before you start”](#before-you-start)
* **Node.js 22+** (an active LTS release) and an Nx 23.x workspace
* **Go** — a [stable release](https://go.dev/dl/) (1.18+ for multi-module workspaces)
See [version compatibility](/getting-started/installation/#version-compatibility) for supported Nx/gonx version pairs.
## Steps
[Section titled “Steps”](#steps)
1. **Create a workspace with the gonx preset**
```
npx create-nx-workspace go-workspace --preset=@naxodev/gonx
```
This scaffolds an Nx workspace with gonx registered and a starter Go project. If you already have a workspace, install gonx into it instead:
```
npx nx add @naxodev/gonx
```
2. **Create a Go application**
```
cd go-workspace
npx nx g @naxodev/gonx:application my-go-app
```
The generator creates a Go project with a `package main` entry point. gonx detects the `go.mod` and infers `build`, `serve`, `test`, `lint`, `tidy`, and `generate` targets. Pass `--template` to choose `standard`, `cli`, or `tui`. See the [application generator guide](/guides/generators/application) for all options.
3. **Run the application**
```
npx nx run my-go-app:serve
```
The `serve` target runs `go run` from the project root. See the [serve executor guide](/guides/executors/serve).
4. **Test the project**
```
npx nx run my-go-app:test
```
The `test` target runs `go test`. See the [test executor guide](/guides/executors/test).
5. **Build the project**
```
npx nx run my-go-app:build
```
The `build` target compiles an executable. See the [build executor guide](/guides/executors/build).
## Verify
[Section titled “Verify”](#verify)
List the projects Nx detected and the targets inferred for your application:
```
npx nx show projects
npx nx show project my-go-app
```
`nx show project` lists the `build`, `serve`, `test`, `lint`, `tidy`, and `generate` targets with no `project.json` file. Run `npx nx run my-go-app:build` a second time to confirm caching — the second run is served from the Nx cache.
## Next steps
[Section titled “Next steps”](#next-steps)
* [Create your first Go project](/tutorials/first-go-project) — a full walkthrough with explanations
* [Install GoNx](/getting-started/installation) — add gonx to an existing workspace
* [Plugin options](/guides/generators/options) — customize target names and tags
* [Migrate from nx-go to gonx](/community/migration) — coming from nx-go
# Contributing
> How to contribute to @naxodev/gonx.
gonx is MIT licensed and developed on [GitHub](https://github.com/naxodev/oss/tree/main/packages/gonx). Bug reports, feature requests, and pull requests are all welcome.
## Development setup
[Section titled “Development setup”](#development-setup)
This repo is a [bun](https://bun.sh/) workspace with Nx. Clone it and install dependencies:
```
git clone https://github.com/naxodev/oss.git
cd oss
bun install
```
You need:
* **Node.js 22+**
* **bun** (package manager)
* **Go** — a stable release (for running e2e tests)
## Running tests
[Section titled “Running tests”](#running-tests)
Unit tests run on `bun test`. Run a single spec directly:
```
cd packages/gonx && bun test src/graph/static-analysis/parse-go-mod.spec.ts
```
Or run the whole project through Nx (each spec runs in its own bun process for mock isolation):
```
bunx nx run gonx:test
```
End-to-end tests spin up a local Verdaccio registry and install the published tarball into a generated workspace:
```
bunx nx run gonx-e2e:e2e
```
## Linting and formatting
[Section titled “Linting and formatting”](#linting-and-formatting)
```
bunx nx run gonx:lint
bunx nx format:check
bunx nx format:write
```
## Opening a pull request
[Section titled “Opening a pull request”](#opening-a-pull-request)
1. Create a branch from `main`.
2. Make your changes, keeping commits focused.
3. Run lint, tests, and build before pushing:
```
bunx nx affected -t lint test build
```
4. Open a PR with a clear description.
### Commit messages
[Section titled “Commit messages”](#commit-messages)
Commits are validated by **commitlint** using Conventional Commits. Use the package scope:
```
feat(gonx): add new generator option
fix(gonx): resolve import edge case
docs(gonx): update executor reference
```
PR titles matter — squash-merge lands the PR title as the commit subject. Use `feat(gonx)!: ...` for breaking changes.
### Coding rules
[Section titled “Coding rules”](#coding-rules)
* All features or bug fixes must be covered by one or more unit tests.
* All public API methods must be documented.
## Releasing
[Section titled “Releasing”](#releasing)
Releases are independent per project and published manually from a maintainer’s machine (the npm account requires 2FA for writes). See [CONTRIBUTING.md](https://github.com/naxodev/oss/blob/main/CONTRIBUTING.md) for the full release workflow.
## Next steps
[Section titled “Next steps”](#next-steps)
* [How static analysis works](/understanding/static-analysis) — understand the tree-sitter graph
* [Plugin options](/guides/generators/options) — the plugin’s configuration surface
* [Quick start](/getting-started/quick-start) — get familiar with gonx as a user
# Migrate from nx-go to gonx
> How to migrate from nx-go or upgrade to @naxodev/gonx 4.x.
gonx 4.x requires Nx 23 and infers Go targets from `go.mod` files instead of generating `project.json` targets. Adapt your workspace with the steps below.
## Before you start
[Section titled “Before you start”](#before-you-start)
* **Nx 23.x** or later
* **Go** — a stable release (1.18+ for multi-module workspaces)
* A backup of your workspace
## Steps
[Section titled “Steps”](#steps)
1. **Upgrade to Nx 23**
```
npx nx migrate latest
npx nx migrate --run-migrations
```
gonx 4.x requires Nx 23.x. If you are already on 23, skip this step.
2. **Remove nx-go and install gonx** If migrating from [@nx-go/nx-go](https://github.com/nx-go/nx-go), uninstall it first:
```
npm uninstall @nx-go/nx-go
```
Then install gonx and apply its migrations:
```
npx nx add @naxodev/gonx
```
If you are upgrading from an earlier gonx release, `nx add` picks up the migration prompts automatically.
3. **Register the gonx plugin in `nx.json`**
```
{
"plugins": ["@naxodev/gonx"]
}
```
Remove any nx-go plugin entry. gonx infers targets from `go.mod`, so no per-project config is needed.
4. **Delete hand-written Go targets** gonx infers `build`, `serve`, `test`, `lint`, `tidy`, and `generate` from each `go.mod`. The main package is auto-detected — a project with `package main` and `func main()` in `main.go`, or a `cmd/` directory, is treated as an application and gets `build` and `serve` targets. Remove `project.json` files that hand-write those targets:
```
rm apps/my-go-app/project.json
```
Keep `project.json` only for non-Go projects or custom overrides. gonx uses the full project root path as the project name (for example, `apps/my-go-app`), not just the final directory segment — this aligns with Go’s release tagging convention (`projectRoot/vx.x.x`). Update any scripts or CI that reference short project names.
5. **Remove the `cwd` serve option and review `cmd`/`compiler` values** The `cwd` serve option no longer exists — serve runs from the project root. Delete `options.cwd` from any hand-written serve target. Because the main package is auto-detected, `options.main` is optional. The serve `cmd` and build `compiler` options now accept `gow` alongside `go` and `tinygo`. See the [serve executor guide](/guides/executors/serve) and [build executor guide](/guides/executors/build).
6. **Decide whether to keep `go.work`** gonx no longer creates a `go.work` file by default. Build and serve work without one. Keep an existing `go.work` only if you intentionally use a multi-module workspace. To opt in when initializing gonx:
```
npx nx g @naxodev/gonx:init --addGoDotWork
```
7. **Remove `convert-to-one-mod` usage** The `convert-to-one-mod` generator was removed. Delete any script or doc that invokes `nx g @naxodev/gonx:convert-to-one-mod`. Consolidate modules manually with standard Go tooling.
## Verify
[Section titled “Verify”](#verify)
Confirm Nx detects your Go projects and infers their targets:
```
npx nx show projects
npx nx show project apps/my-go-app
```
`nx show project` lists the inferred targets with no leftover `cwd` options. Then build a project to confirm it works without `go.work`:
```
npx nx run apps/my-go-app:build
```
## Next steps
[Section titled “Next steps”](#next-steps)
* [Plugin options](/guides/generators/options) — customize target names and tags
* [Create your first Go project](/tutorials/first-go-project) — walkthrough of generators and executors
* [nx-release-publish executor](/guides/executors/nx-release-publish) — publish Go modules
# Install GoNx
> How to install and configure @naxodev/gonx in your workspace.
How to install `@naxodev/gonx` in an existing Nx workspace and register the inference plugin.
## Before you start
[Section titled “Before you start”](#before-you-start)
* An **Nx 23.x** workspace (or later)
* **Node.js 22+** (an active LTS release)
* **Go** — a [stable release](https://go.dev/dl/) (1.18+ for multi-module workspaces)
Don’t have a workspace yet? Create one with the gonx preset and skip to step 3:
```
npx create-nx-workspace my-org --preset=@naxodev/gonx
```
## Version compatibility
[Section titled “Version compatibility”](#version-compatibility)
Each gonx major targets one Nx major:
| Nx version | gonx version |
| ---------- | ------------ |
| 21.x | 1.x, 2.x |
| 22.x | 3.x |
| 23.x | 4.x |
## Steps
[Section titled “Steps”](#steps)
1. **Install the package**
```
npm install @naxodev/gonx --save-dev
```
Or with Nx’s built-in installer, which also runs any migrations:
```
npx nx add @naxodev/gonx
```
2. **Register the inference plugin in `nx.json`**
Add `@naxodev/gonx` to the `plugins` array:
```
{
"plugins": ["@naxodev/gonx"]
}
```
The plugin infers Nx projects from every `go.mod` matched by `**/go.mod`. No per-project `project.json` is needed.
3. **Verify the plugin is loaded**
```
npx nx show projects
```
Every directory containing a `go.mod` should appear as an Nx project. If you used the preset, your starter Go project will be listed.
## Configuration
[Section titled “Configuration”](#configuration)
To customize inferred target names or disable dependency detection, use the object form with `options`:
```
{
"plugins": [
{
"plugin": "@naxodev/gonx",
"options": {
"buildTargetName": "build",
"testTargetName": "test",
"skipGoDependencyCheck": false
}
}
]
}
```
See the [plugin options reference](/guides/generators/options) for every available option.
## Next steps
[Section titled “Next steps”](#next-steps)
* [Quick start](/getting-started/quick-start) — create, run, test, and build a Go app
* [Create your first Go project](/tutorials/first-go-project) — a full tutorial walkthrough
* [Application generator](/guides/generators/application) — scaffold a Go application
* [Migrate from nx-go to gonx](/community/migration) — coming from nx-go
# Introduction
> What is GoNx and what can it do for you?
GoNx is an [Nx](https://nx.dev/) plugin for [Go](https://go.dev/) development. It brings the benefits of Nx — caching, affected-task detection, project graph visualization, and generators — to Go projects without requiring hand-written `project.json` targets.
## What gonx does
[Section titled “What gonx does”](#what-gonx-does)
gonx infers test, lint, tidy, and generate targets automatically from every `go.mod` in your workspace, plus build and serve for applications. It builds the Nx project graph by parsing Go source files with [tree-sitter](https://tree-sitter.github.io/) to extract import statements and resolve them to Nx projects — no Go toolchain required for graph computation. It also ships generators for scaffolding applications, libraries, and [Go Blueprint](https://github.com/melkeydev/go-blueprint) projects with web frameworks and database drivers.
## Who it’s for
[Section titled “Who it’s for”](#who-its-for)
gonx is for teams and individuals who already use Nx (or want to) and have Go projects in their workspace. It is a fork of [@nx-go/nx-go](https://github.com/nx-go/nx-go), modernized for Nx 23 with inferred tasks and a tree-sitter-based project graph. If you are migrating from nx-go, see the [migration guide](/community/migration).
## Where to go next
[Section titled “Where to go next”](#where-to-go-next)
* New to gonx? Start with the [quick start](/getting-started/quick-start).
* Adding gonx to an existing workspace? See [install gonx](/getting-started/installation).
* Want a step-by-step walkthrough? Read [create your first Go project](/tutorials/first-go-project).
* Curious how the project graph works? See [how static analysis works](/understanding/static-analysis).
# Build executor
> Compiles a Go program into an executable using the go build command.
The build executor compiles a Go program into an executable using `go build`.
## Usage
[Section titled “Usage”](#usage)
```
nx build my-go-app
```
## Options
[Section titled “Options”](#options)
| Option | Type | Default | Description |
| ------------ | ------------------------- | ------- | ---------------------------------------------------------------------------- |
| `main` | string | *-* | Relative path from the project root to the main.go file defining the binary. |
| `compiler` | `go` \| `tinygo` \| `gow` | `go` | The Go compiler to use |
| `outputPath` | string | *-* | The output path of the resulting executable |
| `buildMode` | string | *-* | The build mode to use |
| `env` | object | *-* | Environment variables to set when running the executor |
| `flags` | string\[] | *-* | Flags to pass to the go compiler |
When `main` is set, the build runs from the directory containing that main.go file. When omitted, the build targets `./...` (all packages in the project tree).
## Inferred target
[Section titled “Inferred target”](#inferred-target)
Inferred for projects containing a `main` package (applications). The plugin generates:
```
{
"executor": "@naxodev/gonx:build",
"cache": true,
"dependsOn": ["generate"],
"inputs": ["goSource", "^goSource"],
"options": {
"outputPath": "dist/{projectRoot}/"
},
"outputs": ["{options.outputPath}"]
}
```
The default `outputPath` resolves to `dist//`. Override it via the `outputPath` option.
See [caching and inputs](/guides/generators/add-go-to-existing-workspace#caching-and-inputs) for what `goSource` and `^goSource` hash.
## Next steps
[Section titled “Next steps”](#next-steps)
* [Serve executor](/guides/executors/serve)
* [Test executor](/guides/executors/test)
* [Plugin options](/guides/generators/options)
# Generate executor
> Runs code generation using the go generate command.
The generate executor runs code generation using `go generate ./...`, processing all `//go:generate` directives in the project tree.
## Usage
[Section titled “Usage”](#usage)
```
nx run my-go-project:generate
```
Use `nx run :generate` instead of `nx generate ` to avoid conflicts with Nx’s native generator command.
## Options
[Section titled “Options”](#options)
| Option | Type | Default | Description |
| ------- | --------- | ------- | ------------------------------------------------------ |
| `env` | object | *-* | Environment variables to set when running the executor |
| `flags` | string\[] | *-* | Flags to pass to the go generate command |
## Inferred target
[Section titled “Inferred target”](#inferred-target)
Inferred for all Go projects (applications and libraries):
```
{
"executor": "@naxodev/gonx:generate",
"cache": true,
"dependsOn": ["^generate"],
"inputs": ["goSource"]
}
```
The `^generate` dependency means generate targets run after upstream project generate targets complete. Unlike build/test/lint/tidy, `generate` hashes only the project’s own `goSource` (no `^goSource`) — `go:generate` directives only read the local module, and correctness relative to dependencies is already handled by the `^generate` ordering above. See [caching and inputs](/guides/generators/add-go-to-existing-workspace#caching-and-inputs) for details.
## Next steps
[Section titled “Next steps”](#next-steps)
* [Build executor](/guides/executors/build)
* [Test executor](/guides/executors/test)
* [Plugin options](/guides/generators/options)
# Lint executor
> Formats and lints a Go project.
The lint executor formats and lints a Go project. By default it runs `go fmt ./...`.
## Usage
[Section titled “Usage”](#usage)
```
nx lint my-go-project
```
## Options
[Section titled “Options”](#options)
| Option | Type | Default | Description |
| -------- | --------- | -------- | ------------------------------------------------------------------------ |
| `linter` | string | `go fmt` | The command to execute when running the lint executor instead of go fmt. |
| `args` | string\[] | *-* | Extra args when linting the project |
When `linter` is set, the executor runs that command with `args` and `./...` appended, bypassing `go fmt`.
## Inferred target
[Section titled “Inferred target”](#inferred-target)
Inferred for all Go projects (applications and libraries):
```
{
"executor": "@naxodev/gonx:lint",
"cache": true,
"inputs": ["goSource", "^goSource"]
}
```
See [caching and inputs](/guides/generators/add-go-to-existing-workspace#caching-and-inputs) for what `goSource` and `^goSource` hash.
## Next steps
[Section titled “Next steps”](#next-steps)
* [Test executor](/guides/executors/test)
* [Tidy executor](/guides/executors/tidy)
* [Plugin options](/guides/generators/options)
# nx-release-publish executor
> Publishes a Go module to the Go proxy as part of the Nx release process.
The nx-release-publish executor publishes a Go module to the Go proxy (proxy.golang.org) by running `GOPROXY=proxy.golang.org go list -m @`. The version is resolved from the latest git tag matching the release tag pattern configured in `nx.json`.
The manifest key in `executors.json` is `release-publish`. The inferred target name is `nx-release-publish`.
## Usage
[Section titled “Usage”](#usage)
```
nx nx-release-publish my-go-lib
```
Or through the Nx release pipeline:
```
nx release --publish
```
## Options
[Section titled “Options”](#options)
| Option | Type | Default | Description |
| ------------ | ------- | ------- | ------------------------------------------------------------------------------- |
| `moduleRoot` | string | *-* | Path to the directory containing the go.mod file. Defaults to the project root. |
| `dryRun` | boolean | `false` | Whether to perform a dry run (no actual publishing) |
The `NX_DRY_RUN` environment variable also triggers a dry run when set to `true`.
## Inferred target
[Section titled “Inferred target”](#inferred-target)
Inferred for all Go projects (applications and libraries), with `moduleRoot` resolved to the project’s root path (e.g. `libs/my-go-lib`):
```
{
"executor": "@naxodev/gonx:release-publish",
"options": {
"moduleRoot": "libs/my-go-lib"
},
"configurations": {
"development": {
"dryRun": true
}
}
}
```
The `development` configuration sets `dryRun: true`, allowing test runs via `--configuration=development`.
The default release tag pattern is `v{version}`. Override it in `nx.json` under `release.releaseTag.pattern`, which supports `{projectName}` and `{version}` placeholders.
## Next steps
[Section titled “Next steps”](#next-steps)
* [Build executor](/guides/executors/build)
* [Plugin options](/guides/generators/options)
* [Quick start](/getting-started/quick-start)
# Serve executor
> Runs a Go application using the go run command.
The serve executor runs a Go application using `go run`.
## Usage
[Section titled “Usage”](#usage)
```
nx serve my-go-app
```
## Options
[Section titled “Options”](#options)
| Option | Type | Default | Description |
| ------ | ------------------------- | ------- | ---------------------------------------------------------------------------- |
| `main` | string | *-* | Relative path from the project root to the main.go file defining the binary. |
| `cmd` | `go` \| `tinygo` \| `gow` | `go` | The name of the binary to use |
| `args` | string\[] | *-* | Extra args when starting the app |
| `env` | object | *-* | Environment variables to set when running the application |
When `main` is set, the serve runs from the directory containing that main.go file. When omitted, the serve targets `./...`.
## Inferred target
[Section titled “Inferred target”](#inferred-target)
Inferred for projects containing a `main` package (applications). The target is continuous and not cached:
```
{
"executor": "@naxodev/gonx:serve",
"continuous": true,
"options": {}
}
```
## Next steps
[Section titled “Next steps”](#next-steps)
* [Build executor](/guides/executors/build)
* [Plugin options](/guides/generators/options)
# Test executor
> Runs tests for a Go project using the go test command.
The test executor runs Go tests using `go test ./...`.
## Usage
[Section titled “Usage”](#usage)
```
nx test my-go-project
```
## Options
[Section titled “Options”](#options)
| Option | Type | Default | Description |
| -------------- | ------- | ------- | ------------------------------------------------------------------------------------------------------------------------- |
| `cover` | boolean | `false` | Enable coverage analysis |
| `coverProfile` | string | *-* | Write a coverage profile to the file after all tests have passed |
| `race` | boolean | `false` | Enable race detector |
| `run` | string | *-* | Run only tests matching this regular expression |
| `verbose` | boolean | `false` | Enable verbose test output |
| `count` | number | *-* | Run test N times |
| `timeout` | string | `10m` | If a test binary runs longer than duration d, panic. If d is 0, the timeout is disabled. The default is 10 minutes (10m). |
## Inferred target
[Section titled “Inferred target”](#inferred-target)
Inferred for all Go projects (applications and libraries):
```
{
"executor": "@naxodev/gonx:test",
"cache": true,
"dependsOn": ["generate", "^build"],
"inputs": ["goSource", "^goSource"]
}
```
The `^build` dependency means test targets run after upstream project build targets complete.
See [caching and inputs](/guides/generators/add-go-to-existing-workspace#caching-and-inputs) for what `goSource` and `^goSource` hash.
## Next steps
[Section titled “Next steps”](#next-steps)
* [Build executor](/guides/executors/build)
* [Lint executor](/guides/executors/lint)
* [Plugin options](/guides/generators/options)
# Tidy executor
> Runs go mod tidy to sync go.mod with the project source code.
The tidy executor runs `go mod tidy` to ensure the go.mod file matches the project source code.
## Usage
[Section titled “Usage”](#usage)
```
nx tidy my-go-project
```
## Options
[Section titled “Options”](#options)
| Option | Type | Default | Description |
| ------ | --------- | ------- | ------------------------------------------- |
| `args` | string\[] | *-* | Extra args when mod tidy the app or library |
## Inferred target
[Section titled “Inferred target”](#inferred-target)
Inferred for all Go projects (applications and libraries):
```
{
"executor": "@naxodev/gonx:tidy",
"cache": true,
"inputs": ["goSource", "^goSource"]
}
```
See [caching and inputs](/guides/generators/add-go-to-existing-workspace#caching-and-inputs) for what `goSource` and `^goSource` hash.
## Next steps
[Section titled “Next steps”](#next-steps)
* [Lint executor](/guides/executors/lint)
* [Plugin options](/guides/generators/options)
# Add Go to an existing workspace
> Register the gonx inference plugin in an existing Nx workspace and start adding Go projects.
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”](#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”](#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”](#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”](#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”](#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”](#verify)
```
nx show project my-api
```
The project appears in the graph with its inferred targets — no `project.json` required.
## Next steps
[Section titled “Next steps”](#next-steps)
* [Application generator](/guides/generators/application)
* [Library generator](/guides/generators/library)
* [Init generator reference](/guides/generators/init)
# Application generator
> Generates a Go application and registers it as an Nx project through the gonx inference plugin.
Generates a Go application under the given directory and registers it as an Nx project through the gonx inference plugin. Aliased as `app`.
## Usage
[Section titled “Usage”](#usage)
```
nx g @naxodev/gonx:application
```
## Options
[Section titled “Options”](#options)
| Option | Type | Default | Description |
| ------------ | ---------------------------- | ------------ | -------------------------------------------------------------------------------- |
| `directory` | string | *(required)* | The directory of the new application. Accepted as the first positional argument. |
| `name` | string | *-* | The name of the application. |
| `template` | `standard` \| `cli` \| `tui` | `standard` | The template of application. |
| `tags` | string | *-* | Add tags to the application (used for linting). |
| `skipFormat` | boolean | `false` | Skip formatting files. |
## Notes
[Section titled “Notes”](#notes)
* Runs the init generator first to register the inference plugin in `nx.json`.
* Creates a `go.mod` for the project unless the template already includes one. Adds the project to `go.work` when a Go workspace is present.
* Inferred targets for applications: `build`, `serve`, `test`, `lint`, `tidy`, `generate`, `nx-release-publish`. Application detection requires a `main.go` containing `package main` and `func main(`, or a `cmd/` directory.
## Next steps
[Section titled “Next steps”](#next-steps)
* [Library generator](/guides/generators/library)
* [Build executor](/guides/executors/build)
* [Serve executor](/guides/executors/serve)
# Go Blueprint generator
> Generates a Go application by wrapping the @melkeydev/go-blueprint CLI.
Generates a Go application by wrapping the `@melkeydev/go-blueprint` CLI, which is bundled with this package. Scaffolds a project from a selected web framework, database driver, and optional advanced features.
## Usage
[Section titled “Usage”](#usage)
```
nx g @naxodev/gonx:go-blueprint
```
## Options
[Section titled “Options”](#options)
| Option | Type | Default | Description |
| -------------- | ------------------------------------------------------------------------------------------ | ------------ | -------------------------------------------------------------------------------- |
| `directory` | string | *(required)* | The directory of the new application. Accepted as the first positional argument. |
| `name` | string | *-* | The name of the application. |
| `tags` | string | *-* | Add tags to the project (used for linting) |
| `skipFormat` | boolean | `false` | Skip formatting files |
| `addGoDotWork` | boolean | `false` | Add this project to go.work file |
| `framework` | `chi` \| `gin` \| `fiber` \| `gorilla/mux` \| `httprouter` \| `standard-library` \| `echo` | *(required)* | Framework to use |
| `driver` | `mysql` \| `postgres` \| `sqlite` \| `mongo` \| `redis` \| `scylla` \| `none` | *(required)* | Database drivers to use |
| `feature` | (`react` \| `htmx` \| `githubaction` \| `websocket` \| `tailwind` \| `docker`)\[] | *(prompted)* | Advanced feature to use |
| `git` | `commit` \| `stage` \| `skip` | *(required)* | Git to use |
## Notes
[Section titled “Notes”](#notes)
* The `@melkeydev/go-blueprint` binary is resolved from the bundled npm dependency; no separate installation is required.
* Runs the init generator first to register the inference plugin. Adds the project to `go.work` when `addGoDotWork` is set and a Go workspace is supported.
* Removes `.air.toml`, `README.md`, and `Makefile` from the generated output.
* The `react` feature embeds frontend code inside the Go project directory, which Nx’s project graph does not detect as a separate project.
* Inferred targets for the resulting application: `build`, `serve`, `test`, `lint`, `tidy`, `generate`, `nx-release-publish`.
## Next steps
[Section titled “Next steps”](#next-steps)
* [Application generator](/guides/generators/application)
* [Build executor](/guides/executors/build)
* [Serve executor](/guides/executors/serve)
# Init generator
> Registers the gonx inference plugin in an Nx workspace and optionally creates a go.work file.
Registers the gonx inference plugin in `nx.json` and optionally creates a `go.work` file. Invoked automatically by the other generators.
## Usage
[Section titled “Usage”](#usage)
```
nx g @naxodev/gonx:init
```
## Options
[Section titled “Options”](#options)
| Option | Type | Default | Description |
| -------------- | ------- | ------- | ---------------------------------- |
| `skipFormat` | boolean | `false` | Skip formatting files. |
| `addGoDotWork` | boolean | `false` | Add a go.work file to the project. |
## Notes
[Section titled “Notes”](#notes)
* `go.work` creation requires a locally installed Go toolchain that supports Go workspaces.
* Invoked by the application, library, and go-blueprint generators (and indirectly by the preset generator) with `skipFormat: true`.
## Next steps
[Section titled “Next steps”](#next-steps)
* [Application generator](/guides/generators/application)
* [Library generator](/guides/generators/library)
* [Plugin options](/guides/generators/options)
# Library generator
> Generates a Go library and registers it as an Nx project through the gonx inference plugin.
Generates a Go library under the given directory and registers it as an Nx project through the gonx inference plugin. Aliased as `lib`.
## Usage
[Section titled “Usage”](#usage)
```
nx g @naxodev/gonx:library
```
## Options
[Section titled “Options”](#options)
| Option | Type | Default | Description |
| ------------ | ------- | ------------ | ---------------------------------------------------------------------------- |
| `directory` | string | *(required)* | The directory of the new library. Accepted as the first positional argument. |
| `name` | string | *-* | The name of the library. |
| `tags` | string | *-* | Add tags to the library (used for linting). |
| `skipFormat` | boolean | `false` | Skip formatting files. |
## Notes
[Section titled “Notes”](#notes)
* Runs the init generator first to register the inference plugin in `nx.json`.
* Always creates a `go.mod` for the project. Adds the project to `go.work` when a Go workspace is present.
* Inferred targets for libraries: `test`, `lint`, `tidy`, `generate`, `nx-release-publish`. Libraries do not infer `build` or `serve`.
## Next steps
[Section titled “Next steps”](#next-steps)
* [Application generator](/guides/generators/application)
* [Test executor](/guides/executors/test)
* [Lint executor](/guides/executors/lint)
# Plugin options
> GoPluginOptions reference for the @naxodev/gonx plugin registration in nx.json.
Reference for the `GoPluginOptions` accepted by the `@naxodev/gonx` plugin registration in `nx.json`. The plugin infers Nx projects from every `go.mod` matched by `**/go.mod`.
## Usage
[Section titled “Usage”](#usage)
String form (all defaults apply):
```
{
"plugins": ["@naxodev/gonx"]
}
```
Object form:
```
{
"plugins": [
{
"plugin": "@naxodev/gonx",
"options": {
"buildTargetName": "build",
"skipGoDependencyCheck": true
}
}
]
}
```
## Options
[Section titled “Options”](#options)
| Option | Type | Default | Description |
| ------------------------ | ------- | -------------------- | ------------------------------------------------------------------- |
| buildTargetName | string | `build` | Name of the inferred build target. Inferred only for applications. |
| testTargetName | string | `test` | Name of the inferred test target. |
| runTargetName | string | `serve` | Name of the inferred run target. Inferred only for applications. |
| tidyTargetName | string | `tidy` | Name of the inferred tidy target. |
| lintTargetName | string | `lint` | Name of the inferred lint target. |
| generateTargetName | string | `generate` | Name of the inferred generate target. |
| releasePublishTargetName | string | `nx-release-publish` | Name of the inferred release publish target. |
| tagName | string | - | Tag applied to every inferred Go project. |
| skipGoDependencyCheck | boolean | `false` | Disables Go project dependency detection in the Nx workspace graph. |
## Notes
[Section titled “Notes”](#notes)
* Applications are projects with a `main.go` containing `package main` and `func main(`, or a `cmd/` directory. All other Go projects are treated as libraries.
* `buildTargetName` and `runTargetName` only affect applications; libraries never infer build or run targets regardless of these options.
## Next steps
[Section titled “Next steps”](#next-steps)
* [Application generator](/guides/generators/application)
* [Library generator](/guides/generators/library)
* [Init generator](/guides/generators/init)
# Preset generator
> Preset used by create-nx-workspace to scaffold a new Nx workspace with gonx pre-configured.
Preset used by `create-nx-workspace` to scaffold a new Nx workspace with gonx pre-configured. Delegates to the application, library, or go-blueprint generator based on the selected `type`.
## Usage
[Section titled “Usage”](#usage)
```
npx create-nx-workspace --preset=@naxodev/gonx
```
## Options
[Section titled “Options”](#options)
| Option | Type | Default | Description |
| -------------- | --------------------------------------- | ---------------------------------------------------- | -------------------------------------------------------------------------------- |
| `skipFormat` | boolean | `false` | Skip formatting files. |
| `type` | `binary` \| `library` \| `go-blueprint` | `binary` *(required; default offered by the prompt)* | Define the type of preset to generate. |
| `directory` | string | *(required)* | The directory of the new application. Accepted as the first positional argument. |
| `name` | string | *-* | The name of the application. |
| `tags` | string | *-* | Add tags to the project (used for linting) |
| `addGoDotWork` | boolean | `false` | Add a go.work file to the project. |
### go-blueprint options
[Section titled “go-blueprint options”](#go-blueprint-options)
When `type` is `go-blueprint`, the following options are also required:
| Option | Type | Default | Description |
| ----------- | ------------------------------------------------------------------------------------------ | ------------ | ----------------------- |
| `framework` | `chi` \| `gin` \| `fiber` \| `gorilla/mux` \| `httprouter` \| `standard-library` \| `echo` | *(required)* | Framework to use |
| `driver` | `mysql` \| `postgres` \| `sqlite` \| `mongo` \| `redis` \| `scylla` \| `none` | *(required)* | Database drivers to use |
| `git` | `commit` \| `stage` \| `skip` | *(required)* | Git to use |
| `feature` | (`react` \| `htmx` \| `githubaction` \| `websocket` \| `tailwind` \| `docker`)\[] | *(prompted)* | Advanced feature to use |
## Notes
[Section titled “Notes”](#notes)
* `type=binary` delegates to the application generator; `type=library` delegates to the library generator; `type=go-blueprint` delegates to the go-blueprint generator.
* When invoked programmatically without go-blueprint values, the preset applies `framework=gin`, `driver=none`, `git=skip`, `feature=[]`.
## Next steps
[Section titled “Next steps”](#next-steps)
* [Application generator](/guides/generators/application)
* [Library generator](/guides/generators/library)
* [Go Blueprint generator](/guides/generators/go-blueprint)
# GoNx documentation
> An Nx plugin for Go development
GoNx

An Nx plugin for [Go](https://go.dev/) development. gonx infers test, lint, tidy, and generate targets from each `go.mod` (plus build and serve for applications), builds the project graph from Go imports, and ships generators for applications, libraries, and Go Blueprint projects. Available on [npm](https://www.npmjs.com/package/@naxodev/gonx).
Open source
gonx is MIT licensed and developed on [GitHub](https://github.com/naxodev/oss/tree/main/packages/gonx). Report bugs and request features in the [issue tracker](https://github.com/naxodev/oss/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc).
Community
Join the [Discord server](https://discord.gg/zjDCGpKP2S) to ask questions and get help.
***
## Key features
[Section titled “Key features”](#key-features)
### Inferred tasks
gonx detects each `go.mod` and infers test, lint, tidy, and generate targets automatically — plus build and serve for applications — no hand-written project.json files.
### Project graph from static analysis
A tree-sitter parser reads Go imports and `go.mod` files to build Nx project dependencies.
### Generators
Scaffold applications, libraries, and Go Blueprint projects with web frameworks and database drivers.
***
## Get started
[Quick start](/getting-started/quick-start)
# @naxodev/gonx
## Variables
[Section titled “Variables”](#variables)
* [export=](/reference/variables/export/)
# export=
> `const` **export=**: `NxPlugin`
Defined in: [packages/gonx/src/index.ts:5](https://github.com/naxodev/oss/blob/main/packages/gonx/src/index.ts#L5)
# Create your first Go project
> How to create, run, test, and build a Go project with Nx and gonx.
In this tutorial we’ll create a Go application with Nx, then run, test, and build it using targets that gonx infers from `go.mod`. Along the way we’ll see how Nx caching and the project graph work with Go projects.
## Before we start
[Section titled “Before we start”](#before-we-start)
We need:
* **Node.js 22+** and an **Nx 23.x** workspace
* **Go** — a [stable release](https://go.dev/dl/) (1.18+ for multi-module workspaces)
See [version compatibility](/getting-started/installation/#version-compatibility) for supported Nx/gonx version pairs, and the [introduction](/getting-started/introduction) for background on gonx’s nx-go origins.
## Steps
[Section titled “Steps”](#steps)
1. **Create a workspace with the gonx preset**
We’ll start by creating a fresh Nx workspace with gonx pre-configured:
```
npx create-nx-workspace go-workspace --preset=@naxodev/gonx
```
This scaffolds an Nx workspace with gonx registered in `nx.json` and a starter Go project. If you already have a workspace, install gonx into it instead:
```
npx nx add @naxodev/gonx
```
See [install gonx](/getting-started/installation) for details.
2. **Create a Go application**
Now we’ll generate a Go application:
```
cd go-workspace
npx nx g @naxodev/gonx:application my-go-app
```
The generator creates a Go project with a `package main` entry point and a `go.mod` file. gonx detects the `go.mod` and automatically infers `build`, `serve`, `test`, `lint`, `tidy`, and `generate` targets — no `project.json` needed. We can pass `--template` to choose `standard`, `cli`, or `tui`. See the [application generator guide](/guides/generators/application) for all options.
3. **Run the application**
Let’s run it:
```
npx nx run my-go-app:serve
```
The `serve` target runs `go run` from the project root. It’s a continuous target, so it stays running until we stop it. See the [serve executor guide](/guides/executors/serve).
4. **Test the project**
We can run the project’s tests with:
```
npx nx run my-go-app:test
```
The `test` target runs `go test ./...`. Because the target is cached, running it again with no source changes will return instantly from the Nx cache. See the [test executor guide](/guides/executors/test).
5. **Build the project**
Finally, let’s build an executable:
```
npx nx run my-go-app:build
```
The `build` target compiles a binary and outputs it to `dist//`. See the [build executor guide](/guides/executors/build).
## Verify
[Section titled “Verify”](#verify)
Let’s confirm Nx detected our project and inferred the right targets:
```
npx nx show projects
npx nx show project my-go-app
```
`nx show project` lists the `build`, `serve`, `test`, `lint`, `tidy`, and `generate` targets — all inferred, with no `project.json` file. Run `npx nx run my-go-app:build` a second time to see Nx caching in action: the second run is served from the cache and completes almost instantly.
## Explore the project graph
[Section titled “Explore the project graph”](#explore-the-project-graph)
gonx builds the Nx project graph by parsing Go imports with tree-sitter. Let’s visualize the dependencies:
```
npx nx graph
```
This opens the Nx project graph UI in your browser. If we add a library and import it from our application, the graph will show the dependency edge — even without `go.work`. See [how static analysis works](/understanding/static-analysis) to learn how gonx resolves imports to Nx projects.
## Next steps
[Section titled “Next steps”](#next-steps)
* [Application generator](/guides/generators/application) — all options including templates and tags
* [Library generator](/guides/generators/library) — scaffold a reusable Go package
* [Plugin options](/guides/generators/options) — customize target names and tags
* [How static analysis works](/understanding/static-analysis) — the tree-sitter project graph
* [Migrate from nx-go to gonx](/community/migration) — coming from nx-go
# How static analysis works
> Why gonx uses tree-sitter to build the Nx project graph from Go source.
gonx builds the Nx project graph by parsing Go source files directly with [tree-sitter](https://tree-sitter.github.io/). This approach does not require Go to be installed, which means `nx graph` and affected-task detection work even in environments without a Go toolchain.
## Why tree-sitter
[Section titled “Why tree-sitter”](#why-tree-sitter)
A Go toolchain is not always available in every environment that runs Nx — CI runners, remote caches, or containers may have Node but not Go. Parsing Go source with tree-sitter lets gonx extract import statements and build the project graph without invoking `go list` or any external process. The parser is a WebAssembly binary loaded from the `web-tree-sitter` and `tree-sitter-go` packages, so it runs anywhere Node runs.
## How the graph is built
[Section titled “How the graph is built”](#how-the-graph-is-built)
The dependency detection runs in four stages:
1. **Module discovery** — gonx scans all Nx projects for `go.mod` files and extracts module paths and replace directives. Each `go.mod` defines a Go module; its module path is the key used to resolve imports.
2. **Import extraction** — `.go` files are parsed with tree-sitter to extract `import` statements. `vendor/` and `testdata/` directories are excluded.
3. **Dependency resolution** — imports are resolved to Nx projects using longest-prefix matching. For example, importing `github.com/myorg/shared/utils` resolves to the project whose `go.mod` declares `module github.com/myorg/shared`.
4. **Replace directives** — `replace` directives in `go.mod` are scoped per-project. A replace directive in one project’s `go.mod` only affects that project’s imports, matching Go’s own module resolution semantics.
## Build constraints
[Section titled “Build constraints”](#build-constraints)
gonx honors `//go:build` and legacy `// +build` constraints. The dependency graph is computed against the host platform’s `GOOS`/`GOARCH` — a file gated to a different platform contributes no edges on the host.
Supported in the constraint expression:
* `//go:build` modern boolean form: `&&`, `||`, `!`, parentheses
* `// +build` legacy form (space-separated terms = OR, comma-separated within a term = AND, `!` per-term negation, multiple lines AND’d)
* `unix` pseudo-tag (matches Linux, Darwin, the BSDs, Solaris, AIX, and — note — Android, illumos, iOS, dragonfly, hurd; the full set Go ships in `internal/syslist.UnixOS`)
* `GOOS` values (`linux`, `darwin`, `windows`, …) and `GOARCH` values (`amd64`, `arm64`, `386`, …)
* User-defined tags via the `BuildContext.tags` set, plus `cgo` and `go1.N` policy via `BuildContext.cgoEnabled` / `BuildContext.goVersion` (internal API, not a plugin option)
Filename-based suffixes are also honored, matching Go’s `go/build` algorithm: `name_.go` (e.g. `signal_linux.go`), `name_.go` (e.g. `sha1block_amd64.go`), `name__.go` (e.g. `zsyscall_darwin_arm64.go`), and any of those with a trailing `_test` before `.go`. Note that `unix` is recognized only as an in-source build tag, **not** as a filename suffix — Go itself doesn’t treat `foo_unix.go` as unix-gated, and neither does gonx.
### Edge-case behavior
[Section titled “Edge-case behavior”](#edge-case-behavior)
* `go1.X` version tags evaluate to `true` by default (no Go compiler is handy to consult; over-including is safer than under-including for graph purposes). Set `BuildContext.goVersion` to gate on `N >= M`.
* The `cgo` pseudo-tag evaluates to `false` by default — static analysis never invokes cgo. Set `BuildContext.cgoEnabled` to opt in.
* A malformed constraint expression falls back to “include the file” rather than failing graph construction.
## Limitations
[Section titled “Limitations”](#limitations)
* **No cgo support**: the `import "C"` pseudo-import is filtered out.
* **No dynamic imports**: only static `import` statements are detected.
## Disabling dependency detection
[Section titled “Disabling dependency detection”](#disabling-dependency-detection)
To disable Go dependency detection entirely, set `skipGoDependencyCheck: true` in the plugin options:
```
{
"plugins": [
{
"plugin": "@naxodev/gonx",
"options": {
"skipGoDependencyCheck": true
}
}
]
}
```
See the [plugin options reference](/guides/generators/options) for all configuration options.
## Troubleshooting
[Section titled “Troubleshooting”](#troubleshooting)
### Dependencies not detected
[Section titled “Dependencies not detected”](#dependencies-not-detected)
1. Verify both projects have `go.mod` files.
2. Check that the module paths match the import statements.
3. Ensure the importing project has a `replace` directive pointing to the local project (required when not using `go.work`).
### Debugging
[Section titled “Debugging”](#debugging)
```
NX_VERBOSE_LOGGING=true npx nx graph
```
## Next steps
[Section titled “Next steps”](#next-steps)
* [Plugin options](/guides/generators/options) — `skipGoDependencyCheck` and other settings
* [Quick start](/getting-started/quick-start) — see the project graph in action
* [Contributing](/community/contributing) — how to contribute to gonx
# gonx 4.0.0
> gonx 4.0.0 moves to Nx 23 and ships a more reliable tree-sitter project graph.
gonx 4.0.0 is the Nx 23 release. It brings the plugin in line with the latest Nx major and hardens the tree-sitter project graph so `nx graph` and affected-task detection stay correct across more workspaces. This is a major version because it requires Nx 23 — but for most workspaces the upgrade is a migration command and a rebuild.
## Now on Nx 23
[Section titled “Now on Nx 23”](#now-on-nx-23)
gonx 4.0.0 targets **Nx 23**. The `@naxodev/gonx` migration bumps `nx` and `@nx/devkit` to `^23.0.0`, so a single `nx migrate` brings your workspace and the plugin forward together:
```
npx nx migrate latest
npx nx migrate --run-migrations
```
Everything you already rely on — inferred `build`, `serve`, `test`, `lint`, `tidy`, and `generate` targets from each `go.mod`, plus the Go Blueprint and application/library generators — works unchanged on Nx 23.
## A more reliable project graph
[Section titled “A more reliable project graph”](#a-more-reliable-project-graph)
gonx builds the Nx project graph by parsing Go source with [tree-sitter](https://tree-sitter.github.io/) instead of shelling out to the Go toolchain, so `nx graph` works even on CI runners and containers that have Node but not Go. 4.0.0 makes that graph more trustworthy:
* **Build constraints are honored.** gonx evaluates `//go:build` and legacy `// +build` tags against the host `GOOS`/`GOARCH`, so a file gated to another platform contributes no edges on the host — matching what `go build` actually compiles.
* **Hardened WebAssembly loading.** The `web-tree-sitter` / `tree-sitter-go` WASM parser now loads more robustly across environments, removing a class of graph-computation failures.
* **Per-project `replace` directives.** `replace` directives are scoped to the module that declares them, matching Go’s own resolution semantics.
See [how static analysis works](/understanding/static-analysis) for the full picture.
## Correct releases for release groups
[Section titled “Correct releases for release groups”](#correct-releases-for-release-groups)
`nx release` now resolves the current version correctly when a Go module is part of an Nx **release group**, so versioning and the `nx-release-publish` executor publish the right version. See the [nx-release-publish guide](/guides/executors/nx-release-publish).
## Breaking changes
[Section titled “Breaking changes”](#breaking-changes)
* **Nx 23 is required.** gonx 4.0.0 does not support older Nx majors. Run `nx migrate` before upgrading.
## Upgrade
[Section titled “Upgrade”](#upgrade)
Follow the [migration guide](/community/migration) for the full, step-by-step upgrade — including removing hand-written Go targets and reviewing your `go.work` setup. The short version:
```
npx nx add @naxodev/gonx
npx nx migrate --run-migrations
```
Then confirm your Go projects and their inferred targets still resolve:
```
npx nx show projects
npx nx show project apps/my-go-app
```