24 Commits

Author SHA1 Message Date
Sankalp Mukim f6aedd3615 Add standalone self-host output and align init production scripts (#178)
* feat: add standalone self-host output for vinext build

Generate dist/standalone from output: 'standalone' with a runnable server entry and runtime deps, and align init scripts with vinext build/start for production self-host workflows.

* fmt

* Address bonk review: fix duplicate PHASE constant, complete lazy-chunks extraction, remove dead imports, add process.exit to standalone path

* Address bonk nits: document regex patterns, move PHASE re-exports to bottom, add assets field to BuildManifestChunk

* refactor(standalone): use Vite bundle graph for server externals instead of regex scan

Replace the fragile post-build regex scan of emitted JS files and the
package.json#dependencies over-seeding with a new
vinext:server-externals-manifest Vite plugin. The plugin collects
chunk.imports + chunk.dynamicImports from the SSR/RSC writeBundle hook
and writes dist/server/vinext-externals.json — the authoritative,
compiler-derived list of packages left external in the server bundle.

emitStandaloneOutput now reads this manifest as its sole seed for the
BFS node_modules copy, so standalone output only includes packages the
server actually imports at runtime. Removed collectServerExternalPackages,
walkFiles, the four regex constants, and the package.json deps seeding.

* fix(standalone): copy vinext runtime deps, add node_modules filter to cpSync, remove unused pendingWrites

* fix(standalone): address round-6 bonk nits — explicit root, manifest comment, pre-flight check, bare-specifier comment, export-from re-export

* fix(standalone): address round 7 bonk review comments

- harden outDir resolution in server-externals-manifest: replace fragile
  walk-up heuristic with direct basename check (ssr -> dirname, else dir),
  avoiding misfires when a user's project path contains a 'server' segment
- remove redundant 'chunk' alias in server-externals-manifest writeBundle;
  use 'item' directly after the type guard narrows it to OutputChunk
- add node_modules filter to vinext dist/ cpSync in standalone.ts, matching
  the same defensive filter used for app package copies
- rewrite standalone server.js as pure ESM using import.meta.dirname
  (Node >= 21.2, vinext requires >= 22); drop CJS require/__dirname and
  switch standalone package.json to 'type':'module'
- add explanatory comment for DEFAULT_PHASE constant in next-config.ts
- add comment in cli.ts noting pre-flight path and resolveVinextPackageRoot
  must stay in sync

* fix(standalone): address round 8 bonk review comments

- fix test import: use 'vite-plus/test' instead of 'vitest' in
  standalone-build.test.ts, matching the convention used by every other
  test file in the repo (documented in AGENTS.md)
- extract resolveVinextPackageRoot into utils/vinext-root.ts so cli.ts
  and standalone.ts share a single source of truth; removes the coupling
  comment added in round 7 and the duplicated path traversal logic
- add node_modules filter to dist/client and dist/server cpSync calls for
  defensive consistency with the vinext dist/ and package copies

* interface -> type

* fix(standalone): address round 9 bonk review comments

- add node_modules filter to public/ cpSync for defensive consistency
  with all other cpSync calls in emitStandaloneOutput
- warn on malformed vinext-externals.json instead of silently returning
  an empty list; includes the error string to aid debugging
- add doc comment on copyPackageAndRuntimeDeps clarifying that the return
  value is the full accumulated set (including pre-existing entries), not
  only packages copied by the current call
- document HOST (not HOSTNAME) env var in README standalone section, with
  a note explaining the difference from Next.js standalone behaviour

* fix(standalone): address round 10 bonk review comments

- add comment in writeStandaloneServerEntry explaining why the import of
  vinext/server/prod-server is intentional as a static import: it is a
  documented exports-map entry, always present in the copied dist tree,
  and a static import gives a clearer ERR_MODULE_NOT_FOUND at startup
- generalise outDir sub-directory detection in server-externals-manifest:
  replace basename === 'ssr' with basename !== 'server' so any future
  sub-directory environment (e.g. 'edge') is handled without code changes
- add JSDoc on runtimeDeps clarifying that it returns both dependencies
  and optionalDependencies

* fix(next-config): drop PHASE_DEVELOPMENT_SERVER from re-export

No external consumer imports it from next-config.ts — only
PHASE_PRODUCTION_BUILD is used externally (by cli.ts). Removing it
minimises the public surface area of the module.

---------

Co-authored-by: GPU VM <copilot-gpu-vm@example.com>
Co-authored-by: James <james@eli.cx>
2026-03-30 20:42:40 +01:00
Steve Faulkner a62e5c4901 chore(benchmarks): remove Vite 7 runner, update Next.js to 16.2.1 (#699)
* chore(benchmarks): remove Vite 7 runner, update Next.js to 16.2.1

The vinext-rolldown benchmark runner was identical to the vinext runner
(both resolved to the same Vite version via catalog), producing
duplicate results on the dashboard. Remove it entirely and simplify
to a two-runner comparison: Next.js (Turbopack) vs vinext (Vite 8).

Also bump the Next.js benchmark dependency from 16.1.7 to 16.2.1 to
pick up recent performance improvements.

* fix: remove vinext-rolldown from pnpm-workspace.yaml, fix migration comment
2026-03-27 19:23:50 -05:00
Stephen Zhou e683e0d84d feat: support inline next config (#649)
* feat: support inline next config

* Apply suggestion from @james-elicx

Co-authored-by: James Anderson <james@eli.cx>

* tweaks

---------

Co-authored-by: James Anderson <james@eli.cx>
2026-03-23 08:25:08 +00:00
Gentrit Biba fa03a06bea feat: optimize barrel imports for RSC-incompatible packages (#138)
* feat: add vinext:optimize-imports plugin for barrel import rewriting

Barrel imports like `import { Slot } from "radix-ui"` cause RSC crashes
because Vite eagerly evaluates all re-exported sub-packages, some of which
call React.createContext() — unavailable in the react-server condition.

This plugin rewrites barrel imports into direct sub-module imports on the
server, matching Next.js's optimizePackageImports behavior:

- Parses barrel entry files to build export maps (namespace, named,
  default re-exports, and import-then-export patterns)
- resolveId hook handles pnpm strict hoisting via Vite's own resolver
- Only runs on server environments; client uses Vite's dep optimizer
- Lazy-initialized Set<string> for O(1) package lookups
- Respects experimental.optimizePackageImports from next.config
- Includes Next.js default package list plus radix-ui

Closes cloudflare/vinext#100
Closes cloudflare/vinext#137

* fix: add missing packages to DEFAULT_OPTIMIZE_PACKAGES

Add the full effect ecosystem (17 packages) and all react-icons/*
sub-packages (32 packages) to match Next.js's built-in defaults.

* fix: address bonk review — entryPathCache, buildStart init, Windows path fix, trailing semicolons, fixture-based transform tests

* fix: correct bySource grouping for mixed namespace+named imports, clear barrelCaches on rebuild

- Key bySource map on `${source}::${isNamespace}` instead of just source
  so that a namespace re-export and a named re-export from the same sub-module
  produce two separate import statements rather than one corrupted one.
  Caught by the new 'produces separate statements for namespace and named
  imports from the same source' test.
- Clear barrelCaches.exportMapCache and barrelCaches.subpkgOrigin in buildStart
  alongside entryPathCache so stale barrel analysis doesn't survive rebuilds.
- Add regression test for the mixed namespace+named grouping bug.

* fix: resolve relative barrel re-export paths to absolute, emit default imports for default re-exports

Barrels like lodash-es and lucide-react use relative re-export paths
(e.g. `export { chunk } from './chunk.js'`). Writing those verbatim caused
Vite to resolve './chunk.js' against the importing user file rather than
the barrel package directory.

Fix: resolve any relative source path against the barrel entry's directory
before emitting the replacement import statement, producing an absolute
filesystem path that Vite resolves correctly regardless of where the
importing file lives.

Also fix: `export { default as X }` re-exports now produce `import X from`
(a default import) instead of `import { default as X }` (invalid syntax
that only works via ASI / bundler leniency).

Tests updated to assert absolute paths and added a dedicated test for
default re-export handling.

* refactor: extract barrel optimization to plugins/optimize-imports.ts, add Windows path fix and react-server TODO

- Move all barrel types, helpers, DEFAULT_OPTIMIZE_PACKAGES, and the
  vinext:optimize-imports IIFE from index.ts into a new
  packages/vinext/src/plugins/optimize-imports.ts file with a factory
  function createOptimizeImportsPlugin(getNextConfig, getRoot)
- Forward-slash normalize resolved absolute paths so emitted import
  statements use '/' separators on Windows (path.sep join)
- Add TODO comment in resolveExportsValue noting that the 'react-server'
  condition should be added in a future pass
- Add test for ImportDefaultSpecifier: import MyFoo from 'pkg' rewrites
  to import MyFoo from '<abs>/sub' (22 tests total, all passing)

* fix(optimize-imports): address sixth-pass review comments

- Fix astName() to throw on unexpected nodes instead of String(value)
- Normalize all resolvePackageEntry return values to forward slashes (Windows fix)
- Fix originalName falsy guard: && → !== undefined
- Pre-build quotedPackages in buildStart to avoid per-file template literal allocations
- Add first-wins comment on subpkgOrigin registration
- Add clarifying comment to lucide-react test fixture

* fix(optimize-imports): remove EnvironmentPluginContext cast, expand subpkgOrigin comment

Vite augments rolldown's MinimalPluginContext with `environment: Environment`
via declaration merging, so both resolveId and transform have `this.environment`
typed without any cast. Drop the EnvironmentPluginContext interface and the
`as unknown as EnvironmentPluginContext` cast in the transform handler, using
direct `this.environment` access consistently with resolveId.

Also expand the subpkgOrigin first-wins comment to make explicit why first-wins
is safe: the sub-package specifier resolves to the same path regardless of which
barrel's importer context is used.

* fix(optimize-imports): address seventh-pass review nits

- Fix test imports: vitest → vite-plus/test, Plugin from vite → vite-plus,
  following the convention used by 82 of 85 test files in this repo
- Add TODO comment for extensionless absolute paths produced when barrel
  sources lack file extensions (Vite resolves these correctly in practice)
- Expand subpkgOrigin first-wins comment to explicitly note the nested
  node_modules edge case and why it is out of scope for the default list

* fix(optimize-imports): address james-elicx review comments

- Support wildcard re-exports (export * from './sub') by recursively
  parsing sub-modules and merging their exports into the barrel map
- Add circular-reference guard to prevent infinite loops in recursive
  export map building
- Refactor buildBarrelExportMap into buildExportMapFromFile helper
  with shared recursive logic
- Use switch statements for spec.type handling instead of if-else chains
- Remove non-null assertions and type assertions; use optional chaining
  and typeof guards throughout
- Extract resolvePackageInfo helper to separate concerns in
  resolvePackageEntry
- Tests now import directly from optimize-imports.ts instead of via
  the full vinext() plugin array
- Remove _buildBarrelExportMap re-export from index.ts (no longer needed
  since the plugin has its own file)
- Fix type assertion for optimizePackageImports in next-config.ts using
  a proper type-guard filter
- Apply README nit: 'is always optimized' → 'are always optimized'
- Add tests for wildcard export resolution, no-overwrite semantics,
  and circular re-export safety

* fix(optimize-imports): address ask-bonk review comments

- Resolve relative sources to absolute paths inside buildExportMapFromFile
  so nested wildcard re-exports (e.g. antd-style components/) resolve against
  the correct sub-module directory instead of the barrel root
- Add react-server condition to resolveExportsValue (before node/import) for
  RSC-compatible entry points in packages like react and react-dom
- Add NOTE comment in resolvePackageEntry documenting that only exports["."]
  is checked, not subpath exports
- Eliminate double readFile call in buildBarrelExportMap by passing the
  already-read content to buildExportMapFromFile via new initialContent param
- Update subpkgOrigin guard to check for absolute paths (not startsWith ".")
  since relative sources are now stored as absolute paths in the export map
- Add test for nested subdirectory wildcard path resolution correctness
- Update existing unit tests to expect absolute paths in export map entries

* fix(optimize-imports): only prefer react-server condition in RSC environment

SSR renders with the full React runtime and must not resolve react-server
export condition entries. Thread preferReactServer (env.name === 'rsc')
through resolveExportsValue and resolvePackageEntry, and key entryPathCache
by environment prefix to keep RSC and SSR barrel entries separate.

* fix(optimize-imports): address review nits — TODO comment, type annotation, test names, wildcard dir test

- Add TODO comment on allResolved bail-out suggesting debug logging
- Remove redundant ': string[]' annotation on optimizePackageImports (inferred)
- Rename namespace re-export test to use generic X/barrel names instead of Slot/lucide-react
- Update syntax-error test to match new empty-map-on-parse-error behavior (not null)
- Add test for directory-style 'export * from "./components"' where components/index.js exists

* fix(optimize-imports): address review nits — wildcard extensions, double-read, readFile hoisting, subpkg registration guard

- Add /index.mjs, /index.tsx, and .tsx to wildcard candidate list for ESM-first and TypeScript-first packages
- Pass candidateContent to buildExportMapFromFile in wildcard loop to avoid reading each sub-module file twice
- Add comment clarifying the no-op resolveEntry callback pattern
- Hoist readFileSafe closure outside the import-declaration for-loop (one allocation per transform, not per barrel import)
- Gate subpkgOrigin registration loop with registeredBarrels Set so 50 files importing the same barrel don't each iterate the full export map

* fix(optimize-imports): remove redundant double-cache, extract PluginCtx type alias

- Remove the redundant exportMapCache.set() in buildBarrelExportMap — buildExportMapFromFile
  already stores the result under the same key; the extra set was a no-op but misleading
- Extract PluginCtx type alias for the environment cast so all three hook sites share one
  definition and the verbose inline cast doesn't repeat across resolveId and transform

* fix(optimize-imports): hoist readFileSafe to module level, add namespace import test

- Move readFileSafe from handler scope to module level since it captures
  nothing from the per-file closure; avoids a per-call function allocation
- Add test verifying import * as Pkg from 'barrel' is left unchanged
  (ImportNamespaceSpecifier sets allResolved = false — can't optimize a
  full namespace import to a sub-module)

* fix(optimize-imports): make barrel resolution async, add debug logging, update tests

* fix(optimize-imports): address review feedback — extensions, env-keyed subpkgOrigin, debug gate, graceful astName

* fix: scope registeredBarrels key to env to prevent RSC registration blocking SSR

When RSC and SSR resolve the same barrel entry path (common — most packages
have no react-server export condition), the bare barrelEntry key in
registeredBarrels caused RSC's registration to suppress SSR's inner loop
entirely. SSR's subpkgOrigin map was left empty, making resolveId depend
solely on the cross-env fallback — fragile coupling that could silently break.

Change the registeredBarrels key from barrelEntry to `${envKey}:barrelEntry`
so each environment runs the inner loop and populates its own subpkgOrigin
map independently. Matches the existing entryPathCache key pattern.

Add a regression test covering the shared-barrel-entry scenario.

* fix: handle inline export declarations in barrel sub-modules (date-fns)

date-fns barrels use `export * from "./formatDistanceToNow.js"` where the
sub-module directly declares `export function formatDistanceToNow(...) {}`.
buildExportMapFromFile only handled ExportNamedDeclaration with a source
(re-exports) or specifiers (local re-bindings) — it silently skipped inline
declarations (export function/class/const/let/var), leaving the name absent
from the export map and causing the plugin to log "skipping: could not
resolve specifier" and leave the barrel import unchanged.

Handle the declaration branch: FunctionDeclaration and ClassDeclaration
contribute their id.name; VariableDeclaration iterates all declarators.
The source for inline declaration entries is the sub-module file itself.

Also extend AstBodyNode.declaration typing from `unknown` to the minimal
shape covering all three declaration kinds.

Add three unit tests covering export function, export const (multiple
declarators), and export class; all 38 tests pass.

* refactor: remove DEBUG-gated logging from optimize-imports plugin

* refactor: always emit skip log without DEBUG env gating

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: James <james@eli.cx>
2026-03-21 15:18:54 +00:00
Steve Faulkner 9c2fd26990 docs: update Vite 8 guidance (#596) 2026-03-19 20:44:29 -05:00
Stephen Zhou 25f6e0fc87 chore: enable typeAware and typeCheck, use vp check (#551)
* chore: enable typeAware and typeCheck, use vp check

* Build

* Try cache false

* Revert "Try cache false"

This reverts commit 5f76ed02f1.

* Update

* workaround for vp check

* Try no workaround

* Fix check

* Update to 0.1.12

* denyWarnings
2026-03-16 11:00:47 -05:00
Stephen Zhou 62910e80e9 chore: move to vp pack, merge vitest config (#550)
* chore: migrate to vp pack

* No copy

* Move test

* Update tsconfig
2026-03-15 11:58:42 +00:00
Stephen Zhou 21558f3092 feat: support @vitejs/plugin-react v6 as peer (#525)
* feat: support @vitejs/plugin-react v6 as peer

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update

* Update
2026-03-13 15:35:36 +00:00
James Anderson 764a496ce7 add oxfmt formatter (#380)
* add oxfmt formatter: config, scripts, CI, editor setup, docs

* rebuild lockfile

* fix: add Format to required checks list, remove dead ignore pattern

* run fmt

* add format to agents.md again
2026-03-09 14:56:14 +00:00
James Anderson 23a5cb2ceb refactor: delete app-dev-server.ts, point all callers at entries/ directly (#253 batch 3) (#379)
* refactor: delete app-dev-server.ts and update all references to entries/ directly

The file was already a pure re-export shim with no logic of its own.
Update every import/dynamic-import site to point straight at the
individual entry modules:

  entries/app-rsc-entry.ts    ← generateRscEntry, AppRouterConfig
  entries/app-ssr-entry.ts    ← generateSsrEntry
  entries/app-browser-entry.ts ← generateBrowserEntry

Sites updated:
  packages/vinext/src/index.ts
  tests/entry-templates.test.ts
  tests/app-router.test.ts
  tests/shims.test.ts

Also update stale comments in:
  server/middleware-codegen.ts, server/request-pipeline.ts,
  server/instrumentation.ts, shims/metadata.tsx,
  tests/rsc-streaming.test.ts, tests/nextjs-compat/rsc-context-lazy-stream.test.ts,
  examples/app-router-cloudflare/instrumentation*.ts

* docs: update app-dev-server.ts references in markdown files to entries/
2026-03-09 14:11:07 +00:00
James Anderson 70b18536ab fix: warn when existing vite.config.ts is missing cloudflare plugin on deploy (#315)
* fix: warn when existing vite.config.ts is missing cloudflare plugin on deploy

Closes #312.

- Add `viteConfigHasCloudflarePlugin()` to deploy.ts: when `vinext deploy`
  finds an existing vite.config.ts that doesn't import @cloudflare/vite-plugin,
  it now prints an actionable warning with the exact config fix rather than
  silently proceeding to a broken build.
- Add README prerequisites section to the Cloudflare Workers deploy docs:
  covers wrangler login vs CLOUDFLARE_API_TOKEN (with required permissions)
  and how to supply account_id.
- Add 7 unit tests for `viteConfigHasCloudflarePlugin()`.

* fix: pages router warning shows cloudflare() not cloudflare(())
2026-03-07 14:50:58 +00:00
Abdel d21d541fbc fix typo in README.md (#248) 2026-03-04 17:23:03 +00:00
Steve Faulkner 719dd306e8 docs: document Cloudflare bindings and Nitro multi-platform deployment (#231)
Rework the README deployment section into two clear paths:
- Cloudflare Workers (native) with cloudflare:workers bindings docs
- Other platforms (via Nitro) with collapsible examples for Vercel,
  Netlify, AWS, Deno, Node.js

Frame vinext as 'works everywhere' with Cloudflare as the first native
target and more native adapters planned (#80). Update the agent skill
and config references with the same guidance.
2026-03-03 03:04:40 +00:00
Steve Faulkner 9a6c8a7ba6 Run safe CI for external contributors, add /deploy-preview slash command (#201)
* Skip deploy previews for fork PRs that lack Cloudflare secrets

Fork PRs don't have access to repository secrets (CLOUDFLARE_API_TOKEN,
CLOUDFLARE_ACCOUNT_ID), so deploy/smoke-test/comment steps always fail.
Add a fork detection condition to skip these steps gracefully. The build
steps still run, so example builds are still validated for fork PRs.

* Run safe CI for external contributors, add /deploy-preview slash command

Switch ci.yml from pull_request to pull_request_target so lint, typecheck,
vitest, and e2e run automatically for fork PRs without needing approval.
No secrets are used, so this is safe with untrusted code.

Add a /deploy-preview slash command workflow that lets maintainers trigger
deploy previews on fork PRs. Gated by author_association (org members,
collaborators, repo owners only).

Cloudflare employees who push branches to the main repo continue to get
automatic deploy previews via the existing deploy-examples.yml workflow.

* Revert ci.yml to pull_request, skip deploy-examples for fork PRs

Simpler approach: keep ci.yml on pull_request (first-time contributor
approval is fine, avoids cache poisoning concern with pull_request_target).

The actual fix: add a job-level if condition to deploy-examples.yml so the
entire workflow is skipped for fork PRs. This prevents the noisy
failed/skipped deploy checks on external contributor PRs.

Update docs in AGENTS.md and README.md to reflect the approach.
2026-02-28 16:04:03 -06:00
Steve Faulkner 9939063998 Clarify OpenNext language in README (#166) 2026-02-27 10:42:15 -06:00
Fred K. Schott a498012970 Update README with new project setup instructions
Added instructions for starting a new vinext project.
2026-02-26 23:57:30 -08:00
Steve Faulkner 8dac26c0e5 fix(dotenv): load .env files with Next.js precedence (#70)
* feat(cli): load .env files with Next.js precedence

* fix(dotenv): address review feedback on .env loading

- Document Vite double-loading interaction in loadDotenv JSDoc
- Fix escaped dollar sign bug ($100 was not unescaped when $ wasn't
  followed by a valid variable name)
- Add type cast for parseEnv return value
- Expand test coverage: loadedEnv assertions, production mode
  precedence, ${VAR} expansion, escaped dollars, circular refs,
  missing files, empty result
- Add getDotenvFiles unit tests for all three modes
- Add 'Prefer Node.js Built-in APIs' guideline to AGENTS.md

Co-authored-by: liuxiaopai-ai <liuxiaopai-ai@users.noreply.github.com>

* test(dotenv): add cross-file expansion and multi-line value tests

Address review suggestions: test that .env can reference vars from
higher-priority .env.development.local, and that parseEnv handles
quoted multi-line values correctly.

---------

Co-authored-by: root <root@localhost.localdomain>
Co-authored-by: liuxiaopai-ai <liuxiaopai-ai@users.noreply.github.com>
2026-02-25 14:21:48 -06:00
Skywalker512 cb15a16aaa fix: link to Vite RSC plugin in README (#39)
Updated the link for the Vite RSC plugin to point to the correct repository.
2026-02-25 10:55:21 -06:00
Steve Faulkner 05ef04788c feat(deploy): add --env support with security and parsing improvements (#49)
* feat(deploy): add --env support for wrangler deploy

Adds vinext deploy --env <name> and threads it through to wrangler deploy --env <name>. Keeps --preview working as shorthand for preview environment, adds unit tests for wrangler arg construction, and updates README/help examples. Refs #33.

* fix(deploy): use execFileSync and util.parseArgs for --env support

Build on #44 by liuxiaopai-ai — adds --env flag for wrangler deploy.

Security: switch from execSync(shell string) to execFileSync(binary, args)
to eliminate command injection via unsanitized --env/--name values.

Replace hand-rolled flag parsing (parseStringFlag, parseNumericFlag,
rawArgs.includes) with Node.js built-in util.parseArgs. This gives us
strict mode (throws on unknown flags), automatic --flag=value handling,
and proper error messages for missing values.

Also: buildWranglerDeployArgs now returns { args, env } directly instead
of re-parsing the args array for the log message.

---------

Co-authored-by: root <root@localhost.localdomain>
2026-02-25 06:57:44 -06:00
Marcus Reinhardt 9f5550579e fix vite-rsc link (#20) 2026-02-24 22:35:25 -06:00
Steve Faulkner 197f42106a docs: add LICENSE, sync package README, add bug reporting guidance (#26)
* docs: update README — add blog link, lead with agent skill, fix examples, remove stale benchmarks

* docs: add LICENSE, sync package README from root, add bug reporting guidance

- Add MIT LICENSE to repo root
- Copy root README into package at prepack time instead of maintaining two copies
- Add 'Reporting bugs' section encouraging AI-assisted diagnosis

* fix: update LICENSE copyright to Cloudflare, Inc.
2026-02-24 15:40:12 -06:00
Steve Faulkner 2c732add55 docs: update README — add blog link, lead with agent skill, fix examples, remove stale benchmarks (#19) 2026-02-24 20:11:37 +00:00
Matt Silverlock 009ace26bf add migrate-to-vinext agent skill (#6)
* add migrate-to-vinext agent skill

* Apply suggestion from @elithrar

* remove .claude/skills in favor of .agents/skills
2026-02-24 16:53:38 +00:00
Steve Faulkner 12fea722b6 Initial public release of vinext 2026-02-24 09:29:39 -06:00