FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

docs: document rs hooks lifecycle by chenjiahan · Pull Request #410 · rstackjs/rstack-cli · GitHub

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

Filter by extension

Filter by extension .json  (2) .md  (1) .mdx  (10) All 3 file types selected
Deleted files Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
4 changes: 2 additions & 2 deletions README.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ It also covers local development needs outside Rstack's scope, with Prettier for
| [`rs check`](https://rstack.rs/guide/cli/check) | Run static checks, including lint and format |
| [`rs lib`](https://rstack.rs/guide/cli/lib) | Build library |
| [`rs doc`](https://rstack.rs/guide/cli/doc) | Serve or build docs |
| [`rs setup`](https://rstack.rs/guide/cli/setup) | Install Git hooks |
| [`rs hooks`](https://rstack.rs/guide/cli/hooks) | Manage Git hooks |
| [`rs staged`](https://rstack.rs/guide/cli/staged) | Run tasks on staged Git files |

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 Expand Up @@ -63,7 +63,7 @@ bun add -d rstack
"lib": "rs lib",
"doc": "rs doc",
"format": "rs fmt",
"prepare": "rs setup"
"prepare": "rs hooks"
}
}
```
Expand Down
2 changes: 1 addition & 1 deletion website/docs/en/guide/cli/_meta.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
"check",
"lint",
"fmt",
"setup",
"hooks",
Comment thread
chenjiahan marked this conversation as resolved.
"staged"
]
247 changes: 247 additions & 0 deletions website/docs/en/guide/cli/hooks.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
---
description: 'Install, configure, troubleshoot, and safely remove repository-level Git hooks with Rstack CLI.'
---

# hooks

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

The `rs hooks` command installs, updates, and removes repository-level [Git hooks](https://git-scm.com/docs/githooks). Hook scripts run in the project that installed them.

## Usage

```bash
rs hooks [options]
rs hooks uninstall
```

Run `rs hooks` without a subcommand to install or update hooks.

:::tip Alias
`rs setup` is an alias for `rs hooks`.
Comment thread
chenjiahan marked this conversation as resolved.
:::

## Install hooks

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

Add `rs hooks` to the `prepare` script of the project that owns the repository hooks:

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

Run the script once to install the hooks:

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

You can safely run the installation more than once, and it does not load `rstack.config.*`. Run `rs hooks` again after cloning the repository or if the generated hook files are missing.

:::warning Existing Git hook managers

`rs hooks` updates the repository's [`core.hooksPath`](https://git-scm.com/docs/git-config#Documentation/git-config.txt-corehooksPath). If it detects another hooks path or existing Git hooks, it skips installation. Run `rs hooks --force` to let Rstack manage hooks instead.

:::

## Install options

### `--force`

`--force` (or `-f`) installs Rstack hooks even when another Git hook setup already exists:

```bash
rs hooks --force
```

Rstack keeps the existing hook files and points `core.hooksPath` to its generated hooks directory. While this setting is active, Git does not run hooks from the previous location.

`--force` cannot replace hooks owned by another Rstack project.

:::tip
Run `rs hooks --force` only once. Use `rs hooks` without `--force` in the `prepare` script.
:::

### `--hooks-dir`

Specifies a custom directory for hook scripts, relative to the Git repository root.

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

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

When using a custom directory, add the full command to the `prepare` script of the project that manages hooks:

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

> The path must not contain `..`. This prevents hook files from being created or overwritten outside the repository through a parent directory path.

### `--help`

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

```bash
rs hooks --help
```

## Uninstall hooks

Run the command from the project that installed the hooks:

```bash
rs hooks uninstall
```

Rstack automatically finds the active hooks and removes the `core.hooksPath` setting and the generated `_` directory. It does not delete project hook files such as `.rstack/hooks/pre-commit`. Hooks managed by another project or tool are left untouched.

Remove `rs hooks` from the `prepare` script if you do not want the hooks to be installed again.

If `--force` previously took over hooks in `.git/hooks`, those hooks become active again after uninstalling.

## Hook files

The default directory structure is:

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

Files alongside `_` are repository hook scripts. The `_` directory contains generated files and is ignored by Git. `rs hooks` points `core.hooksPath` to `.rstack/hooks/_`.

## Supported hooks

Rstack CLI 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 alongside the `_` directory.

## Hook runtime

Rstack CLI runs hook scripts with POSIX `sh -e`. It forwards Git's arguments and standard input, then returns the hook's exit code. Before running a hook, Rstack changes to the project that installed the hooks and prepends that project's `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 the Rstack CLI 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 CLI 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.

## Ownership safety

Each generated hooks directory records its owning project. Only that project should include `rs hooks` in its `prepare` script. Rstack skips installation from any other project, even with `--force`, and refuses to remove hooks owned by another project.

To transfer ownership:

1. Remove `rs hooks` from the previous owner's `prepare` script.
2. Run `rs hooks uninstall` from the previous owner.
3. Add `rs hooks` to the new owner's `prepare` script and run it once.

## Monorepo

In a monorepo, the project that provides Rstack CLI may live in a subdirectory such as `frontend/`. Running `rs hooks` there still installs hooks at the Git repository root:

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

Rstack records `frontend` as the owning project. The hook scripts stay at the repository root but run from `frontend`, allowing them to use its configuration and dependencies without an explicit `cd`:

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

## Worktree behavior

Rstack preserves the Git configuration scope of the active `core.hooksPath`. If a linked worktree uses a worktree-scoped hooks path, `rs hooks --force` replaces it in that scope instead of writing a local setting that Git would ignore.

`rs hooks uninstall` also removes the setting from that scope. Removing a worktree-scoped installation affects only the current worktree and leaves hooks in other linked checkouts unchanged. A local `core.hooksPath` setting is shared across linked checkouts, so changing or removing it affects every checkout that does not override it.

## 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 --show-scope --get core.hooksPath` and verify the effective scope and path.
- Rerun `rs hooks` to restore generated files and executable permissions.
- Check that `RSTACK_HOOKS` is not set to `0` in the environment or initialization file.
- If another hook setup is detected, run `rs hooks --force`.
- If another project is reported as the hooks owner, follow the steps in [Ownership safety](#ownership-safety).

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

### Command not found

For exit code 127, Rstack CLI 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.
Loading

Back | FazBrowse Home | New Git URL