Repository navigation
CLI providers cannot use SKILLSPECTOR_MODEL_REGISTRY: an empty REGISTRY_PATH short-circuits the override, forcing the 128k default #459
Description
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
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.
- Consult the override before the guard. Check
SKILLSPECTOR_MODEL_REGISTRYahead of theif not self.REGISTRY_PATHearly return, so a user-supplied registry works for CLI providers as the docstring already promises. - Ship a
model_registry.yamlfor 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 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.
Activity