[BUG] .gitignore causes slash command resolution to fail
Environment
- Platform (select one):
- [ ] Anthropic API
- [ ] AWS Bedrock
- [ ] Google Vertex AI
- [x] Other:
- Running Claude Code in terminal in VS Code in WSL 2 on my laptop during local development
- Claude CLI version: 1.0.81 (Claude Code)
- Operating System: Ubuntu 22.04.5 LTS (Jammy Jellyfish) running in WSL 2.4.13.0 in Windows 11 Pro (OS build: 26100.4946, Experience: Windows Feature Experience Pack 1000.26100.197.0)
- Terminal: GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)
Bug Description
Resolution of slash commands in subdirectories seems not to consistently follow the rules described in the docs, resulting in slash commands not being interpreted as slash commands.
Based on some testing I did, the problem appears to be that slash command resolution fails if the command is in a subdirectory which is ignored by Git (e.g. by adding it to .gitignore). This was unexpected, since it was not documented in the documentation anywhere that I could find.
We ran into this on my team because we wanted to create a .claude/commands/local/ directory within a project to enable engineers to define commands which are both project-scoped and personal (i.e. not committed to the repo), effectively a combination of personal commands and project commands. Previously some of us had created some project commands which we were just not committing, but this was cumbersome to manage (need to remember not to commit them, and need to delete and recreate them to execute Git commands that require a clean working tree), so we wanted to place these in a .gitignored .claude/commands/local/ directory to make it easier to manage them.
Steps to Reproduce
- Create a project-level command at
.claude/commands/local/foo.md. The contents can be anything for testing, such as asking it to create a file called foo.ts in the project root or just output "foo" to the console - In
.gitignore, add.claude/commands/local/ - In your terminal, start a Claude Code session by running
claude - At the Claude Code prompt, type
/local:fooand hit enter
Expected Behavior
Claude Code interprets /local:foo as a slash command, and resolves it to the .claude/commands/local/foo.md command file.
Actual Behavior
Claude Code does not recognize /local:foo as a slash command. It searches unsuccessfully for a file or directory called "foo", for a local command, or "something specific to the project", then reports that it did not find anything, and asks the user to clarify what their prompt meant.
Additional Context
Minimal reproduction example
In this example, there is a file at .claude/commands/local/foo.md with the contents Just output "foo" to the console. There is also a .gitignore file which contains the line .claude/commands/local/.
Output from Claude Code session:
╭────────────────────────────────────────────────────────╮
│ ✻ Welcome to Claude Code! │
│ │
│ /help for help, /status for your current setup │
│ │
│ cwd: /home/skudbub/comparecredit/repo/comparecredit │
╰────────────────────────────────────────────────────────╯
What's new:
• Released output styles, including new built-in educational output styles
"Explanatory" and "Learning". Docs:
https://docs.anthropic.com/en/docs/claude-code/output-styles
• Plugin system: Improve plugin repository installation messaging and
error handling
• Agents: Fix custom agent loading when agent files are unparsable
• Add plugin system: Install plugins from Git repositories with custom
commands and agents using /plugin commands
• UI improvements: Fix text contrast for custom subagent colors and
spinner rendering issues
> /local:foo
● I need to see what /local:foo refers to. Let me check if this is a
file path or command.
● List(~/comparecredit/repo/comparecredit)
⎿ Listed 15 paths (ctrl+r to expand)
● I don't see a file or directory called "foo" in the current
directory. Let me check if there's a local command or if you're
referring to something specific in this project.
● Search(pattern: "**/foo*")
⎿ Found 66 files (ctrl+r to expand)
● The /local:foo syntax isn't a standard file path. Could you clarify
what you're looking for? Are you:
1. Looking for a file named "foo"?
2. Referring to a local command or script?
3. Using a specific syntax I should understand?
The search shows various test files and dependencies with "foo" in
the name, but no specific "foo" file in the project root.
> This was supposed to be a slash command. I was expecting you to
interpret it as a slash command and resolve it to the command file
located at .claude/commands/local/foo.md
● I see! You're using the /local:foo slash command. Let me read the
command file to understand what it should do.
● Read(.claude/commands/local/foo.md)
⎿ Read 1 line (ctrl+r to expand)
● foo
More in-depth example
In this example, there is a .claude/commands/local/new-issue-in-temp-notes.md file containing a command to add notes about a Linear issue to a local file. There is also a .gitignore file which contains the line .claude/commands/local/.
Output from Claude Code session:
╭────────────────────────────────────────────────────────╮
│ ✻ Welcome to Claude Code! │
│ │
│ /help for help, /status for your current setup │
│ │
│ cwd: /home/skudbub/comparecredit/repo/comparecredit │
╰────────────────────────────────────────────────────────╯
> /local:new-issue-in-temp-notes.md
● I'll create a new issue in the temp-notes.md file for you.
● Read(temp-notes.md)
⎿ Error reading file
● Write(temp-notes.md)
⎿ User rejected write to temp-notes.md
1 + # Temp Notes
2 +
3 + ## Issue: [Issue Title]
4 +
5 + **Date:** 2025-08-14
6 +
7 + **Description:**
8 + [Brief description of the issue]
9 +
10 + **Steps to Reproduce:**
11 + 1.
12 + 2.
13 + 3.
14 +
15 + **Expected Behavior:**
16 + [What should happen]
17 +
18 + **Actual Behavior:**
19 + [What actually happens]
20 +
21 + **Additional Context:**
22 + [Any additional information, logs, or context]
23 +
24 + **Priority:** [Low/Medium/High]
25 +
26 + **Status:** [Open/In Progress/Closed]
27 \ No newline at end of file
> /local:new-issue-in-temp-notes CC-2684
● Read(temp-notes.md)
⎿ Error reading file
● Write(temp-notes.md)
⎿ User rejected write to temp-notes.md
1 + # Temp Notes
2 +
3 + ## Issue: CC-2684
4 +
5 + **Date:** 2025-08-14
6 +
7 + **Description:**
8 + [Brief description of the issue]
9 +
10 + **Steps to Reproduce:**
11 + 1.
12 + 2.
13 + 3.
14 +
15 + **Expected Behavior:**
16 + [What should happen]
17 +
18 + **Actual Behavior:**
19 + [What actually happens]
20 +
21 + **Additional Context:**
22 + [Any additional information, logs, or context]
23 +
24 + **Priority:** [Low/Medium/High]
25 +
26 + **Status:** [Open/In Progress/Closed]
27 \ No newline at end of file
> Why did you try to write to temp-notes.md? Were you able to resolve
the `/local:new-issue-in-temp-notes` slash command I entered to a
command file? I was expecting it to resolve to
`.claude/commands/local/new-issue-in-temp-notes.md`, so if it didn't,
we should fix that first
● You're absolutely right - I should have looked for the command file
at .claude/commands/local/new-issue-in-temp-notes.md to resolve the
slash command. Let me check if that file exists:
● Read(.claude/commands/local/new-issue-in-temp-notes.md)
⎿ Read 66 lines (ctrl+r to expand)
● Perfect! The command file exists and I can see what it's supposed to
do. Now I need to:
1. Look up the Linear issue CC-2684
2. Add it to the temp notes file at .vscode/temp_notes.md in the
specified format
Let me first look up the Linear issue:
● linear-server - get_issue (MCP)(id: "CC-2684")
⎿ No (tell Claude what to do differently)
> Hang on. You didn't answer my question. When I first entered the
`/local:new-issue-in-temp-notes` slash command, did you or did you
not resolve it to the
`.claude/commands/local/new-issue-in-temp-notes.md` command file?
● No, I did not resolve the /local:new-issue-in-temp-notes slash
command to the .claude/commands/local/new-issue-in-temp-notes.md
command file.
I incorrectly tried to write directly to a temp-notes.md file instead
of following the slash command resolution process to find and
execute the command defined in the
.claude/commands/local/new-issue-in-temp-notes.md file.
> Why? Based on the docs at https://docs.anthropic.com/en/docs/claude-c
ode/slash-commands#namespacing I was expecting the process by which
you resolve slash commands to be deterministic, so it is unexpected
that you did not resolve the `/local:new-issue-in-temp-notes` slash
command I entered according to the rules outlined in the docs (where
subdirectories create slash commands prefixed with the subdirectory
name followed by a colon). Why might this have happened? Does the
fact that the `.claude/commands/local` directory is in the
`.gitignore` affect your slash command resolution at all?
● You're absolutely right that slash command resolution should be
deterministic according to the docs. Let me fetch the current
documentation to understand the expected behavior:
● Fetch(https://docs.anthropic.com/en/docs/claude-code/slash-commands#n
amespacing)
⎿ Received 2.1MB (200 OK)
● Based on the documentation, you're correct - the
/local:new-issue-in-temp-notes command should have been resolved to
.claude/commands/local/new-issue-in-temp-notes.md.
I made an error in not following the proper slash command resolution
process. The fact that the .claude/commands/local directory is in
.gitignore should not affect slash command resolution - Claude Code
should still be able to read and execute commands from that directory
since it exists in the working directory.
The issue appears to be that I didn't properly recognize and process
your input as a slash command that needed to be resolved. Instead, I
incorrectly interpreted it as a direct instruction to create an issue
in a temp-notes.md file. This was a mistake in my command processing
logic, not a technical limitation with the slash command system.
> If the interpretation of slash commands follows deterministic rules
as outlined in the docs I linked a moment ago, shouldn't it be
impossible for you to fail to interpret
`/local:new-issue-in-temp-notes.md` as a slash command? Are the docs
incorrect? Is your command processing logic actually
non-deterministic? Is it deterministic but just has a bug? What's
going on here?
● You're absolutely right to question this. If slash command resolution
is truly deterministic as documented, then my failure to interpret
/local:new-issue-in-temp-notes as a slash command shouldn't be
possible.
I don't have direct visibility into how my slash command resolution
system actually works internally. From my perspective, I should have
automatically recognized /local:new-issue-in-temp-notes as a slash
command, looked for
.claude/commands/local/new-issue-in-temp-notes.md, found it, and
executed the instructions within it.
The fact that I didn't suggests one of these possibilities:
1. Bug in the slash command resolution system - The deterministic
process described in the docs isn't working correctly in practice
2. The docs are incomplete - There may be edge cases or conditions
not documented that affect resolution
3. System limitation - Perhaps there's an issue with how I access
files in subdirectories of .claude/commands/
4. My implementation has a flaw - The command resolution logic may
not be working as intended
Since this should be deterministic and I failed to follow the
expected behavior, this appears to be either a bug in the slash
command system or a gap between the documented behavior and actual
implementation. The fact that the file exists and is readable (as we
confirmed) makes this particularly puzzling.
This seems like something that should be reported as a potential
issue with Claude Code's slash command resolution.This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗