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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ It also covers local development needs outside Rstack's scope, with Oxfmt format
| `rs lib` | Build library | [Rslib](https://github.com/web-infra-dev/rslib) |
| `rs doc` | Serve or build docs | [Rspress](https://github.com/web-infra-dev/rspress) |
| `rs fmt` | Format code (TODO) | [Oxfmt](https://github.com/oxc-project/oxc) |
| `rs setup` | Set up Git hooks (TODO) | - |
| `rs setup` | Install Git hooks | - |
| `rs staged` | Run tasks on staged Git files | [lint-staged](https://github.com/lint-staged/lint-staged) |

Rstack CLI fits into your existing project workflow. It does not replace your runtime, package manager, or task runner, such as [pnpm](https://github.com/pnpm/pnpm), [Bun](https://github.com/oven-sh/bun), [Turborepo](https://github.com/vercel/turborepo), [Nx](https://github.com/nrwl/nx), and [Nub](https://github.com/nubjs/nub).
Expand Down
2 changes: 1 addition & 1 deletion website/docs/en/guide/cli/_meta.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
["dev", "build", "preview", "lib", "doc", "test", "lint", "staged"]
["dev", "build", "preview", "lib", "doc", "test", "lint", "setup", "staged"]
197 changes: 197 additions & 0 deletions website/docs/en/guide/cli/setup.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
# setup

import { PackageManagerTabs } from '@rspress/core/theme';

The `rs setup` command installs project-local [Git hooks](https://git-scm.com/docs/githooks) in the current repository.

## Usage

```bash
rs setup [options]
```
Comment thread
chenjiahan marked this conversation as resolved.

By default, project hook scripts are stored in `.rstack/hooks`. If the current directory is not inside a Git repository, the command skips installation.

Add `rs setup` to the `prepare` script in the root `package.json` to automatically generate hook files when dependencies are installed:

```json title="package.json"
{
"scripts": {
"prepare": "rs setup"
}
}
```

Run the script once to generate the hook files:

<PackageManagerTabs
command={{
npm: 'npm run prepare',
yarn: 'yarn run prepare',
pnpm: 'pnpm run prepare',
bun: 'bun run prepare',
}}
/>

For example, create a `pre-commit` hook that runs [`rs staged`](./staged):

```sh title=".rstack/hooks/pre-commit"
rs staged
```

:::warning Existing Git hook managers

`rs setup` updates the repository's [`core.hooksPath`](https://git-scm.com/docs/git-config#Documentation/git-config.txt-corehooksPath). If the repository already uses Husky or another Git hook manager, move the required hooks before running the command.

:::

## Options

### `--hooks-dir`

Sets the directory for project hook scripts, relative to the current directory.

```bash
rs setup --hooks-dir config/git-hooks

# Quote paths that contain spaces
rs setup --hooks-dir "config/git hooks"
```

When using a custom directory, add the full command to the `prepare` script in the root `package.json`:

```json title="package.json"
{
"scripts": {
"prepare": "rs setup --hooks-dir config/git-hooks"
}
}
```

### `--help`

`--help` (or `-h`) displays the command's usage and options.

```bash
rs setup --help
```

## Hook files

The default directory structure is:

```text
.rstack/
└── hooks/
├── pre-commit # Project hook script: edit and commit
└── _/ # Generated by rs setup; ignored by Git
├── .gitignore
├── runner
├── pre-commit
├── commit-msg
└── ...
```

Files next to `_` are project hook scripts. The `_` directory contains generated files and is ignored by Git. `rs setup` points `core.hooksPath` to `.rstack/hooks/_`; rerun it after cloning the repository or when generated files are missing.

## Supported hooks

Rstack supports these client-side Git hooks:

- `pre-commit`
- `pre-merge-commit`
- `prepare-commit-msg`
- `commit-msg`
- `post-commit`
- `applypatch-msg`
- `pre-applypatch`
- `post-applypatch`
- `pre-rebase`
- `post-rewrite`
- `post-checkout`
- `post-merge`
- `pre-push`
- `pre-auto-gc`

Create a file with the matching name next to the `_` directory.

## Hook runtime

Rstack runs hook scripts with POSIX `sh -e`, forwards Git's arguments and standard input, and returns the hook's exit code. It also prepends `node_modules/.bin` to `PATH`.

### Disable and debug

Set `RSTACK_HOOKS=0` to skip installation or hook execution:

```bash
RSTACK_HOOKS=0 git commit -m "Skip hooks"
```

Set `RSTACK_HOOKS=2` to trace Rstack's hook runtime, including how it invokes the hook script and handles its exit code; to trace commands inside the hook script, add `set -x` to the script:

```bash
RSTACK_HOOKS=2 git commit -m "Trace hooks"
```

### Configure the hook environment

Before running a hook script, Rstack loads this optional POSIX shell file:

```text
${XDG_CONFIG_HOME:-$HOME/.config}/rstack/hooks-init.sh
```

Use it to initialize a Node.js version manager, update `PATH`, or set `RSTACK_HOOKS=0` for the current user.

## Monorepo

In a monorepo, a project may be located in a Git repository subdirectory, such as `frontend/`. When run from that directory, `rs setup` creates the hooks directory relative to the project and includes the project path in `core.hooksPath`:

```text
frontend/.rstack/hooks/
frontend/.rstack/hooks/_/
core.hooksPath=frontend/.rstack/hooks/_
```

Git runs hooks from the repository root. If the project is in a subdirectory, change to that directory in the hook script before running project commands:

```sh title="frontend/.rstack/hooks/pre-commit"
cd frontend
pnpm test
```

A Git repository has one `core.hooksPath`, so choose either the repository root or one subproject to manage hooks.

## Remove hooks

To remove Rstack-managed hooks:

1. Remove `rs setup` from the `prepare` script.
2. Unset the repository's hooks path:

```bash
git config --local --unset core.hooksPath
```

3. Delete `.rstack/hooks/`, or the directory passed to `--hooks-dir`.

## Troubleshooting

### Hook does not run

- Check that the hook script has a [supported name](#supported-hooks) and is next to the `_` directory.
- Run `git config --local --get core.hooksPath` and verify the configured path.
- Rerun `rs setup` to restore generated files and executable permissions.
- Check that `RSTACK_HOOKS` is not set to `0` in the environment or initialization file.

Hook scripts do not need to be executable because Rstack runs them with `sh`.

### Command not found

For exit code 127, Rstack prints the effective `PATH`. If a GUI Git client cannot find Node.js or the package manager, initialize them in `hooks-init.sh`.

### Windows and Yarn

On Windows, hooks run in the POSIX shell included with [Git for Windows](https://gitforwindows.org/). Use LF line endings and `/` path separators in hooks.

[Yarn PnP](https://yarnpkg.com/features/pnp) does not provide `node_modules/.bin`. Run tools through a Yarn script, such as `yarn run test`, and make Node.js and Yarn available through `hooks-init.sh` when needed.
1 change: 1 addition & 0 deletions website/docs/en/guide/quick-start.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ The following commands are available:
- [`rs doc`](./cli/doc): Develop, build, or preview a documentation site with Rspress.
- [`rs test`](./cli/test): Run tests with Rstest.
- [`rs lint`](./cli/lint): Lint source code with Rslint.
- [`rs setup`](./cli/setup): Install project-local Git hooks.
- [`rs staged`](./cli/staged): Run tasks against files staged in Git with lint-staged.

## Configure Rstack
Expand Down
2 changes: 1 addition & 1 deletion website/docs/zh/guide/cli/_meta.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
["dev", "build", "preview", "lib", "doc", "test", "lint", "staged"]
["dev", "build", "preview", "lib", "doc", "test", "lint", "setup", "staged"]
Loading