Skip to content

Latest commit

 

History

89 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

English | 简体中文

ScriptSpect analyzes package scripts for POSIX shell, Windows cmd, and PowerShell portability problems before the scripts run

CI MIT License

Make package.json scripts work on macOS, Linux, and Windows—before CI or users find the breakage.

ScriptSpect is a preflight checker for npm-style package.json scripts. Point it at a Node.js project or monorepo: without running the scripts, it shows the exact command fragment that will break in posix-sh, Windows cmd, or optional powershell, explains the affected platform, and offers a fix only when its safety conditions are proved.

Important

This repository is a pre-release source evaluation. The npm package and public Action tag do not exist yet; the copy-paste paths below deliberately use an immutable source commit.

See the real demo · Evaluate from source · GitHub Actions · Rules

What it does, who it is for, and how it works

Use ScriptSpect if you maintain a JS/TS app, library, CLI, or monorepo; own CI or releases; or support contributors on more than one operating system. It solves the familiar failure where a script works on its author's Mac or Linux machine but fails for Windows users—or contains Windows-only syntax that fails on Unix CI.

Question Direct answer
Who uses it? JS/TS maintainers, monorepo owners, Windows contributors, and CI/release teams.
What problem does it catch? Shell-specific environment assignment, commands such as rm/cp/mv, expansion, redirection, operators, paths, explicit shell dependencies, and undeclared executables.
How does it check? It discovers the root package and workspaces, structurally parses every script for the selected shell targets, and never executes the target commands.
What do you get? An exact rule ID, package and script name, source span, affected shell/OS, severity, confidence, explanation, and terminal/JSON/PR-annotation output.
How does it help fix it? --fix-dry-run previews a patch. --fix applies only proven safe or precondition-satisfied changes; ambiguous cases stay manual.

The mental model is: repository → static target-shell analysis → exact findings → reviewable fix plan. For the current pre-release, follow Evaluate from source, run node dist/cli.mjs <your-project>, and add --fix-dry-run to preview changes. For pull requests, copy the GitHub Actions preview.

Why it is useful

Catch the breakage Explain the target Keep fixes reviewable
Finds shell-dependent commands, operators, expansion, redirection, paths, and undeclared executables before another OS runs them. Every finding carries a stable rule ID, package/script path, source span, severity, confidence, and affected targets. safe, conditional, and manual classes prevent “helpful” rewrites when equivalence cannot be proved.

ScriptSpect uses a target-specific structural parser rather than scanning quoted text with a stack of regular expressions. It is intentionally not a full shell interpreter: findings should still be reviewed in the project that owns the script.

scripts-doctor is the adjacent analyzer baseline. cross-env, shx, and rimraf are remedies ScriptSpect may recommend when their preconditions are satisfied, not competing analyzers.

Before, result, and after

Everything here is generated from the versioned demo fixture, so the screenshot and patch cannot drift away from executable behavior.

Before — two scripts that assume a POSIX shell:

{
  "name": "portable-demo",
  "private": true,
  "scripts": {
    "build": "NODE_ENV=production vite build",
    "clean": "rm -rf dist"
  },
  "devDependencies": {
    "cross-env": "^7.0.3",
    "rimraf": "^6.0.1",
    "vite": "^7.0.0"
  }
}

Result — PS001 and PS010 identify the exact cmd-incompatible spans:

Generated terminal transcript showing ScriptSpect findings for PS001 and PS010

Selectable terminal text · Full generated patch · Verified after file

After — the conditional rewrites use dependencies already declared by the project:

-"build": "NODE_ENV=production vite build"
-"clean": "rm -rf dist"
+"build": "cross-env NODE_ENV=production vite build"
+"clean": "rimraf dist"

--fix-dry-run prints this patch without writing. --fix uses staged writes, post-write analysis, and a recovery journal; it never installs dependencies or rewrites a lockfile. Regenerate all demo assets with pnpm exec tsx tools/generate-readme-demo.ts.

Evaluate from source (pre-release)

Requires Node.js 22 or newer and pnpm via Corepack. Clone the repository, check out the reviewed commit, install exactly from the lockfile, build, and scan the versioned demo fixture. Findings exit 1; a clean scan exits 0; invalid input, configuration, or I/O exits 2.

git clone https://github.com/Tom409114/scriptspect.git
cd scriptspect
git checkout c9c671c8e150705d78d9169d4c5a8f22cb37fad0
corepack enable
pnpm install --frozen-lockfile
pnpm build
node dist/cli.mjs tests/fixtures/readme-demo

There is deliberately no npx scriptspect quick start yet. The machine-readable release state is docs/readme-status.json.

CLI at a glance

The source build supports human, JSON, and GitHub-friendly output, focused rule runs, explicit target matrices, and opt-in fixes.

node dist/cli.mjs [path]
node dist/cli.mjs [path] --format json
node dist/cli.mjs [path] --target posix-sh,cmd,powershell
node dist/cli.mjs [path] --rule PS001,PS010
node dist/cli.mjs [path] --fix-dry-run
node dist/cli.mjs [path] --fix
node dist/cli.mjs explain PS010

Presentation filters do not hide failure semantics: any configured error fails, and the unfiltered warning count is compared with --max-warnings.

GitHub Actions preview (pre-release)

This complete example checks out both the consumer and an immutable ScriptSpect source commit, then runs the bundled local Action. Do not replace the commit with the nonexistent Tom409114/scriptspect@v0.1 tag. After a verified release, security-sensitive workflows should continue pinning a full commit SHA.

name: scriptspect pre-release evaluation
on: [pull_request]
permissions:
  contents: read
jobs:
  scripts:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          persist-credentials: false
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          repository: Tom409114/scriptspect
          ref: c9c671c8e150705d78d9169d4c5a8f22cb37fad0
          path: .scriptspect
          persist-credentials: false
      - uses: ./.scriptspect
        with:
          path: .

The Action writes annotations, a job summary, and numeric outputs named exit-code, packages, scripts, errors, warnings, and advisories before marking a finding run as failed. Its default mode is read-only.

Real hosted proof — not a mock screenshot. On main at c9c671c8, public CI run #33482453059 consumed uses: ./ against both clean and broken fixtures. The clean consumer reported 1 package · 1 script · 0 errors; the broken fixture emitted 2 check annotations, including PS010: scripts.clean on package.json.

Generated card summarizing the verified hosted Action run

Selectable Action evidence · Committed source evidence · Open the hosted job

Minimal configuration

Defaults target posix-sh and cmd. Put the same small contract in the root package.json under scriptspect, or in scriptspect.config.json:

{
  "targets": ["posix-sh", "cmd"],
  "severity": { "PS015": "advisory" },
  "ignore": [
    { "packages": ["examples/**"], "rules": ["PS030"] },
    { "scripts": ["docs:unix"], "rules": ["PS010", "PS011"] }
  ]
}

Precedence is deterministic and replacement-based: --configpackage.json#scriptspectscriptspect.config.json → defaults. --target then replaces only the selected config's target list. Config sources are never merged. Ignore entries must name rules and should stay narrow enough to explain an intentional platform-specific script.

Contracts: config JSON Schema · JSON output Schema

Scope and honest limits

Area Current source-evaluation behavior
Projects root package.json plus npm/Yarn/Bun workspaces and pnpm-workspace.yaml
Targets posix-sh + cmd by default; opt-in powershell evidence
Findings error, warning, and advisory with high/medium confidence
Output stylish terminal text, versioned JSON, GitHub annotations + summary
Fixes dry-run plus provable safe/conditional rewrites; ambiguous cases stay manual
Privacy offline analysis; scripts are not executed; no telemetry

Release: pre-release; no npm package or public Action reference yet.

The homepage does not claim external adoption, measured precision, comparative superiority, or hosted performance. Even after a verified release, external validation and adoption gates remain evidence-led. The validation ledger keeps repository-controlled work separate from evidence that only real users can create.

FAQ and troubleshooting

Does it run my scripts? No. It reads package manifests and performs static structural analysis.

Why did the scan exit 1 when I filtered warnings from the display? Failure is calculated before presentation filtering: configured errors and the full warning budget still count. Use --format json to inspect the complete contract.

Why was no automatic fix offered? The parser must agree on the replacement's structural role across active targets, and conditional fixes require the exact dependency to be declared. Otherwise the finding remains explanatory and manual.

Which config won? Explicit --config wins, followed by the package.json field, the standalone file, then defaults. Non-default sources are reported in human-readable output.

Can I use it in production CI today? Treat this source checkout as an evaluation build. Wait for public npm, Release, provenance, checksum, and immutable Action-consumer evidence before depending on a released reference.

Go deeper

License

MIT

About

Static analyzer for package.json scripts — catches shell-specific commands before they break Windows, macOS, or Linux builds. Like ShellCheck for npm scripts.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages