From 101c91c4d87a2fde8bbe3563730f30757123df9c Mon Sep 17 00:00:00 2001 From: Ole-Morten Duesund Date: Mon, 16 Feb 2026 13:31:33 +0100 Subject: [PATCH] Rename to claudify, add docs and .deb packaging - Rename package from claude-app to claudify (v0.1.0) - Add README.md with install/usage instructions - Add CLAUDE.md with architecture, build, and known issues - Add .desktop file for application menu integration - Build target set to .deb only - Remove failed CSD button workarounds, document upstream bug - Remove gtk dependency (no longer needed) Co-Authored-By: Claude Opus 4.6 --- CLAUDE.md | 51 ++++++++++++++++++++++++++++++++++ README.md | 56 ++++++++++++++++++++++++++++++++++++++ package.json | 6 ++-- src-tauri/Cargo.lock | 5 ++-- src-tauri/Cargo.toml | 9 ++---- src-tauri/claudify.desktop | 9 ++++++ src-tauri/src/lib.rs | 24 +++------------- src-tauri/src/main.rs | 2 +- src-tauri/tauri.conf.json | 12 ++++---- 9 files changed, 136 insertions(+), 38 deletions(-) create mode 100644 CLAUDE.md create mode 100644 README.md create mode 100644 src-tauri/claudify.desktop diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..d832ba0 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,51 @@ +# Claudify + +Native desktop wrapper for [claude.ai](https://claude.ai) built with Tauri v2 and WebKitGTK. + +## Architecture + +- **Tauri v2** with Rust backend, system WebKitGTK webview on Linux +- **Direct webview navigation** to `https://claude.ai` (not iframe — claude.ai blocks iframes via CSP) +- **No frontend code** — `src/index.html` is a placeholder required by Tauri's build system; the actual UI is claude.ai loaded via `WebviewUrl::External` +- All app logic lives in `src-tauri/src/lib.rs` inside the `setup()` closure + +## Key Files + +| File | Purpose | +|------|---------| +| `src-tauri/src/lib.rs` | All app logic: window, tray, notifications, navigation filter | +| `src-tauri/src/main.rs` | Entry point, calls `claudify::run()` | +| `src-tauri/tauri.conf.json` | Tauri config: app identity, bundle targets, security | +| `src-tauri/capabilities/` | Tauri v2 permission grants for local window and remote claude.ai | +| `src-tauri/Cargo.toml` | Rust dependencies | + +## Building + +### Prerequisites + +```bash +# Debian/Ubuntu system packages +sudo apt install libwebkit2gtk-4.1-dev libxdo-dev librsvg2-dev libayatana-appindicator3-dev + +# Tauri CLI +cargo install tauri-cli --version "^2.0" --locked +``` + +### Build + +```bash +cargo tauri build # Produces .deb in target/release/bundle/deb/ +cargo tauri dev # Development mode with hot reload +``` + +## Known Issues + +- **CSD titlebar buttons non-interactive after hide/show** — Upstream bug in TAO's client-side decoration handling. Titlebar buttons (minimize/maximize/close) become unresponsive after the window is hidden to tray and restored. The close button still works via the tray menu. No known workaround — GTK decoration layout overrides, header bar replacement, resize nudges, and present() were all attempted without success. Tracked at: + - https://github.com/tauri-apps/tauri/issues/11856 + - https://github.com/tauri-apps/tao/issues/1046 + +## Conventions + +- Keep all app logic in `lib.rs` — avoid splitting into multiple modules unless complexity demands it +- Navigation allowlist in `is_allowed_navigation()` — add new OAuth providers here if needed +- Test changes with `cargo tauri dev` before building .deb diff --git a/README.md b/README.md new file mode 100644 index 0000000..e7e10c4 --- /dev/null +++ b/README.md @@ -0,0 +1,56 @@ +# Claudify + +A native Linux desktop app for [claude.ai](https://claude.ai). Not a browser — a dedicated app that lives in your system tray, persists login sessions, and forwards notifications natively. + +Built with [Tauri v2](https://v2.tauri.app/) and WebKitGTK. + +## Features + +- **System tray** — hide/show from tray icon, left-click toggles visibility +- **Session persistence** — cookies and localStorage persist across restarts +- **Native notifications** — browser Notification API bridged to desktop notifications +- **Navigation guard** — only claude.ai, Anthropic, and OAuth provider domains load in-app; all other links open in your default browser +- **Lightweight** — uses system WebKitGTK, no bundled browser engine (~5MB .deb) + +## Install + +### From .deb + +```bash +sudo dpkg -i claudify_0.1.0_amd64.deb +``` + +Requires `libwebkit2gtk-4.1-0` and `libayatana-appindicator3-1` (pulled automatically via `apt`). + +### From source + +```bash +# Install system dependencies +sudo apt install libwebkit2gtk-4.1-dev libxdo-dev librsvg2-dev libayatana-appindicator3-dev + +# Install Tauri CLI +cargo install tauri-cli --version "^2.0" --locked + +# Build +cargo tauri build +``` + +The .deb will be at `src-tauri/target/release/bundle/deb/claudify_0.1.0_amd64.deb`. + +## Usage + +Launch `claudify` from your application menu or terminal. + +- **Close button** hides the window to the system tray (app keeps running) +- **Tray icon left-click** toggles window visibility +- **Tray icon right-click** shows menu: Hide/Show Claude, Quit +- **Ctrl+Plus/Minus** zooms in/out +- **External links** open in your default browser + +## Known Issues + +- Window titlebar buttons (minimize/maximize/close) become non-interactive after hiding and restoring the window from the system tray. This is an [upstream bug](https://github.com/tauri-apps/tauri/issues/11856) in Tauri's GTK client-side decoration handling ([tao#1046](https://github.com/tauri-apps/tao/issues/1046)). Use the tray icon to hide/show and quit. + +## License + +MIT diff --git a/package.json b/package.json index 16185cd..d96af2b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "claude-app", - "version": "1.0.0", + "name": "claudify", + "version": "0.1.0", "private": true, - "description": "Claude desktop app" + "description": "Native desktop wrapper for claude.ai" } diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 5266a4e..14c376c 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -448,10 +448,9 @@ dependencies = [ ] [[package]] -name = "claude-app" -version = "1.0.0" +name = "claudify" +version = "0.1.0" dependencies = [ - "gtk", "serde", "serde_json", "tauri", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index ac2a148..6e9550d 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "claude-app" -version = "1.0.0" -description = "Claude desktop app" +name = "claudify" +version = "0.1.0" +description = "Native desktop wrapper for claude.ai" edition = "2021" [build-dependencies] @@ -15,9 +15,6 @@ serde = { version = "1", features = ["derive"] } serde_json = "1" url = "2" -[target.'cfg(target_os = "linux")'.dependencies] -gtk = { version = "0.18", features = ["v3_24"] } - [features] default = ["custom-protocol"] custom-protocol = ["tauri/custom-protocol"] diff --git a/src-tauri/claudify.desktop b/src-tauri/claudify.desktop new file mode 100644 index 0000000..bfc1198 --- /dev/null +++ b/src-tauri/claudify.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Categories=Network;WebBrowser; +Comment=Native desktop wrapper for claude.ai +Exec=claudify +Icon=claudify +Keywords=claude;ai;anthropic;chat; +Name=Claudify +Terminal=false +Type=Application diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index dbb2449..a153f54 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -97,10 +97,10 @@ pub fn run() { .plugin(tauri_plugin_opener::init()) .invoke_handler(tauri::generate_handler![send_notification]) .setup(|app| { - // NOTE: Decorations disabled due to upstream bug where CSD titlebar - // buttons become non-interactive after hide()/show() on Linux. - // Tracked at: https://github.com/tauri-apps/tauri/issues/11856 - // https://github.com/tauri-apps/tao/issues/1046 + // KNOWN ISSUE: CSD titlebar buttons become non-interactive after + // hide()/show() on Linux. No workaround found. Use tray icon instead. + // https://github.com/tauri-apps/tauri/issues/11856 + // https://github.com/tauri-apps/tao/issues/1046 let webview_window = WebviewWindowBuilder::new( app, "main", @@ -109,7 +109,6 @@ pub fn run() { .title("Claude") .inner_size(1200.0, 800.0) .min_inner_size(400.0, 300.0) - .resizable(true) // Standard WebKit user agent so claude.ai serves the full experience .user_agent("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15") .initialization_script(NOTIFICATION_BRIDGE_JS) @@ -124,21 +123,6 @@ pub fn run() { }) .build()?; - // Replace the default GTK header bar with one that has no buttons. - // The standard CSD buttons become non-interactive after hide()/show() - // due to upstream bug: https://github.com/tauri-apps/tauri/issues/11856 - #[cfg(target_os = "linux")] - { - use gtk::prelude::*; - if let Ok(gtk_win) = webview_window.gtk_window() { - let header = gtk::HeaderBar::new(); - header.set_show_close_button(false); - header.set_title(Some("Claude")); - header.show(); - gtk_win.set_titlebar(Some(&header)); - } - } - // -- System tray -- let toggle_item = MenuItem::with_id(app, "toggle", "Hide Claude", true, None::<&str>)?; diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index f0a03ee..415006f 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -2,5 +2,5 @@ #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] fn main() { - claude_app::run(); + claudify::run(); } diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 7f7065d..d16b987 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { - "productName": "Claude", - "version": "1.0.0", - "identifier": "no.naiv.claude-app", + "productName": "claudify", + "version": "0.1.0", + "identifier": "no.naiv.claudify", "build": { "frontendDist": "../src" }, @@ -17,7 +17,7 @@ }, "bundle": { "active": true, - "targets": ["deb", "appimage"], + "targets": ["deb"], "icon": [ "icons/32x32.png", "icons/128x128.png", @@ -27,7 +27,9 @@ ], "linux": { "deb": { - "depends": ["libwebkit2gtk-4.1-0", "libayatana-appindicator3-1"] + "depends": ["libwebkit2gtk-4.1-0", "libayatana-appindicator3-1"], + "section": "web", + "desktopTemplate": "claudify.desktop" } } }