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
87 changes: 10 additions & 77 deletions .agents/skills/rstack-cli-best-practices/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,92 +1,25 @@
---
name: rstack-cli-best-practices
description: Guidance on using Rstack CLI, including `rs` commands, the `rstack.config.ts` file, and import paths from the `rstack` package. Use for Rstack CLI-related tasks.
description: Guidance for Rstack CLI work involving `rs` commands, `rstack.config.*`, package APIs, or Rstack-based projects and tooling.
---

# Rstack CLI Best Practices

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.
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.

It covers web app, library, docs, test, lint, formatting, Git hook, and staged-file workflows.

## Commands
## ALWAYS read installed docs before working

Use `rs -h` for top-level help, and `rs <command> -h` for command help where supported.
Before any Rstack work, find and read the relevant Markdown documentation shipped with the installed `rstack` package.

| Command | Purpose | Underlying tool | Config |
| ------------ | -------------------------------- | --------------- | --------------- |
| `rs dev` | Run the app dev server | Rsbuild | `define.app` |
| `rs build` | Build the app for production | Rsbuild | `define.app` |
| `rs preview` | Preview the app production build | Rsbuild | `define.app` |
| `rs lib` | Build a library | Rslib | `define.lib` |
| `rs doc` | Serve or build docs | Rspress | `define.doc` |
| `rs test` | Run tests | Rstest | `define.test` |
| `rs lint` | Lint code | Rslint | `define.lint` |
| `rs fmt` | Format code | Prettier | `define.fmt` |
| `rs setup` | Install project-local Git hooks | None | None |
| `rs staged` | Run tasks on staged Git files | lint-staged | `define.staged` |
Model knowledge can be outdated; the installed documentation is the source of truth for the project's Rstack version.

Key behavior:
1. Start with `node_modules/rstack/dist/docs/llms.txt`, then read only the linked pages relevant to the task before proposing or making changes.

- Unless `define.test` already sets `extends`, `rs test` extends `define.app` through `@rstest/adapter-rsbuild` or falls back to `define.lib` through `@rstest/adapter-rslib`. The app config takes precedence when both are defined.
- `rs doc` requires the optional `@rspress/core` dependency.
2. For exact CLI flags and behavior, also run `rs -h` or `rs <command> -h` when supported.

## rstack.config.ts
If the bundled docs are not available at that path, locate the installed `rstack` package.

Rstack CLI loads `rstack.config.{ts,js,mts,mjs}` by default.

Register config with `define.*`:

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

define.app({
// Rsbuild config for `rs dev`, `rs build`, and `rs preview`
});

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

- `define.app(config)`: Rsbuild config for `rs dev`, `rs build`, and `rs preview`. Docs: https://rsbuild.rs/config/
- `define.lib(config)`: Rslib config for `rs lib`; Docs: https://rslib.rs/config/
- `define.doc(config)`: Rspress config for `rs doc`; Docs: https://rspress.rs/api/config/config-basic
- `define.test(config)`: Rstest config for `rs test`; Docs: https://rstest.rs/config/
- `define.lint(config)`: Rslint config for `rs lint`; Docs: https://rslint.rs/config/
- `define.fmt(config)`: Formatting options for `rs fmt`.
- `define.staged(config)`: lint-staged config for `rs staged`; accepts `Record<string, string | string[]>`.

### Lazy Configuration

Prefer async functions with dynamic imports for dependencies. Avoid top-level sync imports of heavy dependencies in `rstack.config.ts`.

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

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

## Import Paths

Prefer Rstack-exported paths:

| Instead of | Prefer |
| ------------------------- | ------------------------ |
| `@rsbuild/core` | `rstack/app` |
| `@rslib/core` | `rstack/lib` |
| `@rstest/core` | `rstack/test` |
| `@rslint/core` | `rstack/lint` |
| `@rsbuild/core/types` | `rstack/types` |
| `@rslib/core/types` | `rstack/types` |
| `@rstest/core/globals` | `rstack/test/globals` |
| `@rstest/core/importMeta` | `rstack/test/importMeta` |

## Git Hooks

Use [`rs setup`](https://rstack.rs/guide/cli/setup) for project-local Git hooks, commonly with `rs staged` in a `pre-commit` hook.
If they are still unavailable, verify that `rstack` is installed, and use CLI help plus the online [Rstack documentation](https://rstack.rs/) as a fallback.
10 changes: 8 additions & 2 deletions scripts/prepare-release.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env node
import { spawn } from 'node:child_process';
import { copyFile, mkdir, readdir, rm } from 'node:fs/promises';
import { copyFile, mkdir, readFile, readdir, rm, writeFile } from 'node:fs/promises';
import path from 'node:path';

const rootDir = path.resolve(import.meta.dirname, '..');
Expand Down Expand Up @@ -71,4 +71,10 @@ for (const relativePath of markdownFiles) {
await copyFile(path.join(websiteDistDir, relativePath), destination);
}

console.log(`Copied ${markdownFiles.length} English Markdown files to ${packageDocsDir}.`);
const llmsTxt = await readFile(path.join(websiteDistDir, 'llms.txt'), 'utf8');
const packageLlmsTxt = llmsTxt.replace(/\]\(\/(?!\/)/g, '](./');
Comment thread
chenjiahan marked this conversation as resolved.
await writeFile(path.join(packageDocsDir, 'llms.txt'), packageLlmsTxt);

console.log(
`Copied ${markdownFiles.length} English Markdown files and llms.txt to ${packageDocsDir}.`,
);