← All writing
tooling·4 min read

Installing Claude Code on macOS and Windows

A practical setup guide for Anthropic's terminal coding agent — installation on both platforms, the PATH and permission problems you will hit, and the configuration that makes it genuinely useful.

Irfan Ali

Software Engineer

Claude Code is Anthropic's terminal-based coding agent. It reads your project, edits files, runs commands, and iterates on the result — from the same shell you already work in.

This is the setup I use on both macOS and Windows, plus the configuration that made the biggest difference once it was running.

Before you start

You need three things:

  • Node.js 18 or newer. Check with node --version.
  • A Claude account on a paid plan, or an Anthropic API key.
  • A terminal you actually like. You will be living in it.

If Node is missing or old, install it first. On macOS I use Homebrew; on Windows, winget.

bash
# macOS
brew install node

# Windows (PowerShell)
winget install OpenJS.NodeJS.LTS

Installing on macOS

Open Terminal and install the CLI globally:

bash
npm install -g @anthropic-ai/claude-code

Then check it resolved:

bash
claude --version

If you get command not found, npm's global bin directory is not on your PATH. Find it and add it to your shell profile:

bash
npm config get prefix
# → /opt/homebrew  (or /usr/local)

echo 'export PATH="$(npm config get prefix)/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc

Avoid sudo npm install -g. It creates root-owned files in your npm prefix that cause permission errors later. If you already did, sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share} will fix the ownership.

Installing on Windows

Claude Code runs natively on Windows and inside WSL. Native is simpler if you are working on Windows-based projects.

powershell
npm install -g @anthropic-ai/claude-code
claude --version

If PowerShell blocks the script with an execution policy error, allow local scripts for your user only:

powershell
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned

Working inside WSL instead? Install it in the Linux environment, not Windows — a Windows-installed binary operating on /mnt/c paths is slow and hits permission problems:

bash
wsl
npm install -g @anthropic-ai/claude-code

First run

Change into a project and start it:

bash
cd ~/projects/my-app
claude

The first run walks you through authentication in the browser. After that, just describe what you want:

text
> add a health check endpoint and a test for it

It reads the relevant files, proposes edits, and asks before running anything that changes your machine.

The settings that actually matter

Configuration lives in .claude/settings.json — either in the project or in ~/.claude/ for every project.

The single highest-value change is an allowlist. By default Claude asks permission for each command; approving read-only ones once removes most of the interruptions:

json
{
  "permissions": {
    "allow": [
      "Bash(npm run test:*)",
      "Bash(npm run lint)",
      "Bash(git status)",
      "Bash(git diff:*)"
    ]
  }
}

Note the :* suffix — it permits arguments after the prefix. Bash(git diff:*) allows any git diff invocation but not git push.

Give it project context

A CLAUDE.md at the repo root is read at the start of every session. Mine covers the things a new contributor would otherwise get wrong:

markdown
# CLAUDE.md

## Commands
npm run dev       # local dev server
npm run verify    # typecheck + lint + tests + build

## Conventions
- Server Components read the database directly; never fetch on the client.
- Every mutation validates with Zod before it touches Prisma.

Keep it short and specific. Write down the things that are surprising, not the things that are obvious from the code.

Two habits worth forming

Ask for a plan before a large change. Getting the approach agreed first is much cheaper than reviewing a hundred lines going in the wrong direction.

Make verification runnable. A single npm run verify that typechecks, lints, tests, and builds means the agent can check its own work instead of handing you something that merely looks finished. This is the difference between "it wrote code" and "it wrote code that works".

Common problems

SymptomCauseFix
command not found: claudenpm global bin not on PATHAdd $(npm config get prefix)/bin to your shell profile
EACCES on installnpm prefix owned by rootchown the prefix to your user, do not use sudo
Very slow inside WSLWorking across /mnt/cKeep the repo in the Linux filesystem
Changes are not picked upSession started before the files existedRestart the session in the project root

Worth knowing

It is an agent, not an autocomplete. It is at its best on tasks with a clear finish line it can verify itself — migrate this to the new API, add coverage for this module, track down why this test fails intermittently. Point it at work you can describe precisely and check afterwards, and it earns its place in the toolchain quickly.