anthropics / anthropics/claude-code
[BUG] Unrecognized slash commands moved from a free, deterministic rejection to a paid, highly variable model call, with cost rising undocumented across releases
- Dominant language
- Python
- Stars
- 145k
- Forks
- 23.1k
- PR merge metrics
- PR metrics pending
Description
### Preflight Checklist
- [x] I have searched [existing issues](https://github.com/anthropics/claude-code/issues?q=is%3Aissue%20state%3Aopen%20label%3Abug) and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
### What's Wrong?
An unrecognized slash command used to be rejected locally, for free, with a fixed error string.
As of 2.1.273 it instead routes through the model via a new `unknown_command_fallback`
attachment kind, at a real cost. Between 2.1.273 and 2.1.274, the cost for the *identical* input
rose roughly 20-27x, and kept varying a lot run to run on the same build:
| Version | Handling | Observed cost | Reply shape |
|---|---|---|---|
| pre-2.1.273 | Rejected locally | $0 | Fixed literal, e.g. `Unknown command: /some-command` |
| 2.1.273 | Routed to the model | $0.000951 (one measurement) | Short fallback line |
| 2.1.274 | Routed to the model, same mechanism | $0.00917, $0.023845, $0.0212, $0.02302, $0.020645, $0.025795, $0.1234 (seven measurements, same session, same unflagged command) | Longer, contextual clarification — e.g. asking whether the user meant an overview of agent/subagent types, or a list of installed plugins |
Nothing indicates the cost or the reply shape changed between 2.1.273 and 2.1.274. There is no
release-note entry we could find for this path, and no way for a caller to tell in advance which
of the seven observed costs a given call will land near.
### What Should Happen?
Any of these would help, in order of preference:
1. **Give non-interactive callers a way back to the old free, deterministic rejection.** A script,
CI job, or agent that sends a mistyped or unsupported slash command via `claude -p` now pays a
real, unpredictable amount for what used to be instant and free, with no opt-out.
2. **Bound the fallback reply's length**, so its cost stays in a narrow, predictable band instead
of ranging from under a cent to well over ten cents for the same input.
3. **Document the change.** The move from a local rejection to a model-routed fallback, and its
cost, do not appear to be documented anywhere a caller would find them before hitting it.
### Error Messages/Logs
```shell
There is no error — every call below succeeds and returns a result record. The defect is the
cost and its variance, not a failure.
Command used for every sample below:
claude -p "/plugin-types" --output-format stream-json --verbose
(any unregistered slash command reproduces the same fallback path; this one was already
instrumented by an internal test)
total_cost_usd observed across 7 back-to-back calls on 2.1.274, same session, same unflagged
install, no conversation state carried between calls:
0.00917
0.1234
0.023845
0.0212
0.02302
0.020645
0.025795
Sample 2.1.274 reply text (paraphrased length, not verbatim, to avoid quoting a live model
response at length): a multi-sentence clarification stating the command isn't installed in this
session, then asking whether the user meant an overview of agent/subagent types or a list of
installed plugins.
2.1.273 baseline (single measurement, recorded 2026-09-16): total_cost_usd 0.000951, short
fallback line.
```
### Steps to Reproduce
1. Install an unflagged, plain Claude Code build.
2. Run:
```bash
claude -p "/some-unregistered-command" --output-format stream-json --verbose
```
3. Read the `result` record's `total_cost_usd` and `result` text from the NDJSON output.
4. Repeat step 2 several times in the same session. The cost varies noticeably call to call for
the identical input.
### Claude Model
Not sure / Multiple models
### Is this a regression?
Yes, this worked in a previous version
### Last Working Version
2.1.272
### Claude Code Version
2.1.274
### Platform
Anthropic API
### Operating System
Windows
### Terminal/Shell
VS Code integrated terminal
### Additional Information
## Is this a regression?
Not a functional regression — nothing breaks, and the older free/deterministic behavior was
deliberately replaced starting 2.1.273. But the further, undocumented rise and the run-to-run
variance observed on 2.1.274 look like an unintended side effect of whatever changed the
fallback's prompting or reply length between these two point releases, not an intentional design
change in its own right.
### Where this was found
Found incidentally while re-anchoring an unrelated string extractor in an internal CLI-build
diffing tool, whose live-tier test suite already probed this exact command as a two-arm control
(one arm with a hooks-related rollout flag, one without) to prove the flag changes local command
recognition. The flagged arm's behavior (a local, free command handler) is unaffected by any of
this — only the unflagged arm's fallback for an unrecognized command is in scope here.
### Related issues
| Issue | State | Relationship |
|---|---|---|
| [#88387](https://github.com/anthropics/claude-code/issues/88387) | open | Filed 2026-08-20 against 2.1.238: `-p` mode's `Unknown command: /foo` still printed a fixed literal and exited 0 at that version — confirms the free, deterministic behavior was still in place after this project's own builds moved past it. Its ask (non-zero exit code) would no longer be sufficient on its own: once the reply is model-generated free text rather than a fixed literal, exit code alone still leaves automation with no reliable way to detect "command not found" vs. a real answer. **Worth cross-linking.** |
| [#76066](https://github.com/anthropics/claude-code/issues/76066) | closed | A maintainer's retest comment on 2.1.233 confirms "a nonexistent command still prints `Unknown command`" — pins the deterministic behavior at least through 2.1.233. Together with #88387, this narrows the change window this report describes to somewhere between 2.1.238 and 2.1.273. **Worth cross-linking.** |
### No cost ceiling is asserted in this report
Our own test suite carries an internal cost ceiling for CI purposes, but that number is a
project-local test guard we picked ourselves, not a documented Claude Code limit, so it is left
out of this report. The seven measurements above are the actual observations this report is
based on.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by reproducing the unregistered slash command with `claude -p "/some-unregistered-command" --output-format stream-json --verbose` and compare the `result` record's `total_cost_usd` and text across repeated calls. Trace the unrecognized-command path and its `unknown_command_fallback` attachment; done means the behavior has a predictable, documented cost and a reliable non-interactive handling option.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, shell
- Domain
- api, cli
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100