diff --git a/README.md b/README.md
index 551f61c8..610488f4 100644
--- a/README.md
+++ b/README.md
@@ -5,11 +5,35 @@
claude-devtools
- Read 3 files told you nothing. This shows you everything.
+ Terminal tells you nothing. This shows you everything.
A desktop app that reconstructs exactly what Claude Code did — every file path, every tool call, every token — from the raw session logs already on your machine.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ No API keys. No configuration. Just download, open, and see everything Claude Code did.
+
+
@@ -20,6 +44,18 @@
---
+## Installation
+
+| Platform | Download | Notes |
+|----------|----------|-------|
+| **macOS** (Apple Silicon) | [`.dmg`](https://github.com/matt1398/claude-devtools/releases/latest) | Drag to Applications. On first launch: right-click → Open (unsigned) |
+| **macOS** (Apple Silicon) | [`.zip`](https://github.com/matt1398/claude-devtools/releases/latest) | Extract and run |
+| **Windows** | [`.exe`](https://github.com/matt1398/claude-devtools/releases/latest) | Standard installer. May trigger SmartScreen — click "More info" → "Run anyway" |
+
+The app reads session logs from `~/.claude/` — the data is already on your machine. No setup, no API keys, no login.
+
+---
+
## Why This Exists
### Claude Code stopped telling you what it's doing.
@@ -109,15 +145,14 @@ Open multiple sessions side-by-side. Drag-and-drop tabs between panes, split vie
---
-## Getting Started
+## Development
-### Prerequisites
+
+Build from source
-- **Node.js** 20+
-- **pnpm** 10+
-- macOS or Windows
+
-### Install & Run
+**Prerequisites:** Node.js 20+, pnpm 10+
```bash
git clone https://github.com/matt1398/claude-devtools.git
@@ -126,9 +161,9 @@ pnpm install
pnpm dev
```
-That's it. The app auto-discovers your Claude Code projects from `~/.claude/`.
+The app auto-discovers your Claude Code projects from `~/.claude/`.
-### Build for Distribution
+#### Build for Distribution
```bash
pnpm dist:mac # macOS (.dmg)
@@ -136,9 +171,7 @@ pnpm dist:win # Windows (.exe)
pnpm dist # Both platforms
```
----
-
-## Scripts
+#### Scripts
| Command | Description |
|---------|-------------|
@@ -151,6 +184,8 @@ pnpm dist # Both platforms
| `pnpm test:coverage` | Coverage report |
| `pnpm check` | Full quality gate (types + lint + test + build) |
+
+
---
## Contributing
diff --git a/src/main/services/infrastructure/UpdaterService.ts b/src/main/services/infrastructure/UpdaterService.ts
index 50eb7566..ec018951 100644
--- a/src/main/services/infrastructure/UpdaterService.ts
+++ b/src/main/services/infrastructure/UpdaterService.ts
@@ -57,9 +57,11 @@ export class UpdaterService {
/**
* Quit the app and install the downloaded update.
+ * On Windows (NSIS): isSilent=true runs the installer with /S (no wizard);
+ * isForceRunAfter=true launches the app after install. Other platforms ignore these.
*/
quitAndInstall(): void {
- autoUpdater.quitAndInstall();
+ autoUpdater.quitAndInstall(true, true);
}
private sendStatus(status: UpdaterStatus): void {
diff --git a/src/renderer/components/common/UpdateBanner.tsx b/src/renderer/components/common/UpdateBanner.tsx
index f0feaba6..c74968fb 100644
--- a/src/renderer/components/common/UpdateBanner.tsx
+++ b/src/renderer/components/common/UpdateBanner.tsx
@@ -21,47 +21,60 @@ export const UpdateBanner = (): React.JSX.Element | null => {
const isDownloading = updateStatus === 'downloading';
const percent = Math.round(downloadProgress);
+ const clampedPercent = Math.max(0, Math.min(percent, 100));
return (
{isDownloading ? (
- <>
-
-
- Downloading update... {percent}%
-
-
+
+
+
+ Updating app
+
+ {clampedPercent}%
+
+
+
- >
+
) : (
- <>
+
-
- Update ready{availableVersion ? ` (v${availableVersion})` : ''}
+
+ Update ready
+ {availableVersion ? (
+
+ v{availableVersion}
+
+ ) : null}
- Restart to Update
+ Restart now
- >
+
)}
{/* Dismiss */}
diff --git a/src/renderer/components/common/UpdateDialog.tsx b/src/renderer/components/common/UpdateDialog.tsx
index 16e5fd70..7ec6e6b9 100644
--- a/src/renderer/components/common/UpdateDialog.tsx
+++ b/src/renderer/components/common/UpdateDialog.tsx
@@ -5,7 +5,7 @@
*/
import { useStore } from '@renderer/store';
-import { Download, X } from 'lucide-react';
+import { X } from 'lucide-react';
export const UpdateDialog = (): React.JSX.Element | null => {
const showUpdateDialog = useStore((s) => s.showUpdateDialog);
@@ -27,7 +27,7 @@ export const UpdateDialog = (): React.JSX.Element | null => {
tabIndex={-1}
/>
{
- {/* Title */}
-
- Update Available
-
-
- {/* Body */}
-
- Version {availableVersion} is available. Would you like to download it?
-
+
+
+ Update Available
+
+ {availableVersion && (
+
+ v{availableVersion}
+
+ )}
+
{/* Release notes */}
{releaseNotes && (
{
)}
{/* Actions */}
-
+
{
-
- Download Update
+ Download
diff --git a/src/renderer/components/layout/SidebarHeader.tsx b/src/renderer/components/layout/SidebarHeader.tsx
index 59170777..79cf254f 100644
--- a/src/renderer/components/layout/SidebarHeader.tsx
+++ b/src/renderer/components/layout/SidebarHeader.tsx
@@ -195,6 +195,9 @@ const ProjectDropdownItem = ({
};
export const SidebarHeader = (): React.JSX.Element => {
+ const isMacElectron =
+ isElectronMode() && window.navigator.userAgent.toLowerCase().includes('mac');
+
const {
repositoryGroups,
selectedRepositoryId,
@@ -330,10 +333,10 @@ export const SidebarHeader = (): React.JSX.Element => {
style={
{
height: `${HEADER_ROW1_HEIGHT}px`,
- paddingLeft: isElectronMode()
+ paddingLeft: isMacElectron
? 'var(--macos-traffic-light-padding-left, 72px)'
: '16px',
- WebkitAppRegion: isElectronMode() ? 'drag' : undefined,
+ WebkitAppRegion: isMacElectron ? 'drag' : undefined,
} as React.CSSProperties
}
>