Summary
SKILLSPECTOR_MODEL_REGISTRY is documented in providers/registry.py as a global override — "overrides the bundled path globally — useful for adding models without editing the package". For every CLI-based provider (claude_cli, codex_cli, gemini_cli) it is unreachable, because the only call site that reads it sits behind an early return that fires first.
Mechanism
providers/_agent_cli_base.py:
REGISTRY_PATH: str = "" # line 43
def get_context_length(self, model: str) -> int | None:
if not self.REGISTRY_PATH:
return None # no registry -> caller uses the package-wide default budget
return registry.lookup_context_length(self.REGISTRY_PATH, model)
registry.lookup_context_length() is the only function that consults SKILLSPECTOR_MODEL_REGISTRY (through _resolve_path). Since providers/claude_cli/provider.py never sets REGISTRY_PATH, get_context_length() returns None before reaching that line, and model_info._resolve_context_length() falls back to constants.DEFAULT_CONTEXT_LENGTH = 128_000.
Setting the env var therefore has no effect on a CLI provider. Verified: with SKILLSPECTOR_MODEL_REGISTRY pointing at a valid YAML that declares the model, a scan still logs the fallback warning (6 times in one run):
No token-limit info for model 'claude-haiku-4-5' — using 128000-token default.
Add the model to model_registry.yaml.
The warning's own remediation is not actionable for these providers: no model_registry.yaml ships under providers/claude_cli/, and the override that would supply one is bypassed. Eight other providers do ship one.
Consequence
The 128k default combines with the len(text) // 4 estimate in llm_analyzer_base.py to build over-limit prompts on dense but perfectly valid UTF-8 files. Measured with claude_cli + claude-haiku-4-5 on a 536,352-byte uv.lock:
|
tokens |
len(text) // 4 estimate |
134,088 |
| actual |
~324,595 |
A 2.42x undercount. The CLI rejects the call:
Prompt is too long · the request is ~324595 tokens (limit 200000) but this
conversation is only ~140161 tokens — the rest is system prompt, tool
definitions, and attachment content.
SkillSpector logs it as:
LLM batch failed for File: uv.lock (lines 1-1693): claude exited with code 1; stderr=''
Note stderr='' — the CLI writes the rejection to stdout, so the captured stderr is empty and the actual cause is invisible in the scan log. The batch is then retried and fails identically. On a repo with a couple of such files this can consume an entire scan: in one measured 51-file run, 2 files produced 5 failure events while the other 49 scanned fine, and the run produced no report before being stopped.
Versions
- SkillSpector 2.9.5
- Also present on
main at 1b875933a666b627c3ed1b695f066a21a6773dc4: same empty REGISTRY_PATH, same early return, still no providers/claude_cli/model_registry.yaml.
Suggested fixes
Any one of these would help; the first is the smallest.
- Consult the override before the guard. Check
SKILLSPECTOR_MODEL_REGISTRY ahead of the if not self.REGISTRY_PATH early return, so a user-supplied registry works for CLI providers as the docstring already promises.
- Ship a
model_registry.yaml for the CLI providers, so the warning's remediation is actionable.
- Surface the provider's failure text. Include the CLI's stdout in the
LLM batch failed warning — Prompt is too long is diagnosable, stderr='' is not.
Items 1 and 3 are independent of any model's real context window, so they hold even as limits change.
Summary
SKILLSPECTOR_MODEL_REGISTRYis documented inproviders/registry.pyas a global override — "overrides the bundled path globally — useful for adding models without editing the package". For every CLI-based provider (claude_cli,codex_cli,gemini_cli) it is unreachable, because the only call site that reads it sits behind an early return that fires first.Mechanism
providers/_agent_cli_base.py:registry.lookup_context_length()is the only function that consultsSKILLSPECTOR_MODEL_REGISTRY(through_resolve_path). Sinceproviders/claude_cli/provider.pynever setsREGISTRY_PATH,get_context_length()returnsNonebefore reaching that line, andmodel_info._resolve_context_length()falls back toconstants.DEFAULT_CONTEXT_LENGTH = 128_000.Setting the env var therefore has no effect on a CLI provider. Verified: with
SKILLSPECTOR_MODEL_REGISTRYpointing at a valid YAML that declares the model, a scan still logs the fallback warning (6 times in one run):The warning's own remediation is not actionable for these providers: no
model_registry.yamlships underproviders/claude_cli/, and the override that would supply one is bypassed. Eight other providers do ship one.Consequence
The 128k default combines with the
len(text) // 4estimate inllm_analyzer_base.pyto build over-limit prompts on dense but perfectly valid UTF-8 files. Measured withclaude_cli+claude-haiku-4-5on a 536,352-byteuv.lock:len(text) // 4estimateA 2.42x undercount. The CLI rejects the call:
SkillSpector logs it as:
Note
stderr=''— the CLI writes the rejection to stdout, so the captured stderr is empty and the actual cause is invisible in the scan log. The batch is then retried and fails identically. On a repo with a couple of such files this can consume an entire scan: in one measured 51-file run, 2 files produced 5 failure events while the other 49 scanned fine, and the run produced no report before being stopped.Versions
mainat1b875933a666b627c3ed1b695f066a21a6773dc4: same emptyREGISTRY_PATH, same early return, still noproviders/claude_cli/model_registry.yaml.Suggested fixes
Any one of these would help; the first is the smallest.
SKILLSPECTOR_MODEL_REGISTRYahead of theif not self.REGISTRY_PATHearly return, so a user-supplied registry works for CLI providers as the docstring already promises.model_registry.yamlfor the CLI providers, so the warning's remediation is actionable.LLM batch failedwarning —Prompt is too longis diagnosable,stderr=''is not.Items 1 and 3 are independent of any model's real context window, so they hold even as limits change.