sh: tailwind: command not found — v4 Ships No Binary at All
Tailwind v4's package declares no `bin`, so npm links nothing. Measured in this repo: 26 entries in node_modules/.bin, none of them tailwind.
sh: tailwind: command not found in a Tailwind v4 project is usually not a broken install. As of v4 the tailwindcss package ships no executable at all — its package.json has no bin field, so npm creates nothing in node_modules/.bin. The CLI moved to a separate package, @tailwindcss/cli.
That distinction matters because the usual advice for this error — delete node_modules, reinstall, add npx, install it globally — fixes a v3 problem. In v4 a perfectly healthy install produces exactly this error the moment something tries to run tailwind or tailwindcss as a command.
What a healthy v4 install actually contains
This storefront is a Tailwind v4 project with 111 product pages, a CSS-first token file and zero build complaints. Here is its Tailwind surface, measured rather than remembered:
$ node -e 'const p=require("tailwindcss/package.json"); console.log(p.version, p.bin)'
4.3.1 undefined
$ ls node_modules/.bin | wc -l
26
$ ls node_modules/.bin | grep -i tailwind
$ echo "exit: $?"
exit: 1
$ ls node_modules/@tailwindcss/
node
oxide
oxide-linux-x64-gnu
oxide-linux-x64-musl
postcss
Three things worth reading carefully. p.bin is undefined — the package declares no executable, so there is nothing for npm to link. The .bin directory has 26 entries and grep finds none of them matching tailwind. And @tailwindcss/cli is not in node_modules/@tailwindcss/ at all, because nothing here needs it.
So tailwindcss is installed, Tailwind compiles on every build, and tailwind --help still fails. That is the expected state, not a symptom.
The commands that produce this error, and what each becomes
| What you ran | Why it fails in v4 | What to run instead |
|---|---|---|
tailwind -i in.css -o out.css | Never a real binary name, even in v3 | npx @tailwindcss/cli -i in.css -o out.css |
tailwindcss -i in.css -o out.css | The tailwindcss package no longer declares a bin | npx @tailwindcss/cli -i in.css -o out.css |
npx tailwindcss init | init was removed with tailwind.config.js | Nothing — configuration moved into CSS via @theme |
npx tailwindcss init -p | Same, plus PostCSS config is now written by hand | Create postcss.config.mjs yourself (four lines, below) |
tailwindcss in an npm script | Resolves through node_modules/.bin, which has no such entry | Either add @tailwindcss/cli as a devDependency, or drop the script |
npm i -g tailwindcss then tailwindcss | A global install of a package with no bin still installs no command | Install @tailwindcss/cli, not tailwindcss |
The row that catches most people is the third. npx tailwindcss init is the single most-copied Tailwind command in circulation, it appears in thousands of tutorials written against v3, and in v4 there is no config file for it to create.
What replaced the CLI in this codebase: four lines of PostCSS
Nothing in this repo ever invokes a Tailwind binary. The compiler runs as a PostCSS plugin, which is the whole of the build wiring:
// postcss.config.mjs
const config = {
plugins: {
"@tailwindcss/postcss": {},
},
};
export default config;
And the scripts that use it never mention Tailwind:
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"format": "prettier --write .",
"format:check": "prettier --check .",
"test": "vitest run"
}
@tailwindcss/postcss@4.3.1 carries the same compiler the CLI would run. Next.js hands it the stylesheet, it returns the compiled CSS, and no shell command is involved at any point. If your framework has a PostCSS or Vite integration — Next.js, Vite, Astro, Nuxt, Remix — you are in this situation too, and the CLI is not part of your build. Adding Tailwind to a React project is the same three lines of config, whichever bundler is underneath.
Where the configuration went
The second half of the init confusion is that there is no tailwind.config.js to generate:
$ ls tailwind.config.*
ls: cannot access 'tailwind.config.*': No such file or directory
Configuration is CSS now. The top of src/app/globals.css is the entire setup:
@import "tailwindcss";
/* Class-based dark mode (toggled by adding `dark` to <html>) */
@custom-variant dark (&:where(.dark, .dark *));
@theme {
--font-sans: var(--font-outfit), ui-sans-serif, system-ui, sans-serif;
/* Brand / primary scale */
--color-primary: #465fff;
--color-primary-25: #f2f7ff;
--color-primary-50: #ecf3ff;
/* … the rest of the scale */
}
One @import replaces the three @tailwind directives, @custom-variant replaces darkMode: "class", and @theme replaces the whole theme.extend object. Moving configuration into CSS is also the change that most affects whether Tailwind is worth adopting at all, since there is no longer a JavaScript config file to review. There is no content array either — v4 discovers sources itself. The full before/after is in the v4 migration guide; the point here is only that init has nothing left to write, which is why it was removed rather than kept as a no-op.
When you genuinely do want @tailwindcss/cli
The CLI still exists and is still the right tool in one situation: a project with no JavaScript build step that needs a compiled stylesheet. A Rails or Phoenix app, a static HTML site, a Hugo theme, a browser extension assembled by hand.
npm install -D @tailwindcss/cli
npx @tailwindcss/cli -i ./src/input.css -o ./dist/output.css --watch
Note what this does not fix: if your build already runs PostCSS or Vite, adding the CLI gives you a second compiler producing a second stylesheet, and the usual result is styles that work in one output and not the other. Reach for it when you have no bundler, not when a command is missing.
The deploy-time version of the same error
The error is more alarming in CI than locally, because the build log reads like a broken lockfile. It is almost always the same cause with a different trigger:
sh: 1: tailwindcss: not found
Error: Command "npm run build" exited with 1
Three checks, in this order. Is there a tailwindcss invocation in any npm script, a Procfile, a Dockerfile RUN, or a Makefile? Was tailwindcss moved into devDependencies while the deploy runs npm ci --omit=dev? And is the platform's build command still a v3-era npx tailwindcss -i … -o … line left over from before the framework integration existed? On this project the answer to all three is "no invocation exists", which is why next build is the only build command in package.json.
Mistakes and how they show up
| Symptom | Cause | Fix |
|---|---|---|
sh: tailwind: command not found after a clean npm install | v4's tailwindcss declares no bin | Expected — use @tailwindcss/cli, or nothing if a bundler compiles for you |
npx tailwindcss init fails or prompts to install a package | init was removed with the config file | Configure in CSS with @theme; write postcss.config.mjs by hand |
Reinstalling node_modules does not help | Nothing is missing; the binary does not exist in v4 | Stop reinstalling and check which command is being run |
npx tailwindcss appears to work but downloads something | npx fetched a remote package because nothing local matched | Name the package explicitly: npx @tailwindcss/cli |
Utilities compile but a new --color-* token does nothing | Turbopack does not hot-reload @theme | Restart npm run dev — a documented gotcha in this repo's own CLAUDE.md |
| Two stylesheets disagree about which classes exist | Both the CLI and the PostCSS plugin are compiling | Pick one; with a bundler, delete the CLI step |
CI fails with tailwindcss: not found but local builds pass | A v3-era build command survives in the platform config | Replace it with the framework's own build command |
Frequently asked questions
Is sh: tailwind: command not found a bug in Tailwind v4?
No. The tailwindcss package intentionally ships no executable in v4 — verified above, its package.json bin field is undefined. The CLI was split out as @tailwindcss/cli so that projects with a bundler do not install a binary they never run.
Do I need @tailwindcss/cli if I use Next.js, Vite or Astro?
No. Those frameworks compile Tailwind through PostCSS or a Vite plugin. This storefront's entire build wiring is the four-line postcss.config.mjs above, and @tailwindcss/cli is absent from its node_modules.
Why does npx tailwindcss init no longer work?
Because tailwind.config.js no longer exists to be initialised. Theme values, custom variants and plugins are declared in CSS — @theme, @custom-variant, @plugin — so there is no file for init to scaffold.
Should I install Tailwind globally to fix this?
No, and it would not help: installing a package with no bin field globally still creates no command. If you want the CLI available ad hoc, npx @tailwindcss/cli runs it without installing anything permanently.
How do I tell whether my project needs the CLI at all?
Search your project for the string tailwindcss outside of package.json and your CSS. If the only hits are a PostCSS or Vite config, your bundler is the compiler and the CLI has no role. If you find it in a shell script, a Procfile or a Dockerfile, that line is what needs updating.
Templates in this post
ASoc Catalyst is an AI-automation agency marketing site with a service grid, delivery process and 3-tier pricing. ASoc Chain is a DeFi-protocol marketing site with self-custody messaging and an on-chain 3D hero visual. ASoc Cognition is an AI-consulting agency landing page with services, pricing, projects and case results. All three are Tailwind v4 builds with the same CSS-first setup described above — one @import, one @theme block, no config file and no CLI step to inherit.
Browse the full sets: Next.js landing page templates, Tailwind landing page templates.
