Claude Code CWD Tracker
A Claude Code plugin that fixes the working directory tracking bug. When Claude runs cd commands, it loses track of where it is—this hook tells it.
The Problem
When Claude Code runs a Bash command containing cd (e.g., mkdir -p foo && cd foo && npm pack), the shell's working directory changes, but Claude is never informed. The system prompt's <env>Working directory: X</env> is static—set at session start and never updated.
This causes Claude to:
- Construct wrong absolute paths in subsequent tool calls
- Try to
cd into directories it's already in
- Use Search/Grep tools with non-existent paths
This bug has been reported 24+ times in GitHub issues #1669, #4100, #11067, #14122, and others.
Example of the Bug
You: "Download the package and extract it"
Claude runs: mkdir -p myproject && cd myproject && npm pack @some/package
✓ Works fine - Claude is now IN myproject/
Claude runs: cd myproject && tar -xzf package.tgz
✗ ERROR: "no such file or directory: myproject"
(Claude tried to cd into a directory it's already in)
Claude runs: ls /original/path/package.tgz
✗ ERROR: file not found
(File is actually at /original/path/myproject/package.tgz)
The Solution
This plugin uses Claude Code's hook system to detect when the working directory changes and notify Claude via the tool output. Claude then knows exactly where it is and constructs correct paths.
How It Works
┌─────────────────────────────────────────────────────────────────┐
│ Claude runs: mkdir -p foo && cd foo && touch file.txt │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ PostToolUse hook fires after Bash command completes │
│ Hook receives JSON with current cwd from Claude Code │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Hook compares current cwd against stored previous cwd │
│ Previous: /home/user/project │
│ Current: /home/user/project/foo │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ CWD changed! Hook outputs to stderr + exits with code 2 │
│ "Note: Working directory changed from '...' to '...'" │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Claude receives notification in tool result │
│ Claude now knows it's in /home/user/project/foo │
│ Subsequent commands use correct paths │
└─────────────────────────────────────────────────────────────────┘
Key insight: Claude Code's hook system feeds stderr + exit code 2 back to the LLM. Exit code 0 with stdout is only shown in the transcript (invisible to Claude).
Tech Stack
- Language: Bash
- Dependencies: Python 3 (for JSON parsing)
- Claude Code Version: 2.x+ (requires hook support)
- Platform: macOS, Linux (anywhere Bash runs)
Prerequisites
- Claude Code CLI installed
- Python 3 (usually pre-installed on macOS/Linux)
- Bash shell
Installation
Option 1: Plugin Marketplace (Recommended)
The easiest way to install is via Claude Code's plugin system:
# Add the marketplace
/plugin marketplace add gruckion/claude-code-cwd-tracker
# Install the plugin
/plugin install cwd-tracker
That's it! The plugin is now active. On session start, you'll see:
✓ CWD Tracker loaded: Working directory changes will be tracked
Option 2: Manual Installation
If you prefer manual installation:
1. Create the hooks directory
mkdir -p ~/.claude/hooks
2. Download the hook script
curl -o ~/.claude/hooks/cwd-notify.sh \
https://raw.githubusercontent.com/gruckion/claude-code-cwd-tracker/main/scripts/cwd-notify.sh
Or clone the repository:
git clone https://github.com/gruckion/claude-code-cwd-tracker.git
cp claude-code-cwd-tracker/scripts/cwd-notify.sh ~/.claude/hooks/
3. Make it executable
chmod +x ~/.claude/hooks/cwd-notify.sh
4. Configure Claude Code
Add the hook to your ~/.claude/settings.json: