Skip to content

feat(vpx): run TypeScript scripts with the vendored oxc-node - #2936

Open
fengmk2 wants to merge 97 commits into
mainfrom
feat/vpx-typescript-scripts
Open

fengmk2 wants to merge 97 commits into
mainfrom
feat/vpx-typescript-scripts

Conversation

@fengmk2

@fengmk2 fengmk2 commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

Summary

vpx <file> runs a script file directly with the project's managed Node.js and the oxc-node loader:

vpx ./scripts/seed.ts --dry-run

TypeScript syntax that Node.js cannot strip (enums, namespaces, parameter properties, legacy decorators, JSX), tsconfig paths, .js → .ts imports, TypeScript dependencies, and ESM/CJS interop work without a tsx or ts-node dependency. Package-binary execution through the global vpx (vpx eslint .) is unchanged. Inside package.json scripts, vpx <pkg> now runs only binaries installed in node_modules/.bin.

Design and findings: rfcs/vpx-script-execution.md.

Changes

  • Vendored oxc-node. The Rust source is cloned by sync-remote, like Rolldown, and compiled into the native binding unpatched. It is pinned to ce22828, a main commit after v0.1.7 whose fixes are not released yet; upgrade-deps moves the pin to the first stable tag that contains it. The binding links it with default-features = false, so oxc-node registers no NAPI exports and no global allocator of its own, and with yarn_pnp, to match the oxc_resolver feature the workspace enables, and packages/cli/binding/src/oxc_node.rs forwards what the loader uses under an oxcNode namespace (createResolve, load, OxcTransformer, setTsconfigPath, setTransformDeps, transformsDep). Its module_exports hook runs init_tracing and detect_runtime_syntax, so OXC_LOG works and using stays native on Node.js 24+. patch-oxc-node.ts only points oxc-node's oxc dependency at the workspace version, so the binding links one oxc: oxc-node's main asks for 0.155.0 and builds unchanged with the workspace's 0.154.0, which Rolldown pins. The preload calls setTransformDeps('typescript'), so TypeScript under node_modules is transformed and other dependencies run as published. The release binding grows by about 130 KB (0.3%).

  • Loader. vpx <file> runs node --require dist/script-preload.cjs --import dist/script-register.js <file>. Node.js 22.22.3+, 24.11.1+, and 26 use the in-thread module.registerHooks() (the releases tsx also switches at); older 22.x and 24.11.0 use module.register(), which takes longer to start; its hooks thread requires the binding as CommonJS, which saves 5–13 ms there. Runtime helpers are emitted under a private module name, vite-plus:oxc-node, and resolved from @oxc-project/runtime, a vite-plus dependency, so helper imports from other oxc-node copies keep their own resolution; CommonJS output require()s them through a Module._resolveFilename wrapper, so a pnpm project or a script outside any project finds them too.

  • CLI. Script detection in the global vpx (Rust) and a new project-local vpx bin, so package.json scripts work without the global CLI. Both implementations decide from one shared table of cases. A missing script is an error, never a package download, with or without --package. An explicit path to a file that is not executable, or to a directory without a package.json, is a vpx error instead of a vp dlx failure. vpx -v/--version prints the Vite+ version. --tsconfig <path> selects the tsconfig, passed to oxc-node's setTsconfigPath(). After -e/--eval, -p/-pe/--print, --run, or --test, the remaining arguments are code arguments, a package script's arguments, or test files and globs, never a script to check, and Node.js options also match with _ for - (--redirect_warnings), as Node.js accepts. Script mode selects the Node.js that vp node selects, including a system-first Node.js found on PATH, and passes Node.js the loader's real path, so --preserve-symlinks works with a pnpm-installed vite-plus.

  • One process on Unix. Like the global vpx, the project-local bin replaces itself with the script's Node.js through process.execve(), so the PID its caller holds, every signal sent to it (kill -INT, SIGUSR1 for the inspector), and the exit status belong to the script, and no second Node.js process (about 50 MB) stays alive while the script runs. The new process starts as a spawned child would: default SIGPIPE and SIGXFSZ dispositions and blocking stdio, which process.execve() otherwise leaves non-blocking (process.execve() passes non-blocking stdio to the new program nodejs/node#66824). When a tool fork()s the bin, it keeps spawning, relays the IPC channel to the script in both directions, as tsx does, and exits with the script's code whichever side closes the channel first; the global vpx passes the channel on through exec. On Windows the bin always spawns, and only a fork() of the bin file carries a channel, not a .cmd shim.

  • Package binaries in package.json scripts. Package managers and vp run put node_modules/.bin first on PATH, so scripts run the project-local bin. It never hands off to the global vpx, so two copies on PATH cannot spawn each other. The nearest binary in node_modules/.bin runs directly, as the global vpx runs it, exec'd in place on Unix, so it needs no package.json above the cwd and installs nothing first. A native binary, or a script whose #! interpreter is one, execs directly; anything else goes through /bin/sh, which reports a file it cannot run as a terminal does. pkg@version, --package, or --shell-mode run with the package's own vp dlx. On Windows, a .cmd binary runs through cmd.exe, so Ctrl+C there can end with the "Terminate batch job (Y/N)?" prompt, which the global vpx avoids by running the .ps1 sibling in a terminal. A tool found only in global packages or on PATH is no longer found there, and a binary that is not installed fails with a hint instead of a download:

    error: vpx: 'eslint' is not installed in node_modules
    note: Add it to devDependencies, or run `vp dlx eslint` to download and run it.
    
  • Toolchain. vp toolchain reports oxc-node with its version and revision.

  • Deps. @oxc-project/runtime follows Rolldown's pin. upgrade-deps.ts bumps the oxc-node pin to new stable tags, but only to a tag that contains the pinned commit, so a pin to an unreleased fix is not dropped.

Upstream

17 issues found while vendoring were filed upstream and fixed: oxc-project/oxc-node#794 to oxc-project/oxc-node#798 in v0.1.5, oxc-project/oxc-node#804 to oxc-project/oxc-node#806 and oxc-project/oxc-node#808 to oxc-project/oxc-node#811 in v0.1.6, and in v0.1.7 oxc-project/oxc-node#807 (a napi feature, so an embedder links it without its exports), oxc-project/oxc-node#820 (CommonJS transformed twice on the registerHooks() path), oxc-project/oxc-node#821 (an option to transform TypeScript dependencies alone), oxc-project/oxc-node#827 (extra file reads added by the #820 fix), and oxc-project/oxc-node#828 (extensionless ES modules). The vendored patch, once 30 hunks, is gone.

12 more were found later, most of them in end-to-end testing against tsx 4.23 on macOS, Linux, and Windows, and all are fixed on oxc-node main and synced here: oxc-project/oxc-node#835 (paths for a file outside every tsconfig include), oxc-project/oxc-node#837 (file names with # or % ran the wrong file), oxc-project/oxc-node#839 (no line and column in errors), oxc-project/oxc-node#840 (.js resolved before .ts), oxc-project/oxc-node#841 (data: URL imports), oxc-project/oxc-node#842 (ERR_REQUIRE_ASYNC_MODULE), oxc-project/oxc-node#843 (invalid UTF-8), oxc-project/oxc-node#844 (an unreadable tsconfig skipped silently), oxc-project/oxc-node#845 (--preserve-symlinks, and OXC_LOG on stdout), oxc-project/oxc-node#846 (a byte order mark before a shebang), oxc-project/oxc-node#856 (# in an import specifier), and oxc-project/oxc-node#862 (a parent URL ending in /, the working directory Node.js resolves the entry point and --import against, resolved as a file, so an extensionless --import ./setup was not found and scripts failed with the working directory at /). Two oxc transformer issues from the same testing are open: oxc-project/oxc#27741 (accessor fields are not lowered) and oxc-project/oxc#27742 (legacy decorator order differs from tsc). The final round also found nodejs/node#66824 (process.execve() passes non-blocking stdio to the new program), worked around in the local bin. Because vpx sets the dependency mode, OXC_TRANSFORM_ALL has no effect under it.

script-preload.ts mirrors the oxc-project/oxc-node#820 fix in upstream's register.mjs: it returns a null source for CommonJS only when oxc-node produced none, so source from another hook is kept. That fix added two file reads per CommonJS-package file with ES module syntax, which the oxc-project/oxc-node#827 fix removed. It also mirrors the oxc-project/oxc-node#842 change, which sets ERR_REQUIRE_ASYNC_MODULE on the binding's error for require() of an ES module with top-level await.

An extensionless shebang script runs as JavaScript, as before; TypeScript in it is not supported, because the name does not tell which it is. With the oxc-project/oxc-node#828 fix, its syntax decides whether it is an ES module in a package without "type", as in Node.js.

Following upstream, a .cts file with import/export fails with one error that suggests renaming it to .mts, as Node.js also rejects it. Without --tsconfig, TS_NODE_PROJECT and OXC_TSCONFIG_PATH apply, as they do for oxnode.

Performance

Compared with tsx 4.23.15 on an Apple M4 Pro (macOS 26.6). Each vpx is compared with the tsx setup it replaces:

  • Global vpx execs Node.js in place, so it is one process, like node --import tsx. Its times include the Rust shim's startup, Node.js resolution, and the loader lookup, which take 5–10 ms.
  • Project-local vpx is what package.json scripts run. It starts its own Node.js before it execs the script, which adds 23–30 ms, against the 32–42 ms the tsx CLI's parent process adds.

How to read it: the percentage is how much less (−) or more (+) time vpx takes than tsx. 🟢 vpx is faster, 🔴 vpx is slower, ⚪ within ±3%, about the run-to-run noise.

Scenarios: hello is 1 file with erasable syntax only; esm-app is 301 modules in an ES module package, and cjs-app the same modules in a package without type; large-cjs and large-esm are one 1.8 MB file, as CommonJS and as ESM.

Global vpx against node --import tsx

Scenario Node.js global vpx tsx, warm cache vpx vs warm tsx, no cache vpx vs no cache
hello 22.18 51 ms 68 ms 🟢 −25% 75 ms 🟢 −33%
hello 24.12 34 ms 46 ms 🟢 −26% 63 ms 🟢 −46%
hello 26.5 37 ms 38 ms 🟢 −4% 61 ms 🟢 −39%
esm-app 22.18 94 ms 124 ms 🟢 −24% 141 ms 🟢 −34%
esm-app 24.12 75 ms 94 ms 🟢 −20% 217 ms 🟢 −65%
esm-app 26.5 77 ms 92 ms 🟢 −16% 216 ms 🟢 −64%
cjs-app 22.18 94 ms 143 ms 🟢 −34% 289 ms 🟢 −67%
cjs-app 24.12 75 ms 116 ms 🟢 −36% 261 ms 🟢 −71%
cjs-app 26.5 77 ms 113 ms 🟢 −32% 257 ms 🟢 −70%
large-cjs 22.18 121 ms 122 ms ⚪ −1% 229 ms 🟢 −47%
large-cjs 24.12 100 ms 90 ms 🔴 +11% 273 ms 🟢 −64%
large-cjs 26.5 93 ms 76 ms 🔴 +21% 258 ms 🟢 −64%
large-esm 22.18 103 ms 107 ms 🟢 −4% 200 ms 🟢 −49%
large-esm 24.12 84 ms 75 ms 🔴 +12% 177 ms 🟢 −53%
large-esm 26.5 86 ms 69 ms 🔴 +24% 173 ms 🟢 −50%

Project-local vpx in package.json scripts against the tsx CLI

Scenario Node.js local vpx tsx CLI, warm cache vpx vs warm tsx CLI, no cache vpx vs no cache
hello 22.18 66 ms 103 ms 🟢 −35% 110 ms 🟢 −40%
hello 24.12 52 ms 83 ms 🟢 −37% 96 ms 🟢 −46%
hello 26.5 57 ms 72 ms 🟢 −22% 94 ms 🟢 −40%
esm-app 22.18 113 ms 165 ms 🟢 −31% 177 ms 🟢 −36%
esm-app 24.12 93 ms 134 ms 🟢 −30% 250 ms 🟢 −63%
esm-app 26.5 98 ms 134 ms 🟢 −27% 249 ms 🟢 −61%
cjs-app 22.18 112 ms 184 ms 🟢 −39% 327 ms 🟢 −66%
cjs-app 24.12 93 ms 155 ms 🟢 −40% 296 ms 🟢 −69%
cjs-app 26.5 99 ms 155 ms 🟢 −36% 291 ms 🟢 −66%
large-cjs 22.18 139 ms 155 ms 🟢 −11% 265 ms 🟢 −48%
large-cjs 24.12 118 ms 122 ms ⚪ −3% 305 ms 🟢 −61%
large-cjs 26.5 113 ms 111 ms ⚪ +2% 294 ms 🟢 −61%
large-esm 22.18 122 ms 139 ms 🟢 −12% 232 ms 🟢 −47%
large-esm 24.12 103 ms 108 ms 🟢 −5% 210 ms 🟢 −51%
large-esm 26.5 107 ms 104 ms ⚪ +3% 206 ms 🟢 −48%
  • 🟢 Against tsx with a warm cache, on hello, esm-app, and cjs-app, the global vpx takes 4–36% less time and the local vpx 22–40% less, on every Node.js version.
  • 🟢 Against tsx without its cache, vpx takes 33–71% less time in every scenario.
  • 🔴 tsx's disk cache wins only for the 1.8 MB files through the global vpx on 24.12 and 26.5, by 11–24% (9–17 ms), because vpx transforms them on every run. Against the tsx CLI, the local vpx is 5–12% faster or level. A transform cache stays a nice-to-have.
  • Against plain node type stripping, on the erasable hello file, the global vpx is 23% faster on 24.12 and 26.5 (34–37 against 44–48 ms) and 3 ms slower on 22.18 (51 against 48 ms), where the shim's 10 ms outweighs the loader's 7 ms lead.
  • Exec in place leaves script startup where spawning the script left it, within 2 ms in every scenario; what it saves is the second Node.js process.
  • Running an installed binary takes about 25 ms through the local vpx, 4 ms less than spawning it, against 9 ms through the global one.

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

✅ Staging deployment successful!

Preview: https://viteplus-staging.void.app/
Commit: 2d68bab

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

🚀 Deploying Preview to Cloudflare 🚀

Preview URL: https://feat-vpx-typescript-scripts-viteplus-dev.voidzero-docs.workers.dev (commit 2d68bab)

This URL reflects your latest Preview deployment

Preview Deployments by commit

Status Deployment URL Commit Updated (UTC) See this deployment's details
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://252fcc5e-viteplus-dev.voidzero-docs.workers.dev 2d68bab 2026-10-20T09:02:13.482Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://1f5d9d72-viteplus-dev.voidzero-docs.workers.dev 86183c8 2026-10-20T08:31:23.821Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://ca133e94-viteplus-dev.voidzero-docs.workers.dev b68a3ae 2026-10-20T04:53:21.415Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://b4a67d34-viteplus-dev.voidzero-docs.workers.dev 388d303 2026-10-20T04:42:36.175Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://b629ae3b-viteplus-dev.voidzero-docs.workers.dev e4cf2d8 2026-10-18T14:36:56.438Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://834b2e34-viteplus-dev.voidzero-docs.workers.dev aeaeeb0 2026-10-18T12:36:50.393Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://4f6a8b6b-viteplus-dev.voidzero-docs.workers.dev 85296a4 2026-10-18T11:40:41.438Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://a792cf79-viteplus-dev.voidzero-docs.workers.dev d345fe7 2026-10-18T07:46:24.848Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://d0b69e88-viteplus-dev.voidzero-docs.workers.dev 4581ed2 2026-10-18T07:21:49.252Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://3f23c56a-viteplus-dev.voidzero-docs.workers.dev 43dad7a 2026-10-18T05:55:02.412Z Visit the dashboard ↗

View all previews: View all previews ↗

@github-actions

github-actions Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

CLI artifact sizes (2d68bab)

Final release artifacts built by the canonical build-upstream and build-windows-cli actions.
The dist rows use the Linux build. The core total excludes .node files to match the release artifact.

Artifact Format Base PR Change
packages/cli/dist Directory total 2.11 MiB 2.15 MiB +39.95 KiB (+1.85%)
packages/core/dist Directory total 4.08 MiB 4.08 MiB 0 B (0.00%)
Combined package dist Directory total 6.19 MiB 6.23 MiB +39.95 KiB (+0.63%)
vp (Linux x64) Binary 7.21 MiB 7.22 MiB +12.00 KiB (+0.16%)
vp (Linux x64) gzip -9 3.34 MiB 3.35 MiB +7.75 KiB (+0.23%)
NAPI (Linux x64) Binary 34.79 MiB 35.13 MiB +341.50 KiB (+0.96%)
NAPI (Linux x64) gzip -9 13.86 MiB 14.00 MiB +143.34 KiB (+1.01%)
vp (macOS ARM64) Binary 4.77 MiB 4.77 MiB +48 B (+0.00%)
vp (macOS ARM64) gzip -9 2.86 MiB 2.87 MiB +7.07 KiB (+0.24%)
NAPI (macOS ARM64) Binary 41.71 MiB 42.00 MiB +291.23 KiB (+0.68%)
NAPI (macOS ARM64) gzip -9 18.02 MiB 18.15 MiB +138.11 KiB (+0.75%)
vp (Windows x64) Binary 5.26 MiB 5.27 MiB +14.50 KiB (+0.27%)
vp (Windows x64) gzip -9 2.46 MiB 2.47 MiB +7.02 KiB (+0.28%)
NAPI (Windows x64) Binary 30.85 MiB 31.19 MiB +345.50 KiB (+1.09%)
NAPI (Windows x64) gzip -9 12.56 MiB 12.71 MiB +157.03 KiB (+1.22%)
Trampoline (Windows x64) Binary 13.50 KiB 13.50 KiB 0 B (0.00%)
Trampoline (Windows x64) gzip -9 7.09 KiB 7.09 KiB 0 B (0.00%)
Installer (Windows x64) Binary 3.64 MiB 3.64 MiB 0 B (0.00%)
Installer (Windows x64) gzip -9 1.78 MiB 1.78 MiB 0 B (0.00%)

@fengmk2
fengmk2 force-pushed the feat/vpx-typescript-scripts branch 2 times, most recently from c616cba to 1869e0e Compare October 8, 2026 15:19
@fengmk2
fengmk2 force-pushed the feat/vpx-typescript-scripts branch from d749d41 to b6ba403 Compare October 10, 2026 11:45
@fengmk2
fengmk2 force-pushed the feat/vpx-typescript-scripts branch from b6ba403 to 07e3bc3 Compare October 10, 2026 13:46
@fengmk2
fengmk2 force-pushed the feat/vpx-typescript-scripts branch from 357c7b5 to dffad11 Compare October 10, 2026 14:37
@fengmk2 fengmk2 added the preview-build Publish this PR's commits to the registry bridge as preview builds label Oct 10, 2026
@fengmk2
fengmk2 force-pushed the feat/vpx-typescript-scripts branch 6 times, most recently from 7744fc2 to 5edae0d Compare October 14, 2026 16:54
fengmk2 added a commit that referenced this pull request Oct 14, 2026
> [!NOTE]
> This PR body was truncated due to platform limits.

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [ast-grep-config](https://redirect.github.com/ast-grep/ast-grep) |
workspace.dependencies | minor | `0.40.1` → `0.50.0` |
| [ast-grep-core](https://ast-grep.github.io/)
([source](https://redirect.github.com/ast-grep/ast-grep)) |
workspace.dependencies | minor | `0.40.1` → `0.50.0` |
| [ast-grep-language](https://redirect.github.com/ast-grep/ast-grep) |
workspace.dependencies | minor | `0.40.1` → `0.50.0` |
| [brush-parser](https://redirect.github.com/reubeno/brush) |
workspace.dependencies | minor | `0.3.0` → `0.4.0` |
| [criterion](https://criterion-rs.github.io/book/index.html)
([source](https://redirect.github.com/criterion-rs/criterion.rs)) |
workspace.dependencies | minor | `0.7` → `0.8` |
| [css-module-lexer](https://redirect.github.com/web-infra-dev/rspack) |
workspace.dependencies | minor | `0.0.15` → `0.102.0` |
| [httpmock](https://redirect.github.com/httpmock/httpmock) |
workspace.dependencies | minor | `0.7` → `0.8` |
| [indoc](https://redirect.github.com/dtolnay/indoc) |
workspace.dependencies | patch | `2.0.7` → `2.0.8` |
| [js-semver](https://redirect.github.com/ryuapp/js-semver) |
workspace.dependencies | patch | `1.0.0` → `1.0.1` |
| [nix](https://redirect.github.com/nix-rust/nix) |
workspace.dependencies | minor | `0.30.1` → `0.31.0` |
| [pgp](https://redirect.github.com/rpgp/rpgp) | workspace.dependencies
| minor | `0.19.0` → `0.21.0` |
| [sha1](https://redirect.github.com/RustCrypto/hashes) |
workspace.dependencies | minor | `0.10.6` → `0.11.0` |
| [sha2](https://redirect.github.com/RustCrypto/hashes) |
workspace.dependencies | minor | `0.10.9` → `0.11.0` |
| [string_cache](https://redirect.github.com/servo/string-cache) |
workspace.dependencies | minor | `0.9.0` → `0.11.0` |
| [tokio-util](https://tokio.rs)
([source](https://redirect.github.com/tokio-rs/tokio)) |
workspace.dependencies | patch | `0.7.19` → `0.7.20` |
| [toml](https://redirect.github.com/toml-rs/toml) |
workspace.dependencies | patch | `1.1.6+spec-1.1.0` → `1.1.8` |

---

> [!WARNING]
> Some dependencies could not be looked up. Check the warning logs for
more information.

---

### Compatibility Changes

The migration code uses the `brush-parser` `0.4.0` constructor and
rewrites commands inside `coproc` bodies.

The script formatter preserves spaces before redirects after `[[ ...
]]`. This prevents invalid Bash scripts when migration rewrites another
command.

Hash assertions use `hex::encode` because the new `sha1` and `sha2`
digest types do not support `{:x}`.

The musl installer jobs pin Node.js to `24.21.0` because new Node.js
releases can precede their musl builds. A cached release index keeps the
published installer on the same version.

---

### Release Notes

<details>
<summary>ast-grep/ast-grep (ast-grep-config)</summary>

###
[`v0.50.0`](https://redirect.github.com/ast-grep/ast-grep/blob/HEAD/CHANGELOG.md#0500)

[Compare
Source](https://redirect.github.com/ast-grep/ast-grep/compare/0.45.3...0.50.0)

- feat(outline): add Java annotation type and element rules
[`#2955`](https://redirect.github.com/ast-grep/ast-grep/pull/2955)
- fix(outline): report Java private/protected fields in the outline
[`#2950`](https://redirect.github.com/ast-grep/ast-grep/pull/2950)
- feat(outline): add Java enum member rule
[`#2954`](https://redirect.github.com/ast-grep/ast-grep/pull/2954)
- chore(deps): update dependency
[@&#8203;types/node](https://redirect.github.com/types/node) to v24.19.1
[`#2983`](https://redirect.github.com/ast-grep/ast-grep/pull/2983)
- chore(deps): update dependency dprint to v0.60.1
[`#2984`](https://redirect.github.com/ast-grep/ast-grep/pull/2984)
- feat(outline): add Java module declaration rule
[`#2956`](https://redirect.github.com/ast-grep/ast-grep/pull/2956)
- chore(deps): update rust crate termimad to v0.35.5
[`#2925`](https://redirect.github.com/ast-grep/ast-grep/pull/2925)
- chore(deps): update rust crate napi-derive to v3.6.10
[`#2936`](https://redirect.github.com/ast-grep/ast-grep/pull/2936)
- chore(deps): update dependency
[@&#8203;napi-rs/cli](https://redirect.github.com/napi-rs/cli) to
v3.10.6
[`#2922`](https://redirect.github.com/ast-grep/ast-grep/pull/2922)
- chore(deps): update dependency chalk to v6.0.1
[`#2979`](https://redirect.github.com/ast-grep/ast-grep/pull/2979)
- chore(deps): update rust crate tokio to v1.53.2
[`#2981`](https://redirect.github.com/ast-grep/ast-grep/pull/2981)
- chore(deps): update rust crate thiserror to v2.0.21
[`#2966`](https://redirect.github.com/ast-grep/ast-grep/pull/2966)
- chore(deps): update dependency oxlint to v1.86.0
[`#2967`](https://redirect.github.com/ast-grep/ast-grep/pull/2967)
- chore(deps): update rust crate smallvec to v1.16.2
[`#2968`](https://redirect.github.com/ast-grep/ast-grep/pull/2968)
- feat(outline): add Java wildcard-import outline rules
[`#2948`](https://redirect.github.com/ast-grep/ast-grep/pull/2948)
- fix(outline): capture C/C++ declarator identifier names
[`#2946`](https://redirect.github.com/ast-grep/ast-grep/pull/2946)
- feat(cli): add trust and revoke custom language policies
[`#2972`](https://redirect.github.com/ast-grep/ast-grep/pull/2972)
- refactor(cli): extract custom language policy
[`#2977`](https://redirect.github.com/ast-grep/ast-grep/pull/2977)
- feat(cli): add custom language loading policy
[`#2971`](https://redirect.github.com/ast-grep/ast-grep/pull/2971)
- fix(schema): reject null relation fields
[`#2969`](https://redirect.github.com/ast-grep/ast-grep/pull/2969)
- chore(deps): update rust crate clap_complete to v4.6.11
[`#2965`](https://redirect.github.com/ast-grep/ast-grep/pull/2965)
- chore(deps): update rust crate clap to v4.6.7
[`#2964`](https://redirect.github.com/ast-grep/ast-grep/pull/2964)
- chore(deps): update rust crate napi to v3.13.0
[`#2932`](https://redirect.github.com/ast-grep/ast-grep/pull/2932)
- chore(deps): update dependency
[@&#8203;types/node](https://redirect.github.com/types/node) to v24.13.6
[`#2941`](https://redirect.github.com/ast-grep/ast-grep/pull/2941)
- feat(language): add Zig support
[`#2942`](https://redirect.github.com/ast-grep/ast-grep/pull/2942)
- fix: require opt-in for custom language libraries
[`#2960`](https://redirect.github.com/ast-grep/ast-grep/pull/2960)
- refactor: parse default run through app
[`#2962`](https://redirect.github.com/ast-grep/ast-grep/pull/2962)
- feat(outline): add Java record_declaration rule
[`#2945`](https://redirect.github.com/ast-grep/ast-grep/pull/2945)
- chore(deps): update rust crate toml_edit to v0.25.15
[`#2937`](https://redirect.github.com/ast-grep/ast-grep/pull/2937)
- chore(deps): update rust crate smallvec to v1.16.1
[`#2920`](https://redirect.github.com/ast-grep/ast-grep/pull/2920)
- chore(deps): update dependency
[@&#8203;types/node](https://redirect.github.com/types/node) to v24.13.4
[`#2931`](https://redirect.github.com/ast-grep/ast-grep/pull/2931)
- chore(deps): update dependency dprint to v0.57.4
[`#2926`](https://redirect.github.com/ast-grep/ast-grep/pull/2926)
- chore(deps): update dependency oxlint to v1.82.0
[`#2928`](https://redirect.github.com/ast-grep/ast-grep/pull/2928)
- chore(deps): update dependency oxlint to v1.81.0
[`#2919`](https://redirect.github.com/ast-grep/ast-grep/pull/2919)
- chore(deps): update rust crate termimad to v0.35.3
[`#2921`](https://redirect.github.com/ast-grep/ast-grep/pull/2921)
- chore(deps): update dependency dprint to v0.57.1
[`#2923`](https://redirect.github.com/ast-grep/ast-grep/pull/2923)
- chore(deps): update dependency
[@&#8203;ast-grep/napi](https://redirect.github.com/ast-grep/napi) to
v0.45.3
[`#2918`](https://redirect.github.com/ast-grep/ast-grep/pull/2918)
- feat(outline): add Java record_declaration rule
([#&#8203;2945](https://redirect.github.com/ast-grep/ast-grep/issues/2945))
[`#2944`](https://redirect.github.com/ast-grep/ast-grep/issues/2944)

###
[`v0.45.3`](https://redirect.github.com/ast-grep/ast-grep/blob/HEAD/CHANGELOG.md#0453)

[Compare
Source](https://redirect.github.com/ast-grep/ast-grep/compare/0.45.2...0.45.3)

> 30 August 2026

- chore(deps): update dependency dprint to v0.57.0
[`#2916`](https://redirect.github.com/ast-grep/ast-grep/pull/2916)
- feat: add min-severity cli
[`#2917`](https://redirect.github.com/ast-grep/ast-grep/pull/2917)
- fix(outline): anchor fallback signatures to names
[`#2913`](https://redirect.github.com/ast-grep/ast-grep/pull/2913)
- feat(outline): add Markdown heading support
[`#2912`](https://redirect.github.com/ast-grep/ast-grep/pull/2912)
- chore(deps): update dependency oxlint to v1.80.0
[`#2908`](https://redirect.github.com/ast-grep/ast-grep/pull/2908)
- chore(deps): update dependency
[@&#8203;ast-grep/napi](https://redirect.github.com/ast-grep/napi) to
v0.45.2
[`#2906`](https://redirect.github.com/ast-grep/ast-grep/pull/2906)
- feat: add min-severity cli
([#&#8203;2917](https://redirect.github.com/ast-grep/ast-grep/issues/2917))
[`#2720`](https://redirect.github.com/ast-grep/ast-grep/issues/2720)
- fix: ast-grep-ignore must be at first be the frist alphabet to take
effect
[`#2909`](https://redirect.github.com/ast-grep/ast-grep/issues/2909)
- chore: update tree-sitter 0.27
[`bb74529`](https://redirect.github.com/ast-grep/ast-grep/commit/bb745292b5e683822c27612858b5b0edb54e273e)
- fix: fix clippy
[`c6b32d7`](https://redirect.github.com/ast-grep/ast-grep/commit/c6b32d74ad12cea690cb331c88f004764df6e985)

###
[`v0.45.2`](https://redirect.github.com/ast-grep/ast-grep/blob/HEAD/CHANGELOG.md#0452)

[Compare
Source](https://redirect.github.com/ast-grep/ast-grep/compare/0.45.1...0.45.2)

> 23 August 2026

- chore(deps): update astral-sh/setup-uv action to v10
[`#2892`](https://redirect.github.com/ast-grep/ast-grep/pull/2892)
- chore(deps): update rust crate terminal-light to v1.9.1
[`#2905`](https://redirect.github.com/ast-grep/ast-grep/pull/2905)
- chore(deps): update dependency web-tree-sitter to v0.26.13
[`#2903`](https://redirect.github.com/ast-grep/ast-grep/pull/2903)
- chore(deps): update rust crate tree-sitter to v0.26.13
[`#2904`](https://redirect.github.com/ast-grep/ast-grep/pull/2904)
- chore(deps): update dependency dprint to v0.56.1
[`#2901`](https://redirect.github.com/ast-grep/ast-grep/pull/2901)
- chore(deps): update dependency
[@&#8203;napi-rs/cli](https://redirect.github.com/napi-rs/cli) to v3.8.6
[`#2882`](https://redirect.github.com/ast-grep/ast-grep/pull/2882)
- fix(deps): update rust-wasm-bindgen monorepo
[`#2878`](https://redirect.github.com/ast-grep/ast-grep/pull/2878)
- chore(deps): update dependency dprint to v0.56.0
[`#2896`](https://redirect.github.com/ast-grep/ast-grep/pull/2896)
- chore(deps): update dependency oxlint to v1.79.0
[`#2897`](https://redirect.github.com/ast-grep/ast-grep/pull/2897)
- chore(deps): update dependency
[@&#8203;ast-grep/napi](https://redirect.github.com/ast-grep/napi) to
v0.45.1
[`#2876`](https://redirect.github.com/ast-grep/ast-grep/pull/2876)
- chore(deps): update dependency web-tree-sitter to v0.26.12
[`#2880`](https://redirect.github.com/ast-grep/ast-grep/pull/2880)
- fix: exit quietly on broken pipe instead of erroring
[`#2887`](https://redirect.github.com/ast-grep/ast-grep/pull/2887)
- feat(outline): extract embedded language symbols
[`#2883`](https://redirect.github.com/ast-grep/ast-grep/pull/2883)
- chore(deps): update dependency oxlint to v1.78.0
[`#2888`](https://redirect.github.com/ast-grep/ast-grep/pull/2888)
- feat: add namedChildren support to wasm
[`#2893`](https://redirect.github.com/ast-grep/ast-grep/issues/2893)
- feat: add namedChildren to napi
[`#2893`](https://redirect.github.com/ast-grep/ast-grep/issues/2893)
- feat: add named_children to pyo3
[`4dc0d36`](https://redirect.github.com/ast-grep/ast-grep/commit/4dc0d3605ac027e45f5feb811966fe7b8220d246)
- fix: bump down napi
[`61f1b98`](https://redirect.github.com/ast-grep/ast-grep/commit/61f1b98cc2379b9a6d37173257612b5aac3473da)
- chore: bump deps
[`912da32`](https://redirect.github.com/ast-grep/ast-grep/commit/912da3272afd258ec464ee8c2e52d19059a620e4)

###
[`v0.45.1`](https://redirect.github.com/ast-grep/ast-grep/blob/HEAD/CHANGELOG.md#0451)

[Compare
Source](https://redirect.github.com/ast-grep/ast-grep/compare/0.45.0...0.45.1)

> 7 August 2026

- fix: match root metavariables against comments
[`#2868`](https://redirect.github.com/ast-grep/ast-grep/pull/2868)
- feat(outline): add C# multiline member signatures
[`#2861`](https://redirect.github.com/ast-grep/ast-grep/pull/2861)
- chore(deps): update rust crate ignore to v0.4.32
[`#2864`](https://redirect.github.com/ast-grep/ast-grep/pull/2864)
- chore(deps): update dependency oxlint to v1.77.0
[`#2865`](https://redirect.github.com/ast-grep/ast-grep/pull/2865)
- chore(deps): update dependency typescript to v7
[`#2833`](https://redirect.github.com/ast-grep/ast-grep/pull/2833)
- chore(deps): update astral-sh/setup-uv action to v9
[`#2839`](https://redirect.github.com/ast-grep/ast-grep/pull/2839)
- chore(deps): update dependency smol-toml to v1.7.1
[`#2848`](https://redirect.github.com/ast-grep/ast-grep/pull/2848)
- chore(deps): update dependency
[@&#8203;napi-rs/cli](https://redirect.github.com/napi-rs/cli) to v3.8.2
[`#2854`](https://redirect.github.com/ast-grep/ast-grep/pull/2854)
- chore(deps): update dependency chalk to v6
[`#2849`](https://redirect.github.com/ast-grep/ast-grep/pull/2849)
- chore(deps): update rust crate clap to v4.6.5
[`#2860`](https://redirect.github.com/ast-grep/ast-grep/pull/2860)
- chore(deps): update rust crate clap_complete to v4.6.8
[`#2850`](https://redirect.github.com/ast-grep/ast-grep/pull/2850)
- chore(deps): update rust crate schemars to v1.2.2
[`#2851`](https://redirect.github.com/ast-grep/ast-grep/pull/2851)
- chore(deps): update dependency oxlint to v1.76.0
[`#2852`](https://redirect.github.com/ast-grep/ast-grep/pull/2852)
- chore(deps): update rust crate napi to v3.12.0
[`#2855`](https://redirect.github.com/ast-grep/ast-grep/pull/2855)
- chore(deps): update rust crate napi-derive to v3.6.2
[`#2853`](https://redirect.github.com/ast-grep/ast-grep/pull/2853)
- Use `std::io::IsTerminal` over `atty`
[`#2857`](https://redirect.github.com/ast-grep/ast-grep/pull/2857)
- chore(deps): update dependency
[@&#8203;ast-grep/napi](https://redirect.github.com/ast-grep/napi) to
v0.45.0
[`#2844`](https://redirect.github.com/ast-grep/ast-grep/pull/2844)
- chore: bump deps
[`2ac18ca`](https://redirect.github.com/ast-grep/ast-grep/commit/2ac18ca571a5d6a50dd549d7bf9b0cb704f0dd87)

###
[`v0.45.0`](https://redirect.github.com/ast-grep/ast-grep/blob/HEAD/CHANGELOG.md#0450)

[Compare
Source](https://redirect.github.com/ast-grep/ast-grep/compare/0.44.1...0.45.0)

> 23 July 2026

- feat: deprecate the sg command
[`#2843`](https://redirect.github.com/ast-grep/ast-grep/pull/2843)
- fix: avoid Defender false positive for Windows sg
[`#2842`](https://redirect.github.com/ast-grep/ast-grep/pull/2842)
- chore(deps): update dependency
[@&#8203;napi-rs/cli](https://redirect.github.com/napi-rs/cli) to v3.7.4
[`#2834`](https://redirect.github.com/ast-grep/ast-grep/pull/2834)
- chore(deps): update dependency oxlint to v1.75.0
[`#2838`](https://redirect.github.com/ast-grep/ast-grep/pull/2838)
- chore(deps): update actions/setup-node action to v7
[`#2810`](https://redirect.github.com/ast-grep/ast-grep/pull/2810)
- chore(deps): update actions/setup-python action to v7
[`#2829`](https://redirect.github.com/ast-grep/ast-grep/pull/2829)
- fix: specify correct MSRV in Cargo.toml
[`#2837`](https://redirect.github.com/ast-grep/ast-grep/pull/2837)
- Revert "chore(deps): update dependency typescript to v7
([#&#8203;2795](https://redirect.github.com/ast-grep/ast-grep/issues/2795))"
[`#2831`](https://redirect.github.com/ast-grep/ast-grep/pull/2831)
- chore(deps): update astral-sh/setup-uv action to v8.3.2
[`#2790`](https://redirect.github.com/ast-grep/ast-grep/pull/2790)
- chore(deps): update dependency typescript to v7
[`#2795`](https://redirect.github.com/ast-grep/ast-grep/pull/2795)
- chore(deps): update rust crate thiserror to v2.0.19
[`#2819`](https://redirect.github.com/ast-grep/ast-grep/pull/2819)
- chore(deps): update dependency
[@&#8203;napi-rs/cli](https://redirect.github.com/napi-rs/cli) to v3.7.3
[`#2801`](https://redirect.github.com/ast-grep/ast-grep/pull/2801)
- chore(deps): update dependency web-tree-sitter to v0.26.11
[`#2802`](https://redirect.github.com/ast-grep/ast-grep/pull/2802)
- chore(deps): update rust crate target-triple to v1.0.1
[`#2817`](https://redirect.github.com/ast-grep/ast-grep/pull/2817)
- chore(deps): update dependency oxlint to v1.74.0
[`#2809`](https://redirect.github.com/ast-grep/ast-grep/pull/2809)
- chore(deps): update dependency dprint to v0.55.2
[`#2808`](https://redirect.github.com/ast-grep/ast-grep/pull/2808)
- chore(deps): update dependency
[@&#8203;ast-grep/napi](https://redirect.github.com/ast-grep/napi) to
v0.44.1
[`#2789`](https://redirect.github.com/ast-grep/ast-grep/pull/2789)
- chore(deps): update dependency oxlint to v1.73.0
[`#2793`](https://redirect.github.com/ast-grep/ast-grep/pull/2793)
- chore(deps): update dependency
[@&#8203;types/node](https://redirect.github.com/types/node) to v24.13.3
[`#2794`](https://redirect.github.com/ast-grep/ast-grep/pull/2794)
- chore(deps): update rust crate bit-set to 0.11.0
[`#2791`](https://redirect.github.com/ast-grep/ast-grep/pull/2791)
- fix: use is_extra instead of comment heuristic
[`#2821`](https://redirect.github.com/ast-grep/ast-grep/issues/2821)
- fix: stop using ignore files outside rule_dirs
[`#2803`](https://redirect.github.com/ast-grep/ast-grep/issues/2803)
- chore: update dependencies
[`b24ca85`](https://redirect.github.com/ast-grep/ast-grep/commit/b24ca85a7aa5aa3e0925da575e8800209f918421)
- feat(outline): support ambient TypeScript modules
[`4f75c21`](https://redirect.github.com/ast-grep/ast-grep/commit/4f75c214094e46d0d3f026674027036459840d61)
- chore: bump versions
[`82eb291`](https://redirect.github.com/ast-grep/ast-grep/commit/82eb2916782ae5ed572813272f5845214b5aa321)

###
[`v0.44.1`](https://redirect.github.com/ast-grep/ast-grep/blob/HEAD/CHANGELOG.md#0441)

[Compare
Source](https://redirect.github.com/ast-grep/ast-grep/compare/0.44.0...0.44.1)

> 4 July 2026

- chore(deps): update rust crate napi to v3.10.3
[`#2786`](https://redirect.github.com/ast-grep/ast-grep/pull/2786)
- chore(deps): update rust crate napi-derive to v3.5.9
[`#2785`](https://redirect.github.com/ast-grep/ast-grep/pull/2785)
- chore(deps): update dependency oxlint to v1.72.0
[`#2780`](https://redirect.github.com/ast-grep/ast-grep/pull/2780)
- chore(deps): update rust crate terminal-light to v1.9.0
[`#2781`](https://redirect.github.com/ast-grep/ast-grep/pull/2781)
- chore(deps): update rust crate clap_complete to v4.6.7
[`#2783`](https://redirect.github.com/ast-grep/ast-grep/pull/2783)
- chore(deps): update rust crate ignore to v0.4.27
[`#2784`](https://redirect.github.com/ast-grep/ast-grep/pull/2784)
- fix(cli): bound outline file queue
[`#2787`](https://redirect.github.com/ast-grep/ast-grep/pull/2787)
- chore(deps): update rust crate clap_complete to v4.6.6
[`#2782`](https://redirect.github.com/ast-grep/ast-grep/pull/2782)
- chore(deps): update dependency
[@&#8203;ast-grep/napi](https://redirect.github.com/ast-grep/napi) to
v0.44.0
[`#2764`](https://redirect.github.com/ast-grep/ast-grep/pull/2764)
- chore(deps): update rust crate tree-sitter to v0.26.10
[`#2779`](https://redirect.github.com/ast-grep/ast-grep/pull/2779)
- chore(deps): update dependency web-tree-sitter to v0.26.10
[`#2778`](https://redirect.github.com/ast-grep/ast-grep/pull/2778)
- chore(deps): update dependency dprint to v0.55.1
[`#2776`](https://redirect.github.com/ast-grep/ast-grep/pull/2776)
- chore(deps): update dependency
[@&#8203;napi-rs/cli](https://redirect.github.com/napi-rs/cli) to v3.7.2
[`#2667`](https://redirect.github.com/ast-grep/ast-grep/pull/2667)
- chore(deps): update rust crate napi to v3.9.4
[`#2696`](https://redirect.github.com/ast-grep/ast-grep/pull/2696)
- chore(deps): update rust crate napi-derive to v3.5.7
[`#2768`](https://redirect.github.com/ast-grep/ast-grep/pull/2768)
- chore(deps): update rust crate anyhow to v1.0.103
[`#2774`](https://redirect.github.com/ast-grep/ast-grep/pull/2774)
- feat: load custom language outline rules from config
[`#2777`](https://redirect.github.com/ast-grep/ast-grep/pull/2777)
- fix(deps): update rust-wasm-bindgen monorepo
[`#2775`](https://redirect.github.com/ast-grep/ast-grep/pull/2775)
- chore(deps): update actions/cache action to v6
[`#2767`](https://redirect.github.com/ast-grep/ast-grep/pull/2767)
- feat: Support \*.bazel files in python
[`#2771`](https://redirect.github.com/ast-grep/ast-grep/pull/2771)
- chore(deps): update oxlint monorepo
[`#2765`](https://redirect.github.com/ast-grep/ast-grep/pull/2765)
- feat: add outline rules for more builtin languages
[`07778fb`](https://redirect.github.com/ast-grep/ast-grep/commit/07778fb326765363557811d5b24e901399bfbdec)
- fix: update pyo3 deps
[`1713e86`](https://redirect.github.com/ast-grep/ast-grep/commit/1713e86fd5960accbe59532eafaf307c6330b303)

###
[`v0.44.0`](https://redirect.github.com/ast-grep/ast-grep/blob/HEAD/CHANGELOG.md#0440)

[Compare
Source](https://redirect.github.com/ast-grep/ast-grep/compare/0.43.0...0.44.0)

> 21 June 2026

- chore: move outline docs and benchmarks out of repo
[`#2763`](https://redirect.github.com/ast-grep/ast-grep/pull/2763)
- chore(deps): update dependency smol-toml to v1.7.0
[`#2762`](https://redirect.github.com/ast-grep/ast-grep/pull/2762)
- Add JavaScript outline rules and stream JSON files
[`#2761`](https://redirect.github.com/ast-grep/ast-grep/pull/2761)
- fix: reject root multi-metavariable patterns
[`#2727`](https://redirect.github.com/ast-grep/ast-grep/pull/2727)
- fix: don't leak metavar bindings across siblings in nthChild ofRule
[`#2677`](https://redirect.github.com/ast-grep/ast-grep/pull/2677)
- fix: extract python from-import modules in outline
[`#2758`](https://redirect.github.com/ast-grep/ast-grep/pull/2758)
- fix: match go outline types by declaration
[`#2759`](https://redirect.github.com/ast-grep/ast-grep/pull/2759)
- fix: skip empty files in outline
[`#2757`](https://redirect.github.com/ast-grep/ast-grep/pull/2757)
- feat: mark duplicate outline names
[`#2756`](https://redirect.github.com/ast-grep/ast-grep/pull/2756)
- refactor: inline outline member kind lookup
[`#2755`](https://redirect.github.com/ast-grep/ast-grep/pull/2755)
- refactor: make outline extract return iterator
[`#2754`](https://redirect.github.com/ast-grep/ast-grep/pull/2754)
- refactor: stream outline extraction items
[`#2753`](https://redirect.github.com/ast-grep/ast-grep/pull/2753)
- perf: use single traversal for outline extraction
[`#2751`](https://redirect.github.com/ast-grep/ast-grep/pull/2751)
- perf: cache transform replace regexes
[`#2750`](https://redirect.github.com/ast-grep/ast-grep/pull/2750)
- fix: don't leak metavar bindings from a negated `not` rule
[`#2676`](https://redirect.github.com/ast-grep/ast-grep/pull/2676)
- refactor: fold outline extract options into extractors
[`#2749`](https://redirect.github.com/ast-grep/ast-grep/pull/2749)
- refactor: split outline extract options and style
[`#2748`](https://redirect.github.com/ast-grep/ast-grep/pull/2748)
- refactor: map outline cli to core options
[`#2747`](https://redirect.github.com/ast-grep/ast-grep/pull/2747)
- feat: apply outline extractor options
[`#2746`](https://redirect.github.com/ast-grep/ast-grep/pull/2746)
- feat: add outline extractor options
[`#2745`](https://redirect.github.com/ast-grep/ast-grep/pull/2745)
- fix: simplify some code
[`#2744`](https://redirect.github.com/ast-grep/ast-grep/pull/2744)
- fix: trailing ast-grep-ignore on a multi-line statement suppresses it
[`#2678`](https://redirect.github.com/ast-grep/ast-grep/pull/2678)
- chore(deps): update actions/checkout action to v7
[`#2731`](https://redirect.github.com/ast-grep/ast-grep/pull/2731)
- fix: cover async rust outline rules
[`#2743`](https://redirect.github.com/ast-grep/ast-grep/pull/2743)
- feat: add bundled outline rules for more languages
[`#2739`](https://redirect.github.com/ast-grep/ast-grep/pull/2739)
- feat: add outline CLI command
[`#2738`](https://redirect.github.com/ast-grep/ast-grep/pull/2738)
- perf: use cursor-backed outline traversal
[`#2737`](https://redirect.github.com/ast-grep/ast-grep/pull/2737)
- feat: run outline extractors
[`#2729`](https://redirect.github.com/ast-grep/ast-grep/pull/2729)
- chore(deps): update oxlint monorepo to v1.70.0
[`#2726`](https://redirect.github.com/ast-grep/ast-grep/pull/2726)
- refactor: split fixer variable validation
[`#2724`](https://redirect.github.com/ast-grep/ast-grep/pull/2724)
- refactor: validate rule core directly
[`#2723`](https://redirect.github.com/ast-grep/ast-grep/pull/2723)
- test: move matcher tests to rule core
[`#2722`](https://redirect.github.com/ast-grep/ast-grep/pull/2722)
- refactor: wrap rewriter config errors
[`#2721`](https://redirect.github.com/ast-grep/ast-grep/pull/2721)
- test: validate global rule fix vars via rule config
[`#2719`](https://redirect.github.com/ast-grep/ast-grep/pull/2719)
- fix: check undefined meta var in fix
[`#2718`](https://redirect.github.com/ast-grep/ast-grep/pull/2718)
- **Breaking change:** fix: remove fix from SerializableCore
[`#2717`](https://redirect.github.com/ast-grep/ast-grep/pull/2717)
- fix: preserve unused suppression fixer
[`#2716`](https://redirect.github.com/ast-grep/ast-grep/pull/2716)
- **Breaking change:** refactor: move optional fixer to RuleConfig
[`#2715`](https://redirect.github.com/ast-grep/ast-grep/pull/2715)
- fix: add fixer var check
[`#2714`](https://redirect.github.com/ast-grep/ast-grep/pull/2714)
- Refactor rule config
[`#2713`](https://redirect.github.com/ast-grep/ast-grep/pull/2713)
- **Breaking change:** refactor: mvoe rewriters into
SerializableRuleCore
[`#2711`](https://redirect.github.com/ast-grep/ast-grep/pull/2711)
- refactor: move rewriter out
[`#2712`](https://redirect.github.com/ast-grep/ast-grep/pull/2712)
- feat: add outline rule schema
[`#2710`](https://redirect.github.com/ast-grep/ast-grep/pull/2710)
- docs: remove outline target alias fields
[`#2709`](https://redirect.github.com/ast-grep/ast-grep/pull/2709)
- chore(deps): update rust crate smallvec to v1.15.2
[`#2701`](https://redirect.github.com/ast-grep/ast-grep/pull/2701)
- fix(deps): update rust-wasm-bindgen monorepo
[`#2704`](https://redirect.github.com/ast-grep/ast-grep/pull/2704)
- fix: remove unused trait/methods
[`#2708`](https://redirect.github.com/ast-grep/ast-grep/pull/2708)
- feat: add outline entry model
[`#2703`](https://redirect.github.com/ast-grep/ast-grep/pull/2703)
- refactor: remove legacy outline placeholders
[`#2702`](https://redirect.github.com/ast-grep/ast-grep/pull/2702)
- feat: add outline CLI shell
[`#2700`](https://redirect.github.com/ast-grep/ast-grep/pull/2700)
- fix(deps): update rust-wasm-bindgen monorepo
[`#2693`](https://redirect.github.com/ast-grep/ast-grep/pull/2693)
- chore(deps): update oxlint monorepo to v1.69.0
[`#2692`](https://redirect.github.com/ast-grep/ast-grep/pull/2692)
- chore(deps): update rust crate regex to v1.12.4
[`#2694`](https://redirect.github.com/ast-grep/ast-grep/pull/2694)
- chore(deps): update dependency
[@&#8203;types/node](https://redirect.github.com/types/node) to v24.13.2
[`#2698`](https://redirect.github.com/ast-grep/ast-grep/pull/2698)
- doc: design outline command
[`#2699`](https://redirect.github.com/ast-grep/ast-grep/pull/2699)
- Outline first builtin rule
[`#2695`](https://redirect.github.com/ast-grep/ast-grep/pull/2695)
- chore(deps): update rust crate tree-sitter-swift to v0.7.3
[`#2672`](https://redirect.github.com/ast-grep/ast-grep/pull/2672)
- chore(deps): update astral-sh/setup-uv action to v8.2.0
[`#2680`](https://redirect.github.com/ast-grep/ast-grep/pull/2680)
- feat: add outline rule definition
[`#2691`](https://redirect.github.com/ast-grep/ast-grep/pull/2691)
- feat: add outline item model
[`#2690`](https://redirect.github.com/ast-grep/ast-grep/pull/2690)
- chore(deps): update codecov/codecov-action action to v7
[`#2686`](https://redirect.github.com/ast-grep/ast-grep/pull/2686)
- feat: add outline command stub
[`#2689`](https://redirect.github.com/ast-grep/ast-grep/pull/2689)
- chore(deps): update dependency
[@&#8203;types/node](https://redirect.github.com/types/node) to v24.13.1
[`#2682`](https://redirect.github.com/ast-grep/ast-grep/pull/2682)
- chore(deps): update rust crate ignore to v0.4.26
[`#2683`](https://redirect.github.com/ast-grep/ast-grep/pull/2683)
- fix: remove all impl, start from scratch
[`#2688`](https://redirect.github.com/ast-grep/ast-grep/pull/2688)
- fix: remove all impl, start from scratch
[`#2687`](https://redirect.github.com/ast-grep/ast-grep/pull/2687)
- fix: report unfixable scan hits with update-all
[`#2684`](https://redirect.github.com/ast-grep/ast-grep/pull/2684)
- Fix typos in comments and grammar in --help text
[`#2674`](https://redirect.github.com/ast-grep/ast-grep/pull/2674)
- chore(deps): update dependency oxlint to v1.68.0
[`#2673`](https://redirect.github.com/ast-grep/ast-grep/pull/2673)
- fix: don't leak metavar bindings from ellipsis-end lookahead
[`#2670`](https://redirect.github.com/ast-grep/ast-grep/pull/2670)
- refactor: collapse nested ifs with let chains
[`#2671`](https://redirect.github.com/ast-grep/ast-grep/pull/2671)
- chore(deps): update rust crate toml_edit to v0.25.12
[`#2666`](https://redirect.github.com/ast-grep/ast-grep/pull/2666)
- chore(deps): update dependency oxlint to v1.67.0
[`#2665`](https://redirect.github.com/ast-grep/ast-grep/pull/2665)
- chore(deps): update dependency
[@&#8203;ast-grep/napi](https://redirect.github.com/ast-grep/napi) to
v0.43.0
[`#2664`](https://redirect.github.com/ast-grep/ast-grep/pull/2664)
- add benchmark
[`b488bd3`](https://redirect.github.com/ast-grep/ast-grep/commit/b488bd3ea1fbd62e354831ab3b6bf71439e6e004)
- vibe
[`6f89a3d`](https://redirect.github.com/ast-grep/ast-grep/commit/6f89a3d8b9260666908b68007dff487b599d1a95)
- fix: update outline rule loading
[`202d8b8`](https://redirect.github.com/ast-grep/ast-grep/commit/202d8b89ddadaa6e1d30eefcc0136b83d98b5222)

###
[`v0.43.0`](https://redirect.github.com/ast-grep/ast-grep/blob/HEAD/CHANGELOG.md#0430)

[Compare
Source](https://redirect.github.com/ast-grep/ast-grep/compare/0.42.3...0.43.0)

> 25 May 2026

- chore(deps): update dependency
[@&#8203;types/node](https://redirect.github.com/types/node) to v24.12.4
[`#2636`](https://redirect.github.com/ast-grep/ast-grep/pull/2636)
- chore(deps): update rust crate assert_cmd to v2.2.2
[`#2632`](https://redirect.github.com/ast-grep/ast-grep/pull/2632)
- chore(deps): update rust crate similar to v3.1.1
[`#2662`](https://redirect.github.com/ast-grep/ast-grep/pull/2662)
- fix(lsp): initialize tracing subscriber to surface tower-lsp errors
[`#2639`](https://redirect.github.com/ast-grep/ast-grep/pull/2639)
- fix(deps): update rust-wasm-bindgen monorepo
[`#2660`](https://redirect.github.com/ast-grep/ast-grep/pull/2660)
- chore(deps): update rust crate tree-sitter to v0.26.9
[`#2656`](https://redirect.github.com/ast-grep/ast-grep/pull/2656)
- chore(deps): update rust crate serde_json to v1.0.150
[`#2659`](https://redirect.github.com/ast-grep/ast-grep/pull/2659)
- chore(deps): update rust crate clap_complete to v4.6.5
[`#2634`](https://redirect.github.com/ast-grep/ast-grep/pull/2634)
- chore(deps): update dependency
[@&#8203;ast-grep/napi](https://redirect.github.com/ast-grep/napi) to
v0.42.3
[`#2653`](https://redirect.github.com/ast-grep/ast-grep/pull/2653)
- chore(deps): update dependency oxlint to v1.66.0
[`#2651`](https://redirect.github.com/ast-grep/ast-grep/pull/2651)
- chore(deps): update dependency web-tree-sitter to v0.26.9
[`#2654`](https://redirect.github.com/ast-grep/ast-grep/pull/2654)
- fix: strip trailing comment artifact in comment suppression
[`#2644`](https://redirect.github.com/ast-grep/ast-grep/issues/2644)
- feat: support ESQuery style selector in run command
[`#2663`](https://redirect.github.com/ast-grep/ast-grep/issues/2663)
- feat: add --follow arg for sg test
[`#2657`](https://redirect.github.com/ast-grep/ast-grep/issues/2657)
- test: add test for run --kind
[`d0d0b30`](https://redirect.github.com/ast-grep/ast-grep/commit/d0d0b3003e19593c16dd91c9e26d77567971e477)
- feat: add markdown support
[`beacc9e`](https://redirect.github.com/ast-grep/ast-grep/commit/beacc9e40c81e33bb3f94298e4a5b6cb046c0d56)
- fix: use Rule instead of pattern in run
[`2759fda`](https://redirect.github.com/ast-grep/ast-grep/commit/2759fdaeb9e15264276b8671a565d591d93e8e36)

###
[`v0.42.3`](https://redirect.github.com/ast-grep/ast-grep/blob/HEAD/CHANGELOG.md#0423)

[Compare
Source](https://redirect.github.com/ast-grep/ast-grep/compare/0.42.2...0.42.3)

> 19 May 2026

- feat: support nth-last-child esquery
[`#2631`](https://redirect.github.com/ast-grep/ast-grep/pull/2631)
- chore(deps): update rust crate dashmap to v6.2.1
[`#2645`](https://redirect.github.com/ast-grep/ast-grep/pull/2645)
- chore(deps): update dependency oxlint to v1.65.0
[`#2635`](https://redirect.github.com/ast-grep/ast-grep/pull/2635)
- chore(deps): update rust crate napi-derive to v3.5.6
[`#2642`](https://redirect.github.com/ast-grep/ast-grep/pull/2642)
- chore(deps): update rust crate napi-build to v2.3.2
[`#2641`](https://redirect.github.com/ast-grep/ast-grep/pull/2641)
- chore(deps): update rust crate napi to v3.9.0
[`#2643`](https://redirect.github.com/ast-grep/ast-grep/pull/2643)
- chore(deps): update dependency
[@&#8203;ast-grep/napi](https://redirect.github.com/ast-grep/napi) to
v0.42.2
[`#2630`](https://redirect.github.com/ast-grep/ast-grep/pull/2630)
- fix: fix windows installation
[`4021ae0`](https://redirect.github.com/ast-grep/ast-grep/commit/4021ae076f15ae6833d6e69f6429555071b4eac8)

###
[`v0.42.2`](https://redirect.github.com/ast-grep/ast-grep/blob/HEAD/CHANGELOG.md#0422)

[Compare
Source](https://redirect.github.com/ast-grep/ast-grep/compare/0.42.1...0.42.2)

> 10 May 2026

- chore(deps): update rust crate tokio to v1.52.3
[`#2620`](https://redirect.github.com/ast-grep/ast-grep/pull/2620)
- fix(deps): update rust-wasm-bindgen monorepo
[`#2623`](https://redirect.github.com/ast-grep/ast-grep/pull/2623)
- chore(deps): update rust crate clap_complete to v4.6.4
[`#2627`](https://redirect.github.com/ast-grep/ast-grep/pull/2627)
- chore(deps): update dependency
[@&#8203;types/node](https://redirect.github.com/types/node) to v24.12.3
[`#2624`](https://redirect.github.com/ast-grep/ast-grep/pull/2624)
- chore(deps): update rust crate tree-sitter-swift to v0.7.2
[`#2619`](https://redirect.github.com/ast-grep/ast-grep/pull/2619)
- chore(deps): update dependency oxlint to v1.63.0
[`#2621`](https://redirect.github.com/ast-grep/ast-grep/pull/2621)
- fix: replace postinstall script with binary resolution in ast-grep
[`#2595`](https://redirect.github.com/ast-grep/ast-grep/pull/2595)
- fix(lsp): use cwd instead of config dir as workspace fallback
[`#2600`](https://redirect.github.com/ast-grep/ast-grep/pull/2600)
- fix(deps): update rust-wasm-bindgen monorepo
[`#2613`](https://redirect.github.com/ast-grep/ast-grep/pull/2613)
- chore(deps): update rust crate napi-derive to v3.5.5
[`#2615`](https://redirect.github.com/ast-grep/ast-grep/pull/2615)
- chore(deps): update rust crate napi to v3.8.6
[`#2614`](https://redirect.github.com/ast-grep/ast-grep/pull/2614)
- chore(deps): update rust crate clap_complete to v4.6.3
[`#2610`](https://redirect.github.com/ast-grep/ast-grep/pull/2610)
- chore(deps): update dependency oxlint to v1.62.0
[`#2611`](https://redirect.github.com/ast-grep/ast-grep/pull/2611)
- chore(deps): update astral-sh/setup-uv action to v8
[`#2604`](https://redirect.github.com/ast-grep/ast-grep/pull/2604)
- chore(deps): update rust crate tree-sitter-c to v0.24.2
[`#2608`](https://redirect.github.com/ast-grep/ast-grep/pull/2608)
- fix(deps): update rust crate tree-sitter-dart to 0.2.0
[`#2609`](https://redirect.github.com/ast-grep/ast-grep/pull/2609)
- chore(deps): update robinraju/release-downloader action to v1.13
[`#2606`](https://redirect.github.com/ast-grep/ast-grep/pull/2606)
- fix(lsp): report unused suppressions without rules
[`#2607`](https://redirect.github.com/ast-grep/ast-grep/pull/2607)
- chore(deps): update rust crate clap_complete to v4.6.2
[`#2589`](https://redirect.github.com/ast-grep/ast-grep/pull/2589)
- chore(deps): update dependency oxlint to v1.61.0
[`#2605`](https://redirect.github.com/ast-grep/ast-grep/pull/2605)
- chore(deps): update rust crate similar to v3.1.0
[`#2587`](https://redirect.github.com/ast-grep/ast-grep/pull/2587)
- fix(deps): update rust crate tree-sitter-scala to 0.26.0
[`#2602`](https://redirect.github.com/ast-grep/ast-grep/pull/2602)
- chore(deps): update rust crate tree-sitter-scala to v0.25.1
[`#2601`](https://redirect.github.com/ast-grep/ast-grep/pull/2601)
- chore(deps): update rust crate tree-sitter-c-sharp to v0.23.5
[`#2591`](https://redirect.github.com/ast-grep/ast-grep/pull/2591)
- chore(deps): update dependency oxlint to v1.60.0
[`#2588`](https://redirect.github.com/ast-grep/ast-grep/pull/2588)
- chore(deps): update rust crate assert_cmd to v2.2.1
[`#2599`](https://redirect.github.com/ast-grep/ast-grep/pull/2599)
- chore(deps): update dependency typescript to v6.0.3
[`#2598`](https://redirect.github.com/ast-grep/ast-grep/pull/2598)
- chore(deps): update dependency
[@&#8203;napi-rs/cli](https://redirect.github.com/napi-rs/cli) to v3.6.2
[`#2593`](https://redirect.github.com/ast-grep/ast-grep/pull/2593)
- chore(deps): update rust crate napi-derive to v3.5.4
[`#2597`](https://redirect.github.com/ast-grep/ast-grep/pull/2597)
- chore(deps): update rust crate napi to v3.8.5
[`#2596`](https://redirect.github.com/ast-grep/ast-grep/pull/2596)
- chore(deps): update rust crate tokio to v1.52.1
[`#2592`](https://redirect.github.com/ast-grep/ast-grep/pull/2592)
- chore(deps): update rust crate clap to v4.6.1
[`#2594`](https://redirect.github.com/ast-grep/ast-grep/pull/2594)
- chore(deps): update pyo3/maturin-action action to v1.51.0
[`#2510`](https://redirect.github.com/ast-grep/ast-grep/pull/2510)
- fix(deps): update rust-wasm-bindgen monorepo
[`#2568`](https://redirect.github.com/ast-grep/ast-grep/pull/2568)
- chore(deps): update dependency
[@&#8203;napi-rs/cli](https://redirect.github.com/napi-rs/cli) to v3.6.1
[`#2583`](https://redirect.github.com/ast-grep/ast-grep/pull/2583)
- chore(deps): update dependency
[@&#8203;ast-grep/napi](https://redirect.github.com/ast-grep/napi) to
v0.42.1
[`#2580`](https://redirect.github.com/ast-grep/ast-grep/pull/2580)
- chore(deps): update dependency oxlint to v1.59.0
[`#2581`](https://redirect.github.com/ast-grep/ast-grep/pull/2581)
- chore(deps): update rust crate toml_edit to v0.25.11
[`#2582`](https://redirect.github.com/ast-grep/ast-grep/pull/2582)
- chore(deps): update rust crate tokio to v1.51.1
[`#2584`](https://redirect.github.com/ast-grep/ast-grep/pull/2584)
- chore(deps): update dependency dprint to v0.54.0
[`#2585`](https://redirect.github.com/ast-grep/ast-grep/pull/2585)
- chore(deps): update rust crate clap_complete to v4.6.1
[`#2586`](https://redirect.github.com/ast-grep/ast-grep/pull/2586)
- chore(deps): update dependency
[@&#8203;types/node](https://redirect.github.com/types/node) to v24.12.2
[`#2579`](https://redirect.github.com/ast-grep/ast-grep/pull/2579)
- fix: enable npx install fallback but still keep postinstall
[`fbc5b9b`](https://redirect.github.com/ast-grep/ast-grep/commit/fbc5b9b67d7f7f4e86406a7fcf491cbfab327098)
- chore: bump kotlin version
[`6f09a5b`](https://redirect.github.com/ast-grep/ast-grep/commit/6f09a5b02dc95ab083b614b4d972059b9afe3a23)
- fix: solve linting
[`945328a`](https://redirect.github.com/ast-grep/ast-grep/commit/945328aa3157370ce8fcc207358e29490d257fb6)

###
[`v0.42.1`](https://redirect.github.com/ast-grep/ast-grep/blob/HEAD/CHANGELOG.md#0421)

[Compare
Source](https://redirect.github.com/ast-grep/ast-grep/compare/0.42.0...0.42.1)

> 4 April 2026

- feat: Support Dart again
[`#2534`](https://redirect.github.com/ast-grep/ast-grep/pull/2534)
- chore(deps): update dependency oxlint to v1.58.0
[`#2569`](https://redirect.github.com/ast-grep/ast-grep/pull/2569)
- chore(deps): update rust crate toml_edit to v0.25.10
[`#2571`](https://redirect.github.com/ast-grep/ast-grep/pull/2571)
- fix(deps): update rust crate similar to v3
[`#2574`](https://redirect.github.com/ast-grep/ast-grep/pull/2574)
- chore(deps): update rust crate tokio to v1.51.0
[`#2578`](https://redirect.github.com/ast-grep/ast-grep/pull/2578)
- chore(deps): update dependency web-tree-sitter to v0.26.8
[`#2570`](https://redirect.github.com/ast-grep/ast-grep/pull/2570)
- chore(deps): update rust crate tree-sitter to v0.26.8
[`#2572`](https://redirect.github.com/ast-grep/ast-grep/pull/2572)
- chore(deps): update dependency dprint to v0.53.2
[`#2573`](https://redirect.github.com/ast-grep/ast-grep/pull/2573)
- chore(deps): update rust crate bit-set to 0.10.0
[`#2566`](https://redirect.github.com/ast-grep/ast-grep/pull/2566)
- fix(deps): update rust-wasm-bindgen monorepo
[`#2561`](https://redirect.github.com/ast-grep/ast-grep/pull/2561)
- chore(deps): update dependency smol-toml to v1.6.1
[`#2556`](https://redirect.github.com/ast-grep/ast-grep/pull/2556)
- chore(deps): update rust crate napi to v3.8.4
[`#2562`](https://redirect.github.com/ast-grep/ast-grep/pull/2562)
- chore(deps): update rust crate toml_edit to v0.25.8
[`#2552`](https://redirect.github.com/ast-grep/ast-grep/pull/2552)
- chore(deps): update rust crate napi-derive to v3.5.3
[`#2563`](https://redirect.github.com/ast-grep/ast-grep/pull/2563)
- chore(deps): update codecov/codecov-action action to v6
[`#2560`](https://redirect.github.com/ast-grep/ast-grep/pull/2560)
- chore(deps): update rust crate tree-sitter-rust to v0.24.2
[`#2554`](https://redirect.github.com/ast-grep/ast-grep/pull/2554)
- chore(deps): update dependency
[@&#8203;napi-rs/cli](https://redirect.github.com/napi-rs/cli) to v3.6.0
[`#2564`](https://redirect.github.com/ast-grep/ast-grep/pull/2564)
- chore(deps): update dependency dprint to v0.53.1
[`#2559`](https://redirect.github.com/ast-grep/ast-grep/pull/2559)
- chore(deps): update dependency oxlint to v1.57.0
[`#2549`](https://redirect.github.com/ast-grep/ast-grep/pull/2549)
- chore(deps): update dependency typescript to v6
[`#2557`](https://redirect.github.com/ast-grep/ast-grep/pull/2557)
- Added a license field to package.json so scanners can pick it up more
easily
[`#2558`](https://redirect.github.com/ast-grep/ast-grep/pull/2558)
- feat: add --color flag to test command
[`#2555`](https://redirect.github.com/ast-grep/ast-grep/pull/2555)
- chore(deps): update dependency
[@&#8203;ast-grep/napi](https://redirect.github.com/ast-grep/napi) to
v0.42.0
[`#2548`](https://redirect.github.com/ast-grep/ast-grep/pull/2548)
- feat: add new built in rule no-suppress-all
[`#2575`](https://redirect.github.com/ast-grep/ast-grep/issues/2575)
- fix: fix SIGSEGV caused by SharedReference stackoverflow
[`#2553`](https://redirect.github.com/ast-grep/ast-grep/issues/2553)
- fix: update ts
[`7fa0e3f`](https://redirect.github.com/ast-grep/ast-grep/commit/7fa0e3f3fc4cb2a6a9daca48ddc132ef0310a773)
- refactor: use more concise style object to manage test output
[`a017fd5`](https://redirect.github.com/ast-grep/ast-grep/commit/a017fd5133982dc725ef817c8ef0fe80eaafa6b5)
- refactor: some code clean up for no-suppress
[`ef7fc1a`](https://redirect.github.com/ast-grep/ast-grep/commit/ef7fc1a91843c8061eda21d50bc88157e89576aa)

###
[`v0.42.0`](https://redirect.github.com/ast-grep/ast-grep/blob/HEAD/CHANGELOG.md#0420)

[Compare
Source](https://redirect.github.com/ast-grep/ast-grep/compare/0.41.1...0.42.0)

> 15 March 2026

- chore(deps): update dependency dprint to v0.53.0
[`#2547`](https://redirect.github.com/ast-grep/ast-grep/pull/2547)
- chore(deps): update rust crate tree-sitter to v0.26.7
[`#2541`](https://redirect.github.com/ast-grep/ast-grep/pull/2541)
- chore(deps): update dependency web-tree-sitter to v0.26.7
[`#2540`](https://redirect.github.com/ast-grep/ast-grep/pull/2540)
- chore(deps): update dependency
[@&#8203;types/node](https://redirect.github.com/types/node) to v24.12.0
[`#2518`](https://redirect.github.com/ast-grep/ast-grep/pull/2518)
- fix(deps): update rust crate tree-sitter-lua to 0.5.0
[`#2506`](https://redirect.github.com/ast-grep/ast-grep/pull/2506)
- chore(deps): update rust crate clap to v4.6.0
[`#2538`](https://redirect.github.com/ast-grep/ast-grep/pull/2538)
- fix(deps): update rust crate tree-sitter-scala to 0.25.0
[`#2536`](https://redirect.github.com/ast-grep/ast-grep/pull/2536)
- chore(deps): update dependency oxlint to v1.55.0
[`#2533`](https://redirect.github.com/ast-grep/ast-grep/pull/2533)
- chore(deps): update rust crate clap_complete to v4.6.0
[`#2539`](https://redirect.github.com/ast-grep/ast-grep/pull/2539)
- chore(deps): update rust crate bit-set to v0.9.1
[`#2537`](https://redirect.github.com/ast-grep/ast-grep/pull/2537)
- chore(deps): update rust crate bit-set to 0.9.0
[`#2527`](https://redirect.github.com/ast-grep/ast-grep/pull/2527)
- chore(deps): update rust crate assert_cmd to v2.2.0
[`#2529`](https://redirect.github.com/ast-grep/ast-grep/pull/2529)
- chore(deps): update rust crate tempfile to v3.27.0
[`#2531`](https://redirect.github.com/ast-grep/ast-grep/pull/2531)
- fix(lsp): scan injected languages for diagnostics
[`#2528`](https://redirect.github.com/ast-grep/ast-grep/pull/2528)
- chore(deps): update dependency
[@&#8203;ast-grep/napi](https://redirect.github.com/ast-grep/napi) to
v0.41.1
[`#2526`](https://redirect.github.com/ast-grep/ast-grep/pull/2526)
- chore(deps): update dependency oxlint to v1.52.0
[`#2524`](https://redirect.github.com/ast-grep/ast-grep/pull/2524)
- feat: support nth-child esquery
[`#2546`](https://redirect.github.com/ast-grep/ast-grep/issues/2546)
- feat: support :is selector
[`#2545`](https://redirect.github.com/ast-grep/ast-grep/issues/2545)
- feat: support :not selector
[`#2544`](https://redirect.github.com/ast-grep/ast-grep/issues/2544)
- feat: support :has rule
[`#2543`](https://redirect.github.com/ast-grep/ast-grep/issues/2543)
- fix(lsp): scan injected languages for diagnostics
([#&#8203;2528](https://redirect.github.com/ast-grep/ast-grep/issues/2528))
[`#2522`](https://redirect.github.com/ast-grep/ast-grep/issues/2522)
- feat: add parameterized util
[`3d90372`](https://redirect.github.com/ast-grep/ast-grep/commit/3d903727c2fad6f7ed24cc4852f66b3adc45c7a2)
- refactor: limit parameterized utils to globals
[`2d69a34`](https://redirect.github.com/ast-grep/ast-grep/commit/2d69a3425b9917653a01f4d56aff9332b0c86538)
- refactor: move parameterized_util
[`c77e38d`](https://redirect.github.com/ast-grep/ast-grep/commit/c77e38d84281e3bbbe3e5828dd9989d8e721a8a1)

###
[`v0.41.1`](https://redirect.github.com/ast-grep/ast-grep/blob/HEAD/CHANGELOG.md#0411)

[Compare
Source](https://redirect.github.com/ast-grep/ast-grep/compare/0.41.0...0.41.1)

> 10 March 2026

- fix: lsp on change encounter deadlock
[`#2511`](https://redirect.github.com/ast-grep/ast-grep/pull/2511)
- chore(deps): update dependency oxlint to v1.51.0
[`#2512`](https://redirect.github.com/ast-grep/ast-grep/pull/2512)
- chore(deps): update rust crate tempfile to v3.26.0
[`#2497`](https://redirect.github.com/ast-grep/ast-grep/pull/2497)
- chore(deps): update rust crate inquire to v0.9.4
[`#2498`](https://redirect.github.com/ast-grep/ast-grep/pull/2498)
- chore(deps): update dependency
[@&#8203;types/node](https://redirect.github.com/types/node) to v24.11.0
[`#2502`](https://redirect.github.com/ast-grep/ast-grep/pull/2502)
- chore(deps): update dependency dprint to v0.52.0
[`#2499`](https://redirect.github.com/ast-grep/ast-grep/pull/2499)
- fix: override severity on `rule` & `inline-rules` flags
[`#2505`](https://redirect.github.com/ast-grep/ast-grep/pull/2505)
- chore(deps): update github artifact actions
[`#2507`](https://redirect.github.com/ast-grep/ast-grep/pull/2507)
- chore(deps): update rust crate tree-sitter to v0.26.6
[`#2501`](https://redirect.github.com/ast-grep/ast-grep/pull/2501)
- chore(deps): update dependency web-tree-sitter to v0.26.6
[`#2500`](https://redirect.github.com/ast-grep/ast-grep/pull/2500)
- chore(deps): update dependency ava to v7
[`#2508`](https://redirect.github.com/ast-grep/ast-grep/pull/2508)
- chore(deps): update dependency oxlint to v1.50.0
[`#2495`](https://redirect.github.com/ast-grep/ast-grep/pull/2495)
- chore(deps): update dependency
[@&#8203;ast-grep/napi](https://redirect.github.com/ast-grep/napi) to
v0.41.0
[`#2494`](https://redirect.github.com/ast-grep/ast-grep/pull/2494)
- fix: bump ls-types version
[`#2525`](https://redirect.github.com/ast-grep/ast-grep/issues/2525)
- refactor: change versioned ast work
[`a86b2ab`](https://redirect.github.com/ast-grep/ast-grep/commit/a86b2abe5dc4997c892274017f40c7a75c7df354)
- fix: bump wasm-bindgen
[`d23e334`](https://redirect.github.com/ast-grep/ast-grep/commit/d23e3344df921bbfe9ef1fa84ee9aeceeb543038)
- fix: fix wasm package
[`0b92e94`](https://redirect.github.com/ast-grep/ast-grep/commit/0b92e941ef54d3c1810283b5471282ad2793f8d5)

###
[`v0.41.0`](https://redirect.github.com/ast-grep/ast-grep/blob/HEAD/CHANGELOG.md#0410)

[Compare
Source](https://redirect.github.com/ast-grep/ast-grep/compare/0.40.5...0.41.0)

> 22 February 2026

- chore(deps): update pyo3/maturin-action action to v1.50.0
[`#2465`](https://redirect.github.com/ast-grep/ast-grep/pull/2465)
- fix(deps): update rust-wasm-bindgen monorepo
[`#2491`](https://redirect.github.com/ast-grep/ast-grep/pull/2491)
- chore(deps): update rust crate toml_edit to v0.25.3
[`#2469`](https://redirect.github.com/ast-grep/ast-grep/pull/2469)
- chore(deps): update dependency web-tree-sitter to ^0.26.0
[`#2492`](https://redirect.github.com/ast-grep/ast-grep/pull/2492)
- refactor: addr_of_mut to OnceLock
[`#2486`](https://redirect.github.com/ast-grep/ast-grep/pull/2486)
- feat: support ast-grep-wasm
[`#2484`](https://redirect.github.com/ast-grep/ast-grep/pull/2484)
- chore(deps): update rust crate clap to v4.5.60
[`#2483`](https://redirect.github.com/ast-grep/ast-grep/pull/2483)
- chore(deps): update rust crate anyhow to v1.0.102
[`#2489`](https://redirect.github.com/ast-grep/ast-grep/pull/2489)
- chore(deps): update dependency oxlint to v1.49.0
[`#2488`](https://redirect.github.com/ast-grep/ast-grep/pull/2488)
- feat: make default rule id to filename
[`#2482`](https://redirect.github.com/ast-grep/ast-grep/pull/2482)
- chore(deps): update dependency oxlint to v1.48.0
[`#2481`](https://redirect.github.com/ast-grep/ast-grep/pull/2481)
- chore(deps): update rust crate napi-derive to v3.5.2
[`#2475`](https://redirect.github.com/ast-grep/ast-grep/pull/2475)
- chore(deps): update rust crate napi to v3.8.3
[`#2474`](https://redirect.github.com/ast-grep/ast-grep/pull/2474)
- chore(deps): update rust crate futures to v0.3.32
[`#2476`](https://redirect.github.com/ast-grep/ast-grep/pull/2476)
- chore(deps): update rust crate clap to v4.5.58
[`#2470`](https://redirect.github.com/ast-grep/ast-grep/pull/2470)
- fix: parse each language injection region as independent tree
[`#2479`](https://redirect.github.com/ast-grep/ast-grep/pull/2479)
- chore(deps): update dependency
[@&#8203;types/node](https://redirect.github.com/types/node) to
v24.10.13
[`#2467`](https://redirect.github.com/ast-grep/ast-grep/pull/2467)
- chore(deps): update rust crate clap_complete to v4.5.66
[`#2471`](https://redirect.github.com/ast-grep/ast-grep/pull/2471)
- chore(deps): update rust crate predicates to v3.1.4
[`#2472`](https://redirect.github.com/ast-grep/ast-grep/pull/2472)
- chore(deps): update dependency oxlint to v1.47.0
[`#2468`](https://redirect.github.com/ast-grep/ast-grep/pull/2468)
- chore(deps): update rust crate tempfile to v3.25.0
[`#2466`](https://redirect.github.com/ast-grep/ast-grep/pull/2466)
- fix(deps): update rust crate toml_edit to 0.25.0
[`#2473`](https://redirect.github.com/ast-grep/ast-grep/pull/2473)
- chore(deps): update rust crate tree-sitter to v0.26.5
[`#2458`](https://redirect.github.com/ast-grep/ast-grep/pull/2458)
- chore(deps): update dependency
[@&#8203;types/node](https://redirect.github.com/types/node) to
v24.10.12
[`#2438`](https://redirect.github.com/ast-grep/ast-grep/pull/2438)
- chore(deps): update rust crate schemars to v1.2.1
[`#2457`](https://redirect.github.com/ast-grep/ast-grep/pull/2457)
- chore(deps): update rust crate clap to v4.5.57
[`#2455`](https://redirect.github.com/ast-grep/ast-grep/pull/2455)
- chore(deps): update rust crate anyhow to v1.0.101
[`#2462`](https://redirect.github.com/ast-grep/ast-grep/pull/2462)
- chore(deps): update rust crate inquire to v0.9.3
[`#2463`](https://redirect.github.com/ast-grep/ast-grep/pull/2463)
- chore(deps): update dependency oxlint to v1.43.0
[`#2459`](https://redirect.github.com/ast-grep/ast-grep/pull/2459)
- chore(deps): update rust crate regex to v1.12.3
[`#2461`](https://redirect.github.com/ast-grep/ast-grep/pull/2461)
- chore(deps): update rust crate clap to v4.5.55
[`#2454`](https://redirect.github.com/ast-grep/ast-grep/pull/2454)
- chore(deps): update dependency oxlint to v1.42.0
[`#2452`](https://redirect.github.com/ast-grep/ast-grep/pull/2452)
- chore(deps): update dependency oxlint to v1.41.0
[`#2447`](https://redirect.github.com/ast-grep/ast-grep/pull/2447)
- chore(deps): update rust crate assert_cmd to v2.1.2
[`#2437`](https://redirect.github.com/ast-grep/ast-grep/pull/2437)
- chore(deps): update rust crate thiserror to v2.0.18
[`#2446`](https://redirect.github.com/ast-grep/ast-grep/pull/2446)
- chore(deps): update dependency oxlint to v1.39.0
[`#2442`](https://redirect.github.com/ast-grep/ast-grep/pull/2442)
- chore(deps): update rust crate inquire to v0.9.2
[`#2445`](https://redirect.github.com/ast-grep/ast-grep/pull/2445)
- fix: improve max diagnostic impl to use one atomic op
[`781ec81`](https://redirect.github.com/ast-grep/ast-grep/commit/781ec81cb4eba2678c3785a1e322f953dbb5a8d8)
- fix: udpate schema
[`e645fdf`](https://redirect.github.com/ast-grep/ast-grep/commit/e645fdfa1af85fc5c69ed167bce2eb123dbeb1cc)
- fix: move dumping to core crate
[`0b2acb9`](https://redirect.github.com/ast-grep/ast-grep/commit/0b2acb96bc8862d8baa657c724402a5b181033e2)

</details>

<details>
<summary>reubeno/brush (brush-parser)</summary>

###
[`v0.4.0`](https://redirect.github.com/reubeno/brush/blob/HEAD/CHANGELOG.md#040---2026-05-02)

[Compare
Source](https://redirect.github.com/reubeno/brush/compare/brush-parser-v0.3.0...brush-parser-v0.4.0)

##### 🚀 Features

- *(parser)* Add official `serde` feature to `brush-parser` for AST
serialization
([#&#8203;783](https://redirect.github.com/reubeno/brush/pull/783))
- *(parser)* \[**breaking**] Replace ParsingNearToken with ParsingNear
([#&#8203;1022](https://redirect.github.com/reubeno/brush/pull/1022))
- Introduce notion of marking errors as fatal
([#&#8203;770](https://redirect.github.com/reubeno/brush/pull/770))
- Expose key bindings for hint acceptance
([#&#8203;802](https://redirect.github.com/reubeno/brush/pull/802))
- Add 'serde' feature to `brush-core`
([#&#8203;831](https://redirect.github.com/reubeno/brush/pull/831))
- Enable using word expander without command substs
([#&#8203;877](https://redirect.github.com/reubeno/brush/pull/877))
- Enable session leading config
([#&#8203;904](https://redirect.github.com/reubeno/brush/pull/904))
- Implement \l sequence in prompt expansion
([#&#8203;913](https://redirect.github.com/reubeno/brush/pull/913))
- *(windows)* Various path fixes for windows platform
([#&#8203;1075](https://redirect.github.com/reubeno/brush/pull/1075))
- Implement fatal error propagation
([#&#8203;773](https://redirect.github.com/reubeno/brush/pull/773))
- Implement `set -u` semantics
([#&#8203;774](https://redirect.github.com/reubeno/brush/pull/774))
- Source tracking improvements
([#&#8203;805](https://redirect.github.com/reubeno/brush/pull/805))
- Support asynchronous builtin execution
([#&#8203;810](https://redirect.github.com/reubeno/brush/pull/810))
- *(builtins)* Implement caller builtin
([#&#8203;812](https://redirect.github.com/reubeno/brush/pull/812))
- Implement "compgen -A binding"
([#&#8203;814](https://redirect.github.com/reubeno/brush/pull/814))
- Emulate `exec` in subshell
([#&#8203;823](https://redirect.github.com/reubeno/brush/pull/823))
- Experimental builtin for serializing full shell state
([#&#8203;835](https://redirect.github.com/reubeno/brush/pull/835))
- Expand tilde expansion support
([#&#8203;842](https://redirect.github.com/reubeno/brush/pull/842))
- Implement `set -e` (a.k.a. `errexit`) + `pipefail` semantics
([#&#8203;852](https://redirect.github.com/reubeno/brush/pull/852))
- Experimental shell/terminal integration
([#&#8203;872](https://redirect.github.com/reubeno/brush/pull/872))
- *(hooks)* Experimental `zsh`-style preexec/precmd hooks
([#&#8203;652](https://redirect.github.com/reubeno/brush/pull/652))
- Rudimentary readline macro support
([#&#8203;880](https://redirect.github.com/reubeno/brush/pull/880))
- Optional TOML-based config file for brush-shell
([#&#8203;895](https://redirect.github.com/reubeno/brush/pull/895))
- *(read)* Fill out more of `read` builtin
([#&#8203;914](https://redirect.github.com/reubeno/brush/pull/914))
- Add convenience cmd line option to set up xtrace
([#&#8203;915](https://redirect.github.com/reubeno/brush/pull/915))
- Scaffolding for winnow parser
([#&#8203;974](https://redirect.github.com/reubeno/brush/pull/974))
- *(completion)* 

> [!IMPORTANT]
> ✂ PR body was truncated to here.


</details>

---

### Configuration

📅 **Schedule**: (in timezone Asia/Shanghai)

- Branch creation
  - "before 10am on monday"
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/voidzero-dev/vite-plus).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMDkuNCIsInVwZGF0ZWRJblZlciI6IjQ0LjE1NS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: voidzero-guard[bot] <278573678+voidzero-guard[bot]@users.noreply.github.com>
Co-authored-by: MK <fengmk2@gmail.com>
@fengmk2
fengmk2 force-pushed the feat/vpx-typescript-scripts branch from 5edae0d to d6a619e Compare October 14, 2026 17:29
fengmk2 pushed a commit that referenced this pull request Oct 15, 2026
<!-- claude-projects-attribution: {"github_login":"Brooooooklyn"} -->
_Requested by **Brooklyn** · [project
thread](https://claude.ai/code/project/chan_018s9RxRdtH424j2EhXdzV3N?thread=cmsg_018s9RxRdtH424j2EhXdzV3NQxbeR8Pt7qaqSQwoq9rEFo)_

<!-- routine:prune-tests:duplicate-shell-and-helper-tests -->

Before: `vp_global_cli` and `vp_pm_cli` carried Rust unit tests that
could not fail when the product broke: an `assert!(true)` in
`create.rs`, four `env use` shell-detection tests that repeat
`commands::shell` tests for code `env use` only imports, and three tests
of test-only helpers. `upgrade_check.rs` had 20 hand-unrolled lookup
tests.

After: those 8 tests are gone and the 20 lookup tests are 2 table-driven
tests that keep every row and comment, with the failing row named in the
assertion message. Only test code changes: every hunk is inside a
`#[cfg(test)]` module or the `#[cfg(test)]`-only
`resolution::test_utils` module.

How: each candidate was defended by mutating product code with the most
realistic regression only it would catch, running the crate's tests, and
reverting. No deleted test failed alone on any mutation.

### Totals

| | Before (origin/main c04bcf6) | After |
|---|---|---|
| Files touched | – | 5 |
| `vp_global_cli` cases collected (Linux) | 502 (+2 ignored) | 479 (+2
ignored) |
| `vp_pm_cli` cases collected | 923 (+2 ignored) | 920 (+2 ignored) |

- Cases deleted: **8** of 1,425 collected in the two touched crates.
Repo-wide: about 2,432 `#[test]`/`#[tokio::test]` attributes in tracked
Rust (static count) and 1,492 static `it`/`test` calls in 101 JS spec
files (not collected; Vitest needs a full `packages/core` build).
- Cases folded: **20 into 2**, every row and comment kept.
Runner-collected total: −26.
- Net lines: **−159** (+42 / −201).
- Runtime saved: about 0.03 s (the 8 deleted cases each report 0.000 s;
the 20 folded cases summed 0.028 s against 0.011 s for the 2
replacements).
- Test-binary time on this shared machine: `vp_global_cli` 3.13 s → 3.32
s, `vp_pm_cli` 27.81 s → 29.06 s (noise).

### Per file

1. **`crates/vp_global_cli/src/commands/create.rs` ›
`test_create_command_module_exists`**
   - Class: tautology (`assert!(true)`).
- Best defense: M1 (delegate `"new"` instead of `"create"`) passes all
502 tests, so this test cannot fail. The whole `mod tests` goes.
- Coverage gap (pre-existing, unchanged by this PR): no unit test covers
`vp create` delegation. It may be covered by the PTY snapshot suite,
which was not run.
2. **`crates/vp_global_cli/src/commands/env/use.rs` ›
`test_detect_shell_vp_shell_{powershell,fish,nu}`,
`test_detect_shell_posix_default`**
- Class: duplicates of stronger tests. `detect_shell` /
`Shell::from_str` live in `commands/shell.rs`; `env use` only imports
them.
- Still covered: `fish` is byte-identical to
`commands::shell::tests::test_detect_shell_vp_shell_fish`; `nu` to
`test_detect_shell_vp_shell_explicit`; lowercase `powershell` by
`test_shell_from_str` and `test_detect_shell_vp_shell_case_insensitive`;
`posix_default` by `test_detect_shell_defaults_without_vp_shell`.
- Best defenses M2–M5: each failed the nominee together with at least
one `commands::shell` test.
- The `use vp_shared::env_vars;` import is now `#[cfg(windows)]`, since
only the three Windows-only tests in the module still use it.
3. **`crates/vp_pm_cli/src/resolution/test_utils.rs` ›
`parses_args_without_a_program_name`,
`parses_subcommands_without_a_program_name`**
   - Class: test tooling testing test tooling.
- Best defense: M7 fails 122 tests and M8 fails 17; every resolution
parser test exercises these helpers.
4. **`crates/vp_pm_cli/src/resolution/commands/list.rs` ›
`list_args_helper_keeps_pattern`** (and its test-only `list_args`
helper, which had no other caller)
- Class: test tooling testing test tooling; it only checked struct
construction.
- Best defenses: M9 fails only
`test_list_with_pattern_and_pass_through_args`; M10 fails
`test_parser_accepts_short_dev_and_global_flags` and
`cli::tests::projects_managed_global_commands`. The nominee passes both.

### Folds (`crates/vp_global_cli/src/upgrade_check.rs`)

- The 9 `is_newer_version_*` tests → `is_newer_version_compares_semver`
(12 rows, original comments kept, one comment added for the `0.0.0`
dev-build row).
- The 11 `should_run_for_*` / `should_not_run_for_*` tests →
`should_run_for_command_skips_excluded_and_machine_readable_commands`
(11 rows).
- M11, M12 and M13 still fail the folded tables.

### Kept after defense — do not re-nominate

None: no nominee survived its defense.

### Case counts

| file | before | after | delta | expected delta |
|---|---|---|---|---|
| vp_global_cli `commands/create.rs` | 1 | 0 | −1 | −1 |
| vp_global_cli `commands/env/use.rs` (Linux) | 16 | 12 | −4 | −4 |
| vp_global_cli `upgrade_check.rs` | 36 | 18 | −18 | −18 (20 folded into
2) |
| vp_pm_cli `resolution/commands/list.rs` | 45 | 44 | −1 | −1 |
| vp_pm_cli `resolution/test_utils.rs` | 2 | 0 | −2 | −2 |
| **Crates total** | 1,425 | 1,399 | −26 | −26 |

**0 new failures** (0 failed and 4 ignored, before and after).

### Mutations

Each was temporary and reverted (`git status` clean afterwards).

1. M1 `create.rs:15`: delegate `"new"` instead of `"create"`. Failed:
none.
2. M2 `shell.rs:30`: `"fish"` → `"fishshell"`. Failed: `use::…_fish`,
`shell::test_shell_from_str`, `shell::…_fish`.
3. M3 `shell.rs:31`: `"nu" | "nushell"` → `"nushell"`. Failed:
`use::…_nu`, `shell::…_explicit`, `shell::test_shell_from_str`.
4. M4 `shell.rs:32`: drop `"powershell"`. Failed: `use::…_powershell`,
`shell::…_case_insensitive`, `shell::test_shell_from_str`.
5. M5 `shell.rs:54`: default always `Cmd`. Failed:
`use::…_posix_default`, `shell::…_defaults_without_vp_shell`,
`shell::…_invalid_vp_shell_falls_back_to_default`.
6. M6 `shell.rs:49`: upper-case the value. Failed: none (equivalent
mutation; `from_str` lowercases).
7. M7 `test_utils.rs:70`: `test_argv` no longer prepends a program name.
Failed: 122 tests, including both nominees.
8. M8 `test_utils.rs:57`: `parse_subcommand` gets raw args. Failed: 17
tests (`config`, `dist_tag`, `owner`, `stage`, `token`, plus the
nominee).
9. M9 `list.rs:78-80`: pnpm drops the pattern. Failed:
`test_list_with_pattern_and_pass_through_args` only.
10. M10 `list.rs:11`: `pattern` becomes `#[arg(long)]`. Failed:
`test_parser_accepts_short_dev_and_global_flags`,
`cli::tests::projects_managed_global_commands`.
11. M11 `upgrade_check.rs:170` (after the fold): `>` → `>=`. Failed:
`is_newer_version_compares_semver`.
12. M12 `upgrade_check.rs:338` (after the fold): `Upgrade` removed from
the excluded commands. Failed:
`should_run_for_command_skips_excluded_and_machine_readable_commands`.
13. M13 `upgrade_check.rs:165` (after the fold): the `0.0.0` early
return removed. Failed: `is_newer_version_compares_semver`.

### What ran and what did not

- Ran, at origin/main and on this branch: `cargo test -p vp_global_cli`
and `cargo test -p vp_pm_cli` with `--report-time`; `cargo clippy -p
vp_global_cli -p vp_pm_cli --all-targets --all-features -- --deny
warnings` with the `just lint` allow-list; `cargo fmt --all -- --check`;
`git diff --check`. All pass.
- Not run: the full workspace `just test` / `just lint` / `just check`;
Windows targets (none installed here, so the `#[cfg(windows)]` import
gate was reviewed but not compiled; Windows CI will compile it); the
JS/Vitest suite; the PTY snapshot suite.

### Excluded pull requests

55 open PRs touch 737 files between them; none of the 5 files here is
among them. #3055 #3052 #3051 #3049 #3047 #3046 #3044 #3040 #3038 #3037
#3020 #3018 #3014 #3012 #3009 #3008 #3000 #2986 #2981 #2966 #2936 #2922
#2900 #2863 #2862 #2810 #2792 #2740 #2721 #2699 #2695 #2574 #2557 #2552
#2549 #2543 #2542 #2541 #2483 #2475 #2463 #2462 #2461 #2456 #2428 #2418
#2357 #2267 #2125 #1958 #1783 #1782 #1614 #1517 #1180.

### Age check (cutoff: 30 days, 2026-09-14)

First-added dates from `git log -S`, followed across the `vite_*` →
`vp_*` crate rename.

| Test | First added |
|---|---|
| `test_create_command_module_exists` | 2026-02-10 (a29ac83, #570) |
| `test_detect_shell_posix_default` | 2026-02-07 (194c0dc, #524) |
| `test_detect_shell_vp_shell_{powershell,fish,nu}` | 2026-05-24
(53ae721, #1658) |
| `test_utils` tests and `list_args_helper_keeps_pattern` | 2026-08-03
(c1574dd, #2140) |
| The 20 folded `upgrade_check` tests | 2026-03-30 (db75675) |

None was added for a bug or incident, and none is in a permission,
security or entitlement suite.

### Checks

| Check | Before | After |
|---|---|---|
| Tests `vp_global_cli` | 502 pass | 479 pass |
| Tests `vp_pm_cli` | 923 pass | 920 pass |
| Clippy (deny warnings) | pass | pass |
| rustfmt | – | pass |
| `git diff --check` | – | clean |

To revert: `git revert 687935d`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01PxVsmvB9xfZKfVnUonY8kf

---
_Generated by [Claude
Code](https://claude.ai/code/session_01PxVsmvB9xfZKfVnUonY8kf)_

Co-authored-by: Claude <noreply@anthropic.com>
fengmk2 added a commit that referenced this pull request Oct 15, 2026
- Status: implemented in #2936 and covered by CI on Linux, macOS, and
  Windows, no longer "verified on macOS".
- `vp toolchain` reports oxc-node 0.1.7, and the glue is about 3,600
  lines.
- Design Decision 9 and Alternative F no longer describe the vendored
  patch as current.
- Windows paths, loader URL, and exit codes are covered by the CI
  snapshot run; only Ctrl+C is left to verify.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@fengmk2
fengmk2 force-pushed the feat/vpx-typescript-scripts branch from 20c4609 to 5a6dac6 Compare October 15, 2026 02:37
fengmk2 added a commit that referenced this pull request Oct 15, 2026
- Status: implemented in #2936 and covered by CI on Linux, macOS, and
  Windows, no longer "verified on macOS".
- `vp toolchain` reports oxc-node 0.1.7, and the glue is about 3,600
  lines.
- Design Decision 9 and Alternative F no longer describe the vendored
  patch as current.
- Windows paths, loader URL, and exit codes are covered by the CI
  snapshot run; only Ctrl+C is left to verify.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@fengmk2 fengmk2 self-assigned this Oct 15, 2026
@fengmk2
fengmk2 force-pushed the feat/vpx-typescript-scripts branch from b71b155 to 0d3a8ac Compare October 15, 2026 07:29
fengmk2 and others added 22 commits October 20, 2026 16:34
Since the oxc-node fix for file names with `#` and `%`, `import './a#b.ts'`
loads a file named `a#b.ts` when one exists, where Node.js treats `#b.ts` as a
URL fragment (oxc-project/oxc-node#856).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
oxc-node fixed the remaining issues from end-to-end testing against tsx on
main, still without a release. Only its Rust source changed: no loader entry,
forwarded signature, or dependency changes.

- A tsconfig that cannot be read prints a warning instead of being skipped
  silently, for a missing `TS_NODE_PROJECT` file and a tsconfig that fails to
  parse (oxc-project/oxc-node#844).
- `--preserve-symlinks` is honored, and `OXC_LOG` writes to stderr (#845).
- A byte order mark before a shebang no longer fails to parse (#846).
- In an import, `#` starts a URL fragment again, as in Node.js (#856).

New snapshot steps cover the byte order mark and the fragment, with a decoy
`a#b.ts` next to the `a.ts` the import must load.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The RFC records the new pin, lists every oxc-node issue from the end-to-end
testing as fixed, and keeps only the two open oxc transformer issues. The guide
says that a missing tsconfig named by `TS_NODE_PROJECT` or
`OXC_TSCONFIG_PATH`, or one that fails to parse, prints a warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Windows local flavor writes `.cmd` shims for the package bins it exposes,
but the list had no `vpx`, so `vpx` there resolved to the global CLI. Every
local-flavor vpx case on Windows ran the global `vpx` and matched the global
snapshot, and the local-only `vpx_package_not_installed` case failed with a
download attempt. The local bin now runs in those cases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With an IPC channel, the local bin exited on the child's `close` event, which
waits for the channel to report EOF. When the process that started `vpx`
disconnected first, the bin closed the script's channel itself, `close` never
fired, and the bin exited 0, losing the script's exit code or signal. It now
exits once the child has exited and its channel has disconnected, whichever
side closed it, and after relaying the script's last messages.

A message the bin cannot serialize for the script, such as a BigInt from a
parent using advanced serialization, is reported instead of crashing the bin.
The IPC snapshot case adds a step in which the parent disconnects first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
No Windows case ran a binary from node_modules/.bin, so the local bin's
cross-spawn path for `.cmd` shims had no coverage there. A Windows-only case
copies a `.cmd` tool into node_modules/.bin and runs it in both flavors,
checking its arguments and exit code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On Windows a `.cmd` shim cannot carry an IPC channel, and the local bin runs
`.cmd` binaries through cmd.exe, so Ctrl+C can end with the batch job prompt
that the global `vpx` avoids through `.ps1` siblings. The RFC also describes
the IPC exit behavior and no longer calls the oxc-node pin a release.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Windows-only case echoed `%*` from the batch file, which shows the quotes
cross-spawn adds around every argument for a `.cmd` file; the program a real
cmd-shim forwards to never sees them. The tool now forwards to a Node.js
script that prints its arguments, so the case checks what the program
receives, including an argument with a space, in both flavors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
From a cleanup review of the whole PR:

- Loader: resolve CommonJS helper `require()`s through a
  `Module._resolveFilename` wrapper, as upstream's `register.mjs` does, instead
  of rewriting transformed code, which also created a `require` per call site.
  Both hook entries load the binding through one `loadOxcNode()`, and the
  binding's `createResolve` drops the options only oxc-node's WASI build reads.
- Local bin: one `childEnv()` for both spawn paths, one `fail(message, note)`,
  the shared `exitCodeFromClose`, and one `node_modules/.bin` walk for both the
  binary lookup and PATH; the lookup returns the stats it already read.
- Global vpx: one script-detection call instead of two, and a `local_bin_env()`
  helper for the three places that build that environment. The shared-table
  tests load the table and build case projects through two helpers.
- Snapshot runner: write a Windows `.cmd` shim for each file in the package's
  `bin/`, as Unix flavors put the whole directory on PATH, instead of a list.
- Tools: drop the unused `tool patch-oxc-node` subcommand and simplify
  `setOxcVersion`; drop a unit test the version grid already covers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
After -e/--eval, -p/-pe/--print, or --run, Node.js runs that code or package
script and passes the remaining positionals as arguments, so a trailing
missing path is not a script. Both CLIs share the option list through the
case table. -pe also takes a value, like -p.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Positionals after --test are test files and globs, not an entry file, so a
  quoted glob such as "./tests/**/*.test.ts" reaches node:test unchanged.
- Option names match with `_` for `-`, as Node.js accepts, so
  --redirect_warnings ./w.ts takes its value instead of being checked as a
  script.
- Document that --check reads the file without the loader, as with tsx.
- Hash packages/tools/src/cargo-toml.ts in the native cache key: the oxc-node
  patch imports it.
- Snapshot redaction builds the file URL variant with the path setter, so
  `#`, `?`, and `%` in a checkout path are encoded as pathToFileURL does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The local bin spawned the script and ignored SIGINT, so a SIGINT sent to its
PID never reached the script and both processes kept running. Like the global
vpx, it now replaces itself with process.execve(): the PID its caller holds,
every signal, and the exit status belong to the script or binary, and no idle
parent stays behind.

- Before the exec, restore what libuv gives a spawned child: default SIGPIPE
  and SIGXFSZ dispositions and blocking stdio, which process.execve() leaves
  non-blocking once Node.js has opened a pipe (nodejs/node#66824).
- A binary execs through /bin/sh, since a failed exec aborts most supported
  Node.js versions.
- Windows, and a bin started with an IPC channel, keep spawning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… path

The registerHooks() resolve hook rewrote a helper specifier before it
recognized a require(), so CommonJS output asked Node.js' CommonJS resolution
for @oxc-project/runtime from the requiring file, which ignores the parentURL
the hook set. A script in a pnpm project or outside any project then failed
with "Cannot find module '@oxc-project/runtime/helpers/…'" on 22.22.3+,
24.11.1+, and 26. A require() now passes through unchanged, so the
Module._resolveFilename wrapper maps it as on the off-thread path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pnpm links vite-plus into its store, where the native binding package sits
next to it. The global vpx passed the loader path through that link, so with
--preserve-symlinks Node.js resolved the binding from the link and failed
with "Cannot find native binding". The loader directory is now resolved
through symlinks first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Since #3100, `vp node` repeats the shell's PATH lookup in system-first mode
and runs the system Node.js found before any Vite+ shim, while vpx script mode
still went straight to shim dispatch and ran managed Node.js. Script mode now
does the same lookup, so a script runs on the Node.js `vp node` selects.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A --require preload runs twice on every off-thread release, 24.11.0
  included, and fs.writeSync() to stdout can hit EAGAIN there, as with tsx.
- Helper require() calls pass through the in-thread resolve hook unchanged.
- Script mode repeats the system-first PATH lookup like `vp node`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s the parent

Node.js resolves the entry point and --import preloads against the working
directory's URL, which ends in `/`. oxc-node reads a parent URL as a file and
resolves from the directory above it, so an extensionless `--import ./setup`
was not found, and with the working directory at `/` (a container without
WORKDIR) every script failed with "Parent URL is not a file URL" on the
in-thread hook path. oxc-node now gets a file in that directory, while Node.js'
own resolution keeps the original URL for its messages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ound

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lace

The local bin no longer keeps a parent process, so the benchmark labels it
by what it does now, and the RFC's tables come from a fresh run of the
current code. Exec in place keeps startup within 2 ms of spawning the
script.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The local bin execs every package binary through /bin/sh, because a failed
process.execve() aborts most supported Node.js versions. Starting the shell
made running an installed binary slower than spawning it had been. A native
binary, or a script whose `#!` interpreter is one, now execs directly; only
anything else goes through the shell, which reports a file it cannot run as
a terminal does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…base

main's dependency upgrade moved @oxc-project/runtime to 0.155.0, but this
branch makes it follow Rolldown's pin (0.154.0, the oxc version the binding
links and the loader transforms with), and sync-remote rewrites it back.
The lockfile is regenerated from main's, adding this branch's pirates and
runtime entries for packages/cli.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
oxc-node fixed oxc-project/oxc-node#862 on main, the last issue from
end-to-end testing, still without a release: a parent URL ending in `/`
resolves from that directory, so an extensionless `--import ./setup` is found
and scripts run with the working directory at `/`. The resolve hook's
workaround for it is gone.

Other changes in the range:

- Byte scans use memchr and SIMD (#860, #863).
- Core watch reporting for `oxnode watch` (#861). The binding does not forward
  `enable_watch_report` yet, so `vpx --watch` is unchanged.
- oxc ^0.155.0 (#868), a manifest change only; patch-oxc-node points it at the
  workspace's 0.154.0, which Rolldown pins.

#861 adds a `yarn_pnp` feature, which the binding enables to match the
`oxc_resolver` feature the workspace turns on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@fengmk2

fengmk2 commented Oct 20, 2026

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

Reviewed commit: 2d68bab038

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@fengmk2 fengmk2 added test: e2e Auto run e2e tests test: install-e2e run vite install e2e test test: create-e2e Run `vp create` e2e tests test: sfw labels Oct 20, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

preview-build Publish this PR's commits to the registry bridge as preview builds test: create-e2e Run `vp create` e2e tests test: e2e Auto run e2e tests test: install-e2e run vite install e2e test test: sfw

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Runtime helpers resolve from the user's file, so a global oxnode fails with ERR_MODULE_NOT_FOUND

2 participants