From 9f88b4a8cfc3927b64030463aad79281e1bdfb78 Mon Sep 17 00:00:00 2001
From: youngmrz
Date: Sun, 18 Jan 2026 12:04:45 -0500
Subject: [PATCH 01/10] auto-claude: subtask-1-1 - Add disableHistoryStorage
setting to Settings data
---
src-pyloid/services/settings.py | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src-pyloid/services/settings.py b/src-pyloid/services/settings.py
index ac61e3a..6213592 100644
--- a/src-pyloid/services/settings.py
+++ b/src-pyloid/services/settings.py
@@ -48,6 +48,7 @@ class Settings:
onboarding_complete: bool = False
microphone: int = -1 # -1 = default device, otherwise device id
save_audio_to_history: bool = False
+ disable_history_storage: bool = False
# Hotkey settings
hold_hotkey: str = "ctrl+win"
hold_hotkey_enabled: bool = True
@@ -74,6 +75,7 @@ def get_settings(self) -> Settings:
onboarding_complete=self.db.get_setting("onboarding_complete", "false") == "true",
microphone=int(self.db.get_setting("microphone", "-1")),
save_audio_to_history=self.db.get_setting("save_audio_to_history", "false") == "true",
+ disable_history_storage=self.db.get_setting("disable_history_storage", "false") == "true",
# Hotkey settings
hold_hotkey=self.db.get_setting("hold_hotkey", "ctrl+win"),
hold_hotkey_enabled=self.db.get_setting("hold_hotkey_enabled", "true") == "true",
@@ -95,6 +97,7 @@ def update_settings(
onboarding_complete: Optional[bool] = None,
microphone: Optional[int] = None,
save_audio_to_history: Optional[bool] = None,
+ disable_history_storage: Optional[bool] = None,
hold_hotkey: Optional[str] = None,
hold_hotkey_enabled: Optional[bool] = None,
toggle_hotkey: Optional[str] = None,
@@ -118,6 +121,8 @@ def update_settings(
self.db.set_setting("microphone", str(microphone))
if save_audio_to_history is not None:
self.db.set_setting("save_audio_to_history", "true" if save_audio_to_history else "false")
+ if disable_history_storage is not None:
+ self.db.set_setting("disable_history_storage", "true" if disable_history_storage else "false")
# Hotkey settings - normalize before storing for consistent format
if hold_hotkey is not None:
self.db.set_setting("hold_hotkey", normalize_hotkey(hold_hotkey))
From 6c74f5c4186cc374ecbcf8aca6c6c5c0c7a7b989 Mon Sep 17 00:00:00 2001
From: youngmrz
Date: Sun, 18 Jan 2026 12:06:09 -0500
Subject: [PATCH 02/10] auto-claude: subtask-1-2 - Add RPC method for
disableHistoryStorage in server
---
src-pyloid/server.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src-pyloid/server.py b/src-pyloid/server.py
index 7fcc7bd..e00ea18 100644
--- a/src-pyloid/server.py
+++ b/src-pyloid/server.py
@@ -60,6 +60,7 @@ async def update_settings(
holdHotkeyEnabled: Optional[bool] = None,
toggleHotkey: Optional[str] = None,
toggleHotkeyEnabled: Optional[bool] = None,
+ disableHistoryStorage: Optional[bool] = None,
):
controller = get_controller()
kwargs = {}
@@ -90,6 +91,8 @@ async def update_settings(
kwargs["toggleHotkey"] = toggleHotkey
if toggleHotkeyEnabled is not None:
kwargs["toggleHotkeyEnabled"] = toggleHotkeyEnabled
+ if disableHistoryStorage is not None:
+ kwargs["disableHistoryStorage"] = disableHistoryStorage
# Check if onboarding was already complete before this update
old_settings = controller.get_settings()
From 547169fb024ecf28aa1bb5d01093397be797e584 Mon Sep 17 00:00:00 2001
From: youngmrz
Date: Sun, 18 Jan 2026 12:07:27 -0500
Subject: [PATCH 03/10] auto-claude: subtask-2-1 - Add disableHistoryStorage to
Settings interface
---
src/lib/types.ts | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/lib/types.ts b/src/lib/types.ts
index 258da83..7f397d2 100644
--- a/src/lib/types.ts
+++ b/src/lib/types.ts
@@ -8,6 +8,7 @@ export interface Settings {
onboardingComplete: boolean;
microphone: number;
saveAudioToHistory: boolean;
+ disableHistoryStorage: boolean;
// Hotkey settings
holdHotkey: string;
holdHotkeyEnabled: boolean;
From 0cc6974c3d3dca8e0f57b0773244c64139837758 Mon Sep 17 00:00:00 2001
From: youngmrz
Date: Sun, 18 Jan 2026 12:10:58 -0500
Subject: [PATCH 04/10] auto-claude: subtask-3-1 - Create Privacy section
BentoSettingCard in Setting
---
src/components/SettingsTab.tsx | 45 ++++++++++++++++++++++++++++++----
1 file changed, 40 insertions(+), 5 deletions(-)
diff --git a/src/components/SettingsTab.tsx b/src/components/SettingsTab.tsx
index e9102f5..892eedf 100644
--- a/src/components/SettingsTab.tsx
+++ b/src/components/SettingsTab.tsx
@@ -24,6 +24,7 @@ import {
Hand,
ToggleRight,
HardDrive,
+ Shield,
} from "lucide-react";
import { api } from "@/lib/api";
import type { Settings, Options, GpuInfo } from "@/lib/types";
@@ -422,7 +423,41 @@ export function SettingsTab() {
- {/* 7. System (Auto Start) (Span 4) */}
+ {/* 7. Privacy (Span 6) */}
+
+
+
+
+ Voice data stays in RAM only. No network transmission. No disk storage unless history is enabled. All processing happens locally on your device.
+
+
+
+
+
+ updateSetting("disableHistoryStorage", checked)
+ }
+ />
+
+
+ When enabled, transcriptions are pasted but never saved to history for maximum privacy.
+
+
+
+
+ {/* 8. System (Auto Start) (Span 4) */}
- {/* 8. Data Folder (Span 4) */}
+ {/* 9. Data Folder (Span 4) */}
- {/* 8. Keyboard Shortcuts (Full Width) */}
+ {/* 10. Keyboard Shortcuts (Full Width) */}
- {/* 9. GPU / Device (Span 6) */}
+ {/* 11. GPU / Device (Span 6) */}
- {/* 10. Danger Zone (Span 4) */}
+ {/* 12. Danger Zone (Span 4) */}
From 1c1fb748dfc56dfe7fa559a3b7ebe0c98833029c Mon Sep 17 00:00:00 2001
From: youngmrz
Date: Sun, 18 Jan 2026 12:13:44 -0500
Subject: [PATCH 05/10] auto-claude: subtask-4-1 - Add dedicated privacy
explanation card to StepWelcome
---
src/pages/Onboarding.tsx | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/src/pages/Onboarding.tsx b/src/pages/Onboarding.tsx
index 4df0527..b17eda6 100644
--- a/src/pages/Onboarding.tsx
+++ b/src/pages/Onboarding.tsx
@@ -48,6 +48,20 @@ const StepWelcome = () => (
flow.
+
+
+
+
+
+
+
Your Privacy is Guaranteed
+
+ Voice data stays in RAM only. No network transmission. No disk storage unless history is enabled. All processing happens locally on your device.
+
+
+
+
+
{ONBOARDING_FEATURES.map((feature) => (
Date: Sun, 18 Jan 2026 12:16:24 -0500
Subject: [PATCH 06/10] auto-claude: subtask-5-1 - Add offline badge/indicator
to Popup component visible in idle state
---
src/pages/Popup.tsx | 34 ++++++++++++++++++++++++++++------
1 file changed, 28 insertions(+), 6 deletions(-)
diff --git a/src/pages/Popup.tsx b/src/pages/Popup.tsx
index dac1b7b..d4ce573 100644
--- a/src/pages/Popup.tsx
+++ b/src/pages/Popup.tsx
@@ -39,16 +39,38 @@ export function Popup() {
className="w-screen h-screen flex items-center justify-center select-none"
style={{ background: "transparent" }}
>
- {/* IDLE: Tiny pill */}
+ {/* IDLE: Offline badge */}
{state === "idle" && (
+ >
+
+
+ OFFLINE
+
+
)}
{/* RECORDING: Simple bars */}
From 07c37a34a435a880169557cd7aa49bb2f5105ecb Mon Sep 17 00:00:00 2001
From: youngmrz
Date: Sun, 18 Jan 2026 12:21:50 -0500
Subject: [PATCH 07/10] auto-claude: subtask-6-1 - End-to-end verification of
privacy dashboard featu
From 7f40155472e8fb48f33fa2cbf0c254191b1f9bb6 Mon Sep 17 00:00:00 2001
From: youngmrz
Date: Sun, 18 Jan 2026 12:40:21 -0500
Subject: [PATCH 08/10] fix: Add missing app_controller integration for privacy
dashboard (qa-requested)
Fixes:
- Add disableHistoryStorage to get_settings() return
- Add disableHistoryStorage mapping in update_settings()
- Wrap history storage in conditional to actually disable when setting is enabled
Verified:
- All three QA issues addressed
- Privacy feature now functional
QA Fix Session: 2
---
src-pyloid/app_controller.py | 38 +++++++++++++++++++++---------------
1 file changed, 22 insertions(+), 16 deletions(-)
diff --git a/src-pyloid/app_controller.py b/src-pyloid/app_controller.py
index d4624a2..c0f6272 100644
--- a/src-pyloid/app_controller.py
+++ b/src-pyloid/app_controller.py
@@ -178,22 +178,25 @@ def transcribe():
info("Pasting text at cursor...")
self.clipboard_service.paste_at_cursor(text)
- # Save to history (and audio if enabled)
- history_id = self.db.add_history(text)
-
- if settings.save_audio_to_history:
- try:
- audio_meta = self._save_audio_attachment(history_id, audio)
- self.db.update_history_audio(
- history_id,
- audio_relpath=audio_meta["audio_relpath"],
- audio_duration_ms=audio_meta["audio_duration_ms"],
- audio_size_bytes=audio_meta["audio_size_bytes"],
- audio_mime=audio_meta["audio_mime"],
- )
- info(f"Saved audio attachment for history {history_id}")
- except (OSError, wave.Error, sqlite3.Error, ValueError) as exc:
- warning(f"Failed to save audio attachment: {exc}")
+ # Save to history (and audio if enabled) - only if not disabled
+ if not settings.disable_history_storage:
+ history_id = self.db.add_history(text)
+
+ if settings.save_audio_to_history:
+ try:
+ audio_meta = self._save_audio_attachment(history_id, audio)
+ self.db.update_history_audio(
+ history_id,
+ audio_relpath=audio_meta["audio_relpath"],
+ audio_duration_ms=audio_meta["audio_duration_ms"],
+ audio_size_bytes=audio_meta["audio_size_bytes"],
+ audio_mime=audio_meta["audio_mime"],
+ )
+ info(f"Saved audio attachment for history {history_id}")
+ except (OSError, wave.Error, sqlite3.Error, ValueError) as exc:
+ warning(f"Failed to save audio attachment: {exc}")
+ else:
+ info("History storage disabled - transcription not saved")
if self._on_transcription_complete:
self._on_transcription_complete(text)
@@ -230,6 +233,7 @@ def get_settings(self) -> dict:
"onboardingComplete": settings.onboarding_complete,
"microphone": settings.microphone,
"saveAudioToHistory": settings.save_audio_to_history,
+ "disableHistoryStorage": settings.disable_history_storage,
"holdHotkey": settings.hold_hotkey,
"holdHotkeyEnabled": settings.hold_hotkey_enabled,
"toggleHotkey": settings.toggle_hotkey,
@@ -246,6 +250,8 @@ def update_settings(self, **kwargs) -> dict:
mapped["onboarding_complete"] = kwargs["onboardingComplete"]
if "saveAudioToHistory" in kwargs:
mapped["save_audio_to_history"] = kwargs["saveAudioToHistory"]
+ if "disableHistoryStorage" in kwargs:
+ mapped["disable_history_storage"] = kwargs["disableHistoryStorage"]
# Hotkey settings (camelCase to snake_case)
if "holdHotkey" in kwargs:
mapped["hold_hotkey"] = kwargs["holdHotkey"]
From e62dd9067bd72ef150878d2998e9b77cf7b5672c Mon Sep 17 00:00:00 2001
From: youngmrz
Date: Sun, 18 Jan 2026 13:25:09 -0500
Subject: [PATCH 09/10] chore: add auto-claude entries to .gitignore
---
.gitignore | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/.gitignore b/.gitignore
index a653d5a..af45347 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,3 +43,12 @@ docs/plans/
*.spec
build_error_log.txt
+
+# Auto Claude generated files
+.auto-claude/
+.auto-claude-security.json
+.auto-claude-status
+.claude_settings.json
+.worktrees/
+.security-key
+logs/security/
From 6341fc770f2e63b923ad32579ef68fb70e933e16 Mon Sep 17 00:00:00 2001
From: youngmrz
Date: Sun, 18 Jan 2026 13:27:06 -0500
Subject: [PATCH 10/10] fix: Remove invalid -p .venv flags from package.json
scripts (qa-requested)
Fixes:
- Removed invalid -p .venv flag from pyloid script
- Removed invalid -p .venv flag from build script
The -p flag was treating .venv as a Python executable name instead of a directory,
causing "No interpreter found for executable name .venv" error on launch.
Now using correct "uv run ./script.py" syntax.
Verified:
- package.json scripts updated correctly
- Launch error resolved
QA Fix Session: 1
Co-Authored-By: Claude Sonnet 4.5
---
package.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/package.json b/package.json
index 2146bba..9620581 100644
--- a/package.json
+++ b/package.json
@@ -7,9 +7,9 @@
"dev": "npm-run-all --parallel vite pyloid",
"dev:watch": "npm-run-all --parallel vite pyloid:watch",
"vite": "vite",
- "pyloid": "uv run -p .venv ./src-pyloid/main.py",
+ "pyloid": "uv run ./src-pyloid/main.py",
"pyloid:watch": "uv run pyloid-watcher --path ./src-pyloid --pattern \"*.py\" --command \"uv run ./src-pyloid/main.py\"",
- "build": "tsc -b && vite build && uv run -p .venv ./src-pyloid/build/build.py",
+ "build": "tsc -b && vite build && uv run ./src-pyloid/build/build.py",
"build:installer": "pnpm run build && cd installer && build-installer.bat",
"setup": "pnpm install && uv venv && uv sync"
},