Skip to content

Case Check ​

devtoolz case-check finds imports whose case doesn't match the real file on disk.

bash
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_modules isn'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's imports map) aren't supported yet.

Example:

bash
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