Skip to content

CLI providers cannot use SKILLSPECTOR_MODEL_REGISTRY: an empty REGISTRY_PATH short-circuits the override, forcing the 128k default #459

Description

@dberzan

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.

  1. 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.
  2. Ship a model_registry.yaml for the CLI providers, so the warning's remediation is actionable.
  3. 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions