Skip to content

Scorecard reports warnings on non-plugin code (standalone Node CLI in same repo) #178

Description

@rogerdigital

Summary

The community plugin scorecard appears to scan all TypeScript source in a repository, including code that is not part of the Obsidian plugin bundle and will never run inside Obsidian. This produces review warnings that cannot be resolved without removing functionality, and that do not reflect the plugin's actual runtime behavior.

Context

vault-inspector ships two independently-built artifacts from one repository:

The plugin (src/main.ts → main.js) — loaded by Obsidian, scanned by the review bot. main.js contains zero CLI code (verified: grep -c 'local-vault|LocalVault' main.js returns 0).
A standalone Node CLI (cli/bin.ts → cli.js, platform: node, #!/usr/bin/env node shebang) — distributed via npm (bin field), used for CI/automation scans of vaults outside Obsidian. It is a separate esbuild target and is never bundled into main.js.
Both main.js and cli.js are listed in package.json files because both are published to npm. The CLI reuses the plugin's scanner logic via import ... from "../src/...".

What happens

The scorecard for the latest release reports 105 warnings, all in cli/:

97 @typescript-eslint/no-unsafe-* errors — caused by the CLI importing node:fs/promises and node:path, which resolve to any/error types because the scan environment does not expose @types/node. (We confirmed the scan runs without @types/node installed: the CLI uses flatMap/matchAll/Object.entries and those resolve fine because we ship lib: ["ES2020"], but Node module APIs have no equivalent lib.)
14 semantic Obsidian-rule warnings — obsidianmd/no-nodejs-modules (4), no-undef for process (7), obsidianmd/prefer-window-timers (2), no-restricted-globals for fetch (1). These are inherent to a Node CLI and cannot be eliminated without breaking it.
The plugin source (src/) produces 0 warnings — confirming the plugin itself fully complies.

What we tried

Adding "cli/" to eslint.config.mjs top-level ignores — did not change the scorecard. The scan appears not to honor project-level ignores for non-test directories (it does suppress src/tests/, but that may be a built-in convention rather than respect for our config).
A dedicated { files: ["cli/**/*.ts"], rules: { "obsidianmd/no-nodejs-modules": "off", ... } } override block — also did not change the scorecard. Per-file rule overrides are not honored either.
tsconfig.json lib: ["ES2020"] — this worked for src/ (eliminated 51 warnings from ES2017+ built-in APIs resolving as any), but cannot help cli/ because Node module types only ship via @types/node, which the scan environment does not install.

Why this matters

The scorecard's stated purpose is to reflect whether a plugin is safe and well-built. But warnings on code that:

Is never shipped in main.js (verified by grep of the release asset),
Runs in a completely different runtime (Node.js, not Obsidian's Electron),
Is distributed via a different channel (npm bin, not the community directory),
do not reflect plugin quality. They are unavoidable false positives for any repository that bundles a tooling/CLI alongside a plugin — a legitimate and increasingly common pattern.

This creates a dilemma with no good outcome:

Accept the warnings → scorecard stuck at "Caution" indefinitely, which may look concerning to users browsing the directory even though the plugin itself is clean.
Move the CLI to a separate repository → significant ongoing maintenance cost (the CLI shares core scanner logic with the plugin; cross-repo version sync, duplicate types, split CI/tests) for zero scorecard benefit, since 14 inherent Node-API warnings would remain.
Vendor a minimal @types/node shim → masks the real problem and adds maintenance burden.

Request

Could the review bot's scan scope be aligned with what actually ships in the plugin? Some options, roughly in order of preference:

Honor the project's eslint.config.mjs ignores for non-src/tests paths too. If a maintainer explicitly ignores cli/, the bot should respect that. (This is the least surprising behavior — src/tests/ is already honored, so extending it to user-declared ignores would be consistent.)
Scope the scan to files actually included in main.js (e.g., trace esbuild/rollup entry points, or scan the bundled main.js directly rather than source).
Document the scan scope assumption (one-repo-one-plugin) and offer an opt-out marker for non-plugin directories (e.g., a package.json field like "obsidianReviewIgnore": ["cli/**"], or a conventional directory name).
Provide a way to mark the repository as containing a secondary non-plugin package, with the bot scanning only the plugin entry.
Any of these would let maintainers of "plugin + companion CLI/tool" repositories get a scorecard that reflects the plugin's actual quality.

Environment

Plugin: vault-inspector v0.4.17
eslint-plugin-obsidianmd: 0.4.1
Repository: https://github.com/rogerdigital/vault-inspector
Scorecard page: https://community.obsidian.md/plugins/vault-inspector
Relevant files: eslint.config.mjs, esbuild.config.mjs (shows the two separate build targets)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions