{"id":13469385,"url":"https://github.com/QuiiBz/sherif","last_synced_at":"2025-03-26T06:32:10.765Z","repository":{"id":195335843,"uuid":"692763838","full_name":"QuiiBz/sherif","owner":"QuiiBz","description":"Opinionated, zero-config linter for JavaScript monorepos","archived":false,"fork":false,"pushed_at":"2025-03-01T11:22:44.000Z","size":1538,"stargazers_count":980,"open_issues_count":9,"forks_count":17,"subscribers_count":10,"default_branch":"main","last_synced_at":"2025-03-20T04:39:27.942Z","etag":null,"topics":["cli","javascript","linter","monorepo"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/QuiiBz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["QuiiBz"]}},"created_at":"2023-09-17T14:11:52.000Z","updated_at":"2025-03-15T11:14:29.000Z","dependencies_parsed_at":null,"dependency_job_id":"c4dd2d45-a275-4210-88cc-e55dcf0a5f9a","html_url":"https://github.com/QuiiBz/sherif","commit_stats":{"total_commits":95,"total_committers":6,"mean_commits":"15.833333333333334","dds":0.08421052631578951,"last_synced_commit":"19f1e345c04830ba5a93d9b6de3172b54ee2391a"},"previous_names":["quiibz/sherif"],"tags_count":28,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/QuiiBz%2Fsherif","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/QuiiBz%2Fsherif/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/QuiiBz%2Fsherif/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/QuiiBz%2Fsherif/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/QuiiBz","download_url":"https://codeload.github.com/QuiiBz/sherif/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245604146,"owners_count":20642946,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","javascript","linter","monorepo"],"created_at":"2024-07-31T15:01:36.976Z","updated_at":"2025-03-26T06:32:10.751Z","avatar_url":"https://github.com/QuiiBz.png","language":"JavaScript","funding_links":["https://github.com/sponsors/QuiiBz"],"categories":["JavaScript","cli","Web Frontend"],"sub_categories":["JS Libraries \u0026 Utilities"],"readme":"\u003cp align=\"center\"\u003e\n  \u003cpicture\u003e\n    \u003cimg alt=\"\" height=\"200px\" src=\"https://github.com/QuiiBz/sherif/blob/main/assets/logo.png\" /\u003e\n  \u003c/picture\u003e\n  \u003cbr /\u003e\n  \u003cb\u003eSherif\u003c/b\u003e: Opinionated, zero-config linter for JavaScript monorepos\n\u003c/p\u003e\n\n---\n\n![Cover](https://github.com/QuiiBz/sherif/blob/main/assets/cover.png)\n\n## About\n\nSherif is an opinionated, zero-config linter for JavaScript monorepos. It runs fast in any monorepo and enforces rules to provide a better, standardized DX.\n\n## Features\n\n- ✨ **PNPM, NPM, Yarn...**: sherif works with all package managers\n- 🔎 **Zero-config**: it just works and prevents regressions\n- ⚡ **Fast**: doesn't need `node_modules` installed, written in 🦀 Rust\n\n## Installation\n\nRun `sherif` in the root of your monorepo to list the found issues. Any error will cause Sherif to exit with a code 1:\n\n```bash\n# PNPM\npnpm dlx sherif@latest\n# NPM\nnpx sherif@latest\n```\n\nWe recommend running Sherif in your CI once [all errors are fixed](#autofix). Run it by **specifying a version instead of latest**. This is useful to prevent regressions (e.g. when adding a library to a package but forgetting to update the version in other packages of the monorepo).\n\nWhen using the GitHub Action, it will search for a `sherif` script in the root `package.json` and use the same arguments automatically to avoid repeating them twice. You can override this behaviour with the `args` parameter.\n\n\u003cdetails\u003e\n\n\u003csummary\u003eGitHub Actions example\u003c/summary\u003e\n\n```yaml\n# Using the `QuiiBz/sherif` action\nname: Sherif\non:\n  pull_request:\njobs:\n  check:\n    name: Run Sherif\n    runs-on: ubuntu-22.04\n    steps:\n      - uses: actions/checkout@v4\n      - uses: QuiiBz/sherif@v1\n        # Optionally, you can specify a version and arguments to run Sherif with:\n        # with:\n          # version: 'v1.4.0'\n          # args: '--ignore-rule root-package-manager-field'\n\n# Using `npx` to run Sherif\nname: Sherif\non:\n  pull_request:\njobs:\n  check:\n    name: Run Sherif\n    runs-on: ubuntu-22.04\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v3\n        with:\n          node-version: 20\n      - run: npx sherif@1.4.0\n```\n\n\u003c/details\u003e\n\n## Autofix\n\nMost issues can be automatically fixed by using the `--fix` (or `-f`) flag. Sherif will automatically run your package manager's `install` command (see [No-install mode](#no-install-mode) to disable this behavior) to update the lockfile. Note that autofix is disabled in CI environments (when `$CI` is set):\n\n```bash\nsherif --fix\n```\n\n### No-install mode\n\nIf you don't want Sherif to run your packager manager's `install` command after running autofix, you can use the `--no-install` flag:\n\n```bash\nsherif --fix --no-install\n```\n\n## Rules\n\nYou can ignore a specific rule by using `--ignore-rule \u003cname\u003e` (or `-r \u003cname\u003e`):\n\n```bash\n# Ignore both rules\nsherif -r packages-without-package-json -r root-package-manager-field\n```\n\nYou can ignore all issues in a package by using `--ignore-package \u003cpathOrName\u003e` (or `-p \u003cpathOrName\u003e`):\n\n```bash\n# Ignore all issues in the `@repo/tools` package\nsherif -p @repo/tools\n# Ignore all issues for packages inside `./integrations/*`\nsherif -p \"./integrations/*\"\n```\n\n\u003e **Note**\n\u003e Sherif doesn't have many rules for now, but will likely have more in the future (along with more features).\n\n#### `empty-dependencies` ❌\n\n`package.json` files should not have empty dependencies fields.\n\n#### `multiple-dependency-versions` ❌\n\nA given dependency should use the same version across the monorepo.\n\nYou can ignore this rule for a specific dependency and version or all versions of a dependency if it's expected in your monorepo by using `--ignore-dependency \u003cname@version\u003e` / `--ignore-dependency \u003cname\u003e` (or `-i \u003cname@version\u003e` / `-i \u003cname\u003e`):\n\n```bash\n# Ignore only the specific dependency version mismatch\nsherif -i react@17.0.2 -i next@13.2.4\n\n# Ignore all versions mismatch of dependencies that start with @next/\nsherif -i @next/*\n\n# Completely ignore all versions mismatch of these dependencies\nsherif -i react -i next\n```\n\n#### `unsync-similar-dependencies` ❌\n\nSimilar dependencies in a given `package.json` should use the same version. For example, if you use both `react` and `react-dom` dependencies in the same `package.json`, this rule will enforce that they use the same version.\n\n\u003cdetails\u003e\n\n\u003csummary\u003eList of detected similar dependencies\u003c/summary\u003e\n\n- `react`, `react-dom`\n- `eslint-config-next`, `@next/eslint-plugin-next`, `@next/font` `@next/bundle-analyzer`, `@next/third-parties`, `@next/mdx`, `next`\n- `@trpc/client`, `@trpc/server`, `@trpc/next`, `@trpc/react-query`\n- `eslint-config-turbo`, `eslint-plugin-turbo`, `@turbo/gen`, `turbo-ignore`, `turbo`\n- `@tanstack/eslint-plugin-query`, `@tanstack/query-async-storage-persister`, `@tanstack/query-broadcast-client-experimental`, `@tanstack/query-core`, `@tanstack/query-devtools`, `@tanstack/query-persist-client-core`, `@tanstack/query-sync-storage-persister`, `@tanstack/react-query`, `@tanstack/react-query-devtools`, `@tanstack/react-query-persist-client`, `@tanstack/react-query-next-experimental`, `@tanstack/solid-query`, `@tanstack/solid-query-devtools`, `@tanstack/solid-query-persist-client`, `@tanstack/svelte-query`, `@tanstack/svelte-query-devtools`, `@tanstack/svelte-query-persist-client`, `@tanstack/vue-query`, `@tanstack/vue-query-devtools`, `@tanstack/angular-query-devtools-experimental`, `@tanstack/angular-query-experimental`\n- `sb`, `storybook`, `@storybook/codemod`, `@storybook/cli`, `@storybook/channels`, `@storybook/addon-actions`, `@storybook/addon-links`, `@storybook/react`, `@storybook/react-native`, `@storybook/components`, `@storybook/addon-backgrounds`, `@storybook/addon-viewport`, `@storybook/angular`, `@storybook/addon-a11y`, `@storybook/addon-jest`, `@storybook/client-logger`, `@storybook/node-logger`, `@storybook/core`, `@storybook/addon-storysource`, `@storybook/html`, `@storybook/core-events`, `@storybook/svelte`, `@storybook/ember`, `@storybook/addon-ondevice-backgrounds`, `@storybook/addon-ondevice-notes`, `@storybook/preact`, `@storybook/theming`, `@storybook/router`, `@storybook/addon-docs`, `@storybook/addon-ondevice-actions`, `@storybook/source-loader`, `@storybook/preset-create-react-app`, `@storybook/web-components`, `@storybook/addon-essentials`, `@storybook/server`, `@storybook/addon-toolbars`, `@storybook/addon-controls`, `@storybook/core-common`, `@storybook/builder-webpack5`, `@storybook/core-server`, `@storybook/csf-tools`, `@storybook/addon-measure`, `@storybook/addon-outline`, `@storybook/addon-ondevice-controls`, `@storybook/instrumenter`, `@storybook/addon-interactions`, `@storybook/docs-tools`, `@storybook/builder-vite`, `@storybook/telemetry`, `@storybook/core-webpack`, `@storybook/preset-html-webpack`, `@storybook/preset-preact-webpack`, `@storybook/preset-svelte-webpack`, `@storybook/preset-react-webpack`, `@storybook/html-webpack5`, `@storybook/preact-webpack5`, `@storybook/svelte-webpack5`, `@storybook/web-components-webpack5`, `@storybook/preset-server-webpack`, `@storybook/react-webpack5`, `@storybook/server-webpack5`, `@storybook/addon-highlight`, `@storybook/blocks`, `@storybook/builder-manager`, `@storybook/react-vite`, `@storybook/svelte-vite`, `@storybook/web-components-vite`, `@storybook/nextjs`, `@storybook/types`, `@storybook/manager`, `@storybook/csf-plugin`, `@storybook/preview`, `@storybook/manager-api`, `@storybook/preview-api`, `@storybook/html-vite`, `@storybook/sveltekit`, `@storybook/preact-vite`, `@storybook/addon-mdx-gfm`, `@storybook/react-dom-shim`, `create-storybook`, `@storybook/addon-onboarding`, `@storybook/react-native-theming`, `@storybook/addon-themes`, `@storybook/test`, `@storybook/react-native-ui`, `@storybook/experimental-nextjs-vite`, `@storybook/experimental-addon-test`, `@storybook/react-native-web-vite`\n- `prisma`, `@prisma/client`, `@prisma/instrumentation`\n- `typescript-eslint`, `@typescript-eslint/eslint-plugin`, `@typescript-eslint/parser`\n- `@stylistic/eslint-plugin-js`, `@stylistic/eslint-plugin-ts`, `@stylistic/eslint-plugin-migrate`, `@stylistic/eslint-plugin`, `@stylistic/eslint-plugin-jsx`, `@stylistic/eslint-plugin-plus`\n- `playwright`, `@playwright/test`\n\n\u003c/details\u003e\n\n#### `non-existant-packages` ⚠️\n\nAll paths defined in the workspace (the root `package.json`' `workspaces` field or `pnpm-workspace.yaml`) should match at least one package.\n\n#### `packages-without-package-json` ⚠️\n\nAll packages matching the workspace (the root `package.json`' `workspaces` field or `pnpm-workspace.yaml`) should have a `package.json` file.\n\n#### `root-package-dependencies` ⚠️\n\nThe root `package.json` is private, so making a distinction between `dependencies` and `devDependencies` is useless - only use `devDependencies`.\n\n#### `root-package-manager-field` ❌\n\nThe root `package.json` should specify the package manager and version to use. Useful for tools like corepack.\n\n#### `root-package-private-field` ❌\n\nThe root `package.json` should be private to prevent accidentaly publishing it to a registry.\n\n#### `types-in-dependencies` ❌\n\nPrivate packages shouldn't have `@types/*` in `dependencies`, since they don't need it at runtime. Move them to `devDependencies`.\n\n#### `unordered-dependencies` ❌\n\nDependencies should be ordered alphabetically to prevent complex diffs when installing a new dependency via a package manager.\n\n## Credits\n\n- [dedubcheck](https://github.com/innovatrics/dedubcheck) that given me the idea for Sherif\n- [Manypkg](https://github.com/Thinkmill/manypkg) for some of their rules\n- [This article](https://blog.orhun.dev/packaging-rust-for-npm/) for the Rust releases on NPM\n\n## Sponsors\n\n![Sponsors](https://github.com/QuiiBz/dotfiles/blob/main/sponsors.png?raw=true)\n\n## License\n\n[MIT](./LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FQuiiBz%2Fsherif","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FQuiiBz%2Fsherif","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FQuiiBz%2Fsherif/lists"}