Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions .agents/skills/migrate-to-rstack-cli/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
name: migrate-to-rstack-cli
description: Use when migrating projects from standalone Rsbuild, Rslib, Rstest, Rslint, Rspress, or lint-staged tooling to the unified `rstack` package, `rs` commands, and `rstack.config.*`.
---

# Migrate to Rstack CLI

Rstack CLI is the `rstack` package, exposed through the `rs` binaries. It provides one CLI, one config file, and a consistent workflow for the Rstack JavaScript toolchain.

## Tool References

Read every matching reference before editing. Load only the tools present in the project.

- `@rsbuild/core`, `rsbuild.config.*`, `rsbuild` commands, or Rsbuild types: [rsbuild.mdx](references/rsbuild.mdx)
- `@rslib/core`, `rslib.config.*`, `rslib` commands, or Rslib types: [rslib.mdx](references/rslib.mdx)
- `@rstest/core`, `@rstest/adapter-*`, `rstest.config.*`, `rstest` commands, or test imports: [rstest.mdx](references/rstest.mdx)
- `@rslint/core`, `rslint.config.*`, `rslint` commands, or lint imports: [rslint.mdx](references/rslint.mdx)
- `@rspress/core`, `rspress.config.*`, `rspress` commands, themes, or plugins: [rspress.mdx](references/rspress.mdx)
- `lint-staged`, its dotfile configs, `lint-staged.config.*`, or a `lint-staged` manifest key: [lint-staged.mdx](references/lint-staged.mdx)

## Workflow

1. Inspect manifests, workspace catalogs, lock files, scripts, standalone configs, Git hooks, TypeScript `types`, and source imports.
2. Read the matching references and inventory behavior that must survive: config functions, CLI arguments, plugins, presets, adapters, custom config paths, and chained commands.
3. Check the latest `rstack` version and inspect its Node.js engine and underlying tool versions. Resolve plugin and adapter peer ranges first; upgrade incompatible extensions or stop when no compatible version exists. Add `rstack` using the repository's existing package manager and version convention, usually as a development dependency.
4. Create `rstack.config.ts`. Move each standalone config into its corresponding `define.*` registration.
5. Rewrite commands and imports as directed by the references.
6. Search again for old direct imports, binaries, config paths, manifest entries, and type references. Remove only entries with no remaining direct or runtime use and no unresolved peer compatibility requirement.
7. Delete a standalone config only after its behavior is represented in `rstack.config.*`.
8. Refresh the lockfile with the repository's package manager. Confirm the expected tool version changes and resolve peer dependency warnings.
9. Run the repository's existing migrated scripts and required checks. Compare generated artifacts or runtime behavior where relevant.

Underlying Rsbuild, Rslib, Rstest, and Rslint packages remain transitive dependencies of `rstack`. Do not require their names to disappear from the lockfile; require obsolete direct manifest entries and imports to disappear.

## Configuration Rules

Use one of the default names: `rstack.config.ts`, `.js`, `.mts`, or `.mjs`. Use `rs -c <path>` or `rs --config <path>` for a custom path.

```ts
import { define } from 'rstack';

define.app({
// Rsbuild config
});

define.test({
// Rstest config
});
```

Prefer async config functions and dynamic imports for runtime plugins and presets:

```ts
define.lint(async () => {
const { js, ts } = await import('rstack/lint');
return [js.configs.recommended, ts.configs.recommended];
});
```
25 changes: 25 additions & 0 deletions .agents/skills/migrate-to-rstack-cli/references/lint-staged.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# lint-staged Migration

Read this reference when the project uses the `lint-staged` binary, a lint-staged dotfile config, `lint-staged.config.*`, or a `lint-staged` key in `package.json`.

## Steps

1. Replace direct `lint-staged` script invocations with `rs staged`.
2. Move a plain task map into `define.staged` in `rstack.config.*`.
3. Remove the old manifest key or config file.
4. Remove the direct `lint-staged` dependency only when no script, config, or programmatic API still uses it.

## Config Pattern

```ts
import { define } from 'rstack';

define.staged({
'*.{ts,tsx,js,jsx}': ['rs lint --fix', 'prettier -w'],
'*.{json,md}': 'prettier -w',
});
```

## Unsupported Cases

Do not carry lint-staged CLI flags to `rs staged`; they are not forwarded. Keep standalone lint-staged when the workflow requires function-based configs, CLI options, or behavior outside a plain task map.
35 changes: 35 additions & 0 deletions .agents/skills/migrate-to-rstack-cli/references/rsbuild.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Rsbuild Migration

Read this reference when the project uses `@rsbuild/core`, `rsbuild.config.*`, `rsbuild` commands, Rsbuild client types, or `@rsbuild/core/types`.

## Steps

1. Replace `rsbuild dev`, `rsbuild build`, and `rsbuild preview` with `rs dev`, `rs build`, and `rs preview`. Preserve supported arguments after the new command.
2. Move the old config export into `define.app`. Preserve async functions, config parameters, plugins, and all options.
3. Replace custom `--config` paths with the migrated `rstack.config.*` path.
4. Replace Rsbuild client and type references:
- `/// <reference types="@rsbuild/core/types" />` to `/// <reference types="rstack/types" />`
- `"types": ["@rsbuild/core/types"]` to `"types": ["rstack/types"]`
- Type-only imports from `@rsbuild/core/types` to `rstack/types`
5. Keep Rsbuild plugins such as `@rsbuild/plugin-react` and `@rsbuild/plugin-vue`, but verify that their peer ranges support the `@rsbuild/core` version installed through `rstack`. Upgrade incompatible plugins before migrating; retaining an older direct core does not make Rstack use it.
6. Search for remaining direct `@rsbuild/core` imports. Remove the direct dependency when no source or runtime API still needs it.
7. Delete `rsbuild.config.*` after the migrated app commands load equivalent config.

## Config Pattern

```ts
import { define } from 'rstack';

define.app(async () => {
const { pluginReact } = await import('@rsbuild/plugin-react');
return {
plugins: [pluginReact()],
};
});
```

If tests also use Rstest, read [rstest.mdx](rstest.mdx). `rs test` derives an Rsbuild test extension from `define.app` unless `define.test` sets `extends`.

## Validate

Run the migrated app build script. Smoke-test dev or preview when those scripts changed or their behavior is material.
29 changes: 29 additions & 0 deletions .agents/skills/migrate-to-rstack-cli/references/rslib.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Rslib Migration

Read this reference when the project uses `@rslib/core`, `rslib.config.*`, `rslib` commands, library build config, or Rslib type imports.

## Steps

1. Replace the `rslib` executable prefix with `rs lib`. Preserve supported arguments after `rs lib`.
2. Move the old config export into `define.lib`. Preserve async functions, config parameters, plugins, and all options.
3. Keep build plugins, but verify that Rsbuild plugin peer ranges support the core version installed through `rstack`. Upgrade incompatible plugins before migrating.
4. Replace `@rslib/core/types` references with `rstack/types` where applicable.
5. Replace custom `--config` paths with the migrated `rstack.config.*` path.
6. Search for remaining direct `@rslib/core` imports. Remove the direct dependency only when no source or runtime API still needs it.
7. Delete `rslib.config.*` after the migrated library commands load equivalent config.

## Config Pattern

```ts
import { define } from 'rstack';

define.lib({
lib: [{ dts: true }],
});
```

If tests also use Rstest, read [rstest.mdx](rstest.mdx). `rs test` derives an Rslib test extension from `define.lib` unless `define.test` sets `extends`.

## Validate

Run the migrated library build script and compare its outputs.
37 changes: 37 additions & 0 deletions .agents/skills/migrate-to-rstack-cli/references/rslint.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Rslint Migration

Read this reference when the project uses `@rslint/core`, `rslint.config.*`, `rslint` commands, or Rslint config imports.

## Steps

1. Replace the `rslint` executable prefix with `rs lint`. For example, replace `rslint --fix` with `rs lint --fix`.
2. Move the old config into `define.lint`. Dynamically import presets from `rstack/lint` inside an async config function.
3. Replace direct config/API imports from `@rslint/core` with exports from `rstack/lint` where available.
4. Replace custom `--config` paths with the migrated `rstack.config.*` path.
5. Remove `@rslint/core` only when no uncovered direct runtime API remains. Delete `rslint.config.*`.

## Config Pattern

```ts
import { define } from 'rstack';

define.lint(async () => {
const { js, ts } = await import('rstack/lint');
return [js.configs.recommended, ts.configs.recommended];
});
```

## Script Pattern

```json
{
"scripts": {
"lint": "rs lint && prettier -c .",
"lint:write": "rs lint --fix && prettier -w ."
}
}
```

## Validate

Run the non-writing lint script.
29 changes: 29 additions & 0 deletions .agents/skills/migrate-to-rstack-cli/references/rspress.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Rspress Migration

Read this reference when the project uses `@rspress/core`, `rspress.config.*`, `rspress` commands, docs config, themes, or plugins.

## Steps

1. Keep `@rspress/core` installed as a direct dependency. `rs doc` requires this optional Rstack peer dependency.
2. Replace the `rspress` executable prefix with `rs doc`: `rspress dev` to `rs doc`, `rspress build` to `rs doc build`, and `rspress preview` to `rs doc preview`. Preserve supported arguments.
3. Move the old config export into `define.doc`. Preserve async functions, themes, plugins, and all options.
4. Replace custom `--config` paths with the migrated `rstack.config.*` path.
5. Keep Rspress-specific type imports from `@rspress/core`; Rstack does not re-export them.
6. Keep themes, plugins, and docs UI packages. Delete `rspress.config.*` only after the migrated docs commands load equivalent config.

## Config Pattern

```ts
import { define } from 'rstack';

define.doc({
root: 'docs',
title: 'Project docs',
});
```

Use an async config and dynamic imports when plugins or themes require runtime imports.

## Validate

Run the migrated docs build script. Smoke-test dev or preview when those workflows changed.
31 changes: 31 additions & 0 deletions .agents/skills/migrate-to-rstack-cli/references/rstest.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Rstest Migration

Read this reference when the project uses `@rstest/core`, `@rstest/adapter-rsbuild`, `@rstest/adapter-rslib`, `rstest.config.*`, `rstest` commands, or Rstest imports and types.

## Steps

1. Replace the `rstest` executable prefix with `rs test`. Preserve supported arguments, such as `-w`, after `rs test`.
2. Move test options into `define.test`.
3. When `define.app` or `define.lib` exists, remove standard `withRsbuildConfig()` or `withRslibConfig()` wiring and its adapter dependency. Rstack derives that extension unless `define.test` sets `extends`.
4. Preserve explicit custom `extends` values. Keep any adapter or package still imported by that custom extension.
5. Replace imports and TypeScript `types` entries:
- `@rstest/core` to `rstack/test`
- `@rstest/core/globals` to `rstack/test/globals`
- `@rstest/core/importMeta` to `rstack/test/importMeta`
6. Search for remaining direct core or adapter imports. Remove `@rstest/core` and adapter dependencies only when no direct use remains.
7. Delete `rstest.config.*` after all behavior is represented or intentionally supplied by automatic app/library extension.

## Config Pattern

```ts
import { define } from 'rstack';

define.test({
setupFiles: ['./tests/setup.ts'],
testEnvironment: 'happy-dom',
});
```

## Validate

Run the migrated test script.