localclawd 2.3.2 → 2.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +4 -5
  2. package/dist/cli.mjs +272 -161
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -272,10 +272,9 @@ localclawd currently recognizes both native and legacy variable names for the lo
272
272
  - `LOCALCLAWD_USE_VLLM`
273
273
  - `LOCALCLAWD_USE_OLLAMA`
274
274
  - `LOCALCLAWD_USE_OPENAI`
275
- - `LOCALCLAWD_LOCAL_BASE_URL`
276
- - `LOCALCLAWD_LOCAL_MODEL`
277
- - `LOCALCLAWD_LOCAL_API_KEY`
278
- - `LOCALCLAWD_AUTO_COMPACT_WINDOW`
275
+ - `LOCALCLAWD_LOCAL_BASE_URL`
276
+ - `LOCALCLAWD_LOCAL_MODEL`
277
+ - `LOCALCLAWD_LOCAL_API_KEY`
279
278
 
280
279
  Legacy compatibility aliases that still work:
281
280
 
@@ -307,7 +306,7 @@ The native installer places the executable at `~/.local/bin/localclawd` on Unix-
307
306
 
308
307
  ## Compact context window
309
308
 
310
- During first-run setup, localclawd asks for a compact context window cap. Use this when your local model becomes unstable before its advertised maximum context size. You can change it later in `/config` under `Compact context window`.
309
+ During first-run setup, localclawd asks for a project-local compact context window cap. Use this when your local model becomes unstable before its advertised maximum context size. You can change it later in `/config` under `Compact context window` or with `/ctx`.
311
310
 
312
311
  ## Why use it instead of the upstream hosted CLI
313
312
 
package/dist/cli.mjs CHANGED
@@ -35907,13 +35907,22 @@ function reportConfigCacheStats() {
35907
35907
  configCacheHits = 0;
35908
35908
  configCacheMisses = 0;
35909
35909
  }
35910
- function migrateConfigFields(config) {
35911
- if (config.installMethod !== undefined) {
35910
+ function removeLegacyGlobalProjectSettings(config) {
35911
+ const legacyLocalOnlyFields = config;
35912
+ if (legacyLocalOnlyFields.compactContextWindowTokens === undefined) {
35912
35913
  return config;
35913
35914
  }
35914
- const legacy = config;
35915
+ const { compactContextWindowTokens: _legacy, ...rest } = legacyLocalOnlyFields;
35916
+ return rest;
35917
+ }
35918
+ function migrateConfigFields(config) {
35919
+ const normalizedConfig = removeLegacyGlobalProjectSettings(config);
35920
+ if (normalizedConfig.installMethod !== undefined) {
35921
+ return normalizedConfig;
35922
+ }
35923
+ const legacy = normalizedConfig;
35915
35924
  let installMethod = "unknown";
35916
- let autoUpdates = config.autoUpdates ?? true;
35925
+ let autoUpdates = normalizedConfig.autoUpdates ?? true;
35917
35926
  switch (legacy.autoUpdaterStatus) {
35918
35927
  case "migrated":
35919
35928
  installMethod = "local";
@@ -35933,7 +35942,7 @@ function migrateConfigFields(config) {
35933
35942
  break;
35934
35943
  }
35935
35944
  return {
35936
- ...config,
35945
+ ...normalizedConfig,
35937
35946
  installMethod,
35938
35947
  autoUpdates
35939
35948
  };
@@ -36480,8 +36489,6 @@ var init_config = __esm(() => {
36480
36489
  "shiftEnterKeyBindingInstalled",
36481
36490
  "editorMode",
36482
36491
  "hasUsedBackslashReturn",
36483
- "autoCompactEnabled",
36484
- "compactContextWindowTokens",
36485
36492
  "localBackendProvider",
36486
36493
  "localBackendBaseUrl",
36487
36494
  "localBackendModel",
@@ -36517,7 +36524,9 @@ var init_config = __esm(() => {
36517
36524
  PROJECT_CONFIG_KEYS = [
36518
36525
  "allowedTools",
36519
36526
  "hasTrustDialogAccepted",
36520
- "hasCompletedProjectOnboarding"
36527
+ "hasCompletedProjectOnboarding",
36528
+ "compactContextWindowTokens",
36529
+ "autoCompactEnabled"
36521
36530
  ];
36522
36531
  TEST_GLOBAL_CONFIG_FOR_TESTING = {
36523
36532
  ...DEFAULT_GLOBAL_CONFIG,
@@ -88251,7 +88260,7 @@ var init_isEqual = __esm(() => {
88251
88260
 
88252
88261
  // src/utils/userAgent.ts
88253
88262
  function getClaudeCodeUserAgent() {
88254
- return `claude-code/${"2.3.2"}`;
88263
+ return `claude-code/${"2.3.4"}`;
88255
88264
  }
88256
88265
 
88257
88266
  // src/utils/workloadContext.ts
@@ -88273,7 +88282,7 @@ function getUserAgent() {
88273
88282
  const clientApp = process.env.CLAUDE_AGENT_SDK_CLIENT_APP ? `, client-app/${process.env.CLAUDE_AGENT_SDK_CLIENT_APP}` : "";
88274
88283
  const workload = getWorkload();
88275
88284
  const workloadSuffix = workload ? `, workload/${workload}` : "";
88276
- return `claude-cli/${"2.3.2"} (${process.env.USER_TYPE}, ${process.env.CLAUDE_CODE_ENTRYPOINT ?? "cli"}${agentSdkVersion}${clientApp}${workloadSuffix})`;
88285
+ return `claude-cli/${"2.3.4"} (${process.env.USER_TYPE}, ${process.env.CLAUDE_CODE_ENTRYPOINT ?? "cli"}${agentSdkVersion}${clientApp}${workloadSuffix})`;
88277
88286
  }
88278
88287
  function getMCPUserAgent() {
88279
88288
  const parts = [];
@@ -88287,7 +88296,7 @@ function getMCPUserAgent() {
88287
88296
  parts.push(`client-app/${process.env.CLAUDE_AGENT_SDK_CLIENT_APP}`);
88288
88297
  }
88289
88298
  const suffix = parts.length > 0 ? ` (${parts.join(", ")})` : "";
88290
- return `claude-code/${"2.3.2"}${suffix}`;
88299
+ return `claude-code/${"2.3.4"}${suffix}`;
88291
88300
  }
88292
88301
  function getWebFetchUserAgent() {
88293
88302
  return `Claude-User (${getClaudeCodeUserAgent()}; +https://support.anthropic.com/)`;
@@ -123552,9 +123561,6 @@ var init_modelCapabilities = __esm(() => {
123552
123561
  });
123553
123562
 
123554
123563
  // src/utils/context.ts
123555
- function getEnvAlias2(localKey, legacyKey) {
123556
- return process.env[localKey] ?? process.env[legacyKey];
123557
- }
123558
123564
  function is1mContextDisabled() {
123559
123565
  return true;
123560
123566
  }
@@ -123584,13 +123590,7 @@ function getLocalProviderContextWindow() {
123584
123590
  return _localProviderContextWindow;
123585
123591
  }
123586
123592
  function getContextWindowForModel(_model, _betas) {
123587
- const envOverrideStr = getEnvAlias2("LOCALCLAWD_MAX_CONTEXT_TOKENS", "CLAUDE_CODE_MAX_CONTEXT_TOKENS");
123588
- if (envOverrideStr) {
123589
- const override = parseContextWindowString(envOverrideStr);
123590
- if (override !== null)
123591
- return override;
123592
- }
123593
- const persisted = getGlobalConfig().compactContextWindowTokens;
123593
+ const persisted = getCurrentProjectConfig().compactContextWindowTokens;
123594
123594
  if (persisted && persisted > 0)
123595
123595
  return persisted;
123596
123596
  if (_localProviderContextWindow && _localProviderContextWindow > 0) {
@@ -158794,7 +158794,7 @@ function getAttributionHeader(fingerprint) {
158794
158794
  if (!isAttributionHeaderEnabled()) {
158795
158795
  return "";
158796
158796
  }
158797
- const version = `${"2.3.2"}.${fingerprint}`;
158797
+ const version = `${"2.3.4"}.${fingerprint}`;
158798
158798
  const entrypoint = process.env.CLAUDE_CODE_ENTRYPOINT ?? "unknown";
158799
158799
  const cch = "";
158800
158800
  const workload = getWorkload();
@@ -174981,7 +174981,7 @@ var init_metadata = __esm(() => {
174981
174981
  COMPOUND_OPERATOR_REGEX = /\s*(?:&&|\|\||[;|])\s*/;
174982
174982
  WHITESPACE_REGEX = /\s+/;
174983
174983
  getVersionBase = memoize_default(() => {
174984
- const match = "2.3.2".match(/^\d+\.\d+\.\d+(?:-[a-z]+)?/);
174984
+ const match = "2.3.4".match(/^\d+\.\d+\.\d+(?:-[a-z]+)?/);
174985
174985
  return match ? match[0] : undefined;
174986
174986
  });
174987
174987
  buildEnvContext = memoize_default(async () => {
@@ -175021,9 +175021,9 @@ var init_metadata = __esm(() => {
175021
175021
  isGithubAction: isEnvTruthy(process.env.GITHUB_ACTIONS),
175022
175022
  isClaudeCodeAction: isEnvTruthy(process.env.CLAUDE_CODE_ACTION),
175023
175023
  isClaudeAiAuth: isClaudeAISubscriber(),
175024
- version: "2.3.2",
175024
+ version: "2.3.4",
175025
175025
  versionBase: getVersionBase(),
175026
- buildTime: "2026-05-10T19:45:00.456Z",
175026
+ buildTime: "2026-05-10T21:07:59.152Z",
175027
175027
  deploymentEnvironment: env3.detectDeploymentEnvironment(),
175028
175028
  ...isEnvTruthy(process.env.GITHUB_ACTIONS) && {
175029
175029
  githubEventName: process.env.GITHUB_EVENT_NAME,
@@ -178714,17 +178714,8 @@ function getToolLocationHint() {
178714
178714
  const deltaEnabled = process.env.USER_TYPE === "ant" || getFeatureValue_CACHED_MAY_BE_STALE("tengu_glacier_2xr", false);
178715
178715
  return deltaEnabled ? "Deferred tools appear by name in <system-reminder> messages." : "Deferred tools appear by name in <available-deferred-tools> messages.";
178716
178716
  }
178717
- function isDeferredTool(tool) {
178718
- if (tool.alwaysLoad === true)
178719
- return false;
178720
- if (tool.isMcp === true)
178721
- return true;
178722
- if (tool.name === TOOL_SEARCH_TOOL_NAME)
178723
- return false;
178724
- if (false) {}
178725
- if (false) {}
178726
- if (false) {}
178727
- return tool.shouldDefer === true;
178717
+ function isDeferredTool(_tool) {
178718
+ return false;
178728
178719
  }
178729
178720
  function formatDeferredToolLine(tool) {
178730
178721
  return tool.name;
@@ -178742,10 +178733,7 @@ Query forms:
178742
178733
  - "select:Read,Edit,Grep" — fetch these exact tools by name
178743
178734
  - "notebook jupyter" — keyword search, up to max_results best matches
178744
178735
  - "+slack send" — require "slack" in the name, rank by remaining terms`;
178745
- var init_prompt8 = __esm(() => {
178746
- init_state();
178747
- init_constants3();
178748
- });
178736
+ var init_prompt8 = () => {};
178749
178737
 
178750
178738
  // src/tools/PowerShellTool/toolName.ts
178751
178739
  var POWERSHELL_TOOL_NAME = "PowerShell";
@@ -200814,6 +200802,29 @@ function createCompactCanUseTool() {
200814
200802
  }
200815
200803
  });
200816
200804
  }
200805
+ function normalizeLocalChatCompletionsUrl(baseUrl) {
200806
+ const trimmed = baseUrl.trim().replace(/\/+$/, "");
200807
+ const withV1 = trimmed.endsWith("/v1") ? trimmed : `${trimmed}/v1`;
200808
+ return `${withV1}/chat/completions`;
200809
+ }
200810
+ function isLocalContextOverflowMessage(message) {
200811
+ return LOCAL_CONTEXT_OVERFLOW_PATTERNS.some((pattern) => pattern.test(message));
200812
+ }
200813
+ async function readProviderErrorMessage(response) {
200814
+ try {
200815
+ const payload = await response.clone().json();
200816
+ const message = payload.error?.message ?? payload.message;
200817
+ if (typeof message === "string" && message.trim()) {
200818
+ return message.trim();
200819
+ }
200820
+ } catch {}
200821
+ try {
200822
+ const text = await response.clone().text();
200823
+ if (text.trim())
200824
+ return text.trim();
200825
+ } catch {}
200826
+ return `HTTP ${response.status}`;
200827
+ }
200817
200828
  function serializeMessagesForCleanRoom(messages, maxChars) {
200818
200829
  const parts = [];
200819
200830
  for (const msg of messages) {
@@ -200840,9 +200851,15 @@ ${text}`);
200840
200851
  `);
200841
200852
  if (full.length <= maxChars)
200842
200853
  return full;
200843
- return `[earlier conversation truncated]
200854
+ const headChars = Math.max(1000, Math.floor(maxChars * 0.2));
200855
+ const tailChars = Math.max(1000, maxChars - headChars);
200856
+ return [
200857
+ full.slice(0, headChars),
200858
+ "[middle conversation omitted for local compaction budget]",
200859
+ full.slice(full.length - tailChars)
200860
+ ].join(`
200844
200861
 
200845
- ` + full.slice(full.length - maxChars);
200862
+ `);
200846
200863
  }
200847
200864
  async function tryDirectLocalCompact({
200848
200865
  messages,
@@ -200868,13 +200885,13 @@ ${serialized}
200868
200885
  </conversation>
200869
200886
 
200870
200887
  ${compactPromptText}`;
200871
- const timeoutMs = parseInt(process.env.COMPACT_TIMEOUT_MS || "", 10) || 5 * 60000;
200888
+ const timeoutMs = LOCAL_COMPACT_TIMEOUT_MS;
200872
200889
  const timeoutController = new AbortController;
200873
200890
  const timer = setTimeout(() => timeoutController.abort(new Error("compact timeout")), timeoutMs);
200874
200891
  const onAbort = () => timeoutController.abort(context4.abortController.signal.reason);
200875
200892
  context4.abortController.signal.addEventListener("abort", onAbort, { once: true });
200876
200893
  try {
200877
- const url2 = `${baseUrl.replace(/\/$/, "")}/chat/completions`;
200894
+ const url2 = normalizeLocalChatCompletionsUrl(baseUrl);
200878
200895
  const res = await fetch(url2, {
200879
200896
  method: "POST",
200880
200897
  headers: {
@@ -200894,7 +200911,13 @@ ${compactPromptText}`;
200894
200911
  signal: timeoutController.signal
200895
200912
  });
200896
200913
  if (!res.ok) {
200897
- logForDebugging(`compact direct-local: HTTP ${res.status}`, { level: "warn" });
200914
+ const providerMessage = await readProviderErrorMessage(res);
200915
+ logForDebugging(`compact direct-local: HTTP ${res.status}: ${providerMessage}`, { level: "warn" });
200916
+ if (isLocalContextOverflowMessage(providerMessage)) {
200917
+ return createAssistantAPIErrorMessage({
200918
+ content: `${PROMPT_TOO_LONG_ERROR_MESSAGE}: ${providerMessage}`
200919
+ });
200920
+ }
200898
200921
  return null;
200899
200922
  }
200900
200923
  const data = await res.json();
@@ -201005,10 +201028,14 @@ async function streamCompactSummary({
201005
201028
  preCompactTokenCount
201006
201029
  });
201007
201030
  if (directResp) {
201008
- const directText = getAssistantMessageText(directResp);
201009
- if (directText && !directResp.isApiErrorMessage && !directText.startsWith(PROMPT_TOO_LONG_ERROR_MESSAGE)) {
201010
- return directResp;
201011
- }
201031
+ return directResp;
201032
+ }
201033
+ if (isLocalLLMProviderEnabled()) {
201034
+ logEvent("tengu_compact_failed", {
201035
+ reason: "local_direct_compact_failed",
201036
+ preCompactTokenCount
201037
+ });
201038
+ throw new Error(ERROR_MESSAGE_INCOMPLETE_RESPONSE);
201012
201039
  }
201013
201040
  const cleanRoomFirst = await tryCleanRoomCompactSummary({
201014
201041
  messages,
@@ -201297,7 +201324,7 @@ function shouldExcludeFromPostCompactRestore(filename, agentId) {
201297
201324
  } catch {}
201298
201325
  return false;
201299
201326
  }
201300
- var POST_COMPACT_MAX_FILES_TO_RESTORE = 5, POST_COMPACT_TOKEN_BUDGET = 50000, POST_COMPACT_MAX_TOKENS_PER_FILE = 5000, POST_COMPACT_MAX_TOKENS_PER_SKILL = 5000, POST_COMPACT_SKILLS_TOKEN_BUDGET = 25000, MAX_COMPACT_STREAMING_RETRIES = 2, ERROR_MESSAGE_NOT_ENOUGH_MESSAGES = "Not enough messages to compact.", MAX_PTL_RETRIES = 3, PTL_RETRY_MARKER = "[earlier conversation truncated for compaction retry]", ERROR_MESSAGE_PROMPT_TOO_LONG = "Conversation too long. Press esc twice to go up a few messages and try again.", ERROR_MESSAGE_USER_ABORT = "API Error: Request was aborted.", ERROR_MESSAGE_INCOMPLETE_RESPONSE = "Compaction interrupted · This may be due to network issues — please try again.", SKILL_TRUNCATION_MARKER = `
201327
+ var POST_COMPACT_MAX_FILES_TO_RESTORE = 5, POST_COMPACT_TOKEN_BUDGET = 50000, POST_COMPACT_MAX_TOKENS_PER_FILE = 5000, POST_COMPACT_MAX_TOKENS_PER_SKILL = 5000, POST_COMPACT_SKILLS_TOKEN_BUDGET = 25000, MAX_COMPACT_STREAMING_RETRIES = 2, LOCAL_COMPACT_TIMEOUT_MS = 120000, LOCAL_CONTEXT_OVERFLOW_PATTERNS, ERROR_MESSAGE_NOT_ENOUGH_MESSAGES = "Not enough messages to compact.", MAX_PTL_RETRIES = 3, PTL_RETRY_MARKER = "[earlier conversation truncated for compaction retry]", ERROR_MESSAGE_PROMPT_TOO_LONG = "Conversation too long. Press esc twice to go up a few messages and try again.", ERROR_MESSAGE_USER_ABORT = "API Error: Request was aborted.", ERROR_MESSAGE_INCOMPLETE_RESPONSE = "Compaction interrupted · This may be due to network issues — please try again.", SKILL_TRUNCATION_MARKER = `
201301
201328
 
201302
201329
  [... skill content truncated for compaction; use Read on the skill path if you need the full text]`;
201303
201330
  var init_compact = __esm(() => {
@@ -201337,6 +201364,15 @@ var init_compact = __esm(() => {
201337
201364
  init_internalLogging();
201338
201365
  init_tokenEstimation();
201339
201366
  init_prompt10();
201367
+ LOCAL_CONTEXT_OVERFLOW_PATTERNS = [
201368
+ /prompt is too long/i,
201369
+ /context.{0,20}(length|limit|window).{0,30}exceeded/i,
201370
+ /input.{0,20}(length|limit).{0,30}exceeded/i,
201371
+ /maximum.{0,20}(context|token)/i,
201372
+ /tokens?.{0,20}exceeds?.{0,20}(max|limit|context)/i,
201373
+ /too.{0,5}many.{0,10}tokens/i,
201374
+ /\bKV.{0,10}cache.{0,20}(full|exceeded)/i
201375
+ ];
201340
201376
  });
201341
201377
 
201342
201378
  // src/constants/systemPromptSections.ts
@@ -207652,7 +207688,7 @@ function getTelemetryAttributes() {
207652
207688
  attributes["session.id"] = sessionId;
207653
207689
  }
207654
207690
  if (shouldIncludeAttribute("OTEL_METRICS_INCLUDE_VERSION")) {
207655
- attributes["app.version"] = "2.3.2";
207691
+ attributes["app.version"] = "2.3.4";
207656
207692
  }
207657
207693
  const oauthAccount = getOauthAccountInfo();
207658
207694
  if (oauthAccount) {
@@ -208104,10 +208140,11 @@ function isAutoCompactEnabled() {
208104
208140
  if (isEnvTruthy(process.env.DISABLE_COMPACT)) {
208105
208141
  return false;
208106
208142
  }
208107
- if (isEnvTruthy(process.env.DISABLE_AUTO_COMPACT)) {
208108
- return false;
208143
+ const projectSetting = getCurrentProjectConfig().autoCompactEnabled;
208144
+ if (typeof projectSetting === "boolean") {
208145
+ return projectSetting;
208109
208146
  }
208110
- return true;
208147
+ return getGlobalConfig().autoCompactEnabled !== false;
208111
208148
  }
208112
208149
  async function shouldAutoCompact(messages, model, querySource, snipTokensFreed = 0) {
208113
208150
  if (querySource === "session_memory" || querySource === "compact" || querySource === "keepgoing_synthesis") {
@@ -208169,6 +208206,7 @@ async function autoCompactIfNeeded(messages, toolUseContext, cacheSafeParams, qu
208169
208206
  var MAX_OUTPUT_TOKENS_FOR_SUMMARY = 20000, AUTOCOMPACT_BUFFER_TOKENS = 13000, WARNING_THRESHOLD_BUFFER_TOKENS = 20000, ERROR_THRESHOLD_BUFFER_TOKENS = 20000, MANUAL_COMPACT_BUFFER_TOKENS = 3000, MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES = 3;
208170
208207
  var init_autoCompact = __esm(() => {
208171
208208
  init_state();
208209
+ init_config();
208172
208210
  init_context();
208173
208211
  init_debug();
208174
208212
  init_envUtils();
@@ -269940,7 +269978,7 @@ function getInstallationEnv() {
269940
269978
  return;
269941
269979
  }
269942
269980
  function getClaudeCodeVersion() {
269943
- return "2.3.2";
269981
+ return "2.3.4";
269944
269982
  }
269945
269983
  async function getInstalledVSCodeExtensionVersion(command) {
269946
269984
  const { stdout } = await execFileNoThrow(command, ["--list-extensions", "--show-versions"], {
@@ -275214,7 +275252,7 @@ async function setupSdkMcpClients(sdkMcpConfigs, sendMcpMessage) {
275214
275252
  const client4 = new Client({
275215
275253
  name: "localclawd",
275216
275254
  title: "localclawd",
275217
- version: "2.3.2",
275255
+ version: "2.3.4",
275218
275256
  description: "local-first AI coding tool",
275219
275257
  websiteUrl: PRODUCT_URL
275220
275258
  }, {
@@ -275556,7 +275594,7 @@ var init_client9 = __esm(() => {
275556
275594
  const client4 = new Client({
275557
275595
  name: "localclawd",
275558
275596
  title: "localclawd",
275559
- version: "2.3.2",
275597
+ version: "2.3.4",
275560
275598
  description: "local-first AI coding tool",
275561
275599
  websiteUrl: PRODUCT_URL
275562
275600
  }, {
@@ -289955,7 +289993,7 @@ function computeFingerprint(messageText, version) {
289955
289993
  }
289956
289994
  function computeFingerprintFromMessages(messages) {
289957
289995
  const firstMessageText = extractFirstMessageText(messages);
289958
- return computeFingerprint(firstMessageText, "2.3.2");
289996
+ return computeFingerprint(firstMessageText, "2.3.4");
289959
289997
  }
289960
289998
  var FINGERPRINT_SALT = "59cf53e54c78";
289961
289999
  var init_fingerprint = () => {};
@@ -289997,7 +290035,7 @@ async function sideQuery(opts) {
289997
290035
  betas.push(STRUCTURED_OUTPUTS_BETA_HEADER);
289998
290036
  }
289999
290037
  const messageText = extractFirstUserMessageText(messages);
290000
- const fingerprint = computeFingerprint(messageText, "2.3.2");
290038
+ const fingerprint = computeFingerprint(messageText, "2.3.4");
290001
290039
  const attributionHeader = getAttributionHeader(fingerprint);
290002
290040
  const systemBlocks = [
290003
290041
  attributionHeader ? { type: "text", text: attributionHeader } : null,
@@ -310749,7 +310787,7 @@ var init_user = __esm(() => {
310749
310787
  deviceId,
310750
310788
  sessionId: getSessionId(),
310751
310789
  email: getEmail(),
310752
- appVersion: "2.3.2",
310790
+ appVersion: "2.3.4",
310753
310791
  platform: getHostPlatformForAnalytics(),
310754
310792
  organizationUuid,
310755
310793
  accountUuid,
@@ -311814,7 +311852,7 @@ async function initializeBetaTracing(resource) {
311814
311852
  });
311815
311853
  logs.setGlobalLoggerProvider(loggerProvider);
311816
311854
  setLoggerProvider(loggerProvider);
311817
- const eventLogger = logs.getLogger("com.anthropic.claude_code.events", "2.3.2");
311855
+ const eventLogger = logs.getLogger("com.anthropic.claude_code.events", "2.3.4");
311818
311856
  setEventLogger(eventLogger);
311819
311857
  process.on("beforeExit", async () => {
311820
311858
  await loggerProvider?.forceFlush();
@@ -311854,7 +311892,7 @@ async function initializeTelemetry() {
311854
311892
  const platform2 = getPlatform();
311855
311893
  const baseAttributes = {
311856
311894
  [ATTR_SERVICE_NAME4]: "claude-code",
311857
- [ATTR_SERVICE_VERSION4]: "2.3.2"
311895
+ [ATTR_SERVICE_VERSION4]: "2.3.4"
311858
311896
  };
311859
311897
  if (platform2 === "wsl") {
311860
311898
  const wslVersion = getWslVersion();
@@ -311899,7 +311937,7 @@ async function initializeTelemetry() {
311899
311937
  } catch {}
311900
311938
  };
311901
311939
  registerCleanup(shutdownTelemetry2);
311902
- return meterProvider2.getMeter("com.anthropic.claude_code", "2.3.2");
311940
+ return meterProvider2.getMeter("com.anthropic.claude_code", "2.3.4");
311903
311941
  }
311904
311942
  const meterProvider = new MeterProvider4({
311905
311943
  resource,
@@ -311919,7 +311957,7 @@ async function initializeTelemetry() {
311919
311957
  });
311920
311958
  logs.setGlobalLoggerProvider(loggerProvider);
311921
311959
  setLoggerProvider(loggerProvider);
311922
- const eventLogger = logs.getLogger("com.anthropic.claude_code.events", "2.3.2");
311960
+ const eventLogger = logs.getLogger("com.anthropic.claude_code.events", "2.3.4");
311923
311961
  setEventLogger(eventLogger);
311924
311962
  logForDebugging("[3P telemetry] Event logger set successfully");
311925
311963
  process.on("beforeExit", async () => {
@@ -311981,7 +312019,7 @@ Current timeout: ${timeoutMs}ms
311981
312019
  }
311982
312020
  };
311983
312021
  registerCleanup(shutdownTelemetry);
311984
- return meterProvider.getMeter("com.anthropic.claude_code", "2.3.2");
312022
+ return meterProvider.getMeter("com.anthropic.claude_code", "2.3.4");
311985
312023
  }
311986
312024
  async function flushTelemetry() {
311987
312025
  const meterProvider = getMeterProvider();
@@ -313171,7 +313209,7 @@ function detectLinuxGlobPatternWarnings() {
313171
313209
  }
313172
313210
  async function getDoctorDiagnostic() {
313173
313211
  const installationType = await getCurrentInstallationType();
313174
- const version = typeof MACRO !== "undefined" ? "2.3.2" : "unknown";
313212
+ const version = typeof MACRO !== "undefined" ? "2.3.4" : "unknown";
313175
313213
  const installationPath = await getInstallationPath();
313176
313214
  const invokedBinary = getInvokedBinary();
313177
313215
  const multipleInstallations = await detectMultipleInstallations();
@@ -314112,8 +314150,8 @@ async function updateLatest(channelOrVersion, forceReinstall = false) {
314112
314150
  const maxVersion = await getMaxVersion();
314113
314151
  if (maxVersion && gt(version, maxVersion)) {
314114
314152
  logForDebugging(`Native installer: maxVersion ${maxVersion} is set, capping update from ${version} to ${maxVersion}`);
314115
- if (gte("2.3.2", maxVersion)) {
314116
- logForDebugging(`Native installer: current version ${"2.3.2"} is already at or above maxVersion ${maxVersion}, skipping update`);
314153
+ if (gte("2.3.4", maxVersion)) {
314154
+ logForDebugging(`Native installer: current version ${"2.3.4"} is already at or above maxVersion ${maxVersion}, skipping update`);
314117
314155
  logEvent("tengu_native_update_skipped_max_version", {
314118
314156
  latency_ms: Date.now() - startTime,
314119
314157
  max_version: maxVersion,
@@ -314124,7 +314162,7 @@ async function updateLatest(channelOrVersion, forceReinstall = false) {
314124
314162
  version = maxVersion;
314125
314163
  }
314126
314164
  }
314127
- if (!forceReinstall && version === "2.3.2" && await versionIsAvailable(version) && await isPossibleLocalClawdBinary(executablePath)) {
314165
+ if (!forceReinstall && version === "2.3.4" && await versionIsAvailable(version) && await isPossibleLocalClawdBinary(executablePath)) {
314128
314166
  logForDebugging(`Found ${version} at ${executablePath}, skipping install`);
314129
314167
  logEvent("tengu_native_update_complete", {
314130
314168
  latency_ms: Date.now() - startTime,
@@ -351919,6 +351957,7 @@ var SUPPORTED_SETTINGS;
351919
351957
  var init_supportedSettings = __esm(() => {
351920
351958
  init_config();
351921
351959
  init_configConstants();
351960
+ init_context();
351922
351961
  init_modelOptions();
351923
351962
  init_validateModel();
351924
351963
  init_theme();
@@ -351948,9 +351987,20 @@ var init_supportedSettings = __esm(() => {
351948
351987
  options: NOTIFICATION_CHANNELS
351949
351988
  },
351950
351989
  autoCompactEnabled: {
351951
- source: "global",
351990
+ source: "project",
351952
351991
  type: "boolean",
351953
- description: "Auto-compact when context is full"
351992
+ description: "Auto-compact when this project approaches its context limit",
351993
+ formatOnRead: (v2) => typeof v2 === "boolean" ? v2 : getGlobalConfig().autoCompactEnabled
351994
+ },
351995
+ compactContextWindowTokens: {
351996
+ source: "project",
351997
+ type: "number",
351998
+ description: "Project-local context window cap used for usage and compaction thresholds",
351999
+ coerceOnWrite: (v2) => {
352000
+ const parsed = typeof v2 === "number" ? Number.isFinite(v2) ? Math.trunc(v2) : null : parseContextWindowString(String(v2));
352001
+ return parsed ? { value: parsed } : { error: "compactContextWindowTokens requires a value like 200k, 1m, or 131072." };
352002
+ },
352003
+ formatOnRead: (v2) => formatCompactContextWindowOption(typeof v2 === "number" ? v2 : undefined)
351954
352004
  },
351955
352005
  autoMemoryEnabled: {
351956
352006
  source: "settings",
@@ -352036,7 +352086,8 @@ var init_supportedSettings = __esm(() => {
352036
352086
  // src/tools/ConfigTool/prompt.ts
352037
352087
  function generatePrompt() {
352038
352088
  const globalSettings = [];
352039
- const projectSettings = [];
352089
+ const userSettings = [];
352090
+ const projectLocalSettings = [];
352040
352091
  for (const [key, config] of Object.entries(SUPPORTED_SETTINGS)) {
352041
352092
  if (key === "model")
352042
352093
  continue;
@@ -352048,12 +352099,16 @@ function generatePrompt() {
352048
352099
  line += `: ${options.map((o) => `"${o}"`).join(", ")}`;
352049
352100
  } else if (config.type === "boolean") {
352050
352101
  line += `: true/false`;
352102
+ } else if (config.type === "number") {
352103
+ line += `: number`;
352051
352104
  }
352052
352105
  line += ` - ${config.description}`;
352053
352106
  if (config.source === "global") {
352054
352107
  globalSettings.push(line);
352108
+ } else if (config.source === "project") {
352109
+ projectLocalSettings.push(line);
352055
352110
  } else {
352056
- projectSettings.push(line);
352111
+ userSettings.push(line);
352057
352112
  }
352058
352113
  }
352059
352114
  const modelSection = generateModelSection();
@@ -352073,8 +352128,12 @@ The following settings are available for you to change:
352073
352128
  ${globalSettings.join(`
352074
352129
  `)}
352075
352130
 
352076
- ### Project Settings (stored in settings.json)
352077
- ${projectSettings.join(`
352131
+ ### User Settings (stored in settings.json)
352132
+ ${userSettings.join(`
352133
+ `)}
352134
+
352135
+ ### Project-Local Settings (stored per project)
352136
+ ${projectLocalSettings.join(`
352078
352137
  `)}
352079
352138
 
352080
352139
  ${modelSection}
@@ -352201,8 +352260,7 @@ function getValue2(source, path10) {
352201
352260
  return;
352202
352261
  return config[key];
352203
352262
  }
352204
- const settings = getInitialSettings();
352205
- let current = settings;
352263
+ let current = source === "project" ? getCurrentProjectConfig() : getInitialSettings();
352206
352264
  for (const key of path10) {
352207
352265
  if (current && typeof current === "object" && key in current) {
352208
352266
  current = current[key];
@@ -352331,9 +352389,23 @@ var init_ConfigTool = __esm(() => {
352331
352389
  };
352332
352390
  }
352333
352391
  let finalValue = value;
352392
+ if (config.coerceOnWrite) {
352393
+ const result = config.coerceOnWrite(finalValue);
352394
+ if ("error" in result) {
352395
+ return {
352396
+ data: {
352397
+ success: false,
352398
+ operation: "set",
352399
+ setting,
352400
+ error: result.error
352401
+ }
352402
+ };
352403
+ }
352404
+ finalValue = result.value;
352405
+ }
352334
352406
  if (config.type === "boolean") {
352335
- if (typeof value === "string") {
352336
- const lower2 = value.toLowerCase().trim();
352407
+ if (typeof finalValue === "string") {
352408
+ const lower2 = finalValue.toLowerCase().trim();
352337
352409
  if (lower2 === "true")
352338
352410
  finalValue = true;
352339
352411
  else if (lower2 === "false")
@@ -352350,6 +352422,21 @@ var init_ConfigTool = __esm(() => {
352350
352422
  };
352351
352423
  }
352352
352424
  }
352425
+ if (config.type === "number") {
352426
+ if (typeof finalValue === "string" && finalValue.trim()) {
352427
+ finalValue = Number(finalValue);
352428
+ }
352429
+ if (typeof finalValue !== "number" || !Number.isFinite(finalValue)) {
352430
+ return {
352431
+ data: {
352432
+ success: false,
352433
+ operation: "set",
352434
+ setting,
352435
+ error: `${setting} requires a finite number.`
352436
+ }
352437
+ };
352438
+ }
352439
+ }
352353
352440
  const options = getOptionsForSetting(setting);
352354
352441
  if (options && !options.includes(String(finalValue))) {
352355
352442
  return {
@@ -352394,6 +352481,23 @@ var init_ConfigTool = __esm(() => {
352394
352481
  return prev;
352395
352482
  return { ...prev, [key]: finalValue };
352396
352483
  });
352484
+ } else if (config.source === "project") {
352485
+ const key = path10[0];
352486
+ if (!key) {
352487
+ return {
352488
+ data: {
352489
+ success: false,
352490
+ operation: "set",
352491
+ setting,
352492
+ error: "Invalid setting path"
352493
+ }
352494
+ };
352495
+ }
352496
+ saveCurrentProjectConfig((prev) => {
352497
+ if (prev[key] === finalValue)
352498
+ return prev;
352499
+ return { ...prev, [key]: finalValue };
352500
+ });
352397
352501
  } else {
352398
352502
  const update = buildNestedObject(path10, finalValue);
352399
352503
  const result = updateSettingsForSource("userSettings", update);
@@ -360399,7 +360503,7 @@ function getAnthropicEnvMetadata() {
360399
360503
  function getBuildAgeMinutes() {
360400
360504
  if (false)
360401
360505
  ;
360402
- const buildTime = new Date("2026-05-10T19:45:00.456Z").getTime();
360506
+ const buildTime = new Date("2026-05-10T21:07:59.152Z").getTime();
360403
360507
  if (isNaN(buildTime))
360404
360508
  return;
360405
360509
  return Math.floor((Date.now() - buildTime) / 60000);
@@ -388428,7 +388532,7 @@ function Feedback({
388428
388532
  platform: env3.platform,
388429
388533
  gitRepo: envInfo.isGit,
388430
388534
  terminal: env3.terminal,
388431
- version: "2.3.2",
388535
+ version: "2.3.4",
388432
388536
  transcript: normalizeMessagesForAPI(messages),
388433
388537
  errors: sanitizedErrors,
388434
388538
  lastApiRequest: getLastAPIRequest(),
@@ -388620,7 +388724,7 @@ function Feedback({
388620
388724
  ", ",
388621
388725
  env3.terminal,
388622
388726
  ", v",
388623
- "2.3.2"
388727
+ "2.3.4"
388624
388728
  ]
388625
388729
  }, undefined, true, undefined, this)
388626
388730
  ]
@@ -388726,7 +388830,7 @@ ${sanitizedDescription}
388726
388830
  ` + `**Environment Info**
388727
388831
  ` + `- Platform: ${env3.platform}
388728
388832
  ` + `- Terminal: ${env3.terminal}
388729
- ` + `- Version: ${"2.3.2"}
388833
+ ` + `- Version: ${"2.3.4"}
388730
388834
  ` + `- Feedback ID: ${feedbackId}
388731
388835
  ` + `
388732
388836
  **Errors**
@@ -391335,7 +391439,7 @@ function buildPrimarySection() {
391335
391439
  }, undefined, false, undefined, this);
391336
391440
  return [{
391337
391441
  label: "Version",
391338
- value: "2.3.2"
391442
+ value: "2.3.4"
391339
391443
  }, {
391340
391444
  label: "Session name",
391341
391445
  value: nameValue
@@ -394554,7 +394658,9 @@ function Config({
394554
394658
  const [, setTheme] = useTheme();
394555
394659
  const themeSetting = useThemeSetting();
394556
394660
  const [globalConfig, setGlobalConfig] = import_react104.useState(getGlobalConfig());
394661
+ const [projectConfig, setProjectConfig] = import_react104.useState(getCurrentProjectConfig());
394557
394662
  const initialConfig = React54.useRef(getGlobalConfig());
394663
+ const initialProjectConfig = React54.useRef(getCurrentProjectConfig());
394558
394664
  const [settingsData, setSettingsData] = import_react104.useState(getInitialSettings());
394559
394665
  const initialSettingsData = React54.useRef(getInitialSettings());
394560
394666
  const [currentOutputStyle, setCurrentOutputStyle] = import_react104.useState(settingsData?.outputStyle || DEFAULT_OUTPUT_STYLE_NAME);
@@ -394682,15 +394788,15 @@ function Config({
394682
394788
  {
394683
394789
  id: "autoCompactEnabled",
394684
394790
  label: "Auto-compact",
394685
- value: globalConfig.autoCompactEnabled,
394791
+ value: projectConfig.autoCompactEnabled ?? globalConfig.autoCompactEnabled,
394686
394792
  type: "boolean",
394687
394793
  onChange(autoCompactEnabled) {
394688
- saveGlobalConfig((current_0) => ({
394794
+ saveCurrentProjectConfig((current_0) => ({
394689
394795
  ...current_0,
394690
394796
  autoCompactEnabled
394691
394797
  }));
394692
- setGlobalConfig({
394693
- ...getGlobalConfig(),
394798
+ setProjectConfig({
394799
+ ...getCurrentProjectConfig(),
394694
394800
  autoCompactEnabled
394695
394801
  });
394696
394802
  logEvent("tengu_auto_compact_setting_changed", {
@@ -394701,17 +394807,17 @@ function Config({
394701
394807
  {
394702
394808
  id: "compactContextWindowTokens",
394703
394809
  label: "Compact context window",
394704
- value: formatCompactContextWindowOption(globalConfig.compactContextWindowTokens),
394810
+ value: formatCompactContextWindowOption(projectConfig.compactContextWindowTokens),
394705
394811
  options: [formatCompactContextWindowOption(undefined), ...COMPACT_CONTEXT_WINDOW_CHOICES.map(formatCompactContextWindowOption)],
394706
394812
  type: "enum",
394707
394813
  onChange(value) {
394708
394814
  const compactContextWindowTokens = COMPACT_CONTEXT_WINDOW_CHOICES.find((tokens) => formatCompactContextWindowOption(tokens) === value);
394709
- saveGlobalConfig((current_0) => ({
394815
+ saveCurrentProjectConfig((current_0) => ({
394710
394816
  ...current_0,
394711
394817
  compactContextWindowTokens
394712
394818
  }));
394713
- setGlobalConfig({
394714
- ...getGlobalConfig(),
394819
+ setProjectConfig({
394820
+ ...getCurrentProjectConfig(),
394715
394821
  compactContextWindowTokens
394716
394822
  });
394717
394823
  logEvent("tengu_compact_context_window_changed", {
@@ -395259,8 +395365,8 @@ function Config({
395259
395365
  id: "showExternalIncludesDialog",
395260
395366
  label: "External LOCALCLAWD.md includes",
395261
395367
  value: (() => {
395262
- const projectConfig = getCurrentProjectConfig();
395263
- if (projectConfig.hasClaudeMdExternalIncludesApproved) {
395368
+ const projectConfig2 = getCurrentProjectConfig();
395369
+ if (projectConfig2.hasClaudeMdExternalIncludesApproved) {
395264
395370
  return "true";
395265
395371
  } else {
395266
395372
  return "false";
@@ -395409,11 +395515,11 @@ function Config({
395409
395515
  if (globalConfig.autoInstallIdeExtension !== initialConfig.current.autoInstallIdeExtension) {
395410
395516
  formattedChanges.push(`${globalConfig.autoInstallIdeExtension ? "Enabled" : "Disabled"} auto-install IDE extension`);
395411
395517
  }
395412
- if (globalConfig.autoCompactEnabled !== initialConfig.current.autoCompactEnabled) {
395413
- formattedChanges.push(`${globalConfig.autoCompactEnabled ? "Enabled" : "Disabled"} auto-compact`);
395518
+ if (projectConfig.autoCompactEnabled !== initialProjectConfig.current.autoCompactEnabled) {
395519
+ formattedChanges.push(`${projectConfig.autoCompactEnabled ?? globalConfig.autoCompactEnabled ? "Enabled" : "Disabled"} auto-compact`);
395414
395520
  }
395415
- if (globalConfig.compactContextWindowTokens !== initialConfig.current.compactContextWindowTokens) {
395416
- formattedChanges.push(`Set compact context window to ${source_default.bold(formatCompactContextWindowOption(globalConfig.compactContextWindowTokens))}`);
395521
+ if (projectConfig.compactContextWindowTokens !== initialProjectConfig.current.compactContextWindowTokens) {
395522
+ formattedChanges.push(`Set compact context window to ${source_default.bold(formatCompactContextWindowOption(projectConfig.compactContextWindowTokens))}`);
395417
395523
  }
395418
395524
  if (globalConfig.respectGitignore !== initialConfig.current.respectGitignore) {
395419
395525
  formattedChanges.push(`${globalConfig.respectGitignore ? "Enabled" : "Disabled"} respect .gitignore in file picker`);
@@ -396016,7 +396122,7 @@ function Config({
396016
396122
  }
396017
396123
  }, undefined, false, undefined, this)
396018
396124
  }, undefined, false, undefined, this) : showSubmenu === "ChannelDowngrade" ? /* @__PURE__ */ jsx_dev_runtime176.jsxDEV(ChannelDowngradeDialog, {
396019
- currentVersion: "2.3.2",
396125
+ currentVersion: "2.3.4",
396020
396126
  onChoice: (choice) => {
396021
396127
  setShowSubmenu(null);
396022
396128
  setTabsHidden(false);
@@ -396028,7 +396134,7 @@ function Config({
396028
396134
  autoUpdatesChannel: "stable"
396029
396135
  };
396030
396136
  if (choice === "stay") {
396031
- newSettings.minimumVersion = "2.3.2";
396137
+ newSettings.minimumVersion = "2.3.4";
396032
396138
  }
396033
396139
  updateSettingsForSource("userSettings", newSettings);
396034
396140
  setSettingsData((prev_27) => ({
@@ -411807,7 +411913,7 @@ async function autoDetectProviderContextWindow() {
411807
411913
  return;
411808
411914
  _detected = true;
411809
411915
  try {
411810
- const configured = getGlobalConfig().compactContextWindowTokens;
411916
+ const configured = getCurrentProjectConfig().compactContextWindowTokens;
411811
411917
  if (configured && configured > 0) {
411812
411918
  setLocalProviderContextWindow(configured);
411813
411919
  logForDebugging(`[context] Using persisted context window: ${configured} tokens`);
@@ -411826,8 +411932,11 @@ async function autoDetectProviderContextWindow() {
411826
411932
  }
411827
411933
  if (detected && detected > 0) {
411828
411934
  setLocalProviderContextWindow(detected);
411829
- saveGlobalConfig((c5) => ({ ...c5, compactContextWindowTokens: detected }));
411830
- logForDebugging(`[context] Auto-detected context window from ${provider}: ${detected} tokens (persisted)`);
411935
+ saveCurrentProjectConfig((c5) => ({
411936
+ ...c5,
411937
+ compactContextWindowTokens: detected
411938
+ }));
411939
+ logForDebugging(`[context] Auto-detected context window from ${provider}: ${detected} tokens (persisted for project)`);
411831
411940
  }
411832
411941
  } catch (err2) {
411833
411942
  logForDebugging(`[context] Auto-detect context window failed (non-fatal): ${err2}`);
@@ -411860,7 +411969,11 @@ function barLine(used, total, width = 40) {
411860
411969
  return `[${"█".repeat(filled)}${" ".repeat(empty)}] ${Math.round(pct * 100)}%`;
411861
411970
  }
411862
411971
  function applySize(parsed, model, onDone) {
411863
- saveGlobalConfig((c5) => ({ ...c5, compactContextWindowTokens: parsed }));
411972
+ saveCurrentProjectConfig((c5) => ({ ...c5, compactContextWindowTokens: parsed }));
411973
+ saveGlobalConfig((c5) => {
411974
+ const { compactContextWindowTokens: _legacy, ...rest } = c5;
411975
+ return rest;
411976
+ });
411864
411977
  setLocalProviderContextWindow(parsed);
411865
411978
  onDone([
411866
411979
  `Context window set to ${fmtTokens(parsed)} tokens.`,
@@ -411892,15 +412005,16 @@ var call51 = async (onDone, context7, args) => {
411892
412005
  return applySize(parsed, model, onDone);
411893
412006
  }
411894
412007
  if (sub === "reset") {
412008
+ saveCurrentProjectConfig((c5) => {
412009
+ const { compactContextWindowTokens: _drop, ...rest } = c5;
412010
+ return rest;
412011
+ });
411895
412012
  saveGlobalConfig((c5) => {
411896
412013
  const { compactContextWindowTokens: _drop, ...rest } = c5;
411897
412014
  return rest;
411898
412015
  });
411899
412016
  setLocalProviderContextWindow(null);
411900
412017
  resetContextWindowDetection();
411901
- const hadEnv = process.env.LOCALCLAWD_MAX_CONTEXT_TOKENS || process.env.CLAUDE_CODE_MAX_CONTEXT_TOKENS;
411902
- delete process.env.LOCALCLAWD_MAX_CONTEXT_TOKENS;
411903
- delete process.env.CLAUDE_CODE_MAX_CONTEXT_TOKENS;
411904
412018
  await autoDetectProviderContextWindow();
411905
412019
  const detected = getLocalProviderContextWindow();
411906
412020
  const effective = getContextWindowForModel(model);
@@ -411910,9 +412024,6 @@ var call51 = async (onDone, context7, args) => {
411910
412024
  `Effective window: ${fmtTokens(getEffectiveContextWindowSize(model))} (minus output reservation).`,
411911
412025
  `Auto-compact threshold: ${fmtTokens(getAutoCompactThreshold(model))}.`
411912
412026
  ];
411913
- if (hadEnv) {
411914
- lines2.push("", "Note: LOCALCLAWD_MAX_CONTEXT_TOKENS / CLAUDE_CODE_MAX_CONTEXT_TOKENS were set in this", "process and have been cleared for this session. Unset them in your shell to make it", "permanent.");
411915
- }
411916
412027
  onDone(lines2.join(`
411917
412028
  `), { display: "system" });
411918
412029
  return null;
@@ -411921,7 +412032,7 @@ var call51 = async (onDone, context7, args) => {
411921
412032
  const toggle = parts[1]?.toLowerCase();
411922
412033
  if (toggle === "on" || toggle === "off") {
411923
412034
  const enable = toggle === "on";
411924
- saveGlobalConfig((c5) => ({ ...c5, autoCompactEnabled: enable }));
412035
+ saveCurrentProjectConfig((c5) => ({ ...c5, autoCompactEnabled: enable }));
411925
412036
  onDone(`Auto-compact ${enable ? "enabled" : "disabled"}.`, { display: "system" });
411926
412037
  return null;
411927
412038
  }
@@ -411931,7 +412042,7 @@ var call51 = async (onDone, context7, args) => {
411931
412042
  const totalWindow = getContextWindowForModel(model);
411932
412043
  const effectiveWindow = getEffectiveContextWindowSize(model);
411933
412044
  const autoCompactThreshold = getAutoCompactThreshold(model);
411934
- const persisted = getGlobalConfig().compactContextWindowTokens;
412045
+ const persisted = getCurrentProjectConfig().compactContextWindowTokens;
411935
412046
  const detectedFromProvider = getLocalProviderContextWindow();
411936
412047
  const tokenUsage = tokenCountWithEstimation(context7.messages);
411937
412048
  const autoCompact = isAutoCompactEnabled();
@@ -413547,7 +413658,7 @@ function Help(t0) {
413547
413658
  let t6;
413548
413659
  if ($2[31] !== tabs) {
413549
413660
  t6 = /* @__PURE__ */ jsx_dev_runtime218.jsxDEV(Tabs, {
413550
- title: `localclawd v${"2.3.2"}`,
413661
+ title: `localclawd v${"2.3.4"}`,
413551
413662
  color: "professionalBlue",
413552
413663
  defaultTab: "general",
413553
413664
  children: tabs
@@ -430809,7 +430920,7 @@ function getRecentReleaseNotes(currentVersion, previousVersion, changelogContent
430809
430920
  }
430810
430921
  return [];
430811
430922
  }
430812
- async function checkForReleaseNotes(lastSeenVersion, currentVersion = "2.3.2") {
430923
+ async function checkForReleaseNotes(lastSeenVersion, currentVersion = "2.3.4") {
430813
430924
  if (process.env.USER_TYPE === "ant") {
430814
430925
  const changelog = MACRO.VERSION_CHANGELOG;
430815
430926
  if (changelog) {
@@ -430836,7 +430947,7 @@ async function checkForReleaseNotes(lastSeenVersion, currentVersion = "2.3.2") {
430836
430947
  releaseNotes
430837
430948
  };
430838
430949
  }
430839
- function checkForReleaseNotesSync(lastSeenVersion, currentVersion = "2.3.2") {
430950
+ function checkForReleaseNotesSync(lastSeenVersion, currentVersion = "2.3.4") {
430840
430951
  if (process.env.USER_TYPE === "ant") {
430841
430952
  const changelog = MACRO.VERSION_CHANGELOG;
430842
430953
  if (changelog) {
@@ -430993,7 +431104,7 @@ function getRecentActivitySync() {
430993
431104
  return cachedActivity;
430994
431105
  }
430995
431106
  function getLogoDisplayData() {
430996
- const version = process.env.DEMO_VERSION ?? "2.3.2";
431107
+ const version = process.env.DEMO_VERSION ?? "2.3.4";
430997
431108
  const serverUrl = getDirectConnectServerUrl();
430998
431109
  const displayPath = process.env.DEMO_VERSION ? "/code/claude" : getDisplayPath(getCwd());
430999
431110
  const cwd2 = serverUrl ? `${displayPath} in ${serverUrl.replace(/^https?:\/\//, "")}` : displayPath;
@@ -432093,7 +432204,7 @@ function Logo() {
432093
432204
  if ($2[2] === Symbol.for("react.memo_cache_sentinel")) {
432094
432205
  t2 = () => {
432095
432206
  const currentConfig = getGlobalConfig();
432096
- if (currentConfig.lastReleaseNotesSeen === "2.3.2") {
432207
+ if (currentConfig.lastReleaseNotesSeen === "2.3.4") {
432097
432208
  return;
432098
432209
  }
432099
432210
  saveGlobalConfig(_temp325);
@@ -432752,12 +432863,12 @@ function Logo() {
432752
432863
  return t41;
432753
432864
  }
432754
432865
  function _temp325(current) {
432755
- if (current.lastReleaseNotesSeen === "2.3.2") {
432866
+ if (current.lastReleaseNotesSeen === "2.3.4") {
432756
432867
  return current;
432757
432868
  }
432758
432869
  return {
432759
432870
  ...current,
432760
- lastReleaseNotesSeen: "2.3.2"
432871
+ lastReleaseNotesSeen: "2.3.4"
432761
432872
  };
432762
432873
  }
432763
432874
  function _temp240(s_0) {
@@ -463216,7 +463327,7 @@ async function captureMemoryDiagnostics(trigger, dumpNumber = 0) {
463216
463327
  smapsRollup,
463217
463328
  platform: process.platform,
463218
463329
  nodeVersion: process.version,
463219
- ccVersion: "2.3.2"
463330
+ ccVersion: "2.3.4"
463220
463331
  };
463221
463332
  }
463222
463333
  async function performHeapDump(trigger = "manual", dumpNumber = 0) {
@@ -463801,7 +463912,7 @@ var init_bridge_kick = __esm(() => {
463801
463912
  var call86 = async () => {
463802
463913
  return {
463803
463914
  type: "text",
463804
- value: `${"2.3.2"} (built ${"2026-05-10T19:45:00.456Z"})`
463915
+ value: `${"2.3.4"} (built ${"2026-05-10T21:07:59.152Z"})`
463805
463916
  };
463806
463917
  }, version, version_default;
463807
463918
  var init_version = __esm(() => {
@@ -471745,7 +471856,7 @@ function generateHtmlReport(data, insights) {
471745
471856
  </html>`;
471746
471857
  }
471747
471858
  function buildExportData(data, insights, facets, remoteStats) {
471748
- const version2 = typeof MACRO !== "undefined" ? "2.3.2" : "unknown";
471859
+ const version2 = typeof MACRO !== "undefined" ? "2.3.4" : "unknown";
471749
471860
  const remote_hosts_collected = remoteStats?.hosts.filter((h2) => h2.sessionCount > 0).map((h2) => h2.name);
471750
471861
  const facets_summary = {
471751
471862
  total: facets.size,
@@ -475944,7 +476055,7 @@ var init_sessionStorage = __esm(() => {
475944
476055
  init_settings2();
475945
476056
  init_slowOperations();
475946
476057
  init_uuid();
475947
- VERSION6 = typeof MACRO !== "undefined" ? "2.3.2" : "unknown";
476058
+ VERSION6 = typeof MACRO !== "undefined" ? "2.3.4" : "unknown";
475948
476059
  MAX_TOMBSTONE_REWRITE_BYTES = 50 * 1024 * 1024;
475949
476060
  SKIP_FIRST_PROMPT_PATTERN = /^(?:\s*<[a-z][\w-]*[\s>]|\[Request interrupted by user[^\]]*\])/;
475950
476061
  EPHEMERAL_PROGRESS_TYPES = new Set([
@@ -477075,7 +477186,7 @@ var init_filesystem = __esm(() => {
477075
477186
  });
477076
477187
  getBundledSkillsRoot = memoize_default(function getBundledSkillsRoot2() {
477077
477188
  const nonce = randomBytes20(16).toString("hex");
477078
- return join154(getClaudeTempDir(), "bundled-skills", "2.3.2", nonce);
477189
+ return join154(getClaudeTempDir(), "bundled-skills", "2.3.4", nonce);
477079
477190
  });
477080
477191
  getResolvedWorkingDirPaths = memoize_default(getPathsForPermissionCheck);
477081
477192
  });
@@ -486312,7 +486423,7 @@ function buildSystemInitMessage(inputs) {
486312
486423
  slash_commands: inputs.commands.filter((c5) => c5.userInvocable !== false).map((c5) => c5.name),
486313
486424
  apiKeySource: getAnthropicApiKeyWithSource().source,
486314
486425
  betas: getSdkBetas(),
486315
- claude_code_version: "2.3.2",
486426
+ claude_code_version: "2.3.4",
486316
486427
  output_style: outputStyle2,
486317
486428
  agents: inputs.agents.map((agent) => agent.agentType),
486318
486429
  skills: inputs.skills.filter((s2) => s2.userInvocable !== false).map((skill) => skill.name),
@@ -500469,7 +500580,7 @@ var init_useVoiceEnabled = __esm(() => {
500469
500580
  function getSemverPart(version2) {
500470
500581
  return `${import_semver10.major(version2, { loose: true })}.${import_semver10.minor(version2, { loose: true })}.${import_semver10.patch(version2, { loose: true })}`;
500471
500582
  }
500472
- function useUpdateNotification(updatedVersion, initialVersion = "2.3.2") {
500583
+ function useUpdateNotification(updatedVersion, initialVersion = "2.3.4") {
500473
500584
  const [lastNotifiedSemver, setLastNotifiedSemver] = import_react214.useState(() => getSemverPart(initialVersion));
500474
500585
  if (!updatedVersion) {
500475
500586
  return null;
@@ -500509,7 +500620,7 @@ function AutoUpdater({
500509
500620
  return;
500510
500621
  }
500511
500622
  if (false) {}
500512
- const currentVersion = "2.3.2";
500623
+ const currentVersion = "2.3.4";
500513
500624
  const channel = getInitialSettings()?.autoUpdatesChannel ?? "latest";
500514
500625
  let latestVersion = await getLatestVersion(channel);
500515
500626
  const isDisabled = isAutoUpdaterDisabled();
@@ -500720,12 +500831,12 @@ function NativeAutoUpdater({
500720
500831
  logEvent("tengu_native_auto_updater_start", {});
500721
500832
  try {
500722
500833
  const maxVersion = await getMaxVersion();
500723
- if (maxVersion && gt("2.3.2", maxVersion)) {
500834
+ if (maxVersion && gt("2.3.4", maxVersion)) {
500724
500835
  const msg = await getMaxVersionMessage();
500725
500836
  setMaxVersionIssue(msg ?? "affects your version");
500726
500837
  }
500727
500838
  const result = await installLatest(channel);
500728
- const currentVersion = "2.3.2";
500839
+ const currentVersion = "2.3.4";
500729
500840
  const latencyMs = Date.now() - startTime;
500730
500841
  if (result.lockFailed) {
500731
500842
  logEvent("tengu_native_auto_updater_lock_contention", {
@@ -500860,17 +500971,17 @@ function PackageManagerAutoUpdater(t0) {
500860
500971
  const maxVersion = await getMaxVersion();
500861
500972
  if (maxVersion && latest && gt(latest, maxVersion)) {
500862
500973
  logForDebugging(`PackageManagerAutoUpdater: maxVersion ${maxVersion} is set, capping update from ${latest} to ${maxVersion}`);
500863
- if (gte("2.3.2", maxVersion)) {
500864
- logForDebugging(`PackageManagerAutoUpdater: current version ${"2.3.2"} is already at or above maxVersion ${maxVersion}, skipping update`);
500974
+ if (gte("2.3.4", maxVersion)) {
500975
+ logForDebugging(`PackageManagerAutoUpdater: current version ${"2.3.4"} is already at or above maxVersion ${maxVersion}, skipping update`);
500865
500976
  setUpdateAvailable(false);
500866
500977
  return;
500867
500978
  }
500868
500979
  latest = maxVersion;
500869
500980
  }
500870
- const hasUpdate = latest && !gte("2.3.2", latest) && !shouldSkipVersion(latest);
500981
+ const hasUpdate = latest && !gte("2.3.4", latest) && !shouldSkipVersion(latest);
500871
500982
  setUpdateAvailable(!!hasUpdate);
500872
500983
  if (hasUpdate) {
500873
- logForDebugging(`PackageManagerAutoUpdater: Update available ${"2.3.2"} -> ${latest}`);
500984
+ logForDebugging(`PackageManagerAutoUpdater: Update available ${"2.3.4"} -> ${latest}`);
500874
500985
  }
500875
500986
  };
500876
500987
  $2[0] = t1;
@@ -500904,7 +501015,7 @@ function PackageManagerAutoUpdater(t0) {
500904
501015
  wrap: "truncate",
500905
501016
  children: [
500906
501017
  "currentVersion: ",
500907
- "2.3.2"
501018
+ "2.3.4"
500908
501019
  ]
500909
501020
  }, undefined, true, undefined, this);
500910
501021
  $2[3] = verbose;
@@ -508464,7 +508575,7 @@ function buildStatusLineCommandInput(permissionMode, exceedsHalfContext, setting
508464
508575
  project_dir: getOriginalCwd(),
508465
508576
  added_dirs: addedDirs
508466
508577
  },
508467
- version: "2.3.2",
508578
+ version: "2.3.4",
508468
508579
  output_style: {
508469
508580
  name: outputStyleName
508470
508581
  },
@@ -520036,7 +520147,7 @@ async function submitTranscriptShare(messages, trigger, appearanceId) {
520036
520147
  } catch {}
520037
520148
  const data = {
520038
520149
  trigger,
520039
- version: "2.3.2",
520150
+ version: "2.3.4",
520040
520151
  platform: process.platform,
520041
520152
  transcript,
520042
520153
  subagentTranscripts: Object.keys(subagentTranscripts).length > 0 ? subagentTranscripts : undefined,
@@ -537009,7 +537120,7 @@ function appendToLog(path17, message) {
537009
537120
  cwd: getFsImplementation().cwd(),
537010
537121
  userType: process.env.USER_TYPE,
537011
537122
  sessionId: getSessionId(),
537012
- version: "2.3.2"
537123
+ version: "2.3.4"
537013
537124
  };
537014
537125
  getLogWriter(path17).write(messageWithTimestamp);
537015
537126
  }
@@ -537268,7 +537379,7 @@ To attach: ${source_default.bold(`tmux attach -t ${tmuxSessionName}`)}`));
537268
537379
  startToolRpcServer();
537269
537380
  startScheduler();
537270
537381
  initSecretStore();
537271
- const persistedCtx = getGlobalConfig().compactContextWindowTokens;
537382
+ const persistedCtx = getCurrentProjectConfig().compactContextWindowTokens;
537272
537383
  if (persistedCtx && persistedCtx > 0) {
537273
537384
  logForDebugging(`[context] Using configured context window: ${persistedCtx} tokens`);
537274
537385
  } else if (isLocalLLMProviderEnabled()) {
@@ -540808,8 +540919,8 @@ async function getEnvLessBridgeConfig() {
540808
540919
  }
540809
540920
  async function checkEnvLessBridgeMinVersion() {
540810
540921
  const cfg = await getEnvLessBridgeConfig();
540811
- if (cfg.min_version && lt("2.3.2", cfg.min_version)) {
540812
- return `Your version of localclawd (${"2.3.2"}) is too old for Remote Control.
540922
+ if (cfg.min_version && lt("2.3.4", cfg.min_version)) {
540923
+ return `Your version of localclawd (${"2.3.4"}) is too old for Remote Control.
540813
540924
  Version ${cfg.min_version} or higher is required. Run \`localclawd update\` to update.`;
540814
540925
  }
540815
540926
  return null;
@@ -541281,7 +541392,7 @@ async function initBridgeCore(params) {
541281
541392
  const rawApi = createBridgeApiClient({
541282
541393
  baseUrl,
541283
541394
  getAccessToken,
541284
- runnerVersion: "2.3.2",
541395
+ runnerVersion: "2.3.4",
541285
541396
  onDebug: logForDebugging,
541286
541397
  onAuth401,
541287
541398
  getTrustedDeviceToken
@@ -547000,7 +547111,7 @@ async function startMCPServer(cwd3, debug4, verbose) {
547000
547111
  setCwd(cwd3);
547001
547112
  const server = new Server({
547002
547113
  name: "claude/tengu",
547003
- version: "2.3.2"
547114
+ version: "2.3.4"
547004
547115
  }, {
547005
547116
  capabilities: {
547006
547117
  tools: {}
@@ -548081,7 +548192,7 @@ function WelcomeLogo() {
548081
548192
  dimColor: true,
548082
548193
  children: [
548083
548194
  "v",
548084
- "2.3.2"
548195
+ "2.3.4"
548085
548196
  ]
548086
548197
  }, undefined, true, undefined, this)
548087
548198
  ]
@@ -548272,7 +548383,7 @@ __export(exports_update, {
548272
548383
  });
548273
548384
  async function update() {
548274
548385
  logEvent("tengu_update_check", {});
548275
- writeToStdout(`Current version: ${"2.3.2"}
548386
+ writeToStdout(`Current version: ${"2.3.4"}
548276
548387
  `);
548277
548388
  const channel = getInitialSettings()?.autoUpdatesChannel ?? "latest";
548278
548389
  writeToStdout(`Checking for updates to ${channel} version...
@@ -548347,8 +548458,8 @@ async function update() {
548347
548458
  writeToStdout(`localclawd is managed by Homebrew.
548348
548459
  `);
548349
548460
  const latest = await getLatestVersion(channel);
548350
- if (latest && !gte("2.3.2", latest)) {
548351
- writeToStdout(`Update available: ${"2.3.2"} → ${latest}
548461
+ if (latest && !gte("2.3.4", latest)) {
548462
+ writeToStdout(`Update available: ${"2.3.4"} → ${latest}
548352
548463
  `);
548353
548464
  writeToStdout(`
548354
548465
  `);
@@ -548364,8 +548475,8 @@ async function update() {
548364
548475
  writeToStdout(`localclawd is managed by winget.
548365
548476
  `);
548366
548477
  const latest = await getLatestVersion(channel);
548367
- if (latest && !gte("2.3.2", latest)) {
548368
- writeToStdout(`Update available: ${"2.3.2"} → ${latest}
548478
+ if (latest && !gte("2.3.4", latest)) {
548479
+ writeToStdout(`Update available: ${"2.3.4"} → ${latest}
548369
548480
  `);
548370
548481
  writeToStdout(`
548371
548482
  `);
@@ -548379,8 +548490,8 @@ async function update() {
548379
548490
  writeToStdout(`localclawd is managed by apk.
548380
548491
  `);
548381
548492
  const latest = await getLatestVersion(channel);
548382
- if (latest && !gte("2.3.2", latest)) {
548383
- writeToStdout(`Update available: ${"2.3.2"} → ${latest}
548493
+ if (latest && !gte("2.3.4", latest)) {
548494
+ writeToStdout(`Update available: ${"2.3.4"} → ${latest}
548384
548495
  `);
548385
548496
  writeToStdout(`
548386
548497
  `);
@@ -548445,11 +548556,11 @@ async function update() {
548445
548556
  `);
548446
548557
  await gracefulShutdown(1);
548447
548558
  }
548448
- if (result.latestVersion === "2.3.2") {
548449
- writeToStdout(source_default.green(`localclawd is up to date (${"2.3.2"})`) + `
548559
+ if (result.latestVersion === "2.3.4") {
548560
+ writeToStdout(source_default.green(`localclawd is up to date (${"2.3.4"})`) + `
548450
548561
  `);
548451
548562
  } else {
548452
- writeToStdout(source_default.green(`Successfully updated from ${"2.3.2"} to version ${result.latestVersion}`) + `
548563
+ writeToStdout(source_default.green(`Successfully updated from ${"2.3.4"} to version ${result.latestVersion}`) + `
548453
548564
  `);
548454
548565
  await regenerateCompletionCache();
548455
548566
  }
@@ -548509,12 +548620,12 @@ async function update() {
548509
548620
  `);
548510
548621
  await gracefulShutdown(1);
548511
548622
  }
548512
- if (latestVersion === "2.3.2") {
548513
- writeToStdout(source_default.green(`localclawd is up to date (${"2.3.2"})`) + `
548623
+ if (latestVersion === "2.3.4") {
548624
+ writeToStdout(source_default.green(`localclawd is up to date (${"2.3.4"})`) + `
548514
548625
  `);
548515
548626
  await gracefulShutdown(0);
548516
548627
  }
548517
- writeToStdout(`New version available: ${latestVersion} (current: ${"2.3.2"})
548628
+ writeToStdout(`New version available: ${latestVersion} (current: ${"2.3.4"})
548518
548629
  `);
548519
548630
  writeToStdout(`Installing update...
548520
548631
  `);
@@ -548559,7 +548670,7 @@ async function update() {
548559
548670
  logForDebugging(`update: Installation status: ${status2}`);
548560
548671
  switch (status2) {
548561
548672
  case "success":
548562
- writeToStdout(source_default.green(`Successfully updated from ${"2.3.2"} to version ${latestVersion}`) + `
548673
+ writeToStdout(source_default.green(`Successfully updated from ${"2.3.4"} to version ${latestVersion}`) + `
548563
548674
  `);
548564
548675
  await regenerateCompletionCache();
548565
548676
  break;
@@ -549801,7 +549912,7 @@ Run with --debug for more details.
549801
549912
  }
549802
549913
  }
549803
549914
  logForDiagnosticsNoPII("info", "started", {
549804
- version: "2.3.2",
549915
+ version: "2.3.4",
549805
549916
  is_native_binary: isInBundledMode()
549806
549917
  });
549807
549918
  registerCleanup(async () => {
@@ -550585,7 +550696,7 @@ Usage: localclawd --remote "your task description"`, () => gracefulShutdown(1));
550585
550696
  pendingHookMessages
550586
550697
  }, renderAndRun);
550587
550698
  }
550588
- }).version("2.3.2 (localclawd)", "-v, --version", "Output the version number");
550699
+ }).version("2.3.4 (localclawd)", "-v, --version", "Output the version number");
550589
550700
  program2.option("-w, --worktree [name]", "Create a new git worktree for this session (optionally specify a name)");
550590
550701
  program2.option("--tmux", "Create a tmux session for the worktree (requires --worktree). Uses iTerm2 native panes when available; use --tmux=classic for traditional tmux.");
550591
550702
  if (canUserConfigureAdvisor()) {
@@ -551099,7 +551210,7 @@ if (false) {}
551099
551210
  async function main2() {
551100
551211
  const args = process.argv.slice(2);
551101
551212
  if (args.length === 1 && (args[0] === "--version" || args[0] === "-v" || args[0] === "-V")) {
551102
- console.log(`${"2.3.2"} (localclawd)`);
551213
+ console.log(`${"2.3.4"} (localclawd)`);
551103
551214
  return;
551104
551215
  }
551105
551216
  const {
@@ -551190,4 +551301,4 @@ localclawd crashed: ${msg}
551190
551301
  process.exit(1);
551191
551302
  });
551192
551303
 
551193
- //# debugId=24BCE86E7F99FBEB64756E2164756E21
551304
+ //# debugId=A5F8BEA60598962064756E2164756E21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "localclawd",
3
- "version": "2.3.2",
3
+ "version": "2.3.4",
4
4
  "description": "Local-first coding CLI for vLLM, Ollama, and OpenAI-compatible backends.",
5
5
  "private": false,
6
6
  "type": "module",