Skip to content

check-proxy.sh's recovery command drops --config, --anthropic-upstream and --idle-exit, so pasting it turns keep-alive off and bypasses a configured gateway #225

Description

@amiddavid

Found during the round-4 review of #222, which fixed the same class of defect in start-proxy.sh's success note (#224). This one is in the sibling script and is pre-existing on main from #196 / #212 and the upstream work, so it gets its own issue rather than riding that branch.

What happens

When a session's requests are being routed to a proxy that is not answering, check-proxy.sh prints a recovery command for the user to paste (scripts/check-proxy.sh:71-74):

To fix it now, in a terminal (the dashboard flags matter: without them /dashboard/ is a 404, and
this proxy would then hold the port for the whole --idle-exit window with no way to notice why):
  context-guru-proxy --listen 127.0.0.1:${PORT} --preset ${CLAUDE_PLUGIN_OPTION_PRESET:-cache} \
    --dashboard --dashboard-db "${STATE_DIR}/dashboard-${PORT}.db"

That command does not reproduce the proxy the plugin itself starts. check-proxy.sh contains no mention of UPSTREAM or --config at all (0 matches), while start-proxy.sh passes both. Three configured things are silently dropped:

Dropped start-proxy.sh Consequence of pasting the printed command
--config <keepalive yaml> :264-267 keep-alive comes back OFF after the user explicitly turned it on. The file exists and is what start-proxy.sh keys on, so the hook-started proxy had it and this one does not.
--anthropic-upstream :248-251 the proxy goes straight to api.anthropic.com, bypassing the gateway that holds the credential. plugin.json's own upstream description: "on at least one pod, rewriting model names: bypassing it sends model ids the real API has never heard of and every request fails."
--idle-exit :273 the flag defaults to 0 = never exit (cmd/context-guru-proxy/main.go:98), so the pasted proxy runs until killed — the opposite of the idle_exit option's promise that "nothing is left running on your machine".

And --preset ${CLAUDE_PLUGIN_OPTION_PRESET:-cache} names the plugin option, which is not what is in effect whenever a keep-alive config exists, because --config replaces the preset entirely (loadConfig returns config.Load(path) and never consults preset). That is exactly the misreport #224 fixed for the success note, in the same three lines that also drop the config.

Why it matters more than a wrong string

This text is shown at the one moment the user is already broken and least able to check the plugin's reasoning: requests are hanging with no error. It is presented as "to fix it now", so it will be pasted. The result is a proxy that answers /healthz — so every signal the plugin surfaces afterwards says healthy — while quietly running with a feature the user pays for turned off, and, for anyone behind a gateway, failing every request for a reason nothing in the output points at.

Suggested fix

Build the printed command from the same values start-proxy.sh uses, rather than re-deriving a subset of them: include --config when keepalive-${PORT}.yaml exists, include --anthropic-upstream when an upstream is configured, include --idle-exit, and report the preset actually in effect (the config file's, when one is in play) the way start-proxy.sh now does after #224.

Worth a test in the shape of TestStartProxyReportsThePresetActuallyInEffect: with a keep-alive config and an upstream configured, assert the printed command contains --config and --anthropic-upstream and does not name the option's preset. The two scripts deriving the same launch line independently is the root cause, so a test that pins them together is more valuable than one that pins the string.

Note

Reported by the reviewing session rather than fixed there, per the repo rule about defects on main unrelated to the branch under review. Related: #224 (the same misreport in start-proxy.sh's note) and #223 (per-option fallback discovery, which makes CLAUDE_PLUGIN_OPTION_PRESET legitimately a plugin.json default rather than anything the user set).

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

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions