The six publishable libraries (@threadplane/chat, @threadplane/langgraph, @threadplane/ag-ui, @threadplane/render, @threadplane/a2ui, @threadplane/telemetry) ship together at a synchronized version via Nx Release. Releases use minor bumps (0.1.0 → 0.2.0 → …). Never cut 1.0.0 without explicit approval from the repository owner, every time.
Nx updates internal dependency and peer ranges with the synchronized release. preserveMatchingDependencyRanges is disabled so a prior ^0.0.x peer range cannot block the next patch or leave companion packages on incompatible versions. External dependency ranges remain unchanged.
First release? See First
@threadplanerelease below — the flow is different because there's no prior package under the new npm org yet.
Warning
Do not use nx release patch. The one-shot nx release command does not
work in this repo. nx.json configures git options under
release.changelog.git, and Nx rejects the top-level command whenever
granular git config is present:
NX The "release" top level command cannot be used with granular git configuration.
Use the subcommands below instead.
From a clean main branch:
git checkout main && git pull
# 1. Version bump. Runs preVersionCommand (builds all six projects), rewrites every
# package.json, updates package-lock.json, and stages the result.
npx nx release version --specifier=minor
# 2. Regenerate the public agent-context files. They embed the release
# version, and the Website unit suite fails the release commit until
# `apps/website/public/{AGENTS,CLAUDE}.md` say the new version.
npm run generate-agent-context
git add apps/website/public/AGENTS.md apps/website/public/CLAUDE.md
# 3. Changelog + commit + tag + GitHub Release.
# Pass the BARE version — see the warning below.
npx nx release changelog 0.0.57
# 4. Push. The Publish workflow fires on the tag and publishes to npm
# with provenance via OIDC trusted publishing.
git push origin main --tagsWarning
Pass the bare version to changelog, not vX.Y.Z. releaseTagPattern is
v{version}, so Nx prepends the v itself. Passing v0.0.57 produces a
malformed vv0.0.57 tag and a GitHub Release at
/releases/tag/vv0.0.57. Pass 0.0.57.
Always --dry-run step 2 first and check the printed tag URL before
committing to it.
Step 4 is what actually ships. Prefer the tag-driven workflow: it rebuilds the
versioned sources, runs the package gates, and publishes with provenance without
local npm credentials. If publishing locally, first rebuild all six packages
and Growth, then run telemetry:test-install-pack and
telemetry:test-development-bundle before npx nx release publish --groups=publishable.
The version command's pre-build embeds the old runtime version; a rebuild after
versioning is required to align collector payloads with the new package manifests.
Step 1 regenerates package-lock.json. On macOS that can drop the Linux
@next/swc-* bindings and break CI. The diff should be only the version
lines for the six libs:
git diff --cached package-lock.json | grep -E '^-' | grep -icE 'linux|darwin|musl|gnu'
# must print 0If it prints anything else, revert the lockfile and re-apply the version lines by hand.
The first publish under the @threadplane npm org is manual. The packages must exist on npm before trusted publishing can be configured package-by-package. Run this from a clean, merged main branch.
# 1. Install and build everything
npm ci
npx nx run-many -t lint,test,build --projects=chat,langgraph,ag-ui,render,a2ui,telemetry --skip-nx-cache
# 2. Verify release metadata
node scripts/verify-release-versions.mjs --tag v$(node -p "require('./libs/chat/package.json').version")
npx nx release publish --groups=publishable --dry-run
# 3. Publish manually.
npm publish dist/libs/telemetry --access public
npm publish dist/libs/a2ui --access public
npm publish dist/libs/render --access public
npm publish dist/libs/chat --access public
npm publish dist/libs/ag-ui --access public
npm publish dist/libs/langgraph --access public
# 5. Verify all package pages resolve.
npm view @threadplane/telemetry version
npm view @threadplane/a2ui version
npm view @threadplane/render version
npm view @threadplane/chat version
npm view @threadplane/ag-ui version
npm view @threadplane/langgraph versionAfter the first @threadplane release, configure npm trusted publishing for all six packages against .github/workflows/publish.yml. Subsequent patch bumps use the one-shot flow above.
Always sanity-check before a real release. Dry-run each subcommand — the
one-shot nx release patch --dry-run fails the same way the real command does:
npx nx release version --specifier=minor --dry-run
npx nx release changelog 0.0.57 --dry-run # bare version; check the printed tag URLThese print what would happen without modifying anything.
Version bumps on main do not publish — only a pushed vX.Y.Z tag does. Main
routinely drifts ahead of npm, and the version on disk can match the version on
npm while the code differs. Check before assuming:
git rev-list --count "v$(npm view @threadplane/chat version)"..origin/mainAnything above 0 means main has unpublished commits.
Publish workflow accepts workflow_dispatch with a dry-run input (default true). Trigger from the GitHub Actions UI to verify CI's publish path without actually shipping.
Releases bump the minor component (0.1.0 → 0.2.0 → …). Breaking changes can still land in any release while the major is 0, so consumers should lock to an exact version; the changelog names the breaking entries.
1.0.0 is a deliberate gate, not something to infer from scope or stability: ask the repository owner and wait for an explicit yes before cutting it.
Through v0.0.66 the project used patch-only bumps. That ended on 2026-09-08, when a backlog of breaking changes made the patch counter actively misleading.
Caret-prefixed ranges (^0.0.1) do not include subsequent 0.0.x patches. Nx updates internal peers during each synchronized release so a newly installed package resolves compatible companion APIs. Do not preserve stale narrow ranges or manually restore wildcard peers after versioning.