This document is a quick reference for maintainers and frequent contributors. It complements the contributor guide (which is contributor-facing) and contains deeper, actionable instructions for setting up, testing, and developing the project. We use Husky to manage our git hooks. When you install dependencies locally, the environment is configured automatically. See the Hooks section below for more info.
# clone
git clone https://github.com/cashubtc/cashu-ts.git
cd cashu-ts
# install exact dependencies used by CI
npm ci
# prepare browser dependencies for integration tests (one-time)
npm run test:prepare
This repository no longer uses a separate development branch. All development now happens directly against main.
The project will continue to support the last prior major release on a version branch. At the time of this change main tracks v4, while the v3 linage exists on v3-dev.
If you are backporting fixes to the v3 line, please open pull requests against the v3-dev branch instead.
Notes:
npm ci requires a package-lock.json and produces a reproducible node_modules tree.package.json (engine: node >=22.4.0). Use nvm, volta, or asdf to pin your local Node version.npm ci after switching major branchesWhen switching between major branches (for example main for v4 and v3-dev for v3) the lockfile and installed dependencies can differ. This frequently causes confusing failures when compiling or running api-extractor.
Always run a clean install after switching major branches to ensure node_modules matches the checked-in lockfile:
# after checkout
npm ci
If you still see strange build or extractor errors, do a full refresh of dependencies:
rm -rf node_modules
npm ci
This callout is important — please don't skip it when moving between major branches, it saves a lot of time debugging mysterious build/test failures.
npm (node package manager), git, optional nvm/volta for Node version management.npm run test:prepare).During local install, husky wires up the pre-commit, pre-push, and commit-msg hooks through the prepare script.
We also configure your local git config commit.template to use the project's .gitmessage.
This project follows the Conventional Commits specification. This is required because it powers our automated versioning and changelog generation.
<type>(<scope>): <description>feat: A new feature (triggers a MINOR version bump).fix: A bug fix (triggers a PATCH version bump).docs: Documentation changes only.chore: Maintenance tasks or library updates..gitmessage template to help you structure your messages. This is automatically configured as your local commit.template when you run npm install.If your message doesn't fit the format, the commit-msg hook will prevent the commit.
If your commit fails the commitlint check, you don't need to retype it.
Git keeps the attempted message in .git/COMMIT_EDITMSG. To reopen, fix, and retry it:
git commit --edit --file=.git/COMMIT_EDITMSG
commit-msg: validates the commit message with Commitlint and points you at .git/COMMIT_EDITMSG if the message needs fixing.pre-commit: runs lint-staged on staged files only.
*.{js,ts}: eslint --fix, then prettier --write*.{json,md,yml,yaml}: prettier --writepre-push: runs repository-wide npm run check-lint and npm run check-format.This keeps commits fast while still blocking pushes with lint or formatting drift.
The hooks do not run compile, unit tests, integration tests, or API Extractor for you. Run the checks that fit your change before opening a PR.
The repo includes a convenience script:
npm run prtasks
This runs (in order): lint, format, api:update (compile + api-extractor), tests, and git status
Caution: api:update can modify generated files (e.g. API reports). Inspect and commit any intended changes.
Run the checks that match the risk of your change before pushing. As a baseline:
npm run check-lint
npm run check-format
npm test
For public API changes, also run:
npm run api:update
For mint, wallet, transport, or event changes, run the Node integration tests against a fresh local mint:
DEV=1 make cdk-stable-up
npm run test-integration
DEV=1 make cdk-stable-down
For browser-facing integration changes, use the local browser wrapper. It starts a fresh mint for each browser because LN invoices must be unique per run:
npm run test-integration:browser:local:cdk
# or a single browser:
npm run test-integration:browser:local:cdk -- firefox
Consumer smoke tests are also run in CI. Run npm run test:consumer when packaging, exports, browser bundles, or consumer compatibility are involved.
npm run prtasks is available when you want the heavier all-in local sweep. It runs lint, format, api:update, tests, and git status.
The repository provides Makefile targets that make it easy to spin up the most popular cashu mints (currently cdk and nutshell). These are used in the CI for integration testing and made available locally. Use the Makefile as the single source of truth for the pinned Docker image versions.
Spin up / tear down locally
# start the mint (uses Makefile defaults unless you override)
DEV=1 make cdk-stable-up
# stop the mint
DEV=1 make cdk-stable-down
# start nutshell
DEV=1 make nutshell-stable-up
# stop nutshell
DEV=1 make nutshell-stable-down
# run a specific mint image with a custom container name
# NOTE: cdk-up is the base target, cdk-stable-up/cdk-rc-up use the stable/rc values
CDK_IMAGE=cashubtc/mintd:0.13.4 CDK_NAME=my-local-mint DEV=1 make cdk-up
make cdk-stable-up / make nutshell-stable-up) so the runtime behavior in CI matches local usage.latest) so PRs will update numeric tags.npm run test-integration or the browser integration equivalent.npm cinpm run test:prepareDEV=1 make cdk-stable-up (and/or DEV=1 make nutshell-stable-up, DEV=1 make cdk-rc-up, DEV=1 make nutshell-rc-up)npm run test-integrationDEV=1 make cdk-stable-down / DEV=1 make nutshell-stable-downFor browser integration tests, prefer npm run test-integration:browser:local:cdk or npm run test-integration:browser:local:nutshell; those commands handle fresh mint setup and teardown per browser.
npm run api:check to create a temporary API report and compare it to the recorded status-quo at /etc/cashu-ts.api.md.npm run api:update to update the /etc status-quo when a public API change is intended.When running api:update locally:
npm run api:update
# inspect changes under /etc
git add /etc/cashu-ts.api.md
git commit -m "docs(api): update API report"
If api:update modifies generated code or types, run the test/build steps and ensure CI passes.
Run unit tests (node + browser) locally:
npm test
The npm test script runs Vitest with coverage enabled (--coverage) and emits reports
into the coverage/ directory.
After the run you can open the HTML report locally (coverage/index.html) in
your browser to inspect per-file metrics.
CI uploads coverage to Codecov from the main test workflow, and the README badge/link points to the latest public report there.
If a test requires Node-only features, name the file with .node. in the filename
(for example cbor.node.test.ts). The Vite/Vitest configuration will then
skip browser testing for that file and run it only in the Node environment.
Likewise, you can use .browser. in the filename to mark a test as
browser-only (we currently don't have any browser-only tests, but the convention is supported).
Run only node tests or a single test file with vitest (useful for rapid iteration):
npx vitest --run --filter <pattern>
npm run test:prepare
npm run test-integration
Browser integration tests can be run against an already-running fresh mint:
npm run test-integration:browser:firefox
For local full-browser runs, prefer the wrapper:
npm run test-integration:browser:local:cdk
If tests are flaky locally, run with increased verbosity or use --run --inspect / --watch where supported.
npm install <pkg> --save
# or for dev dependencies
npm install <pkg> --save-dev
package-lock.json (CI will use that exact lockfile).npm ci.Cashu-TS uses semantic versioning.
The repository uses a single primary development branch, main, which tracks the current major release (v4).
All new development is merged into main via pull requests.
The previous major version (v3) is maintained on the v3-dev branch for critical fixes only.
If you need to backport a fix to v3, open a separate PR targeting v3-dev (do not mix both in a single PR).
Stable v4 releases on main are automated with release-please.
main is analyzed by release-please.main.feat and fix commits since the last releaseCHANGELOG.mdfeat → minor version bumpfix → patch version bumpfeat! / fix!) → major version bumplatest (with provenance)Merging the Release PR is the release action. No additional steps are required.
Release candidates are cut manually from a branch, keeping main clean for the pending release-please PR.
main (e.g. v4-rc1).package.json to the RC version (e.g. 4.0.0-rc.1).version.yml) detects the prerelease version and publishes to npm with the next dist-tag.main.When the RC phase is complete, merge the release-please PR on main to cut the stable release.
v3 maintenance releases are handled manually — release-please only watches main.
Open a release PR targeting v3-dev.
Include the cherry-picked fixes and bump package.json to the next patch version (e.g. 3.6.2).
Merge the PR into v3-dev.
Tag the merged v3-dev commit that contains the version bump:
git fetch origin v3-dev --tags
git tag -a v3.6.2 origin/v3-dev -m "v3.6.2"
git push origin v3.6.2
Create a GitHub Release from the tag (or use workflow_dispatch on the publish workflow with the tag).
The publish workflow detects major version 3 and publishes to npm with the v3-lts dist-tag.
| Version | npm dist-tag | Install command |
|---|---|---|
| v4 stable | latest |
npm install @cashu/cashu-ts |
| v4 RC / prerelease | next |
npm install @cashu/cashu-ts@next |
| v3 LTS | v3-lts |
npm install @cashu/cashu-ts@v3-lts |
main are determined automatically by release-please; contributors should not attempt to control versions directly.package.json.If you see strange compile or api-extractor errors after switching branches: run npm ci to ensure node_modules matches the checked-in lockfile. If problems persist, try removing node_modules and running npm ci again.
To reproduce CI locally, run the same checks your change requires: npm run check-lint, npm run check-format, npm run compile, npm test, npm run api:update for public API changes, and npm run test-integration when mint behavior is involved.
Feel free to join the matrix server or telegram channel