Case Check
devtoolz case-check finds imports whose case doesn't match the real file on disk.
devtoolz case-check [paths...] [options]Windows and macOS don't care about case in filesystem paths by default, so import './foo' against a real Foo.ts opens without a single complaint — right up until that same code builds on Linux CI, where case matters. Every path segment is checked, not just the file name itself (./Utils/helper against a real utils/ directory is a finding too, not just the final file), plus an import with no extension (import './Foo' is compared by its shared prefix without the extension, the real file can be Foo.ts).
Real output — a file got renamed from Helper.ts to helper.ts, the import was never updated:
🧰 devtoolz, reporting for duty
Scanned 2 files.
1 case mismatch found:
src/main.ts:1:23 ./helper.js → ./Helper.js
(pass --fix -y to apply, or --fix --diff to preview the fix)tsconfig.json aliases
Aliases from compilerOptions.paths/baseUrl are resolved just like regular relative imports — tsconfig.json is auto-detected in --cwd by default, or set explicitly with --tsconfig. A mismatch found through an alias is flagged separately and is not rewritten by --fix:
🧰 devtoolz
Scanned 2 files.
1 case mismatch found:
src/main.ts:1:23 @/utils/format.js → ./Utils/format.js (alias, not auto-fixed)The reason: rewriting @/utils/format.js to the real case would mean changing the alias itself into something that no longer matches what was set up in tsconfig.json — safer to report it and leave the decision to a human.
Options
--fix
Rewrite the mismatched specifier to its real case (alias-resolved ones excluded, see above). The originally written extension is preserved — only the name's own case changes. --fix alone writes nothing without -y/--yes, for consistency with the other commands.
Previewing the fix (--fix --diff --dry-run):
🧰 devtoolz — chores, automated
Scanned 2 files.
1 case mismatch found:
src/main.ts:1:23 ./helper.js → ./Helper.js
Would fix 1 import(s) in 1 file(s) — pass -y to apply.
── src/main.ts (1 import) ────────────────────────────────────────────
@@ -1,3 +1,3 @@
-import { greet } from './helper.js'
+import { greet } from './Helper.js'
console.log(greet('world'))Applying the fix (--fix -y):
🧰 devtoolz — chores, automated
Scanned 2 files.
1 case mismatch found:
src/main.ts:1:23 ./helper.js → ./Helper.js
Fixed 1 import(s) in 1 file(s).--tsconfig <path>
tsconfig.json to read path aliases from (auto-detected in --cwd by default).
--dry-run
Preview without writing anything.
-y, --yes
Actually apply the fix.
--diff
A unified diff per changed file.
--cwd <path>
Root paths are resolved against.
--ext <list>
Comma-separated extensions to include. Default: .ts,.tsx,.js,.jsx,.cjs,.mjs,.vue.
--ignore <glob>
Extra ignore pattern (repeatable) on top of the built-in defaults.
--no-respect-gitignore
Don't also honor the project's .gitignore.
Known limitations
- Bare package imports (
import 'lodash') are out of scope —node_modulesisn't checked. - A case-insensitive filesystem might not even record a file rename as a git change locally — the tool checks against what's really on disk right now, not git history; that's a limitation of the method, not a bug.
- Subpath imports (
#internal/...,package.json'simportsmap) aren't supported yet.
Example:
devtoolz case-check src # just find them
devtoolz case-check src --fix --diff --dry-run # preview the fix
devtoolz case-check src --fix -y # apply it
devtoolz case-check src --tsconfig ./tsconfig.app.json --fix -y