Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
46146a7
fix: minor issues
dbale-arg Jan 21, 2026
d61bb5a
chore(deps): bump lodash from 4.17.21 to 4.17.23
dependabot[bot] Jan 21, 2026
f16f7b4
Merge pull request #740 from protofire/dependabot/npm_and_yarn/lodash…
dbale-arg Jan 23, 2026
2f8915e
Merge branch 'develop' into fix-minor-issues
dbale-arg Jan 23, 2026
824f13c
fix: scoped packs for shareable configs
dbale-arg Jan 23, 2026
824fcd7
fix: ci
dbale-arg Jan 23, 2026
6962269
Merge branch 'develop' into fix-allow-scoped-packages
dbale-arg Jan 23, 2026
5785a58
Merge pull request #741 from protofire/fix-allow-scoped-packages
dbale-arg Jan 23, 2026
b9b0721
Update LICENSE
xiaobei0715 Feb 10, 2026
3afc011
chore(deps): bump ajv from 6.12.6 to 8.18.0
dependabot[bot] Feb 17, 2026
24c61c4
chore(deps): bump minimatch
dependabot[bot] Feb 28, 2026
d70c46d
Merge pull request #745 from xiaobei0715/patch-1
dbale-arg Mar 5, 2026
9706299
fix: natspect on unnamed params
dbale-arg Mar 5, 2026
2441fef
Merge pull request #749 from protofire/i742-natspec-fix
dbale-arg Mar 5, 2026
bbebe43
fix: natspec rule and other issues
dbale-arg Mar 10, 2026
1b09621
fix: natspec rule and other issues
dbale-arg Mar 10, 2026
ef86710
fix: natspec rule and other issues
dbale-arg Mar 10, 2026
fbb3a38
Merge branch 'develop' into i742-natspec-fix
dbale-arg Mar 10, 2026
0c3c4af
Merge branch 'develop' into fix-minor-issues
dbale-arg Mar 10, 2026
79986f1
fix: natspec rule and other issues
dbale-arg Mar 10, 2026
66a20f5
Merge pull request #739 from protofire/fix-minor-issues
dbale-arg Mar 10, 2026
bd5bdcf
Merge branch 'develop' into i742-natspec-fix
dbale-arg Mar 10, 2026
63a5ccb
Merge pull request #750 from protofire/i742-natspec-fix
dbale-arg Mar 10, 2026
fb0a249
Add pluginPaths support for plugin resolution
dbale-arg Mar 10, 2026
a291d33
Document pluginPaths plugin resolution behavior
dbale-arg Mar 10, 2026
0933819
Add e2e plugin scenarios for pluginPaths resolution
dbale-arg Mar 10, 2026
6167809
add: e2e tests
dbale-arg Mar 10, 2026
fb4de79
add: mote e2e tests
dbale-arg Mar 10, 2026
87106c7
Merge pull request #751 from protofire/codex/add-support-for-pluginpa…
dbale-arg Mar 10, 2026
71c300d
Merge branch 'develop' into dependabot/npm_and_yarn/ajv-8.18.0
dbale-arg Mar 17, 2026
d506ba1
Merge branch 'develop' into dependabot/npm_and_yarn/multi-dec2961506
dbale-arg Mar 17, 2026
fa4aa5b
Merge pull request #748 from protofire/dependabot/npm_and_yarn/multi-…
dbale-arg Mar 17, 2026
4f74aca
add changelog
dbale-arg Mar 17, 2026
6ff6d96
Merge branch 'develop' into bump-ajv-to-8.18.0
dbale-arg Mar 17, 2026
a028c18
fix: update code for ajv v8 compatibility
claude Mar 17, 2026
89f871c
merged with claude bump
dbale-arg Mar 17, 2026
4c8e48d
Merge pull request #753 from protofire/bump-ajv-to-8.18.0
dbale-arg Mar 17, 2026
2832551
prerelease v610
dbale-arg Mar 17, 2026
41b31b6
prerelease v610
dbale-arg Mar 17, 2026
d1c3fd4
Merge branch 'develop' into pre-relase-610
dbale-arg Mar 17, 2026
07857ac
Merge pull request #755 from protofire/pre-relase-610
dbale-arg Mar 17, 2026
832959e
Merge branch 'master' into develop
dbale-arg Mar 17, 2026
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
5 changes: 5 additions & 0 deletions .github/workflows/E2E.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ jobs:

- name: Check solhint version
run: solhint --version

- name: Debug fixtures presence
run: |
ls -R e2e/14-shareable-config/filesystem01/project || true
ls -R e2e/14-shareable-config/filesystem04/project || true

- name: Run E2E Tests
run: npm run ci:e2e
Expand Down
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# ignore all node_modules by default
node_modules/

/.idea/
test2.sol
convertLib.sol
Expand All @@ -12,3 +14,11 @@ _temp/
.env
**/.DS_Store
solhint*.tgz

# Exception on E2E fixtures' node_modules (they are part of the test data)
# only allow useful test files in those node_modules
!e2e/**/node_modules/**/*.js
!e2e/**/node_modules/**/*.json

# allow test plugins inside e2e fixtures
!e2e/15-plugins/**
28 changes: 28 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,31 @@
## [6.1.0] - 2026-03-17
🛠️ Fix: `natspec` rule no longer flags unnamed parameters, which Solidity prohibits documenting with @param (#749)

🛠️ Fix: `natspec` rule and `import-path-check` rules related issues (#750)

🛠️ Fix: scoped package names now supported for shareable configs (#741)

🛠️ Fix: misc minor issues and general polish (#739)
<br><br>

🧱 Enhancement: added `pluginPaths` config option for resolving plugins from custom locations.
Supports editor integrations and external project setups. Failed plugins emit warnings instead of crashing (#751)
<br><br>

🧹 Chore: bump ajv to 8.18.0

🧹 Chore: bump minimatch to 10.2.4

🧹 Chore: bump loadash to 4.17.23

🧹 Chore: update LICENSE copyright year to 2026 (thanks xiaobei0715!!) (#745)
<br><br>

✨🛡️ Kudos to our contributors! 🛡️✨

- [xiaobei0715](https://github.com/xiaobei0715)


## [6.0.3] - 2026-01-20
🛠️ `Fix`: removed unused files, normalized schema for validation, load-rules, base-checker and validator improvements

Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2017-2025 Protofire
Copyright (c) 2017-2026 Protofire

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,31 @@ Project ROOT =>
A full list of all supported rules can be found [here](docs/rules.md).
<br><br>


### Plugins and `pluginPaths`

Solhint resolves plugins using Node resolution from:

1. `process.cwd()` (default behavior, unchanged)
2. each configured entry in `pluginPaths`
3. each configured `<pluginPath>/node_modules`

This makes plugin loading work in environments where Solhint runs outside the project folder (for example IDE/editor integrations), while preserving the standard local `node_modules` behavior.

Example:

```json
{
"pluginPaths": ["/some/path"],
"plugins": ["myplugin"],
"rules": {
"myplugin/some-rule": "error"
}
}
```

If a plugin fails to load, Solhint will warn and continue linting with core rules and any other valid plugins.

### Ignore Configuration
You can exclude files from linting using a `.solhintignore` file (name by default) or `--ignore-path` followed by a custom name.
It uses the same syntax as `.gitignore`, including support for negation with !.
Expand Down
2 changes: 1 addition & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
FROM node:20-alpine
LABEL maintainer="diego.bale@protofire.io"
ENV VERSION=6.0.3
ENV VERSION=6.1.0

RUN npm install -g solhint@"$VERSION"
22 changes: 22 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,28 @@ node_modules/
additional-tests.sol
```


### Plugins and `pluginPaths`

Solhint resolves plugins from `process.cwd()` by default and can also use extra paths from `pluginPaths`.

Resolution paths include:

1. `process.cwd()`
2. each `pluginPaths` entry
3. each `<pluginPath>/node_modules`

`pluginPaths` accepts either a string or an array:

```json
{
"pluginPaths": ["/some/path"],
"plugins": ["myplugin"]
}
```

If one plugin cannot be loaded, Solhint emits a warning and continues linting with core rules and any other valid plugins.

### Configure linter with comments

You can use comments in the source code to configure solhint in a given line or file.
Expand Down
2 changes: 1 addition & 1 deletion docs/rules/best-practices/use-natspec.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ This rule accepts an array of options:
### Notes
- For `internal` or `private` function this rule checks natspec as configured, only if there are tags present. If not, function is skipped.
- For `external` or `public` function this rule checks natspec as specified in the config.
- If a function or return value has unnamed parameters (e.g. `function foo(uint256)`), the rule only checks the number of `@param` or `@return` tags, not their names.
- If a function or return value has unnamed parameters (e.g. `function foo(uint256, uint256 _amount)`), the rule DOES not check ANY of the params/return tags
- If a function or variable has `@inheritdoc`, the rule skips the validation.
- The rule supports both `///` and `/** */` style NatSpec comments.
- If a custom config is provided, it is merged with the default config. Only the overridden fields need to be specified.
Expand Down
2 changes: 1 addition & 1 deletion docs/rules/miscellaneous/import-path-check.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ This rule accepts an array of options:
- If `searchOn` has value, will be concatenated with DEFAULT_LOCATIONS.
- If config has `extends:recommended` or `all` and rule is overwritten with `searchOn`, values are concatenated with DEFAULT_LOCATIONS.

*Default Locations:*
*DEFAULT_LOCATIONS:*
- /[`~current-project`]
- /[`~current-project`]/contracts
- /[`~current-project`]/src
Expand Down
107 changes: 101 additions & 6 deletions docs/shareable-configs.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,122 @@ Shareable configs are configurations that you can use and extend from. They can

To use a shareable config, you have to add it to your Solhint configuration:

```
```json
{
"extends": ["solhint:recommended", "protofire"]
}
```

This example shows the two types of shareable configs that you can use:

- **Built-in Solhint configs**, which start with `solhint:` (e.g. `solhint:recommended`, `solhint:all`)
- **Shareable configs installed from npm**


## Using npm shareable configs

Unscoped shareable configs are npm packages prefixed with `solhint-config-`.

For example, this configuration:

```json
{
"extends": ["protofire"]
}
```

Will load the package:

```
solhint-config-protofire
```

which must be installed beforehand:

```
npm install solhint-config-protofire
```

You can also reference the full package name explicitly:

```json
{
"extends": ["solhint-config-protofire"]
}
```

Shareable configs are resolved from the project's `node_modules` directory (the current working directory), even when Solhint is installed globally.


## Scoped shareable configs

Solhint also supports **scoped** shareable configs.

Given the npm package:

```
@scope/solhint-config-myconfig
```

You can use it in your configuration as:

```json
{
"extends": ["@scope/solhint-config-myconfig"]
}
```

For convenience, Solhint also supports the ESLint-style shorthand:

```json
{
"extends": ["@scope/myconfig"]
}
```

This example shows the two types of shareable configs that you can use: the ones included with Solhint, that start with `solhint:`, and the ones that you can install from npm. The latter are packages that are prefixed with `solhint-config-`, so in this case the package would be installed doing `npm install solhint-config-protofire` but used as just `protofire` when adding it.
Which resolves to:

```
@scope/solhint-config-myconfig
```

Note: Only package-level scoped configs are supported (`@scope/name`). Deep paths such as `@scope/name/extra` are not supported.


## Creating your own shareable config

Shareable configs are regular npm packages. There are only two conditions:

- The name of the package must start with `solhint-config-`
- The package must export a regular object with the same structure as a regular configuration object (i.e. the one in your `.solhint.json`).
- The package name must start with `solhint-config-`
(for scoped packages: `@scope/solhint-config-*`)
- The package must export a regular object with the same structure as a standard Solhint configuration (i.e. the one in your `.solhint.json`)

For example, a very minimal `index.js` in this package could be:

```javascript
```js
module.exports = {
rules: {
'max-line-length': 80
}
}
```

After creating this package you can publish it to npm to make it available for everyone.
After creating this package, you can publish it to npm to make it available for everyone.


## Configuration inheritance

Solhint supports **hierarchical configuration**.

When linting a file, configurations are merged in the following order:

1. The project root configuration
2. Each parent directory configuration
3. The directory containing the file (**highest precedence**)

For each configuration file, any `extends` entries are resolved first, and then all configurations are merged according to directory hierarchy.

Rules and settings defined in deeper directories **override** those from higher-level directories and from extended configs.

In short:
**`extends` are resolved first, directory hierarchy is applied after, and the closest config always wins.**
3 changes: 3 additions & 0 deletions e2e/14-shareable-config/filesystem01/project/.solhint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": ["@test/demo"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract A {
function f() public {}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions e2e/14-shareable-config/filesystem02/project/.solhint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": ["@test/base"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"rules": {
"max-line-length": ["error", 80]
}
}

4 changes: 4 additions & 0 deletions e2e/14-shareable-config/filesystem02/project/contracts/A.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract A { function f() public { uint x = 1; uint y = 2; uint z = 3; uint w = 4; } function g() public { } }

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions e2e/14-shareable-config/filesystem03/project/.solhint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": ["@test/base"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"rules": {
"max-line-length": ["error", 60],
"no-empty-blocks": "off"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract B { function g() public { uint x = 1; uint y = 2; uint z = 3; uint w = 4; } function g() public { }}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions e2e/14-shareable-config/filesystem04/project/.solhint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": ["a", "b"]
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract C { function f() public { } }


Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions e2e/14-shareable-config/filesystem05/project/.solhint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"extends": ["a", "b"],
"rules": { "no-empty-blocks": "off" }
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract C { function f() public { } }


Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions e2e/14-shareable-config/filesystem06/project/.solhint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": ["@test/solhint-config-demo"]
}

Loading
Loading