This guide covers setting up your development environment, building the library, running tests, and contributing code to the AdGuard Scriptlets and Redirect Resources library.
| Tool | Version | Notes |
|---|---|---|
| Node.js | 22 | Use nvm to manage versions |
| pnpm | >=10.33.4 and <11 | Package manager |
| Git | Latest | Version control |
Note: Development is tested on macOS and Linux. Windows users should use WSL or a virtual machine.
git clone git@github.com:AdGuardSoftwareLimited/ext-scriptlets.git
cd ext-scriptletsThe canonical source lives in the private repo
AdGuardSoftwareLimited/ext-scriptlets; it is mirrored to the publicAdguardTeam/Scriptletson every push tomaster.
pnpm installNote on the
basic-ftpoverride:package.jsonpins the transitivebasic-ftpdependency to the security-fixed5.2.1viapnpm.overrides. It is not declared in any manifest directly — it comes in through Puppeteer's proxy chain (get-uri→pac-proxy-agent), which QUnit tests use. When this override can be dropped: once the upstream chain resolvesbasic-ftp@>=5.2.1on its own (checkpnpm why basic-ftp), remove the entry fromoverrides.
pnpm buildBuild output goes to dist/.
# All tests (Vitest + smoke + QUnit)
pnpm test
# Vitest only (API, validators, converters)
pnpm test:vitest
# QUnit only (scriptlets)
pnpm test:qunit scriptlets
# QUnit only (redirects)
pnpm test:qunit redirects
# Single scriptlet with rebuild
pnpm test:qunit scriptlets --name <scriptlet-name> --build# All linters
pnpm lint
# Individual linters
pnpm lint:code # ESLint
pnpm lint:types # TypeScript type checking
pnpm lint:md # markdownlint| Command | Description |
|---|---|
pnpm install |
Install dependencies |
pnpm build |
Clean dist/ and build all bundles |
pnpm test |
Run all tests (Vitest + smoke + QUnit) |
pnpm test:vitest |
Run Vitest tests only (API, validators, converters) |
pnpm test:qunit scriptlets |
Run QUnit tests for all scriptlets |
pnpm test:qunit redirects |
Run QUnit tests for all redirects |
pnpm test:qunit helpers |
Run QUnit tests for helpers |
pnpm test:qunit scriptlets --name <name> --build |
Run a single scriptlet test with rebuild |
pnpm test:qunit:build |
Build QUnit test bundles (CI split-stage) |
pnpm test:qunit:run |
Run QUnit tests without rebuilding (CI split-stage) |
pnpm tgz |
Pack scriptlets.tgz (needs a version) |
pnpm lint |
Run all linters |
pnpm lint:code |
Run ESLint |
pnpm lint:types |
Run TypeScript type checking (tsc --noEmit) |
pnpm lint:md |
Run markdownlint |
pnpm wiki:build-table |
Regenerate compatibility table |
pnpm wiki:build-docs |
Regenerate scriptlet/redirect wiki docs from JSDoc |
Note:
pnpm tgz(andpnpm pack) need a version inpackage.json, which ships versionless. CI stamps the dev version via the sharedset-dev-versionaction before packaging; locally you must stamp it first (mirroringtests/smoke/exports/test.sh), otherwisepnpm tgzfails withERR_PNPM_PACKAGE_VERSION_NOT_FOUND.
- Create a feature branch from
master - Make your changes
- Ensure all checks pass (see Before Committing below)
- Submit a pull request to
master
Run these checks before every commit:
# Lint all (ESLint + TypeScript + markdownlint)
pnpm lint
# Run the relevant test suite
pnpm test:qunit scriptlets --name <name> --build # for scriptlet changes
pnpm test:vitest # for API/converter/validator changesBoth must pass with no errors.
Every commit message MUST start with the ticket number (AG-XXX) so it
auto-links with the task tracker, followed by a short description in the
present tense:
AG-XXX <short description in present tense>
Examples:
AG-55716 Add reusable publish-release workflowAG-4321 Fix redirect after loginAG-99 Update dependencies
Automated commits that CI creates on its own (for example, the wiki
regeneration during the release flow, which has no ticket number) use a
Conventional Commits prefix such as docs: — e.g.
docs: regenerate wiki docs for release.
- Run
/sdd-spec <scriptlet description>then/sdd-planto create the spec and plan. - Create
src/scriptlets/<name>.tswith a JSDoc@scriptletheader. - Add a QUnit test file at
tests/scriptlets/<name>.test.js. - Update
scripts/compatibility-table.jsonwith the new entry. - Run
pnpm test:qunit scriptlets --name <name> --buildto verify. - Run
pnpm wiki:build-docsto regenerate the wiki documentation.
- Run
/sdd-spec <redirect description>then/sdd-plan. - Create the source file in
src/redirects/and a YAML manifest alongside it. - Add a QUnit test file at
tests/redirects/<name>.test.js. - Update
scripts/compatibility-table.jsonwith the new entry. - Run
pnpm test:qunit redirects --buildto verify. - Run
pnpm wiki:build-docsto regenerate the wiki documentation.
# Regenerate compatibility table
pnpm wiki:build-table
# Regenerate scriptlet/redirect docs from JSDoc
pnpm wiki:build-docsNote: Files in
wiki/are auto-generated. Do not edit them manually.
Releases are driven by CHANGELOG.md and GitHub Actions; package.json has no
version field (it is injected at build time).
Clean local builds do not modify package.json. They derive a development
version by incrementing the patch component of the latest released
CHANGELOG.md heading and appending -dev. CI stamps that same development
version via the shared set-dev-version action before Docker packaging.
Developer preconditions before requesting a release:
- Ensure the changes are listed under
## [Unreleased]inCHANGELOG.md. - If a release adds new scriptlets/redirects, resolve the
@added unknownwiki-version TODO at the top ofCHANGELOG.mdfor the target version (the wiki is regenerated from JSDoc during the release flow).
For the full release flow (Prepare release PR → merge → Publish release), see DEPLOYMENT.md.
- AGENTS.md — AI agent instructions and code guidelines
- README.md — Project overview and usage documentation
- CHANGELOG.md — Version history
- AdGuard JavaScript Code Guidelines