diff --git a/src/ClaudeDo.Localization/locales/de.json b/src/ClaudeDo.Localization/locales/de.json
index e507e90c..d062644e 100644
--- a/src/ClaudeDo.Localization/locales/de.json
+++ b/src/ClaudeDo.Localization/locales/de.json
@@ -40,6 +40,10 @@
"usageGateSevenDayPct": "7-Tage-Fenster (%)",
"autoContinueOnUsageLimit": "Nach Limit-Reset fortsetzen",
"autoContinueOnUsageLimitHint": "Ist ein Run am Nutzungslimit abgebrochen, wird er nach Ablauf des 5-Stunden-Fensters automatisch fortgesetzt. Weckt außerdem die pausierte Queue genau zum Reset-Zeitpunkt statt erst beim nächsten Backstop-Check.",
+ "throttleStagesHeading": "Throttle-Stufen",
+ "throttleStagesHint": "Die Parallelität wird vor dem harten Gate begrenzt: soft auf 2 Slots, hard auf 1. Eingestellt wird das durch Ziehen der Marker an den Gauges im Usage-Monitor. Der Monitor schließt diese Einstellungen — vorher speichern, wenn du etwas geändert hast.",
+ "throttleStagesValues": "5h: soft {0}% / hard {1}% · 7d: soft {2}% / hard {3}%",
+ "openUsageMonitor": "Usage-Monitor öffnen...",
"reportExcludedPaths": "Bericht: ausgeschlossene Pfade (einer pro Zeile)",
"standupWeekday": "Standup-Wochentag",
"weekdaySunday": "Sonntag",
@@ -66,6 +70,10 @@
"confirmRemoveAll": "ALLE Worktrees entfernen? Nicht committete Arbeit geht verloren."
},
"files": {
+ "cliSection": "CLAUDE CLI",
+ "claudeBinHint": "Befehl oder vollständiger Pfad, den der Worker startet. Leer setzt auf \"claude\" zurück. Gilt ab dem nächsten Task-Run — kein Neustart nötig.",
+ "claudeBinResolved": "Aufgelöst zu: {0}",
+ "claudeBinUnresolved": "Nicht im PATH gefunden — Task-Runs schlagen fehl, solange das so bleibt.",
"agentsSection": "AGENTEN",
"agentsHint": "Mitgelieferte Standard-Agenten wiederherstellen. Vorhandene Dateien werden nicht überschrieben.",
"restoreDefaultAgents": "Standard-Agenten wiederherstellen",
@@ -762,6 +770,9 @@
"forceRemoving": "Worktree wird zwangsweise entfernt…",
"batchMerging": "Merge {0}/{1}…"
},
+ "claudeBin": {
+ "saving": "claude_bin wird gespeichert…"
+ },
"skills": {
"installing": "Skill wird geklont…",
"updating": "Skill wird aktualisiert…",
diff --git a/src/ClaudeDo.Localization/locales/en.json b/src/ClaudeDo.Localization/locales/en.json
index 32cfc353..eeac0fac 100644
--- a/src/ClaudeDo.Localization/locales/en.json
+++ b/src/ClaudeDo.Localization/locales/en.json
@@ -40,6 +40,10 @@
"usageGateSevenDayPct": "7-day window (%)",
"autoContinueOnUsageLimit": "Continue on session limit reset",
"autoContinueOnUsageLimitHint": "When a run stops because it hit the usage limit, automatically continue it once the 5-hour window resets. Also wakes the paused queue exactly at reset time instead of waiting for the next backstop check.",
+ "throttleStagesHeading": "Throttle stages",
+ "throttleStagesHint": "Parallelism is capped before the hard gate: soft caps at 2 slots, hard at 1. Edited by dragging the markers on the usage-monitor gauges. Opening the monitor closes these settings — save first if you changed anything.",
+ "throttleStagesValues": "5h: soft {0}% / hard {1}% · 7d: soft {2}% / hard {3}%",
+ "openUsageMonitor": "Open usage monitor...",
"reportExcludedPaths": "Report: excluded paths (one per line)",
"standupWeekday": "Standup weekday",
"weekdaySunday": "Sunday",
@@ -66,6 +70,10 @@
"confirmRemoveAll": "Remove ALL worktrees? Uncommitted work will be lost."
},
"files": {
+ "cliSection": "CLAUDE CLI",
+ "claudeBinHint": "Command or full path the worker starts. Blank resets to \"claude\". Applies to the next task run — no restart needed.",
+ "claudeBinResolved": "Resolves to: {0}",
+ "claudeBinUnresolved": "Not found on PATH — task runs will fail until this resolves.",
"agentsSection": "AGENTS",
"agentsHint": "Restore bundled default agents. Existing files are not overwritten.",
"restoreDefaultAgents": "Restore default agents",
@@ -762,6 +770,9 @@
"forceRemoving": "Force-removing worktree…",
"batchMerging": "Merging {0}/{1}…"
},
+ "claudeBin": {
+ "saving": "Saving claude_bin…"
+ },
"skills": {
"installing": "Cloning skill…",
"updating": "Updating skill…",
diff --git a/src/ClaudeDo.Ui/ViewModels/Modals/SettingsModalViewModel.cs b/src/ClaudeDo.Ui/ViewModels/Modals/SettingsModalViewModel.cs
index 4b55b3e6..f47a7f7c 100644
--- a/src/ClaudeDo.Ui/ViewModels/Modals/SettingsModalViewModel.cs
+++ b/src/ClaudeDo.Ui/ViewModels/Modals/SettingsModalViewModel.cs
@@ -66,6 +66,18 @@ public sealed partial class SettingsModalViewModel : ViewModelBase
[RelayCommand]
private void OpenRepoImport() => RequestRepoImport?.Invoke();
+ // Same deal for the usage monitor, which owns the throttle-stage editor. It must *close* this
+ // modal rather than stack on top: Save() writes the throttle values it read at open, so a drag
+ // made while Settings is still open would be overwritten on save.
+ public Action? RequestUsageMonitor { get; set; }
+
+ [RelayCommand]
+ private void OpenUsageMonitor() => RequestUsageMonitor?.Invoke();
+
+ /// Read-only echo of the four throttle percentages, which are edited by dragging the
+ /// usage-monitor gauges — without this the Execution tab silently carries them through.
+ [ObservableProperty] private string _throttleSummary = "";
+
[ObservableProperty] private string _validationError = "";
[ObservableProperty] private bool _isBusy;
[ObservableProperty] private string _statusMessage = "";
@@ -135,6 +147,9 @@ public sealed partial class SettingsModalViewModel : ViewModelBase
_throttleStages = (
dto.UsageThrottleFiveHourSoftPct, dto.UsageThrottleFiveHourHardPct,
dto.UsageThrottleSevenDaySoftPct, dto.UsageThrottleSevenDayHardPct);
+ ThrottleSummary = Loc.T("settings.general.throttleStagesValues",
+ _throttleStages.FiveSoft, _throttleStages.FiveHard,
+ _throttleStages.SevenSoft, _throttleStages.SevenHard);
Worktrees.WorktreeStrategy = dto.WorktreeStrategy ?? "sibling";
Worktrees.CentralWorktreeRoot = dto.CentralWorktreeRoot;
Worktrees.WorktreeAutoCleanupEnabled = dto.WorktreeAutoCleanupEnabled;
@@ -148,6 +163,7 @@ public sealed partial class SettingsModalViewModel : ViewModelBase
}
else StatusMessage = Loc.T("vm.settingsModal.workerOffline");
+ await Files.LoadClaudeBinAsync();
await Prime.LoadAsync();
await OnlineInbox.LoadAsync();
await SessionSkills.LoadAsync(dto?.SessionSkills);
diff --git a/src/ClaudeDo.Ui/Views/Modals/SettingsModalView.axaml b/src/ClaudeDo.Ui/Views/Modals/SettingsModalView.axaml
index 4f652b51..8b96ed38 100644
--- a/src/ClaudeDo.Ui/Views/Modals/SettingsModalView.axaml
+++ b/src/ClaudeDo.Ui/Views/Modals/SettingsModalView.axaml
@@ -252,6 +252,18 @@
+
+
+
+
+
+
+
+
@@ -394,6 +406,22 @@
+
+
+
+
+
+
+
+
+
+
+
+ {
+ dlg.Close();
+ if (Shell is not null) _ = Shell.OpenUsageMonitorCommand.ExecuteAsync(null);
+ };
await dlg.ShowDialog(ActiveOwner());
}