Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Stop native `--apply` from bloating the patched binary with a large zero-padding gap on Linux/ELF installs: the rebuilt `.bun` section was placed at LIEF's `nextVirtualAddress()` (which rounds up to a coarse boundary) and extending the writable segment to reach it materialized the virtual-address gap as real zero bytes in the file (Claude Code 2.1.218 grew from 273MB to 721MB, ~59% zeros); it is now placed immediately after the writable segment when that segment is topmost, cutting the same patched binary to ~460MB (#915) - @StreamDemon
- Stop `--apply` corrupting non-ASCII characters in double- and single-quoted system prompts on native installs: the `\uXXXX` encoding for Bun's Latin-1 module ran before the backslash-doubling from #664, so the doubling escaped the backslash the encoder had just emitted and an em dash reached Claude Code as the literal text `\u2014`; the encoding now runs after the string-literal escaping (#920) - @StreamDemon
- Decode `\"` and `\'` when generating a system prompt's markdown, so the file shows the prompt text instead of JavaScript string-literal syntax and `--apply` stops embedding a real backslash where the bundle only had a quote; this is applied to prompts that are plain text end to end, since inside a `${...}` interpolation those escapes belong to nested JavaScript and decoding them would make the prompt look unterminated and be skipped (#921) - @StreamDemon
- Add an opt-in patch that prevents Claude Code from loading enterprise settings delivered by Anthropic or a gateway (#725) - @mike1858

## [v4.3.2](https://github.com/Piebald-AI/tweakcc/releases/tag/v4.3.2) - 2026-07-20

Expand Down
2 changes: 2 additions & 0 deletions src/applyPlan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ export function isPatchEnabledByConfig(
return !!misc?.suppressRateLimitOptions;
case 'suppress-rate-limit-warning':
return !!misc?.suppressRateLimitWarning;
case 'disable-server-managed-settings':
return !!misc?.disableServerManagedSettings;
case 'token-count-rounding':
return !!misc?.tokenCountRounding;
case 'remember-skill':
Expand Down
1 change: 1 addition & 0 deletions src/defaultSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,7 @@ export const DEFAULT_SETTINGS: Settings = {
suppressLineNumbers: false,
suppressRateLimitOptions: false,
suppressRateLimitWarning: false,
disableServerManagedSettings: false,
mcpConnectionNonBlocking: true,
mcpServerBatchSize: null,
statuslineThrottleMs: null,
Expand Down
96 changes: 96 additions & 0 deletions src/patches/disableServerManagedSettings.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { describe, expect, it } from 'vitest';
import { writeDisableServerManagedSettings } from './disableServerManagedSettings';

const makeEligibilityGate = (
delimiter = '}',
names = {
fn: 'cEe',
cache: 'lEe',
overridePath: 'JOe',
recordDecision: 'XOe',
provider: 'Hn',
gatewayConfig: 'Cy',
isGatewayEnabled: 'B5e',
}
) =>
`${delimiter}function ${names.fn}(){if(${names.cache}!==void 0)return ${names.cache};if(${names.overridePath}())return ${names.cache}=${names.recordDecision}(!0);if(${names.provider}()==="gateway")return ${names.cache}=${names.recordDecision}(${names.isGatewayEnabled}(${names.gatewayConfig}()));if(${names.provider}()!=="firstParty")return ${names.cache}=${names.recordDecision}(!1);return ${names.cache}=${names.recordDecision}(!1)}`;

describe('writeDisableServerManagedSettings', () => {
it('disables the Claude Code 2.1.220 remote settings eligibility gate', () => {
const input =
makeEligibilityGate() +
'function JUs(){if(cEe())Pmt=new Promise(e=>{})}' +
'function Vu_(){return `${Rs().BASE_API_URL}/api/claude_code/settings`}';

const result = writeDisableServerManagedSettings(input);

expect(result).not.toBeNull();
expect(result).toContain('function cEe(){return !1;if(lEe!==void 0)');
expect(result).toContain('function JUs(){if(cEe())');
expect(result).toContain('/api/claude_code/settings');
});

it('supports the formatted Claude Code 2.1.220 syntax', () => {
const input = `}
function cEe() {
if (lEe !== void 0) return lEe;
if (JOe()) return (lEe = XOe(!0));
if (Hn() === "gateway") return (lEe = XOe(B5e(Cy())));
if (Hn() !== "firstParty") return (lEe = XOe(!1));
return (lEe = XOe(!1));
}
`;

const result = writeDisableServerManagedSettings(input);

expect(result).not.toBeNull();
expect(result).toMatch(/function cEe\(\) \{\s*return !1;/);
});

it('matches independently of minified identifier names', () => {
const input = makeEligibilityGate(';', {
fn: '$a',
cache: 'B$2',
overridePath: 'Q0',
recordDecision: 'r$9',
provider: 'zZ',
gatewayConfig: 'C$y',
isGatewayEnabled: 'm4',
});

const result = writeDisableServerManagedSettings(input);

expect(result).not.toBeNull();
expect(result).toContain('function $a(){return !1;if(B$2!==void 0)');
});

it('returns the file unchanged when already patched', () => {
const patched = writeDisableServerManagedSettings(makeEligibilityGate())!;

expect(writeDisableServerManagedSettings(patched)).toBe(patched);
});

it('supports all efficient boundary delimiters', () => {
for (const delimiter of [',', ';', '}', '{']) {
const result = writeDisableServerManagedSettings(
makeEligibilityGate(delimiter)
);
expect(result).not.toBeNull();
expect(result).toContain('(){return !1;if(');
}
});

it('does not patch a generic memoized boolean helper', () => {
const input =
'}function other(){if(cache!==void 0)return cache;if(hasOverride())return cache=record(!0);return cache=record(!1)}';

expect(writeDisableServerManagedSettings(input)).toBeNull();
});

it('returns null for a partial remote settings gate', () => {
const input =
'}function cEe(){if(lEe!==void 0)return lEe;if(JOe())return lEe=XOe(!0);if(Hn()==="gateway")return true}';

expect(writeDisableServerManagedSettings(input)).toBeNull();
});
});
54 changes: 54 additions & 0 deletions src/patches/disableServerManagedSettings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { debug } from '../utils';
import { showDiff } from './index';

/**
* Disable Claude Code's server-managed settings eligibility gate.
*
* This gate controls the initial load, cache use, refresh, and polling paths for
* settings delivered by Anthropic's API or a configured gateway. Local managed
* settings files use separate loaders and intentionally remain unaffected.
*
* CC 2.1.220:
* ```diff
* function cEe(){
* + return !1;
* if(lEe!==void 0)return lEe;
* if(JOe())return lEe=XOe(!0);
* if(Hn()==="gateway")return lEe=XOe(B5e(Cy()));
* ```
*/
export const writeDisableServerManagedSettings = (
oldFile: string
): string | null => {
const alreadyPatched =
/[,;{}]\s*function\s+([$\w]+)\s*\(\s*\)\s*\{\s*return\s+!1;\s*if\s*\(\s*([$\w]+)\s*!==\s*void\s+0\s*\)\s*return\s+\2;\s*if\s*\(\s*([$\w]+)\s*\(\s*\)\s*\)\s*return\s+\(?\s*\2\s*=\s*[$\w]+\s*\(\s*!0\s*\)\s*\)?;\s*if\s*\(\s*([$\w]+)\s*\(\s*\)\s*===\s*"gateway"\s*\)\s*return\s+\(?\s*\2\s*=\s*[$\w]+\s*\(/;
if (alreadyPatched.test(oldFile)) return oldFile;

// The override-file and gateway branches uniquely identify the remote-settings
// eligibility helper without depending on minified names from a specific build.
const pattern =
/[,;{}]\s*function\s+([$\w]+)\s*\(\s*\)\s*\{\s*if\s*\(\s*([$\w]+)\s*!==\s*void\s+0\s*\)\s*return\s+\2;\s*if\s*\(\s*([$\w]+)\s*\(\s*\)\s*\)\s*return\s+\(?\s*\2\s*=\s*[$\w]+\s*\(\s*!0\s*\)\s*\)?;\s*if\s*\(\s*([$\w]+)\s*\(\s*\)\s*===\s*"gateway"\s*\)\s*return\s+\(?\s*\2\s*=\s*[$\w]+\s*\(/;
const match = oldFile.match(pattern);

if (!match || match.index === undefined) {
debug(
'patch: disableServerManagedSettings: failed to find remote settings eligibility gate'
);
return null;
}

const functionBodyOffset = match[0].indexOf('{', 1) + 1;
if (functionBodyOffset === 0) {
debug(
'patch: disableServerManagedSettings: matched eligibility gate without a function body'
);
return null;
}
const insertIndex = match.index + functionBodyOffset;
const insertion = 'return !1;';
const newFile =
oldFile.slice(0, insertIndex) + insertion + oldFile.slice(insertIndex);

showDiff(oldFile, newFile, insertion, insertIndex, insertIndex);
return newFile;
};
12 changes: 12 additions & 0 deletions src/patches/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ import { writeIncreaseFileReadLimit } from './increaseFileReadLimit';
import { writeSuppressLineNumbers } from './suppressLineNumbers';
import { writeSuppressRateLimitOptions } from './suppressRateLimitOptions';
import { writeSuppressRateLimitWarning } from './suppressRateLimitWarning';
import { writeDisableServerManagedSettings } from './disableServerManagedSettings';
import { writeSessionMemory } from './sessionMemory';
import { writeRememberSkill } from './rememberSkill';
import { writeThinkingBlockStyling } from './thinkingBlockStyling';
Expand Down Expand Up @@ -355,6 +356,13 @@ const PATCH_DEFINITIONS = [
description:
'Rate limit warning banners will be suppressed (errors still shown)',
},
{
id: 'disable-server-managed-settings',
name: 'Disable server-managed settings',
group: PatchGroup.MISC_CONFIGURABLE,
description:
'Prevent Claude Code from loading enterprise settings delivered by a server',
},
{
id: 'token-count-rounding',
name: 'Token count rounding',
Expand Down Expand Up @@ -859,6 +867,10 @@ export const applyCustomization = async (
fn: c => writeSuppressRateLimitWarning(c),
condition: !!config.settings.misc?.suppressRateLimitWarning,
},
'disable-server-managed-settings': {
fn: c => writeDisableServerManagedSettings(c),
condition: !!config.settings.misc?.disableServerManagedSettings,
},
'token-count-rounding': {
fn: c =>
writeTokenCountRounding(c, config.settings.misc!.tokenCountRounding!),
Expand Down
35 changes: 35 additions & 0 deletions src/tests/applyPlan.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,41 @@ describe('applyPlan', () => {
).toBe(false);
});

it('includes server-managed settings patch only when enabled', () => {
const disabled = configWithDefaults();
const enabled = configWithDefaults({
misc: {
...DEFAULT_SETTINGS.misc,
disableServerManagedSettings: true,
},
});

expect(
isPatchEnabledByConfig(
'disable-server-managed-settings',
disabled,
'2.1.220'
)
).toBe(false);
expect(
isPatchEnabledByConfig(
'disable-server-managed-settings',
enabled,
'2.1.220'
)
).toBe(true);
expect(
getPlannedPatches(disabled, '2.1.220', [
'disable-server-managed-settings',
])
).toEqual([]);
expect(
getPlannedPatches(enabled, '2.1.220', [
'disable-server-managed-settings',
]).map(p => p.id)
).toEqual(['disable-server-managed-settings']);
});

it('respects --patches filter', () => {
const planned = getPlannedPatches(configWithDefaults(), '2.1.200', [
'session-memory',
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ export interface MiscConfig {
suppressLineNumbers: boolean;
suppressRateLimitOptions: boolean;
suppressRateLimitWarning: boolean;
disableServerManagedSettings: boolean;
mcpConnectionNonBlocking: boolean;
mcpServerBatchSize: number | null;
statuslineThrottleMs: number | null;
Expand Down
15 changes: 15 additions & 0 deletions src/ui/components/MiscView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export function MiscView({ onSubmit }: MiscViewProps) {
suppressLineNumbers: false,
suppressRateLimitOptions: false,
suppressRateLimitWarning: false,
disableServerManagedSettings: false,
mcpConnectionNonBlocking: true,
mcpServerBatchSize: null as number | null,
statuslineThrottleMs: null as number | null,
Expand Down Expand Up @@ -340,6 +341,20 @@ export function MiscView({ onSubmit }: MiscViewProps) {
});
},
},
{
id: 'disableServerManagedSettings',
title: 'Disable server-managed settings',
description:
'Prevents Claude Code from downloading enterprise settings from Anthropic or a gateway. Local managed settings still apply.',
getValue: () => settings.misc?.disableServerManagedSettings ?? false,
toggle: () => {
updateSettings(settings => {
ensureMisc();
settings.misc!.disableServerManagedSettings =
!settings.misc!.disableServerManagedSettings;
});
},
},
{
id: 'mcpNonBlocking',
title: 'Non-blocking MCP startup',
Expand Down