https://github.com/itsnickbarry/exec-staged
Run commands against the current git index ๐๏ธ
https://github.com/itsnickbarry/exec-staged
commit exec git hook lint lint-staged pre-commit staged wow
Last synced: 29 days ago
JSON representation
Run commands against the current git index ๐๏ธ
- Host: GitHub
- URL: https://github.com/itsnickbarry/exec-staged
- Owner: ItsNickBarry
- License: mit
- Created: 2025-06-08T19:30:14.000Z (about 1 year ago)
- Default Branch: master
- Last Pushed: 2025-06-23T22:15:04.000Z (12 months ago)
- Last Synced: 2025-07-26T10:56:19.717Z (11 months ago)
- Topics: commit, exec, git, hook, lint, lint-staged, pre-commit, staged, wow
- Language: TypeScript
- Homepage:
- Size: 298 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Exec Staged
Run commands against files staged in git, ignoring unstaged changes and untracked files.
### Use Cases
- ๐งต Lint new changes before commit.
- ๐งช Test changes in isolation before commit.
- โจ ???
### How it Works
1. Unstaged changes and untracked files are hidden in a git stash. This includes unstaged deletions, which are temporarily restored.
2. User-configured tasks are run, with staged files passed in according to configuration.
3. Any changes made by tasks are added to the git index. This includes additions and deletions.
4. The stashed changes are restored.
5. If any step fails, the initial state is fully restored.
## Installation
Install from npm, using your preferred package manager:
```bash
npm install --save-dev exec-staged
```
## Requirements
- Git >= 2.22.0
## Usage
### Run from the CLI
If an `exec-staged` configuration file is present, it will be loaded by the executable:
```bash
npx exec-staged
```
If no configuration is present, the executable can still run tasks passed as arguments:
```bash
npx exec-staged "npm test"
```
### Run in a Script
```typescript
import { execStaged } from 'exec-staged';
const cwd = process.cwd();
const tasks = [`npm test`];
const options = { quiet: true };
const result = await execStaged(cwd, tasks, options);
if (!result) {
throw new Error('exec-staged task failed');
}
```
### Run in a Pre-Commit Hook
[Husky](https://github.com/typicode/husky) is recommended for handling pre-commit hooks.
Install Husky:
```bash
npm install --save-dev husky
```
Add a hook to `.husky/pre-commit`:
```bash
#!/bin/sh
npx exec-staged
```
Run husky:
```bash
npx husky
```
Add a `package.json` script to run husky whenever your repository is cloned:
```json
{
"scripts": {
"prepare": "husky"
}
}
```
`exec-staged` will do nothing unless configured. See configuration information below.
## Configuration
`exec-staged` configuration consists of a list of commands to execute against the stage. Each command may be formatted as a plain `string`, or as an object containing additional attributes.
All [Cosmiconfig-compatible](https://www.npmjs.com/package/cosmiconfig#searchplaces) configuration files are supported.
Here is an example configuration:
```typescript
// exec-staged.config.ts
import type { ExecStagedUserConfig } from 'exec-staged/types';
const config: ExecStagedUserConfig = [
'knip',
'knip --production',
{ task: 'prettier --write $FILES', glob: '*.{js,ts,json,md}' },
];
export default config;
```
Plain commands are run every time, as-is:
```typescript
'knip --production'
```
Commands which include the `$FILES` token are only run if staged files are found, and those files are interpolated into the command in place of the token.
```typescript
'prettier --write $FILES'
// => prettier --write new_file.js modified_file.js
```
File filtering can be customized.
To filter files by name, add a `glob` filter (defaults to `'**'`):
```typescript
{ task: 'prettier --write $FILES', glob: '*.{js,ts,json,md}' }
```
To filter files by git status, add a `diff` filter (defaults to `'AM'`; see [here](https://git-scm.com/docs/git-status#_short_format)):
```typescript
{ task: 'prettier --write $FILES', diff: 'A' }
```
Defining `diff` or `glob` on a task that does not include the `$FILES` token has no effect:
```typescript
{ task: 'knip', diff: 'NO EFFECT', glob: 'NO EFFECT' }
```
## Safety Features
Before running any potentially destructive scripts, `exec-staged` stores all outstanding changes, including untracked files, in a backup stash. If any task fails, or if `exec-staged` is interrupted by an end-process signal (such as via Ctrl + C), the repository's original state is restored using this stash. Avoid running any tasks that interact with git, especially those that make commits or modify the stash.
### Recovery
If `exec-staged` fails to exit safely, such as due to power loss or if its process is killed via `SIGKILL`, run the recovery tool to restore your repository to its original state:
```bash
npx exec-staged recover
```
This will automatically find and apply the backup stash, restore any merge metadata, and clean up leftover artifacts.
To prevent data loss, `exec-staged` will not run if artifacts from a previous run are present.
## See Also
- [`lint-staged`](https://github.com/lint-staged/lint-staged): the inspiration for `exec-staged`.
- [`knip`](https://github.com/webpro-nl/knip): a linter that analyzes interactions between files, which is outside of the designed scope of `lint-staged`.