A high-performance CLI tool written in Go to automatically format and sort JavaScript and TypeScript imports by length. Optimized for very large repositories and CI/CD pipelines.
➜ express-api git:(main) jsimportfmt ./router/apps.ts --dry-runThe output is all my imports are now formatted from shortest to longest.
Yes, Its a very niche tool and I just like my imports looking neet
--- ./router/apps.ts (original)
+++ ./router/apps.ts (formatted)
@@ -1,13 +1,13 @@
import { Router } from "express";
-import { getTaxonomy } from "#/controllers/apps/taxonomy.Controller";
-import * as RfsController from "#/controllers/apps/rfs.Controller";
-import * as AppsController from "#/controllers/apps/apps.Controller";
-import * as ContributeController from "#/controllers/apps/contribute.Controller";
-import * as SubmitController from "#/controllers/apps/submit.Controller";
-import { authenticate } from "#/middleware/auth.middleware";
import { UserRole } from "#/models/user.model";
+import { authenticate } from "#/middleware/auth.middleware";
import { validate } from "#/middleware/validation.middleware";
import * as ValidationSchema from "#/validation/apps.validation";
+import * as RfsController from "#/controllers/apps/rfs.Controller";
+import * as AppsController from "#/controllers/apps/apps.Controller";
+import { getTaxonomy } from "#/controllers/apps/taxonomy.Controller";
+import * as SubmitController from "#/controllers/apps/submit.Controller";
+import * as ContributeController from "#/controllers/apps/contribute.Controller";
const router = Router();
✔ scanned 1 files- Blazing Fast: Written in Go using concurrent worker pools.
- Smart Parsing: Uses a lightweight state-machine parser instead of a slow AST, ensuring comments, spacing, and formatting within imports are perfectly preserved.
- Git & Gitignore Aware: Automatically respects
.gitignorerules if a.gitfolder is found within 2 levels of the target. - Non-Git Support: Works seamlessly in any directory, even without a Git repository.
- Type Separation: Built-in support to separate type imports (
--separate-types). - Interactive Mode: Launch a guided session by simply running
jsimportfmt. - Multiple Modes: Supports Write (
--write), Check (--check), and Dry-Run (--dry-run) modes.
go install github.com/0necontroller/jsimportfmt@latestgit clone https://github.com/0necontroller/jsimportfmt.git
cd jsimportfmt
go build -o jsimportfmt .Launch a guided session by running the command without arguments:
jsimportfmtScan and rewrite all supported files in a folder:
jsimportfmt ./src --writeTarget a specific file directly:
jsimportfmt ./src/App.tsx --writeSee a unified diff of what would change without modifying any files:
jsimportfmt src --dry-runExample Output:
--- src/index.ts (original)
+++ src/index.ts (formatted)
@@ -1,6 +1,6 @@
+import fs from "fs";
+import path from "path";
import { App } from "./App";
import { Config } from "./config";
-import path from "path";
-import fs from "fs";Sort regular imports and type imports into separate blocks:
jsimportfmt src --write --separate-typesExample: Before:
import type { User } from "./types";
import React from "react";
import type { Config } from "./config";
import { Button } from "./components";After:
import React from "react";
import { Button } from "./components";
import type { User } from "./types";
import type { Config } from "./config";List the default ignores and those parsed from .gitignore:
jsimportfmt . --check-ignoreAllow formatting in ignored directories using a .jifallow file or the --allow flag.
Automatic Persistence:
Using the --allow flag (e.g., --allow dist) will automatically append the directory to your .jifallow file if it's not already listed. If the file doesn't exist, it will be created with a helpful header comment.
jsimportfmt . --allow dist --allow buildThe .jifallow file supports # comments and one directory per line. Any directory listed there (or passed via --allow) will bypass both default ignores and .gitignore rules.
See .jifallow.example for a concrete example.
Verify formatting without making changes:
jsimportfmt src --checkYou can use jsimportfmt in your CI pipeline to enforce import formatting. Use the --check flag:
steps:
- name: Check Import Formatting
run: jsimportfmt . --check0: Success (no formatting needed, or all files successfully formatted in write mode)1: Formatting needed (returned in--checkmode)2: Fatal error (e.g., file parsing failed or system error)
jsimportfmt streams file discovery and feeds a worker pool matched to your system's CPU count (runtime.NumCPU()). It reads, parses, and formats files incrementally, ensuring low memory overhead even for monorepos with tens of thousands of files.