fix(gateway): run Claude Code's /usage without CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC (#438)

With CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC set, Claude Code refuses its
own /api/oauth/usage request, so /usage only prints a snapshot another
Claude Code process left in ~/.claude.json within the last hour, and the
usage card shows "Usage unavailable" otherwise.

The /usage run now drops that flag unless the user set it, and sets
DISABLE_TELEMETRY, DISABLE_ERROR_REPORTING and DISABLE_AUTOUPDATER.
cleanClaudeEnv is unchanged, so the bridge and the model probe still run
with the flag. Without the flag, the /usage run also sends Claude Code's
startup config fetch, the org fast-mode check and the Grove notice config
request.

TestClaudeUsageSendsItsRequest checks the environment of the /usage run,
of the warm-up, and of a /usage run where the user set the flag.

Fixes #437
This commit is contained in:
lainbo authored and GitHub committed 2026-10-02 11:08:04 +08:00
1 parent 4696d14726
commit fc036d1db4
2 files changed
+47 -2

No files matched your search

+12 -1
View File
@@ -6,6 +6,7 @@ import (
"encoding/json"
"errors"
"os"
"slices"
"strings"
"github.com/yetone/magpie/internal/netproxy"
@@ -90,7 +91,17 @@ func claudeUsage(ctx context.Context) (string, error) {
cmd := proc.CommandContext(ctx, binary, claudeUsageArgs()...)
cmd.Dir = tmp
cmd.Stdin = strings.NewReader("")
cmd.Env = netproxy.EnvWith(claudeProxy(ctx), cleanClaudeEnv(os.Environ()))
// CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC makes /usage skip its request
// and print only a reading another run left in the last hour, so it stays
// only when the user set it.
env := cleanClaudeEnv(os.Environ())
if os.Getenv("CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC") == "" {
env = slices.DeleteFunc(env, func(e string) bool {
return strings.HasPrefix(e, "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=")
})
}
env = append(env, "DISABLE_TELEMETRY=1", "DISABLE_ERROR_REPORTING=1", "DISABLE_AUTOUPDATER=1")
cmd.Env = netproxy.EnvWith(claudeProxy(ctx), env)
var out, stderr bytes.Buffer
cmd.Stdout, cmd.Stderr = &out, &stderr
runErr := cmd.Run()
+35 -1
View File
@@ -23,7 +23,9 @@ func fakeWarmClaude(t *testing.T, out string, code int) string {
log := filepath.Join(dir, "log")
script := "#!/bin/sh\n" +
"{ printf 'args:'; for a in \"$@\"; do printf '[%s]' \"$a\"; done; echo; " +
"echo \"dir:$CLAUDE_CONFIG_DIR\"; echo \"base:$ANTHROPIC_BASE_URL\"; echo \"pwd:$(pwd)\"; printf 'stdin:'; cat; echo; } > " + log + "\n" +
"echo \"dir:$CLAUDE_CONFIG_DIR\"; echo \"base:$ANTHROPIC_BASE_URL\"; echo \"pwd:$(pwd)\"; printf 'stdin:'; cat; echo; " +
"echo \"traffic:$CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC\"; echo \"telemetry:$DISABLE_TELEMETRY\"; " +
"echo \"errors:$DISABLE_ERROR_REPORTING\"; echo \"updater:$DISABLE_AUTOUPDATER\"; } > " + log + "\n" +
"echo '" + out + "'\nexit " + string(rune('0'+code)) + "\n"
if err := os.WriteFile(filepath.Join(dir, "claude"), []byte(script), 0o755); err != nil {
t.Fatal(err)
@@ -123,6 +125,38 @@ func TestClaudeUsageRunsClaudeCode(t *testing.T) {
}
}
// /usage runs without CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, which keeps
// Claude Code from asking for the usage, unless the user set it; telemetry,
// error reporting and autoupdate stay off. The warm-up keeps it.
func TestClaudeUsageSendsItsRequest(t *testing.T) {
log := fakeWarmClaude(t, `{"type":"result","is_error":false,"result":"Current session: 13% used"}`, 0)
for _, k := range []string{"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC", "DISABLE_TELEMETRY", "DISABLE_ERROR_REPORTING", "DISABLE_AUTOUPDATER"} {
t.Setenv(k, "")
}
if _, err := claudeUsage(context.Background()); err != nil {
t.Fatal(err)
}
b, _ := os.ReadFile(log)
for _, want := range []string{"traffic:\n", "telemetry:1\n", "errors:1\n", "updater:1\n"} {
if !strings.Contains(string(b), want) {
t.Errorf("/usage run lacks %q:\n%s", want, b)
}
}
if err := warmClaude(context.Background(), ""); err != nil {
t.Fatal(err)
}
if b, _ := os.ReadFile(log); !strings.Contains(string(b), "traffic:1\n") {
t.Errorf("warm-up lacks CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC:\n%s", b)
}
t.Setenv("CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC", "1")
if _, err := claudeUsage(context.Background()); err != nil {
t.Fatal(err)
}
if b, _ := os.ReadFile(log); !strings.Contains(string(b), "traffic:1\n") {
t.Errorf("/usage run dropped the user's CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC:\n%s", b)
}
}
// With Claude Code's verbose output on (its /config, kept in .claude.json),
// claude -p --output-format json prints every message as an array, the
// system init first and the result last (KevinXC on Discord: usage