Skip to content

[BUG] claude_cli provider omits --setting-sources=, so the spawned claude runs the user's hooks (4 LLM calls -> 3h09m CPU, 1225 hook sessions) #295

Closed

Description

@Mark2Mac

Description

The claude_cli provider builds a capability-stripped claude -p argv, but does not pass --setting-sources=. The spawned CLI therefore loads the user's settings.json and executes their hooks — SessionStart, UserPromptSubmit, PostToolUse, Stop.

If any of those hooks is itself agent-shaped (a session-memory plugin, a logger that calls back into claude, a formatter that spawns tooling), each LLM call the scanner makes turns into a full hook cycle. On my machine one scan with 4 attempted LLM calls consumed 3h09m of CPU time, 6.1 GB RSS and 2.5 GB swap over 52 minutes of wall clock, and registered 1225 sessions in a session-memory plugin that hooks SessionStart.

The amplification is not linear in the number of LLM calls, because the spawned hooks can enqueue work that spawns further processes. In my case it reached a livelock: hundreds of orphaned sessions retrying against a process cap that the retries themselves kept saturated.

Version: SkillSpector v2.3.13.

Cause

skillspector/providers/_agent_cli.py, _build_claude_argv:

return [
    binary,
    "-p",
    "--output-format", "text",
    *model_arg,
    "--allowed-tools", "",
    "--permission-mode", "dontAsk",
    "--strict-mcp-config",
    "--disable-slash-commands",
]

The intent is clearly isolation — tools stripped, MCP servers stripped, slash commands disabled. Hooks are the one capability left connected, and they are the one that can re-enter Claude Code.

The docstring notes --strict-mcp-config is used so "zero MCP servers load". --setting-sources= is the equivalent for settings-derived capabilities, hooks included.

Suggested fix

    "--strict-mcp-config",
    "--setting-sources=",
    "--disable-slash-commands",

Worth a line in the docstring next to the --strict-mcp-config rationale, since the reason is the same and non-obvious.

Verification

Same prompt, same flags, measured by growth of the hook plugin's log and its session table:

log lines sessions created
current argv 33 1
with --setting-sources= 0 0

For comparison, the session-memory plugin on the same machine spawns its own claude subprocesses with --setting-sources= --strict-mcp-config, which is why those never recursed.

Notes

Two things made this hard to attribute, which may be worth considering independently:

  • llm_calls_attempted: 4 in the report metadata is accurate but does not reflect the cost incurred, so the report looks cheap while the machine is saturated.
  • The work happens in spawned children, so it does not appear under the scanner's own resource usage.

I hit this via a systemd timer running --changed scans unattended, where there was no one watching to notice the machine had 8 cores pinned. Users running the CLI interactively would likely notice sooner, but would still be paying for the extra token usage — the spawned hooks run against the user's own Claude subscription.

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