ItWorksBut is a Node.js CI tool for static checks in JavaScript, Node.js, web, Tauri, and Electron vibe coding projects.
It focuses on common "it works, but..." risks often found in AI-generated or rushed prototypes: committed env files, missing lockfiles, weak CI, unsafe web APIs, broad desktop permissions, and similar issues.
For every finding, ItWorksBut gives you a copy-ready fix prompt you can paste into your coding agent. It does not just say what is wrong; it tells your AI exactly what to inspect, what to change, and what not to leak.
It mostly reads files and reports findings. It does not send telemetry. The outdated-package check may invoke your local package manager, and the CLI only writes files when you explicitly ask for todo.md with --todo or report.md with --report.
- Installation
- Quick Start
- Options
- Terminal Experience
- GitHub Actions
- Configuration
- Example Output
- What It Detects
- What It Does Not Guarantee
npm install --global itworksbut
itworksbut scanWith the Homebrew tap:
brew tap oliverjessner/tap
brew install itworksbut
itworksbut scanitworksbut scanscan is intentionally the strict/default path: all checks are enabled, only heavy generated folders are skipped, and the default fail-on threshold is low so more issues fail early. Use --config only when you deliberately want to tune or suppress checks.
Common commands:
itworksbut scan --path .
itworksbut deps
itworksbut stress
itworksbut scan --fail-on high
itworksbut scan --json
itworksbut scan --sarif > itworksbut.sarif
itworksbut scan --todo
itworksbut scan --report
itworksbut scan --config itworksbut.config.json
itworksbut scan --verbose
itworksbut --versionitworksbut scan [options]
itworksbut deps [options]
itworksbut stress [options]
deps: Run only dependency checks, including lockfile hygiene, install-script risk, audit script availability, and outdated packages.stress: Discover API endpoints and run a controlled Artillery load test against local or explicitly authorized targets.--path <path>: Scan a specific project directory. Defaults to the current directory.--config <path>: Use a custom config file. Defaults toitworksbut.config.jsonwhen present.--fail-on <severity>: Exit with code1when a finding at or above the severity exists. Levels:critical,high,medium,low,info. Default:low.--target <url>: Stress-test target. Defaults tohttp://localhost:3000. External targets require--i-own-this.--duration <seconds>: Stress-test duration. Default30, maximum300.--arrival-rate <number>: Arrival rate in requests per second. Default5, maximum50.--max-vusers <number>: Virtual user cap. Default50, maximum100.--i-own-this: Required for non-local stress-test targets.--json: Print machine-readable JSON only. No banner, colors, spinner, table, or extra text.--sarif: Print SARIF JSON for GitHub Code Scanning. No banner, colors, spinner, table, or extra text.--todo: Write an AI-readytodo.mdinto the scanned project with prioritized findings, fix prompts, and acceptance criteria.--report: Write a Markdownreport.mdinto the current working directory.--verbose: Include scanner warnings and extra metadata in console output.--quiet: Print only the summary.--no-color: Disable colored output.--no-banner: Disable the ASCII intro banner.--version,-v: Print the installed ItWorksBut version.
Exit codes:
0: no findings at or above the configuredfail-onseverity1: at least one finding at or above the configuredfail-onseverity2: tool/runtime error
Severity levels are critical, high, medium, low, and info.
Normal console output is intentionally more opinionated than the machine-readable reporters:
itworksbut scanConsole-only flags:
--no-color--no-banner--quiet--verbose
In CI, spinners and banners are automatically disabled. With --json and --sarif, stdout contains only valid machine-readable output. The edgy tone applies only to the Console Reporter.
To create a fix list for a coding agent:
itworksbut scan --todoThis writes todo.md to the scanned project. The file is ordered by severity and includes agent rules, exact fix prompts, locations, recommendations, and final verification checkboxes.
To create a Markdown scan report:
itworksbut scan --reportThis writes report.md to the current working directory with check statuses, summaries, details, and recommendations.
To run a controlled API stress test:
itworksbut stress
itworksbut stress --target https://my-own-api.example --i-own-this
itworksbut stress --reportstress only tests local targets by default. For external hosts, pass --i-own-this to confirm that you own the target or have explicit authorization. Mutating endpoints such as POST, PUT, PATCH, and DELETE are discovered but skipped automatically.
name: ItWorksBut
on:
pull_request:
push:
branches: [main]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npx itworksbut scan --fail-on highFor GitHub Code Scanning-style output:
itworksbut scan --sarif > itworksbut.sarifOptional itworksbut.config.json:
{
"ignore": ["dist/**", "build/**", "node_modules/**"],
"failOn": "low",
"checks": {
"env.env-file-tracked": true,
"dependencies.lockfile-missing": true,
"node.rate-limit-missing": false
}
}Checks are enabled by default. Set a check id to false to disable it.
This repository also has itworksbut.self.config.json for its own CI run. It ignores intentional test fixtures and scanner regex files. Do not use that profile if you want the highest finding rate.
Default ignored paths:
node_modules/**
dist/**
build/**
.next/**
.nuxt/**
coverage/**
.git/**
target/**
src-tauri/target/**
out/**
release/**
.vite/**
The baseline includes 51 modular checks:
git.gitignore-missinggit.gitignore-incompletegit.ignored-files-trackedenv.env-file-trackedenv.env-example-missingenv.possible-secret-in-codeenv.frontend-secret-exposuresecrets.secrets-in-logsdependencies.lockfile-missingdependencies.multiple-lockfilesdependencies.install-scripts-riskdependencies.audit-script-missingdependencies.outdated-packagespackage.scripts-missingci.no-ci-configci.npm-install-instead-of-npm-cici.no-build-stepci.no-test-stepnode.express-json-limit-missingnode.rate-limit-missingnode.helmet-missingnode.cors-wildcardnode.child-process-user-inputweb.client-side-auth-onlyweb.dangerous-inner-htmlweb.missing-output-sanitizationapi.missing-auth-on-routesapi.idor-riskauth.jwt-secret-weak-or-fallbackauth.password-hashing-missingauth.missing-csrf-protectionapi.missing-method-guardapi.mass-assignment-riskapi.no-schema-validationdatabase.raw-sql-interpolationdatabase.no-migrationscookies.insecure-session-cookieuploads.public-executable-uploadwebhooks.missing-raw-bodyllm.prompt-injection-riskfrontend.sourcemaps-productionfrontend.localstorage-tokenfiles.path-traversal-riskssrf.user-controlled-fetchnext.public-server-code-riskconfig.debug-productionelectron.node-integration-enabledelectron.context-isolation-disabledelectron.remote-content-with-nodetauri.dangerous-allowlist-or-capabilitiestauri.remote-url-permissions-risk
Each check is a plain ESM module with an id, metadata, and async run(context) function. Add new checks under src/checks/ and register them in src/checks/index.js.
ItWorksBut is a static heuristic scanner. Findings intentionally use wording such as "possible", "potential", and "appears to" when a check is heuristic.
Use it as a CI guardrail for common project hygiene and security mistakes. For production systems, combine it with code review, tests, dependency scanning, secrets scanning, threat modeling, and focused security assessment.
