* feat: merge desktop client into monorepo under client/ Move the Tauri 2.0 + SvelteKit desktop client from the separate pocketpaw-client repo into client/ to create a monorepo. Update .gitignore with client build artifact ignores and add Desktop Client section to CLAUDE.md. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(client): unignore client/src/lib and broaden node/sveltekit ignores The root .gitignore `lib/` pattern was blocking client/src/lib/ from being tracked. Anchor it to `/lib/` so only the root Python lib dir is ignored. Also generalize node_modules/ and .svelte-kit/ patterns to work at any depth. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(client): fix white OAuth screen on Windows Load a local loading page first in the OAuth popup window, then navigate to the external OAuth URL via eval(). WebView2 on Windows may not be fully initialized when WebviewUrl::External is used directly, resulting in a permanently white window. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(client): replace WebView OAuth popup with system browser + localhost server WebView2 secondary windows fail to render on Windows (white/transparent screen). Replace the OAuth popup with a temporary localhost HTTP server that captures the callback, and open the authorize URL in the system browser instead. Also pre-create sidepanel and quickask windows in tauri.conf.json (with visible: false) so they initialize alongside the main window, avoiding the same WebView2 rendering issue with dynamically-created transparent windows. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add multi-mode workspace client design Design for transforming the desktop client into a full workspace IDE with tabbed workspaces, tiling layout engine, pluggable widgets, real-time agent collaboration, unified file management (local + remote + cloud), and responsive mobile support. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add multi-mode workspace implementation plan Detailed 6-phase implementation plan with ~49 new files across Rust backend (fs commands, PTY, git, widget windows), SvelteKit frontend (tiling layout, Monaco editor, file previews, widget system, terminal), filesystem providers (local, remote, cloud), and co-work features. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: rewrite design as AI file explorer (Poly.app-inspired) Complete redesign from VS Code-like IDE to file-explorer-first UI. Primary interface is a visual file grid with rich thumbnails and 5 view modes (Icon, Grid, List, Column, Gallery). AI chat lives in a collapsible right sidebar with folder/file context awareness. Agent actions (create, edit, delete files) reflect in the grid in real-time. Terminal output is inline in chat, not a separate panel. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(client): add file explorer with list view, search/filter, and context menu Implements a full file explorer with Rust-backed filesystem operations (read, write, delete, rename, watch, thumbnails), multiple view modes (icon grid + list table), inline search/filter, and an enhanced context menu with rename, new folder, and keyboard shortcuts (Ctrl+F, F2, Del). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(deep-work): add v2 engine — retry, timeout, cancel, output chaining, PawKit schema Deep Work v2 hardens the execution engine and lays the foundation for PawKit-based Command Centers. This is the first WIP PR toward the blueprints-strategy vision. Engine improvements: - Task retry: auto-retry failed tasks up to configurable max_retries - Task timeout: per-task asyncio.wait_for with timeout_minutes - Output storage: task.output field for cross-task chaining - Error tracking: task.error_message for diagnostics - Project cancellation: CANCELLED status, stop_all_project_tasks, skip pending tasks with error_message - Manual retry API: POST /projects/{id}/tasks/{tid}/retry New PawKit config schema v0.1: - Pydantic v2 models for Command Center templates - Layout (panels, sections), workflows, user_config, integrations - YAML load/save utilities with PyYAML Files changed: - src/pocketpaw/mission_control/models.py — 5 new Task fields - src/pocketpaw/deep_work/models.py — TaskSpec v2 + CANCELLED status - src/pocketpaw/mission_control/executor.py — retry, timeout, output, stop_all - src/pocketpaw/deep_work/session.py — cancel(), materialize v2 fields - src/pocketpaw/deep_work/api.py — cancel + retry endpoints - src/pocketpaw/deep_work/__init__.py — cancel_project export - src/pocketpaw/deep_work/pawkit.py — NEW: PawKit config schema - tests/test_deep_work_v2.py — 71 new tests - tests/test_mission_control_executor.py — adapted for retry defaults Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test(deep-work): add 21 E2E tests for v2 engine features API-level E2E tests using httpx.AsyncClient with ASGI transport. Real file-based store, session, scheduler, and executor — only the agent backend (LLM calls) is mocked. Coverage: full lifecycle, output chaining, auto-retry, timeout, cancellation, manual retry API, get plan API, skip task API, and PawKit YAML round-trip. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs(deep-work): add v2 feature docs — retry, timeout, cancel, output chaining, PawKit Updated the Deep Work guide with new sections covering auto-retry, task timeout, output chaining, project cancellation, and PawKit template format. Added API endpoint pages for Cancel Project and Retry Task. Updated sidebar navigation in docs-config.json. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add Command Centers concept page and PawKit technical reference New standalone pages for the two biggest ideas in the v2 engine: - docs/concepts/command-centers.mdx — the "why": agent-operated dashboards, PawKits as templates, conversational building, Kit Store marketplace, how it all connects - docs/advanced/pawkit.mdx — the "how": full YAML schema reference with panel types, workflow triggers, user config fields, integrations, and Python API examples Trimmed the PawKit section in deep-work.mdx to a cross-reference since the content now lives in dedicated pages. Updated sidebar navigation with both new entries. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(client): enhance file explorer with viewers, clipboard, and editor save Add file preview support (audio, video, PDF, markdown with syntax highlighting), copy/cut/paste with keyboard shortcuts, file properties dialog, open-in-terminal, editable code editor with Ctrl+S save and dirty tracking, and improved AI model settings panel with Ollama model fetching. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(client): migrate stores to REST-first architecture, WS push-only Move all request-response flows (sessions, chat, settings) to REST HTTP. WebSocket is now exclusively for server-initiated push events. - Add createSession() REST method to client - Remove WS convenience methods (chat, newSession, switchSession, etc.) - Remove bindEvents/disposeEvents from all stores - Rewrite sessionStore to use POST /sessions and REST history - Rewrite settingsStore.saveApiKey to use PUT /settings - Simplify connectionStore (remove sessionId, connection_info listener) - Simplify initializeStores (no more bindEvents calls) - Clean up WS types (remove chat/session event types) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(api): REST-first architecture, fix WS dual-delivery and persistent client bugs (#384) Move all request-response flows to REST HTTP. WebSocket is now push-only. Fixes dual-delivery bug where SSE chat responses were broadcast to all WS clients, and persistent Claude SDK client issues with stale data across sessions. Backend changes: - Add POST /sessions endpoint with SessionCreateResponse schema - Fix WS adapter send() — drop messages for unknown chat_ids instead of broadcasting - Fix WS adapter on_system_event() — route by session_key, not broadcast - Enhance PUT /settings with runtime side-effects (reset_router + memory reload) - Add cancel_task() to AgentLoop — lightweight cancellation without stopping router - Fix _on_done callback race — don't remove newer task's entry from _active_tasks - Add session lock contention logging for diagnostics Chat streaming fixes: - Cancel in-flight SSE streams when new request arrives for same session - Only cancel agent tasks when there IS a competing stream (not on every request) - Add diagnostic logging to SSE bridge event delivery Claude SDK persistent client fixes: - Include session_key in persistent client key — different sessions get fresh subprocesses - Drain trailing ResultMessage from subprocess pipe after each query to prevent stale data on subsequent queries (root cause of "second message shows first response") - Add dispatch/event logging for persistent vs stateless path diagnostics Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> * feat(api): add PawKits system + MC/DW route mounting for serve command - Add kits module (models, store, catalog, builtin YAML kits) - Add kits API router with CRUD, catalog, and data resolution endpoints - Add api:agents and api:standup source resolvers in kits data resolution - Mount MC and DW routers in serve.py (was only in dashboard.py) - Fix standup resolver to use manager.generate_standup() Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: merge desktop client into monorepo (#290) * feat: merge desktop client into monorepo under client/ Move the Tauri 2.0 + SvelteKit desktop client from the separate pocketpaw-client repo into client/ to create a monorepo. Update .gitignore with client build artifact ignores and add Desktop Client section to CLAUDE.md. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(client): unignore client/src/lib and broaden node/sveltekit ignores The root .gitignore `lib/` pattern was blocking client/src/lib/ from being tracked. Anchor it to `/lib/` so only the root Python lib dir is ignored. Also generalize node_modules/ and .svelte-kit/ patterns to work at any depth. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(client): fix white OAuth screen on Windows Load a local loading page first in the OAuth popup window, then navigate to the external OAuth URL via eval(). WebView2 on Windows may not be fully initialized when WebviewUrl::External is used directly, resulting in a permanently white window. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(client): replace WebView OAuth popup with system browser + localhost server WebView2 secondary windows fail to render on Windows (white/transparent screen). Replace the OAuth popup with a temporary localhost HTTP server that captures the callback, and open the authorize URL in the system browser instead. Also pre-create sidepanel and quickask windows in tauri.conf.json (with visible: false) so they initialize alongside the main window, avoiding the same WebView2 rendering issue with dynamically-created transparent windows. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add multi-mode workspace client design Design for transforming the desktop client into a full workspace IDE with tabbed workspaces, tiling layout engine, pluggable widgets, real-time agent collaboration, unified file management (local + remote + cloud), and responsive mobile support. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add multi-mode workspace implementation plan Detailed 6-phase implementation plan with ~49 new files across Rust backend (fs commands, PTY, git, widget windows), SvelteKit frontend (tiling layout, Monaco editor, file previews, widget system, terminal), filesystem providers (local, remote, cloud), and co-work features. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: rewrite design as AI file explorer (Poly.app-inspired) Complete redesign from VS Code-like IDE to file-explorer-first UI. Primary interface is a visual file grid with rich thumbnails and 5 view modes (Icon, Grid, List, Column, Gallery). AI chat lives in a collapsible right sidebar with folder/file context awareness. Agent actions (create, edit, delete files) reflect in the grid in real-time. Terminal output is inline in chat, not a separate panel. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(client): add file explorer with list view, search/filter, and context menu Implements a full file explorer with Rust-backed filesystem operations (read, write, delete, rename, watch, thumbnails), multiple view modes (icon grid + list table), inline search/filter, and an enhanced context menu with rename, new folder, and keyboard shortcuts (Ctrl+F, F2, Del). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(client): enhance file explorer with viewers, clipboard, and editor save Add file preview support (audio, video, PDF, markdown with syntax highlighting), copy/cut/paste with keyboard shortcuts, file properties dialog, open-in-terminal, editable code editor with Ctrl+S save and dirty tracking, and improved AI model settings panel with Ollama model fetching. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(client): migrate stores to REST-first architecture, WS push-only Move all request-response flows (sessions, chat, settings) to REST HTTP. WebSocket is now exclusively for server-initiated push events. - Add createSession() REST method to client - Remove WS convenience methods (chat, newSession, switchSession, etc.) - Remove bindEvents/disposeEvents from all stores - Rewrite sessionStore to use POST /sessions and REST history - Rewrite settingsStore.saveApiKey to use PUT /settings - Simplify connectionStore (remove sessionId, connection_info listener) - Simplify initializeStores (no more bindEvents calls) - Clean up WS types (remove chat/session event types) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(client): full Mission Control integration — agents, execution, projects, notifications - Add MC/DW types (AgentProfile, MCTask, MCMessage, MCProject, etc.) - Add 25+ API methods (mcRequest + dwRequest helpers) for agents, tasks, execution, notifications, projects - Add mcStore (agents, running tasks, execution streaming, notifications) and projectStore (project lifecycle, planning) - Add AgentRoster panel with CRUD, KanbanBoard enhancements (assignment, run/stop, messages, running indicator) - Add TaskExecutionPanel slide-over for live agent streaming - Add NotificationBell in titlebar with unread badge - Add StandupPanel and document viewer/editor in DataTable - Add /projects route with creation wizard, plan review, lifecycle controls - Remove internal-docs from git tracking - Rename tabs: Deep Work → PawKits, Projects → Deep Work Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> * feat(client): add PawKits catalog, layout renderer, and remaining panel components Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(api): add PawKits system + MC/DW route mounting for serve command - Add kits module (models, store, catalog, builtin YAML kits) - Add kits API router with CRUD, catalog, and data resolution endpoints - Add api:agents and api:standup source resolvers in kits data resolution - Mount MC and DW routers in serve.py (was only in dashboard.py) - Fix standup resolver to use manager.generate_standup() Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: add plans and update lockfile Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: remove plans and revert uv.lock Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: resolve merge breakages in chat, context builder, and MC routes - Add missing FileContext model and field to ChatRequest schema - Add file_context parameter to build_system_prompt() - Move /tasks/running route before /tasks/{task_id} to fix 404 - Remove unused TaskStatus import in kits.py Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: resilient SDK streaming, in-app file viewer, and explorer tool - Replace _safe_iter with _resilient_receive to handle MessageParseError by re-creating the iterator instead of losing the stream - Add file-open command interception (start, xdg-open, etc.) to redirect to the in-app explorer viewer via PreToolUse hook - Add /api/files/content endpoint for serving file contents with MIME types - Add explorer built-in tool and open_in_explorer CLI command - Update dashboard frontend with file viewer modal and transparency fixes - Set SDK stream close timeout to 24h for long-running tool use - Suppress API-key errors in ResultMessage to avoid noisy logs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(client): tabbed explorer, file viewers, command palette, and onboarding refresh - Add multi-tab explorer with history, file type filtering, and address bar - Implement PDF, spreadsheet, notebook, document, and text preview viewers - Add command palette (Ctrl+K) with fuzzy search - Overhaul onboarding wizard with model search and backend setup - Add Tauri fs commands for file content and metadata - Improve chat input, file preview, and session dropdown - Update dialog components and workspace tabs - Add content preview caching and binary utils for file handling Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Rohit Kushwaha <technicalrohit06@gmail.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Rohit Kushwaha <rohitk290106@gmail.com>
5.4 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
PocketPaw is a Tauri v2 desktop client for the PocketPaw AI assistant backend. The frontend is SvelteKit (Svelte 5 runes mode) with Tailwind CSS 4 and shadcn-svelte components. The backend lives at the repo root (../) and runs on localhost:8888. This client directory is part of the pocketpaw monorepo.
Development Commands
# Frontend dev server (port 1420)
bun run dev
# Full desktop app (frontend + Tauri shell)
bun run tauri dev
# Type checking
bun run check
bun run check:watch
# Build
bun run build # Frontend only
bun run tauri build # Full desktop app
# Mobile
bun run tauri:android # Android dev
bun run tauri:ios # iOS dev
Note: The backend must be running on localhost:8888 for the app to function. There are no test commands configured.
Architecture
App Initialization Flow
+layout.svelte is the entry point. It handles authentication (OAuth token from ~/.pocketpaw/access_token or OAuth flow), then calls initializeStores(token) which:
- Creates the REST client and exchanges the token for a session cookie
- Connects the WebSocket
- Binds WebSocket events to all stores
- Loads sessions and settings via REST in the background
Routing
SPA mode — SSR is disabled (+layout.ts), static adapter with fallback: "index.html". Routes:
/— Chat (main view)/settings,/explore,/activity— wrapped in AppShell with sidebar/sidepanel,/quickask— separate Tauri windows, skip AppShell, initialize stores independently/onboarding— first-run wizard/oauth-callback— OAuth redirect handler
The layout detects the route and conditionally renders AppShell vs standalone window layouts.
State Management
Stores are Svelte 5 rune-based class singletons in src/lib/stores/. Each store exports a single instance:
- connectionStore — REST client + WebSocket lifecycle
- chatStore — Messages, streaming, abort control
- sessionStore — Session list, active session
- settingsStore — Backend settings, channel configs
- activityStore — Activity log entries
- skillStore — Available skills
- uiStore — Sidebar state, search focus
- platformStore — Platform detection (desktop/mobile/tablet)
Stores that need real-time updates expose bindEvents(ws) / disposeEvents() for WebSocket wiring.
API Layer
- REST:
PocketPawClientinsrc/lib/api/client.ts— auto-retries on 401 with token refresh, SSE streaming for chat - WebSocket:
PocketPawWebSocketinsrc/lib/api/websocket.ts— auto-reconnect with exponential backoff, heartbeat every 30s - Config:
src/lib/api/config.ts—BACKEND_URL = "http://localhost:8888",API_PREFIX = "/api/v1"
Tauri (Rust Side)
src-tauri/src/lib.rs is the entry point. Desktop-only features use #[cfg(desktop)]:
- System tray (
tray.rs) — menu with Open, Quick Ask, Settings, Quit - Close-to-tray — intercepts window close, hides instead
- Multi-window (
side_panel.rs,quick_ask.rs) — created viaWebviewWindowBuilder - Global shortcuts — registered from the frontend via
tauri-plugin-global-shortcut - Invoke commands (
commands.rs,oauth.rs) —read_access_token,toggle_side_panel, OAuth token CRUD
Auth Flow
OAuth PKCE flow in src/lib/auth/:
- Read stored tokens → if valid, use directly
- If expired, refresh via refresh token
- If no tokens, open OAuth browser window, handle callback at
/oauth-callback - Exchange access token for session cookie via
POST /auth/login - Token updates emit
token-updatedTauri event for multi-window sync
Svelte 5 Rules (Critical)
- Props:
let { prop } = $props()— uselet, notconst - Derived:
$derived(expr)for expressions,$derived.by(() => {...})for function bodies.$derived(() => {...})is WRONG (wraps a function, doesn't execute it) - Dynamic components:
<svelte:component>is deprecated. Use uppercase variables:let Icon = $derived(...)then<Icon /> {@const}only works inside block tags ({#if},{#each}), not at template top level
Tailwind CSS 4 Rules (Critical)
- Never use string interpolation in class attributes:
class="static {dynamic}"breaks Tailwind 4's Vite plugin. Always useclass={cn("static", dynamic)}orclass={expression} - Dark mode uses
.darkclass variant:@custom-variant dark (&:is(.dark *)); - Design tokens are oklch-based CSS custom properties in
src/styles/global.css
Conventions
- Package manager: Bun
- Icons:
@lucide/svelte— import from@lucide/svelte/icons/icon-name - UI components: shadcn-svelte in
src/lib/components/ui/ - Utility function:
cn()from$lib/utils(clsx + tailwind-merge) - Path aliases:
$lib→src/lib,@/*→src/lib/* - Fonts: Inter (variable) for body, JetBrains Mono (variable) for code
- DOMPurify: Option is
ALLOWED_TAGS(notALLOW_TAGS)
Tauri 2 Gotchas
Image::from_bytes(include_bytes!("..."))— nofrom_pngmethodtauri::Emittertrait must be imported for.emit()onAppHandle- Tray closures need explicit types:
|app: &AppHandle<Wry>, event| tauri-plugin-autostartv2 has noxdgfeature- Capabilities defined in
src-tauri/capabilities/default.json(desktop) andmobile.json