← All posts

May 10, 2026

Your .gitignore Is Doing More Work Than You Think

Claude .gitignore — what stays local, what ships to GitHub

If you've ever accidentally pushed an API key to GitHub, you know the exact sinking feeling. A .gitignore file tells Git which files to skip entirely — it never tracks them, never includes them in commits, never sends them to the remote. But a well-crafted one, especially for a Claude Code project, does a lot of quiet heavy lifting.

Here's a breakdown of every section in this .gitignore and what would break without each one.

Download a copy of this .gitignore from my Github page: https://github.com/guillaumelai/claude-code-starter/blob/main/.gitignore


Claude Code: The Files That Should Never Leave Your Machine

Entry What it is What happens without it
.claude/settings.local.json Your personal Claude preferences (local overrides) Your local tweaks stomp on teammates' settings every time you commit
.claude/.credentials.json Your API keys and auth tokens Your credentials go public — anyone with repo access can use them
.claude/cache/ Cached responses and indexes Repo fills with gigabytes of cache data that rebuilds itself anyway
.claude/sessions/ Active session state Other devs check out your half-finished session, causing confusing state
.claude/transcripts/ Conversation history with Claude Private conversations and context get committed to version history
.claude/todos/ Your personal task lists Your private TODOs become part of the shared codebase
.claude/projects/ Per-project local metadata Merge conflicts on files that should never be shared
.claude/statsig/ Feature flag evaluation cache Stale flag state gets accidentally shared across environments
.claude/shell-snapshots/ Shell environment snapshots Machine-specific paths and env vars pollute others' setups
.claude/ide/ IDE integration state Editor-specific state causes confusion across different IDE setups

Anthropic SDK Noise

Entry What it is What happens without it
.anthropic/ SDK-level cache and config SDK noise clutters your repo history
*.claude.log Debug log files from Claude Potentially sensitive prompts/responses end up in version control

Secrets & Environment Variables

This is the critical section. Getting this wrong is a security incident waiting to happen.

Entry What it is What happens without it
.env Local environment variables (API keys, DB URLs) Credentials pushed to a public repo — a serious security incident
.env.* All env variants (.env.production, .env.staging) Same risk, across every environment
!.env.example Exception: the example file IS committed Intentional — the template stays, the real values don't
!.env.sample Exception: .env.sample IS committed Same idea — a safe placeholder with dummy values
*.pem SSL/TLS certificate files Private keys exposed — your HTTPS trust can be compromised
*.key Private key files Same risk as .pem files
secrets/ Any folder named secrets/ Ironically, your secrets folder would be completely public

OS Files

Entry What it is What happens without it
.DS_Store macOS folder metadata Every Mac developer pollutes the repo with invisible OS files
Thumbs.db Windows thumbnail cache Every Windows user does the same
desktop.ini Windows folder config More Windows clutter with zero value to the project

Editor / IDE Files

Entry What it is What happens without it
.vscode/ VS Code workspace config Your editor layout, theme, and font size get forced on everyone
!.vscode/settings.json Exception: shared settings ARE committed Shared formatter rules and language settings benefit the whole team
!.vscode/extensions.json Exception: recommended extensions ARE committed Team sees extension suggestions when they open the project
.idea/ JetBrains IDE config IntelliJ/WebStorm personal settings get committed
*.swp, *.swo Vim swap files Open-file indicators from Vim end up in the repo
*~ Backup files (Emacs, etc.) Editor temp files get tracked as if they were real source files

Logs & Temp Files

Entry What it is What happens without it
*.log Any log file Logs grow unbounded inside your git history
logs/ Logs directory Same, but for the whole folder
tmp/, .tmp/, *.tmp Temporary files Transient data gets permanently stored in version history

Node / JavaScript

Entry What it is What happens without it
node_modules/ NPM/Yarn/pnpm dependencies Tens of thousands of files committed — clones become enormous and slow
.pnp.* Plug'n'Play files (Yarn Berry) PnP-specific files cause conflicts on non-Yarn setups
.yarn/cache Yarn's offline cache Large binary files clog the repo history
.yarn/install-state.gz Yarn install state snapshot Machine-specific install state causes broken setups for others
dist/, build/ Compiled output Generated code gets committed — source of truth becomes ambiguous
.next/ Next.js build cache Framework-specific cache fills up the repo
.turbo/ Turborepo build cache Build tool cache committed unnecessarily
.vercel/ Vercel deployment config/cache Local deployment state and sensitive project config gets shared
coverage/ Test coverage reports Auto-generated HTML reports committed instead of generated fresh

Python

Entry What it is What happens without it
__pycache__/ Python bytecode cache Platform-specific .pyc files cause errors on different OSes
*.py[cod] Compiled Python files (.pyc, .pyo, .pyd) Binary bytecode gets version-controlled — it's regenerated anyway
*.egg-info/ Python package metadata Build artifacts clutter the source tree
.venv/, venv/ Python virtual environments Gigabytes of packages get committed; breaks on any other machine
.pytest_cache/ pytest's test cache Test run artifacts get unnecessarily tracked
.mypy_cache/ mypy type-checking cache Type checker cache is machine-specific and large
.ruff_cache/ Ruff linter cache Linter artifacts don't belong in version control

Misc Build Artifacts

Entry What it is What happens without it
*.tsbuildinfo TypeScript incremental build info TS compiler state files get committed — they're machine-specific
.cache/ Generic cache directories Catch-all for tool caches that would otherwise bloat the repo

The Three Rules Behind All of This

Every entry in this .gitignore falls into one of three categories:

1. Secrets — credentials, API keys, env files, private keys. These should never touch version control. A single leaked key can mean a compromised account, unexpected cloud bills, or a full security incident.

2. Runtime state — caches, sessions, logs, temp files. These are generated fresh each time you run your project. Committing them creates merge conflicts, repo bloat, and machine-specific files that break other people's setups.

3. Build artifactsnode_modules, dist, __pycache__, virtual environments. These are derived from your source code and can always be regenerated. They don't belong in git.

Notice what's not ignored: CLAUDE.md, .claude/settings.json, .claude/agents/, .claude/commands/, .claude/skills/, .claude/hooks/. These are the files meant to be shared — they define how Claude behaves for the whole team. The .gitignore draws a clear line between "yours alone" and "everyone's."

A good .gitignore is the quiet guardrail that keeps your repo clean, your secrets safe, and your team collaborating without friction.