This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
@naxodev/oss is an Nx 22 monorepo (pnpm workspace, Node 22) that publishes two independent Nx plugins to npm:
@naxodev/nx-cloudflare(packages/nx-cloudflare) — Nx plugin for Cloudflare Workers (generators, executors, and acreateNodesV2inference plugin around Wrangler).@naxodev/gonx(packages/gonx) — Nx plugin for using Go in an Nx workspace (fork of nx-go, modernized). Includes a tree-sitter–based Go static-analysis graph.
Supporting (non-published) projects: e2e-utils (shared e2e helpers), nx-cloudflare-e2e / gonx-e2e (e2e suites), and gonx-docs (Astro Starlight docs site at packages/docs/gonx-docs).
All Nx invocations use pnpm exec nx .... The package manager is pnpm (not npm/yarn).
# Build a single plugin (outputs to dist/packages/<name>)
pnpm exec nx build nx-cloudflare
pnpm exec nx build gonx
# Lint / test a project
pnpm exec nx lint gonx
pnpm exec nx test nx-cloudflare
# Run only what's affected (this is what CI runs)
pnpm exec nx affected -t lint test build
# Formatting (Prettier, via nx)
pnpm exec nx format:check # verify
pnpm exec nx format:write # fix
# e2e (spins up a local Verdaccio registry — see note below)
pnpm exec nx e2e nx-cloudflare-e2e
pnpm exec nx e2e gonx-e2eUnit tests run on Jest (via @nx/jest, ts-jest). Pass Jest CLI args after --:
# By file
pnpm exec nx test gonx -- src/graph/static-analysis/parse-go-mod.spec.ts
# By test name
pnpm exec nx test nx-cloudflare -- -t "deploy executor"Note: the Nx config registers both the Jest and Vite plugins under the test target name; the actual unit suites here are Jest. The @naxodev/nx-cloudflare package scaffolds Vitest configs into generated user projects — don't confuse the scaffolded test setup with this repo's own test setup.
Each plugin is an Nx library project built with @nx/js:tsc. The published shape is driven by three manifests at the package root:
generators.json— maps generator names →src/generators/<name>/generator.ts+schema.json.executors.json— maps executor names →src/executors/<name>/executor.ts+schema.json.package.jsonexports— for nx-cloudflare, a detailed exports map exposes./plugin, per-generator/executorschema/generatorentry points. When adding a generator/executor, update both the relevant*.jsonmanifest and (for nx-cloudflare) theexportsmap.
src/index.ts is the programmatic public API. For gonx it exports the NxPlugin object (createNodesV2 + createDependencies); for nx-cloudflare it re-exports the generators for composition by other plugins.
Both plugins infer Nx targets from project files rather than requiring hand-written project.json targets:
- nx-cloudflare (
src/plugin.ts): detects Wrangler config and builds Worker lifecycle targets (serve/deploy/typegen/version-upload/tail) that shell out to the Wrangler CLI vianx:run-commands. Target names are configurable viaCloudflarePluginOptions. - gonx (
src/graph/):createNodesV2.tsinfers targets from Go projects;create-dependencies.tsbuilds the project graph from Go imports. Thesrc/graph/static-analysis/module parsesgo.mod/go.workand Go source with tree-sitter (web-tree-sitter+tree-sitter-go) to resolve the local import graph. Seepackages/gonx/docs/static-analysis.md.
Releases are independent per project (nx.json → release.projects: ["gonx", "nx-cloudflare"]), driven by Conventional Commits. Versioning/changelog/GitHub-release creation are handled by nx release. Publishing is triggered by publishing a GitHub Release whose tag follows {projectName}@v{version} (e.g. gonx@v3.0.0); .github/workflows/release.yml parses the project from the tag, builds it, and runs nx release publish with npm provenance. Prereleases (GitHub "prerelease" flag) publish under the next npm tag, otherwise latest.
Because releases are conventional-commit driven, commit messages and PR titles matter — squash-merge lands the PR title as the commit subject. Use Conventional Commits with the package scope, e.g. feat(nx-cloudflare): ..., fix(gonx): ..., feat(nx-cloudflare)!: ... for breaking changes.
e2e suites (*-e2e) install the published tarball from a local Verdaccio registry into a freshly generated Nx workspace (packages/e2e-utils/src/lib/create-test-project.ts → real create-nx-workspace + install), so they exercise peerDependencies, the exports map, and migrations the way real consumers do — not a copied dist fixture.
The two e2e projects share one Verdaccio instance (same port/storage). tools/scripts/start-local-registry.ts coordinates ownership via per-pid lock files so parallel globalSetup/globalTeardown don't race. Consequently CI runs e2e serially (--parallel=1), and e2e is skipped on Windows.
.github/workflows/ci.yml runs on push to main and PRs across Ubuntu/macOS/Windows: nx format:check, then nx affected -t lint test, nx affected -t build, then nx affected -t e2e --parallel=1 (non-Windows). Uses nrwl/nx-set-shas for affected detection and Nx Cloud for caching.
- Commit messages are validated by commitlint (
@commitlint/config-conventional). - ESLint enforces
@nx/enforce-module-boundariesand@nx/nx-plugin-checks(validatespackage.json/generators.jsonfor the plugins). Run lint before considering plugin manifest changes done. - Projects are tagged
scope:public/type:plugin.